자바스크립트는 대체 누가 실행하는가
Article
자바스크립트를 처음 배울 때 대부분 이렇게 시작한다. 에디터를 켜고, console.log("hello")를 치고, 화면에 hello가 뜨는 걸 본다. 그리고 넘어간다.
그런데 여기서 한 번쯤 멈춰서 물어볼 만한 게 있다. 그 코드를 누가 읽고 실행한 건가?
이 질문에 답할 수 있으면 나중에 만날 수많은 "왜 안 되지?"가 미리 풀린다. document가 왜 브라우저에서는 되고 Node.js에서는 안 되는지, setTimeout이 왜 자바스크립트 문법이 아닌지 같은 것들이다.
이번 강의는 문법을 하나도 다루지 않는다. 대신 자바스크립트가 놓인 자리를 본다.
웹페이지를 이루는 세 가지
먼저 큰 그림부터 잡는다. 웹페이지는 세 가지 언어로 만들어진다.
| 언어 | 역할 | 비유 |
|---|---|---|
| HTML | 구조와 내용 | 건물의 뼈대 |
| CSS | 생김새 | 페인트와 인테리어 |
| JavaScript | 동작 | 엘리베이터와 자동문 |
버튼이 눌리면 창이 열리고, 스크롤하면 요소가 나타나고, 입력값이 틀리면 빨간 경고가 뜬다. 이 "움직임"을 담당하는 게 자바스크립트다.
여기까지는 대부분 안다. 문제는 그다음이다.
자바스크립트는 스스로 실행되지 않는다
.js 파일은 그냥 글자가 적힌 텍스트 파일이다. 메모장으로 열어도 읽힌다. 컴퓨터는 이 글자들을 그 자체로는 이해하지 못한다.
누군가 이 텍스트를 읽고, 무슨 뜻인지 해석하고, 실제 작업으로 옮겨줘야 한다. 그 일을 하는 프로그램을 자바스크립트 엔진이라고 부른다.
- app.js그냥 텍스트 파일
- 자바스크립트 엔진읽고 해석한다
- 실제 동작화면이 바뀐다
중요한 건 엔진이 자바스크립트로 만들어지지 않았다는 점이다. 크롬의 엔진인 V8은 C++로 작성됐다. 자바스크립트를 실행해주는 프로그램은 자바스크립트가 아니다.
엔진은 여러 개다
엔진은 하나가 아니다. 브라우저마다 다른 엔진을 쓴다.
| 엔진 | 만든 곳 | 쓰는 곳 |
|---|---|---|
| V8 | 구글 | 크롬, 엣지, Node.js |
| SpiderMonkey | 모질라 | 파이어폭스 |
| JavaScriptCore | 애플 | 사파리 |
여기서 자연스러운 의문이 생긴다. 엔진이 제각각이면 같은 코드가 브라우저마다 다르게 동작하는 거 아닌가?
그렇게 되지 않도록 표준 명세가 있다. 이름은 ECMAScript다. "자바스크립트라는 언어는 이렇게 동작해야 한다"고 적어둔 규격서다. 엔진 제작자들은 이 규격서를 보고 각자 엔진을 만든다.
엔진만으로는 아무것도 못 한다
여기가 진짜 핵심이다. 이걸 넘기면 나중에 반드시 헷갈린다.
엔진은 자바스크립트 언어 자체만 안다. 변수를 만들고, 숫자를 더하고, 함수를 호출하는 것. 딱 거기까지다.
그런데 우리가 실제로 쓰는 코드를 보자.
document.querySelector("h1").textContent = "안녕";
setTimeout(() => {
console.log("3초 지났다");
}, 3000);
document는 뭘까? setTimeout은? console은?
전부 자바스크립트 문법이 아니다. ECMAScript 명세 어디에도 document라는 단어는 없다. 엔진은 이런 걸 모른다.
이것들은 엔진 바깥에서, 엔진을 감싸고 있는 환경이 제공한다. 그 환경을 런타임이라고 부른다.
- 브라우저 런타임
- 자바스크립트 엔진
- 변수 · 함수 · 연산
- 내장 객체
- Web API
- document
- setTimeout
- fetch
- console
- 자바스크립트 엔진
즉 우리가 "자바스크립트"라고 뭉뚱그려 부르는 것은 사실 두 덩어리다. 엔진이 주는 것과, 런타임이 주는 것.
런타임이 바뀌면 되는 것도 바뀐다
브라우저만 런타임인 건 아니다. 자바스크립트를 컴퓨터에서 그냥 돌리고 싶다면 Node.js를 쓴다. Node.js는 V8 엔진을 가져다가 다른 것들을 붙여놓은 런타임이다.
브라우저
V8 + Web API
document로 화면을 바꾼다fetch로 서버에 요청한다localStorage에 저장한다- 파일을 직접 읽지 못한다
Node.js
V8 + Node API
fs로 파일을 읽고 쓴다http로 서버를 연다process로 실행 정보를 본다document가 아예 없다
같은 V8 엔진인데 되는 게 다르다. 엔진은 그대로고 주변 환경이 다르기 때문이다.
그래서 Node.js에서 이런 코드를 돌리면 이렇게 된다.
console.log(1 + 1);
console.log(document);
- 2
- ReferenceError: document is not defined
1 + 1은 엔진이 하는 일이라 잘 된다. document는 브라우저가 주는 것이라 Node.js에는 없다. 에러 메시지도 "document를 못 찾겠다"고 정확히 말해준다.
정리하면
지금까지 나온 것을 한 줄로 줄이면 이렇다.
자바스크립트 코드는 엔진이 실행하고, 엔진 혼자서는 부족한 기능을 런타임이 채워준다.
- 01
자바스크립트는 텍스트다
그 자체로는 아무 일도 하지 않는다.
- 02
엔진이 읽고 실행한다
V8, SpiderMonkey, JavaScriptCore. ECMAScript 명세를 따라 만들어졌다.
- 03
엔진은 언어만 안다
변수, 함수, 연산. 화면 조작이나 시간 지연은 모른다.
const sum = 1 + 2; // 엔진이 처리한다 - 04
런타임이 나머지를 준다
브라우저는 document를, Node.js는 파일 시스템을 준다.
document.title = "안녕"; // 브라우저가 처리한다
앞으로 배울 문법은 대부분 첫 번째 덩어리, 엔진이 아는 영역이다. 변수, 자료형, 함수, 객체 같은 것들. 이 시리즈에서는 그 부분을 순서대로 다진다.
다음 강의에서는 실제로 코드를 실행해본다. 별도의 설치 없이, 지금 보고 있는 브라우저에서 바로 할 수 있다.