View
JS 책 첫 장을 펴면 자바스크립트, ECMAScript, DOM, BOM이라는 단어가 우르르 쏟아진다. 솔직히 입문자 열에 아홉은 "이게 다 같은 것 아닌가?" 하고 넘어간다. 그러나 이 넷은 전부 다른 표준이고, 만드는 주체도 다르며, 심지어 BOM은 표준조차 아니다. 이 글 하나만 읽으면 관계가 명확히 정리되고, 면접에서 "ECMAScript가 무엇인가?"라는 질문을 받았을 때 말을 더듬지 않게 된다.
출처: blog.csdn.net
자바스크립트는 사실 한 덩어리가 아니다
자바스크립트라는 이름이 가리키는 세 가지 레이어
우리가 흔히 "자바스크립트로 짠다"고 할 때 쓰는 코드는 사실 세 가지 레이어가 섞여 있다.
- 언어 코어 — 변수, 함수, 객체, 배열, Promise 같은 문법 자체
- DOM API — document.querySelector, element.addEventListener 같은 HTML 조작
- BOM API — window.alert, location.href, navigator.userAgent 같은 브라우저 조작
이 중에서 진짜 "자바스크립트 언어"에 해당하는 것은 첫 번째 레이어뿐이다. 나머지 둘은 브라우저가 따로 얹어주는 API이며, 표준화 단체도 완전히 다르다. 그래서 Node.js에서는 document가 없고, 브라우저에서는 fs.readFile이 없는 것이다.
핵심 한 줄 — JS = ECMAScript(언어 코어) + 호스트 API
이 문장 하나만 외워도 절반은 끝난 셈이다.
자바스크립트 = ECMAScript(언어 코어) + 호스트 환경 API(DOM, BOM, Node API 등)
ECMAScript가 문법과 기본 내장 객체를 정하고, 호스트 환경이 그 위에 자기 환경에 맞는 API를 얹는다. 브라우저는 DOM/BOM을 얹고, Node.js는 fs, http, process 같은 것을 얹는 방식이다.
한 장으로 보는 관계 정리
| 구분 | 표준화 단체 | 역할 | 예시 |
| ECMAScript | Ecma International (TC39) | 언어 문법과 내장 객체 | `let`, `const`, `Array`, `Promise` |
| DOM | WHATWG (옛날엔 W3C) | HTML/XML 문서 조작 | `document`, `querySelector` |
| BOM | 공식 표준 없음 (일부 WHATWG) | 브라우저 환경 조작 | `window`, `location`, `navigator` |
| Node.js API | Node.js TSC | 서버 환경 조작 | `fs`, `http`, `process` |
ECMAScript는 자바스크립트의 "문법 표준"이다
누가 만드는가? Ecma International과 TC39 위원회
Ecma International은 스위스 제네바에 있는 국제 표준화 단체이다. 원래 1961년에 만들어진 조직인데, 지금 가장 유명한 일이 ECMAScript 관리이다. 그 안에서 실제로 자바스크립트 스펙을 설계하는 주체는 TC39(Technical Committee 39)라는 위원회이고, 구글, MS, 애플, 모질라, 페북 같은 주요 브라우저 회사 엔지니어들이 모두 들어가 있다.
매년 6월에 그 해 버전이 공식 릴리즈되는 사이클로 굴러간다. 2015년부터는 이 연단위 릴리즈가 고정되었고, 제안서는 Stage 0부터 Stage 4까지 단계를 거쳐 표준으로 승격된다.
왜 따로 표준화하는가? Netscape vs Microsoft 표준 전쟁사
옛날에는 정말 난장판이었다. 1995년 넷스케이프(Netscape)가 Navigator 2.0에 자바스크립트를 박아넣었는데, 1996년 마이크로소프트가 IE에 JScript라는 거의 똑같지만 미묘하게 다른 것을 집어넣었다. 둘이 서로 자기 것을 쓰라고 싸우는 바람에 웹 개발자들만 고통받았다. 조건문 하나가 다르게 동작해서 한쪽 브라우저에서만 터지는 일이 흔했다.
이 꼴을 더는 못 보겠다 싶어서 1997년 넷스케이프가 Ecma International에 표준화를 요청했고, 그렇게 나온 것이 ECMA-262 1판이다. "자바스크립트"라는 이름은 넷스케이프가 상표권을 가지고 있어서 쓸 수 없었고, 대신 "ECMAScript"라는 중립적인 이름으로 표준을 만들었다. 그래서 오늘날까지도 공식 명칭은 ECMAScript이고, 자바스크립트는 그 구현체 중 하나라는 포지션이 되었다.
ES5, ES6, ES2024... 버전 명칭 정리
이 부분이 헷갈리는 사람이 많은데 정리하면 다음과 같다.
| 버전 | 릴리즈 연도 | 다른 이름 | 대표 기능 |
| ES3 | 1999 | — | 정규식, try/catch |
| ES5 | 2009 | — | `strict mode`, JSON, `Array.forEach` |
| ES6 | 2015 | ES2015 | `let/const`, 화살표 함수, 클래스, Promise |
| ES7 | 2016 | ES2016 | `**` 연산자, `Array.includes` |
| ES8 | 2017 | ES2017 | `async/await`, `Object.entries` |
| ES2020 | 2020 | ES11 | 옵셔널 체이닝, null 병합 |
| ES2024 | 2024 | ES15 | `Object.groupBy`, 정규식 v 플래그 |
ES6 = ES2015, 같은 것이다. 2015년부터 연도로 부르는 관례로 바뀌었는데, ES6라는 이름이 워낙 유명해서 지금도 둘 다 쓰인다. 신입이 "ES6 특징을 말해보세요"라는 질문을 받았을 때 "ES2015를 말씀하시는 것이죠?"라고 받아치면 아는 사람이구나 싶게 한다.
어디까지가 ECMAScript인가
여기가 진짜 핵심이다. 이것을 아느냐 모르느냐로 입문자 티가 확 난다.
ECMAScript에 포함되는 것:
- 문법 (if, for, class, function, 화살표 함수 등)
- 기본 타입 (Number, String, Boolean, Symbol, BigInt)
- 내장 객체 (Array, Map, Set, Promise, Date, RegExp)
- async/await, Iterator, Generator
ECMAScript에 포함되지 않는 것:
- console.log — 이것은 호스트 환경이 제공하는 기능이다
- document.querySelector — DOM, 브라우저 전용
- window.alert — BOM, 브라우저 전용
- setTimeout — 이것도 사실 ECMAScript가 아니라 호스트 환경이 주는 기능이다
- fetch, XMLHttpRequest — 브라우저나 Node.js가 제공
- require, fs, http — Node.js API
console.log가 ECMAScript가 아니라는 사실을 처음 들으면 "엥?" 싶을 수 있다. 다만 실제 ECMA-262 스펙 문서를 아무리 뒤져도 console 오브젝트는 나오지 않는다. 브라우저와 Node.js가 알아서 제공해주는 것이라서 두 환경에서 비슷하게 동작할 뿐이다.
DOM은 HTML 문서를 다루는 별도의 표준이다
DOM = Document Object Model, WHATWG가 관리
DOM(Document Object Model)은 HTML이나 XML 문서를 프로그래밍 인터페이스로 추상화한 것이다. 브라우저가 HTML을 파싱해서 메모리에 트리 구조로 올려놓은 것을, 자바스크립트가 조작할 수 있게 해주는 인터페이스가 바로 DOM이다.
예전에는 W3C(World Wide Web Consortium)가 DOM 표준을 관리했는데, 2004년쯤부터 W3C가 XHTML 2.0에 헤매던 시절 애플, 모질라, 오페라 엔지니어들이 분개해서 WHATWG(Web Hypertext Application Technology Working Group)를 따로 만들었다. 한동안 W3C와 WHATWG가 따로 표준을 내는 황당한 상황이었는데, 2019년에 둘이 합의해서 이제 WHATWG의 HTML Living Standard가 공식 표준이 되었다. DOM 표준도 WHATWG가 유지보수한다.
ECMAScript가 아닌 이유
DOM이 ECMAScript에 들어가지 않은 이유는 단순하다. ECMAScript는 환경에 독립적인 언어 코어여야 하기 때문이다. 브라우저 밖에서 돌아갈 때도 동작해야 하는데, document 같은 것은 브라우저 없이는 의미가 없다. Node.js에서 document를 찍어보면 그저 ReferenceError가 뜨는 것도 이 때문이다.
document.querySelector() 같은 것이 모두 DOM API이다
흔히 쓰는 DOM API는 대략 다음과 같다.
- document.querySelector, document.getElementById
- element.appendChild, element.remove
- element.addEventListener
- element.classList.add/remove/toggle
- element.innerHTML, element.textContent
리액트를 쓰는 사람들은 이것을 직접 만질 일이 별로 없어서 DOM을 "기억 저편의 무언가"로 묻어버리는 경우가 많은데, 리액트도 내부적으로는 이 API를 호출해서 실제 DOM을 업데이트한다. 가상 DOM도 결국 진짜 DOM 위에 얹힌 최적화 계층일 뿐이다. 각 API의 최신 동작은 MDN Web Docs에서 확인할 수 있다.
DOM 레벨 1~4에서 Living Standard로
옛날 W3C 시절에는 DOM Level 1 (1998), Level 2 (2000), Level 3 (2004), Level 4 순으로 버전을 매겨서 릴리즈했다. 그러나 웹이 너무 빨리 바뀌다 보니 매번 버전을 끊어서 내는 것이 무의미해졌고, WHATWG가 가져오면서 Living Standard로 바꾸었다. 이제는 계속 업데이트되는 단일 문서이다. 버전은 없다.
BOM은 표준이 없는 "브라우저 오브젝트 모델"이다
BOM = Browser Object Model, 사실 공식 표준이 아니다
BOM(Browser Object Model)은 브라우저 창 자체를 조작하는 API 모음인데, 놀랍게도 공식 표준 문서가 따로 없다. 정말이다. ECMAScript 스펙에도 없고, DOM 스펙에도 없으며, BOM 스펙이라는 것도 없다. 일부 인터페이스만 WHATWG의 HTML Living Standard 안에 녹아 들어가 있다.
그래서 예전에 브라우저마다 window.open 옵션이나 navigator 속성이 미묘하게 달라서 크로스 브라우저 이슈로 고생한 사람들이 많았다. 지금도 완벽히 표준화된 것은 아니고, 브라우저 구현에 기대고 있는 부분이 꽤 있다.
window, navigator, location, history, screen — 모두 BOM이다
대표적인 BOM 객체는 다음과 같다.
- window — 브라우저 창 전체, 전역 객체
- navigator — 브라우저 정보, 플랫폼, 언어
- location — 현재 URL, 페이지 이동
- history — 브라우저 히스토리, 뒤로/앞으로 가기
- screen — 모니터 해상도 정보
- alert, confirm, prompt — 브라우저 네이티브 다이얼로그

