컴파일러와 인터프리터
컴파일러 언어와 인터프리터 언어, 두 가지 언어에 대해서 살펴보자
컴파일러와 인터프리터에 대한 쉽고 재밌는 영상이 하나 있다!
우리가 쓰는 소스코드는 컴퓨터가 이해하지 못한다. 그래서 이런 소스 코드를 컴퓨터가 이해할 수 있는 기계어로 번역해주는 것이 컴파일러와 인터프리터 언어이다.
예를 들어, 자바스크립트는 사람이 이해하기 쉬운 형태이지만, 이런 영어 단어?의 집합을 컴퓨터는 이해하지 못한다. 그래서 일정한 규칙을 가지고 컴퓨터가 이해할 수 있게끔 바꾸어주는 것이다!
컴파일러는 무엇일까?
우선 컴파일러는 무엇일까?
컴파일러는 프로그램 전체를 스캔하여 명령어를 번역해주는 프로그램을 말한다. 프로그램 전체를 스캔해야하기 때문에, 준비 시간이 오래걸린다.
하지만, 시작하면 프로그램은 매우 빠르게 실행된다. 그리고 컴파일러는 전체 코드를 검사하면서 오류 메시지를 생성하기 때문에 실행 전에 오류를 발견할 수 있다.
인터프리터는 무엇일까?
인터프리터는 소스 코드를 기계어로 변환하지 않고, 한줄 한줄 해석해서 바로 명령어로 실행하는 것이다. 그래서 바로 실행이 가능하다는 장점이 있고, 결과도 바로 확인할 수 있다.
하지만 한줄한줄해석하는 동안 동작이 쉬게 된다. 그래서 컴파일러에 비해 동작이 느리다. 또 프로그램을 실행해봐야 오류 발견이 가능하다.
둘 차이를 영단어로 쉽게 받아들이기
위 영상에서 설명하듯이 컴파일러와 인터프리터의 개념이 헷갈린다면 단어 그대로를 생각해보면 된다.
컴파일러(Compiler)는 Compile → pile together로 차곡차곡 쌓는다는 뜻이다. 쌓아놓은것을 한번에 처리한다!
인터프리터(Interpreter)는 단어를 보면 Inter(=between, 사이)+Preter로 컴퓨터와 프로그램 사이에 있으면서 한 줄씩 번역해주는 것이다.
자바 스크립트는 인터프리터 언어로 분류 되지만, 일부 해석 엔진에서 컴파일을 하는 언어이다. 이것이 무슨 말인가를 알아보자.
우선 console창에서 스크립트를 작성해 실행하는 데에 컴파일이 필요없다. f12에서 console창 명령 내리면 바로 실행이 되는 것처럼!
이렇게 자바스크립트가 구현된 것은, 웹 문서 구조를 동적으로 바로바로 나타내기 위해서이다.
그래서 자바스크립트의 동작은 위 그림처럼 나타낼 수 있다.
토큰화하고, 파서를 통해 AST 트리로 만들고, 그것을 바이트 코드로 변환하는 것이다.
그런데 이런 자바스크립트 엔진은 인터프리터기 때문에 컴파일러에 비해 동작이 느렸다. 그래서 여러 자바스크립트 엔진들이 등장한다.
V8 엔진 동작 원리
자바 스크립트에는 여러 엔진이 있는데, 그 중 V8과 같은 JS 엔진에서 컴파일이 필요한 경우에는 컴파일을 진행한다!
V8엔진(chrome, node)은 구글이 개발한 엔진이다. 구글이 2009년 구글 맵스를 개발하려고 할때, 실행 속도의 한계를 느끼고 개발한 것이라고 한다.
우리가 자주 쓰는 node도 이 v8엔진을 기반으로 한 것이다.
기존에는 브라우저에 자바스크립트 해석엔진이 있어서, 자바스크립트 코드를 인터넷 브라우저 위에서만 실행할 수 있었는데, node.js를 통해 브라우저 외의 다른 환경에서도 자바스크립트를 사용할 수 있다
그럼 이제 V8엔진이 어떻게 돌아가는지를 살펴보자.
동작은 아래 순서이다.
- 엔진이 실행할 JS 파일을 받는다.
- Parser에서 소스 코드 분석를 분석한다.
- AST(Abstract Syntac Tree : 추상 구문 트리)를 구축하고 결과물을 인터프리터에 보낸다.
- 인터프리터가 코드를 읽아 Bytecode로 변환한다.
- 컴파일러인 TurboFan이 자주 사용되는 코드 구문(반복문 등)을 최적화된 코드로 다시 컴파일한다.
컴파일러가 왜 도입되었는지, 위에서 살펴본 특징을 통해 생각해볼 수 있다. 컴파일러는 실행 전 모두 기계어로 바꾸어 놓는 것이 가장 큰 특징이었다.
아래 예시 코드를 통해 쉽게 살펴보자
function sum () {
let result = 0
for (let i = 1 ; i <= 10 ; i++){
result += i;
}
return result;
}
sum()
sum()
sum()
(출처: https://velog.io/@seungchan__y/자바스크립트는-Compiler-Interpreter-언어다)
만약 위 함수를 인터프리터로 실행한다고 생각해보자. 인터프리터는 한줄씩 실행한다. 만약 여기서 sum()을 만나면, 매번 function sum을 실행하며 for문을 돌아야한다.
하지만 이것을 컴파일러로 실행하면, 컴파일을 끝난 sum의 결과는 미리 저장되어있고 그것을 가져다 쓰면 되는 것이다.!!
그래서 V8 엔진의 컴파일러인 turbofan은 자주 사용되는 코드를 컴파일해서 실행 속도를 줄인 것이다.
'JavaScript > JS를 파헤쳐보자' 카테고리의 다른 글
libuv의 이벤트 루프를 파헤쳐보자 (1) - libuv와 이벤트 루프 실행 흐름 (0) | 2025.01.08 |
---|---|
C10K와 node.js의 비동기 처리 (0) | 2024.08.22 |
[JS] 자바스크립트의 비동기 처리 (0) | 2024.07.30 |
Node.js는 완전한 싱글 스레드일까? (0) | 2024.07.26 |
Call Stack과 클로저함수 (0) | 2024.07.24 |