cat-1cat-2cat-3cat-4cat-5cat-6

JavaScript

JavaScript는 어떻게 동작할까? 1편

20:19

thumbnail

안녕하세요. NekoNynagYee입니다.

요즘 공부를 하고 있는 와중에 그런 생각이 들었습니다.

자바스크립트는 어떻게 동작하더라?

순간 이 생각이 드니까 이것도 제대로 모르면서 자바스크립트 메서드 관련 글만 쓰려고 했으니 넥스트를 얼마전에 입문한 저로써 자신을 다시 돌아보는 시간이었습니다...

자 그래서!!ㅋㅋㅋㅋ 오늘 주제는 다시 초심으로 돌아가서 자바스크립트는 어떤 언어이며 어떻게 동작하는지를 알아보려 합니다!!

이번 게시물은 참고 여기서 참고해서 제가 이해한 것을 바탕으로 작성하였습니다.

1. 자바스크립트의 전체적인 동작 구조


NodeJS를 설명할 때 제가 JavaScript는 웹 페이지에 글 넣고, 그림 넣는 HTML이라는 언어를 조작해서 동적으로 바꿔주게 하는 언어입니다. 라고 설명드린 부분이 있었습니다. 그럼 이 자바스크립트가 어떻게 동작을 해서 이렇게 사이트를 동적으로 움직이게 하는지 전체적인 구조를 알아보려합니다.

js-heap-stack

먼저 자바스크립트를 실행하기 위해서는 자바스크립트 엔진이 필요합니다.

자바스크립트 엔진의 종류에는 V8, Rhino, SpiderMonkey등 여러 엔진이 있지만 그 중에서 대표적인 것은 구글에서 제작한 V8엔진입니다. 위 사진은 자바스크립트를 실행할 수 있게 해주는 V8 엔진을 간략하게 표현한 그림입니다.

엔진은 크게 Memory Heap, Call Stack 2가지로 구성되어있습니다. Memory Heap(메모리 힙)은 메모리가 할당되는 곳이고, Call Stack(호출 스택)은 코드 실행에 따라 스택이 하나씩 차곡차곡 쌓이는 곳입니다.

여기서 용어 정리!!

  • Stack: 후입선출(LIFO)로 마지막에 들어간 것이 먼저 나가는 방식입니다.

그리고 자바스크립트를 사용하다 보면 setTimeOut()이나 setinterval()과 같은 타이머 생성자 함수 외에도 여러 API를 사용합니다.

그럼 과연 이 API들은 자바스크립트 엔진에서 자체적으로 지원하는 걸까요?

아닙니다. 이러한 API들은 웹 브라우저 혹은 NodeJS와 같은 자바스크립트 런타임에서 지원 해주는 WEB API입니다. 이 API는 브라우저마다 지원될수도 안될수도 있기 때문에 항상 사용하기전에 지원여부를 따져보고 써야 합니다.

event-loop-callback-queue

한가지 더, 자바스크립트는 아까도 그렇고 전에 설명한 setTimeOut()이나 setinterval()과 같은 비동기 코드 작성이 가능함에도 불구하고, 자바스크립트는 비동기 코드를 처리한다라는 개념이 없습니다. 그런데도 어떻게 비동기 코드를 처리할 수 있었을까요?

바로 WEB API와 더불어 웹 브라우저나 런타임에서 Event LoopCallback Queue로 인해 가능했던 거였습니다. 즉, 위와 같은 동작 구조가 탄생할 수 있게 된 것입니다.

여기서 용어 정리!!

  • Callback Queue: Callback Queue는 비동기 함수들을 보관하는 장소로 Event Loop에서 비동기 함수를 꺼내기 전까지는 계속 Queue방식으로 보관하게 됩니다.

    • Queue: 선입선출(FIFO)로 먼저 들어간 것이 먼저 나가는 방식입니다.
  • Event Loop: Call StackCallback Queue를 상태를 계속 감시하며 Call Stack에 함수들이 존재하지 않는다면 Callback Queue에 있는 비동기 함수들을 Call Stack에 밀어 넣고 그 후 Call Stack에서 비동기 함수를 실행시키게 됩니다.

2. 자바스크립트는 그래서 무슨 언어인가요?


아까 위에서 V8 엔진의 구조를 간단하게 봤을 때 하나의 Call Stack(호출 스택)과 하나의 Memory Heap(메모리 힙)으로 이루어진 것을 확인할 수 있었습니다.

Call Stack은 기본적으로 자바스크립트 코드를 위에서부터 한줄 한줄 해석해가며 우리가 짠 코드를 순서대로 돌아갈 수 있도록 보장하는 데이터 구조입니다.

Stack을 사용하기 때문에 위에서 용어 정리 했듯이 LIFO(후입 선출)의 구조입니다.

Call Stack에 쌓이는 하나의 사각형을 스택 프레임(Stack Frame)이라고 하는데, 만약 함수가 실행이 된다면은 스택의 맨 위에 있던 스택 프레임을 가리키는 중이며, 함수의 실행이 끝날 때 해당 스택 프레임을 Call Stack에서 제거하게 됩니다.

예시로 아래 코드는 사각형 넓이 구하는 코드입니다.

function multiply(x, y) {
  return x * y;
}
function printSquare(x) {
  var s = multiply(x, x);
  console.log(s);
}
printSquare(5);

callstack

맨 처음에는 자바스크립트 코드가 실행되지 않았기에 첫번째 콜 스택에는 아무것도 없었지만 코드를 실행하며 가장 먼저 printSquare를 호출하기 때문에 printSquarePush 해서 스택에 쌓고 읽어가다 그 ㄴ다음에 만난 multiplyPush 해서 스택에 쌓습니다. 더 이상 쌓을 함수가 존재하지 않는다면 맨 위의 스택 프레임부터 하나씩 처리하며 출력하게 됩니다.

그런데 만약에 스택을 무한대로 호출해서 초과시킨다면 어떻게 될까요? 결과는 Maximum call stack size 에러가 발생하게 됩니다.

Maximum-call-stack-size

Stack-Overflow

무한 루프가 될 때를 그림으로 표현하면 위의 그림처럼 표현할 수 있습니다. Call Stack정해진 스택 사이즈가 존재하고, 하나씩 쌓이기 스택 프레임(Stack Frame) 때문에 Call Stack의 정해진 용량을 초과하게 되면 에러가 발생하게 됩니다. 이것을 Stack Overflow(스텍이 흘러넘침)라고 말합니다.

이처럼 자바스크립트는 하나의 Call Stack을 가지고 코드를 순차적으로 처리하기 때문에 한 번에 하나의 명령어만 실행될 수밖에 없습니다. 때문에 자바스크립트는 단일 스레드이며 동기식 언어라고 할 수 있습니다.

나머지 내용은 2편에서 다루겠습니다.

강릉 여행 -  2일차 (05/22)다음 포스트

강릉 여행 - 2일차 (05/22)

강릉 여행 - 2일차 (05/21) 여행 일지 입니다.
NodeJS가 무엇이며 간단하게 웹서버 구축하기(with Express)이전 포스트

NodeJS가 무엇이며 간단하게 웹서버 구축하기(with Express)

NodeJS의 이해와 간단하게 웹서버를 구축해봅니다.