출처: velog.io
DOM이 BOM에 포함되는 것인가? 거꾸로인가?
이것은 면접에서 정말 많이 틀리는 포인트이다. 직관적으로는 BOM(브라우저) 안에 DOM(문서)이 들어있을 것 같은데, 실제 객체 관계는 그것이 맞다. 다만 BOM이라는 정식 카테고리가 없는 것이다.
정확히 말하면 다음과 같다.
- window는 브라우저의 전역 객체이다
- document는 window.document로 접근 가능한 속성이다
- 즉 객체 포함관계로 보면 DOM이 window 안에 있다
- 다만 표준화 관점에서는 DOM은 W3C/WHATWG 공식 표준이고, BOM은 느슨한 관습적 집합이다
그래서 "DOM과 BOM 중 무엇이 상위인가?"라는 질문 자체가 살짝 함정이다. "객체 계층상으로는 window가 document의 상위이지만, BOM은 공식 표준이 아니라 그저 사람들이 모아 부르는 이름이다"라고 답하면 정답이다.
표준이 왜 이렇게 갈라져 있는가? (이것이 진짜 핵심이다)
호스트 환경(host environment)이라는 개념
호스트 환경은 ECMAScript가 실행되는 외부 환경을 부르는 말이다. ECMA-262 스펙에 정식으로 나오는 용어이고, "자바스크립트는 호스트 환경이 제공하는 API를 더해서 완성된다"는 개념이 스펙 전반에 깔려 있다.
호스트 환경의 예시는 다음과 같다.
- 브라우저 (Chrome, Firefox, Safari, Edge) → DOM/BOM 제공
- Node.js → fs, http, path 같은 서버 API 제공
- Deno, Bun → 모던한 런타임, 브라우저 API도 일부 지원
- 임베디드 JS 엔진 (자동차, TV, IoT) → 각자 필요한 API만 노출
코어와 환경별 API를 분리해야 모두 가능하다
각설하고, 이제 "왜 표준이 갈라져 있는가"에 대한 답이 나온다.
만약 ECMAScript에 document를 넣어버린다면? 그러면 Node.js는 document가 없는 불완전한 자바스크립트가 되거나, 쓸모없는 빈 객체를 들고 다녀야 한다. 반대로 fs를 ECMAScript에 넣는다면? 브라우저에서 파일 시스템 접근이 가능해지는 순간 보안 사고가 터진다.
그래서 TC39는 "어떤 환경에서도 말이 되는 것만 언어 코어에 넣는다"는 원칙을 고수한다. 문자열, 숫자, 배열, Promise, 비동기 함수처럼 환경과 무관한 기능들만 ECMAScript가 관리하고, 환경 특화 기능은 각자 알아서 하라는 식이다. 이것이 자바스크립트가 브라우저 밖에서도 살아남은 근본 이유이다.
표준화 주체가 다르다
정리하면 다음과 같은 구조이다.
| 표준 | 관리 주체 | 스펙 문서 |
| ECMAScript | Ecma International / TC39 | ECMA-262 |
| DOM | WHATWG | DOM Living Standard |
| HTML (BOM 일부 포함) | WHATWG | HTML Living Standard |
| Node.js API | Node.js TSC | Node.js 공식 문서 |
| Web API (fetch, WebGL 등) | W3C, WHATWG 혼재 | 각자 따로 |
주체가 다른 것 자체가 자바스크립트 생태계의 확장성을 보장하는 구조이다. 한 조직이 모두 가져가려고 했다면 지금처럼 Deno, Bun, Cloudflare Workers 같은 다양한 런타임은 나오지 못했을 것이다.
콘솔에서 직접 확인해보는 미니 실험
window === this 출력해보기
브라우저 콘솔에서 다음을 실행한다.
console.log(window === this); // true (최상위 스코프에서)
console.log(globalThis === window); // true
window가 곧 브라우저의 전역 객체라는 증거이다. globalThis는 ES2020에 추가된, 환경 독립적으로 전역 객체에 접근하는 방법이며 이것은 ECMAScript 쪽이다.
document 프로토타입 찍어보기
console.log(Object.getPrototypeOf(document));
// HTMLDocument
console.log(Object.getPrototypeOf(Object.getPrototypeOf(document)));
// Document
document가 DOM 노드 타입임을 확인할 수 있다. DOM 스펙에 정의된 Document 인터페이스를 구현한 객체라는 뜻이다.
Node.js REPL에서 document 쳐보기
터미널에서 node 입력 후 다음을 실행한다.
> document
Uncaught ReferenceError: document is not defined
당연하다. Node.js에는 DOM이 없다. 호스트 환경이 다르니 호스트 API도 다르다. 반대로 Node.js에서는 fs가 되지만 브라우저에서는 ReferenceError가 뜬다.
면접에서 자주 나오는 질문 정리
"ECMAScript와 자바스크립트 차이를 설명해보세요"
모범 답변:
ECMAScript는 Ecma International이 관리하는 언어 표준이고, 자바스크립트는 그 표준을 구현한 언어 중 가장 널리 쓰이는 구현체이다. 실무에서는 둘을 같은 뜻으로 쓰기도 하지만, 엄밀히는 ECMAScript가 문법과 내장 객체만 정의하고, document나 console 같은 것은 호스트 환경이 따로 제공하는 API이다.
"DOM과 BOM의 차이는?"
모범 답변:
DOM은 W3C와 WHATWG가 만든 HTML 문서 조작 표준이고, BOM은 브라우저 창 자체를 다루는 객체들을 뭉뚱그려 부르는 비공식 용어이다. BOM은 공식 표준 문서가 따로 없고 일부만 HTML Standard에 정의되어 있다. DOM은 document 중심, BOM은 window, navigator, location, history 같은 것들 중심이다.
"ES6의 주요 특징은?"
모범 답변:
ES6는 ES2015와 같은 버전이다. let과 const, 화살표 함수, 클래스 문법, 템플릿 리터럴, 디스트럭처링, 기본 매개변수, 스프레드 연산자, Promise, 모듈 시스템(import/export), Symbol 등이 추가되었다. 매년 연단위 릴리즈 사이클이 시작된 시점이기도 하다.
피해야 할 답변
- "자바스크립트는 ECMAScript의 구현체이다" 한 줄로 끝내기 — 이해하지 못한 것이 티난다. 호스트 환경과 함께 설명해야 한다
- "BOM은 브라우저 객체를 관리하는 공식 표준이다" — BOM은 표준이 아니다. 팩트 오류
- "ES6는 2016년에 나온 버전이다" — 2015년이다. 연도를 틀리면 감점이 크다
세 줄 요약
- ECMAScript는 언어 문법 표준이며, Ecma International의 TC39 위원회가 관리한다
- DOM은 HTML 문서 조작 표준이며, WHATWG가 관리하는 별도의 스펙이다
- BOM은 공식 표준이 없는 브라우저 환경 객체 모음으로, window, navigator 등이 포함된다
표준이 갈라진 진짜 이유는 자바스크립트가 브라우저 밖에서도 돌아가야 하기 때문이다. ECMAScript를 언어 코어로 얇게 유지하고, 호스트 환경이 필요한 API를 얹는 구조라서 Node.js나 Deno, Bun 같은 다양한 런타임이 가능한 것이다. 이것을 한 번 이해하고 나면 면접이든 실무든 "JS 스펙"이라는 말을 들었을 때 머릿속이 명확해진다.
다음 글에서는 TC39 프로세스가 실제로 어떻게 굴러가는지, ES2024에 무엇이 새로 들어왔는지 같은 내용을 이어서 다뤄볼 예정이다.
'Frontend' 카테고리의 다른 글
| TypeScript 7.0 Beta 공개, 무엇이 달라졌는가 (0) | 2026.04.27 |
|---|---|
| 표준화되는 Tailwind CSS, Bootstrap의 위상은 진짜 꺾였는가 (0) | 2026.04.24 |
| Promise와 async/await의 차이, 헷갈리는 지점 정리 (2025) (0) | 2026.04.23 |
| Chrome 효과적인 유저 디렉토리 설정 방법 (0) | 2022.11.18 |
| 프론트엔드 모노레포 전략 (0) | 2022.05.03 |
