본문 바로가기

Language/Javascript

자바스크립트 Javascript 와 동작방식, V8에 대해서 이해하기

by engineer M 2020. 2. 17.
기록하는 것이 남는 것이다! 개발중에 항상 썼던 Javascript이지만 좀 더 제대로 이해하고 싶어서 개념정리를 해보고자 한다. 

 

1. Javascript는 동적 언어이다. (Dynamic programming language)

 

동적언어란 뭘까? 

동적언어란 컴파일 시에 자료형 (타입)이 정해지지 않는 언어이다. (예를 들어 Javascipt, Ruby, Python 등이 있다.) 동적 언어의 자료형은 실행시 (runtime 때) 정해된다. 그럼 반대로 정적 언어는 컴파일시에 자료형(타입) 이 지정되는 언어이다. 예로, Java, C++, C#, C 등 우리가 흔히 알고 있는 안정적인 느낌을 주는 언어들이다. 

 

 따라서 이에 따라 오는 문제점들이 있을 것이라고 예상해 볼 수 있다. Javascript의 경우 자료형을 미리 지정해 주지 않기때문에, 나중에 런타임때 오류가 날 확률이 있고 안정성이 높지 않은 대신에, 컴파일 언어에 비해 유동적이다. 

 정적언어의 경우 미리 타입을 지정해 주기 때문에 안정성이 높고 실행이 빠르다. 

 

 동적언어의 타입의 부재를 해결해주기 위해서 Typescript가 있다. 실제 사용해 본 결과 자바와 비슷해서 놀랐다. 평상시 조금 불안정하다고 생각했던 점을 보완해주는듯!

 

2. Javascript는 스크립트 언어이다.

 

스크립트 언어가 뭘까? 컴파일 언어는?

 스크립트 언어는 컴파일을 하지 않아도 실행할 수 있는 언어이다. 컴파일을 해서 기계어로 바꿔주지 않아도 동작한다. 

 

처음에는 스크립트 언어와 컴파일 언어의 구분이 많이 헷갈렸다. 왜냐면 자바스크립트는 스크립트 언어이고, 분명 컴파일을 안한다고 했는데, v8엔진은 컴파일을 해주는데??? 하는 모순이 걸렸기 때문.

 하지만 이를 찾아보니,  JIT (Just-In-Time) compiler 로 컴파일이 가능해졌을 뿐이지, 컴파일이 된다고 해서 언어 자체의 성질이 스크립트 언어가 아닌 것은 아니라고 한다. 애초에 자바스크립트는 컴파일이 안되어도, 읽을 수 있게 만들어졌기 때문에 언어 자체의 성격은 스크립트 언어라고 한다. 

 

 

 나와 같은 궁금증이 들었다면, 우리와 같은 질문을 하는 사람의 질문과 답을 찾았으니 참고해도 좋을 것 같다.  

https://stackoverflow.com/questions/11420954/can-javascript-be-considered-a-interpreted-language-when-using-google-chrome-v8

 

Can Javascript be considered a interpreted language when using Google Chrome (V8)?

I was reading this excellent article on V8, Google's Javascript engine: https://developers.google.com/v8/design#mach_code. At one point, they say that Javascript is compiled directly into machine

stackoverflow.com

 

 

 

 

3. Javascript는 객체지향 언어이다. (오잉?) 

 객체지향 언어 (OOL)은 자바를 대표적으로 알고 있었는데 Javascript도 객체지향 언어라고 한다! 다만 자바처럼 클래스나 상속이 없다. 

 

4. 자바스크립트는 인터프리터 언어로서 클라이언트의 웹 브라우저에 의해 해석되고 실행된다.

 말 그대로 인터프리터 언어라서 웹브라우저가 해석하고 실행해 준다. 자바스크립트 자체가 웹 브라우저를 위해 만들어진 언어이다.

 


 

그럼 자바스크립트에 대해 대충 이해했는데... 어떻게 동작하는 것일까? 

 

V8 엔진이란?

 

v8 엔진은 자바스크립트 엔진으로 구글에서 개발했고, C++로 개발되었다. 다른 엔진들과의 차이점은, Node.js런타임으로 사용된다는 것, 그리고 바이트코드와 같은 중간 코드를 생산하지 않아서 머신코드의 실행을 매우 빠르게 할 수 있으며, 인터프리터가 필요 없다는 것이다. 크롬이 이엔진을 사용해서 자바스크립트 코드를 번역해 준다.

 나는 V8엔진이 마치 코드 부스터 같은 역할을 수행한다고 이해했다.

 

다음 링크를 참고하면 V8자체를 이해하는 데 많은 도움이 될 것 같다.

 

 

