학습 자료

자바스크립트는 대체 누가 실행하는가


Article

자바스크립트를 처음 배울 때 대부분 이렇게 시작한다. 에디터를 켜고, console.log("hello")를 치고, 화면에 hello가 뜨는 걸 본다. 그리고 넘어간다.

그런데 여기서 한 번쯤 멈춰서 물어볼 만한 게 있다. 그 코드를 누가 읽고 실행한 건가?

이 질문에 답할 수 있으면 나중에 만날 수많은 "왜 안 되지?"가 미리 풀린다. document가 왜 브라우저에서는 되고 Node.js에서는 안 되는지, setTimeout이 왜 자바스크립트 문법이 아닌지 같은 것들이다.

이번 강의는 문법을 하나도 다루지 않는다. 대신 자바스크립트가 놓인 자리를 본다.

웹페이지를 이루는 세 가지

먼저 큰 그림부터 잡는다. 웹페이지는 세 가지 언어로 만들어진다.

언어역할비유
HTML구조와 내용건물의 뼈대
CSS생김새페인트와 인테리어
JavaScript동작엘리베이터와 자동문

버튼이 눌리면 창이 열리고, 스크롤하면 요소가 나타나고, 입력값이 틀리면 빨간 경고가 뜬다. 이 "움직임"을 담당하는 게 자바스크립트다.

여기까지는 대부분 안다. 문제는 그다음이다.

자바스크립트는 스스로 실행되지 않는다

.js 파일은 그냥 글자가 적힌 텍스트 파일이다. 메모장으로 열어도 읽힌다. 컴퓨터는 이 글자들을 그 자체로는 이해하지 못한다.

누군가 이 텍스트를 읽고, 무슨 뜻인지 해석하고, 실제 작업으로 옮겨줘야 한다. 그 일을 하는 프로그램을 자바스크립트 엔진이라고 부른다.

코드가 실행되기까지
  1. app.js그냥 텍스트 파일
  2. 자바스크립트 엔진읽고 해석한다
  3. 실제 동작화면이 바뀐다

중요한 건 엔진이 자바스크립트로 만들어지지 않았다는 점이다. 크롬의 엔진인 V8은 C++로 작성됐다. 자바스크립트를 실행해주는 프로그램은 자바스크립트가 아니다.

엔진은 여러 개다

엔진은 하나가 아니다. 브라우저마다 다른 엔진을 쓴다.

엔진만든 곳쓰는 곳
V8구글크롬, 엣지, Node.js
SpiderMonkey모질라파이어폭스
JavaScriptCore애플사파리

여기서 자연스러운 의문이 생긴다. 엔진이 제각각이면 같은 코드가 브라우저마다 다르게 동작하는 거 아닌가?

그렇게 되지 않도록 표준 명세가 있다. 이름은 ECMAScript다. "자바스크립트라는 언어는 이렇게 동작해야 한다"고 적어둔 규격서다. 엔진 제작자들은 이 규격서를 보고 각자 엔진을 만든다.

엔진만으로는 아무것도 못 한다

여기가 진짜 핵심이다. 이걸 넘기면 나중에 반드시 헷갈린다.

엔진은 자바스크립트 언어 자체만 안다. 변수를 만들고, 숫자를 더하고, 함수를 호출하는 것. 딱 거기까지다.

그런데 우리가 실제로 쓰는 코드를 보자.

document.querySelector("h1").textContent = "안녕";

setTimeout(() => {
  console.log("3초 지났다");
}, 3000);

document는 뭘까? setTimeout은? console은?

전부 자바스크립트 문법이 아니다. ECMAScript 명세 어디에도 document라는 단어는 없다. 엔진은 이런 걸 모른다.

이것들은 엔진 바깥에서, 엔진을 감싸고 있는 환경이 제공한다. 그 환경을 런타임이라고 부른다.

브라우저 런타임의 구조
  • 브라우저 런타임크롬, 파이어폭스 …
    • 자바스크립트 엔진V8 — 언어 자체를 실행
      • 변수 · 함수 · 연산let, function, +
      • 내장 객체Array, Object, Math
    • Web API브라우저가 추가로 제공
      • document화면 조작 (DOM)
      • 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를 못 찾겠다"고 정확히 말해준다.

정리하면

지금까지 나온 것을 한 줄로 줄이면 이렇다.

자바스크립트 코드는 엔진이 실행하고, 엔진 혼자서는 부족한 기능을 런타임이 채워준다.

다시 짚어보기
  1. 01

    자바스크립트는 텍스트다

    그 자체로는 아무 일도 하지 않는다.

  2. 02

    엔진이 읽고 실행한다

    V8, SpiderMonkey, JavaScriptCore. ECMAScript 명세를 따라 만들어졌다.

  3. 03

    엔진은 언어만 안다

    변수, 함수, 연산. 화면 조작이나 시간 지연은 모른다.

    const sum = 1 + 2;  // 엔진이 처리한다
  4. 04

    런타임이 나머지를 준다

    브라우저는 document를, Node.js는 파일 시스템을 준다.

    document.title = "안녕";  // 브라우저가 처리한다

앞으로 배울 문법은 대부분 첫 번째 덩어리, 엔진이 아는 영역이다. 변수, 자료형, 함수, 객체 같은 것들. 이 시리즈에서는 그 부분을 순서대로 다진다.

다음 강의에서는 실제로 코드를 실행해본다. 별도의 설치 없이, 지금 보고 있는 브라우저에서 바로 할 수 있다.

자바스크립트는 대체 누가 실행하는가 — 디코드랩(DCODELAB)