https://hackernoon.com/javascript-v8-engine-explained-3f940148d4ef   

 

JavaScript V8 Engine Explained

Well, I think I heard the name V8 a million times. The first time it came up was at 2008, when an engineer from my team explained to me why the performance of some code would be ok — he said: “V8 will take care of it!” — I nodded. Although I didn’t know wh

hackernoon.com

 

 

 

 

v8이 하는 일 : 
  1. Compiles and executes JS code | JS코드를 컴파일하고 실행해준다.
  2. Handling call stack — running your JS functions in some order | 콜스택을 다룬다. (나의 js코드를 일련의 순서대로 작동되게 하는 것 )
  3. Managing memory allocation for objects — the memory heap | object을 메모리를 통해 관리 (the memory heap)
  4. Garbage collection — of objects which are no longer in use | 자바에 있는 가비지 콜랙션기능 제공.
  5. Provide all the data types, operators, objects and functions | 데이타 타입, 옵젝과 functions 제공.

 

이렇게 보면 정말 많은 일을 하는 것 같다. 실제로 v8실행 과정을 찍어 보면, hello world를 찍는 단순한 function 구현에도 총 6단계를 거쳐서 구현되는 것을 알 수 있다. 이에 대한 예시는 다음링크에서 확인 가능하다. 

 

저렇게 위에 설명만 보면 그래서 뭐가 어떻게 돌아가는 건데? 라는 의문이 생길 수 있다. 

따라서 아래에 순서대로 어떻게 동작하는지 설명을 해보고자 한다. 

직접 코드로 설명하면 이해가 빠를 것 같다.

 

 나와같이 자바 같이 비동기 프로그래밍을 주로 하던 사람들은 처음에 자바스크립트를 사용할때 의아할 수 있다. 나역시 처음에 혼돈이 오게 된 계기가 다음과 같았다. 

 

이 과정을 봤을 때. 결과가 어떻게 출력될까? 

내가 자바스크립트를 사용해 보지 않았더라면, 아마 func1 -> func2 -> func3 이렇게 출력 될거라고 생각했을 것이다. 하지만 실제 출력결과는 다음과 같다.

 

 

위 코드의 실제 실행 단계는 다음과 같다. 

일단 func1이 호출된다 -> func2가 호출되면서 'setTimeout'함수가 실행되고 Call Stack에 들어간다음, 바로 빠져나온다. -> 내부에 걸려있던 핸들러는 event queue영역으로 들어간다. 그리고 나서 func3 함수가 Call Stack 으로 들어간다. (콜백함수는 항상 마지막에 배치된다)

-> func3이 실행되면서 func3이 찍히고, 작업을 모두 마친 func3함수가 call stack 에서 pop된다. 이어서 func2함수와 func1 함수까지 call stack에서 pop이 된다. 이때 이벤트 루프의 call stack이 비어있게 된다. 이 시점에 queue의 head에서 하나의 event를 가져와서 Call Stack으로 넣는다. 이 이벤트는 setTimeout함수 내부에 있던 익명함수이다. 그리고 이 함수가 실행된다. 

 

이렇게 나오는 이유은, v8의 구조 때문이다.

v8을 비롯해 자바스크립트 엔진들은 대부분 다음과 같은 세 영역으로 나뉜다.

 

Call Stack, 
Task Queue(Event Queue)
Heap 

 

그리고 Event Loop가 존재해서, task관리를 한다.

 

 

Call Stack

 자바스크립트는 기본적으로 싱글 쓰레드 기반 언어이다. 호출 스택이 하나이기 때문에 한번에 한 작업만 처리 가능하다.

 자바스크립트는 요청이 들어올 때마다 해당 요청을 순차적으로 호출 스택에 담아 처리한다. 그리고 해당 메소드가 끝나면 stack에서 pop되게 된다. 

 

Task Queue (Event Queue)

 자바스크립트의 런타임 환경에서는 처리해야 하는 Task들을 임시 저장하는 대기 큐가 존재한다. 그 대기 큐를 Task Queue혹은 Event Queue라고 한다. 그리고 Call Stack이 비어졌을 때 먼저 대기열에 들어온 순서대로 수행된다.

Memory Heap

 메모리 할당이 일어나는 곳이다.

 

 

이벤트 루프는 보통 다음과 같이 implemented된다. 

while (queue.waitForMessage()) {
  queue.processNextMessage()
}

 

자바스크립트는 단일 호출 스택을 사용하는데, 어떻게 비동기 요청이 이루어 질까? 

이에 대해서는 다음 블로그에서 설명이 잘 되어있어서 링크를 첨부한다.

 

https://meetup.toast.com/posts/89

댓글