DOM
웹 문서를 프로그램이 다룰 수 있는 객체의 트리로 표현하는 규격입니다. 마크업이 들어가면 노드의 트리가 나옵니다. 그 트리를 무엇이라 부르고 어떻게 읽고 고치는지를 명세 문서가 정해 둡니다.
쉽고 빠른 이해
문서를 노드의 트리로 표현하고, 그 트리를 읽고 고치는 방법을 정하는 표준입니다. 예를 들어
브라우저에서 document.querySelector('h1') 로 문서 안의 요소를 찾아내는 것이 이 표준이 정한
방법입니다.
이게 없으면 브라우저마다 문서를 다루는 방법이 따로 놀아서, 같은 스크립트가 브라우저마다 다르게 동작합니다.
돌아가는 방식은 이렇습니다.
- 문서를 노드의 트리로 표현합니다.
- 어떤 노드가 무엇의 자식이 될 수 있는지를 정합니다.
- 노드를 찾고 읽고 고치는 방법을 인터페이스로 정의합니다.
대가 — 이 표준은 인터페이스만 정합니다. 노드를 안에서 실제로 어떻게 저장하는지는 정하지 않습니다.
상세
DOM(Document Object Model, 문서 객체 모델)은 원래 뜻으로는 문서에 접근하고 문서를 조작하는 API(Application Programming Interface, 응용 프로그램 인터페이스)입니다. 지금의 명세는 자신이 정하는 것을 셋으로 적습니다. 이벤트, 진행 중이던 활동을 도중에 멈추는 것(abort), 그리고 노드 트리입니다. 셋 다 특정 플랫폼에 중립인 모델로 정의한다고 못 박습니다. 이 문서는 셋 가운데 노드 트리만 다룹니다. 이벤트와 활동의 중단은 각각 다른 표제어가 받습니다.
여기서 문서는 HTML(HyperText Markup Language, 하이퍼텍스트 마크업 언어) 문서만이 아닙니다. 명세는 마크업에 기반한 자원이면 전부 문서로 부릅니다. 짧은 정적 문서부터 멀티미디어가 풍부한 긴 글이나 보고서, 완전한 대화형 애플리케이션까지가 그 범위입니다. 그런 문서 하나하나가 노드 트리로 표현됩니다. 트리 안의 어떤 노드는 자식을 가질 수 있고, 어떤 노드는 언제나 잎(자식이 없는 노드)입니다.
노드는 Node 를 구현하는 객체입니다. 하지만 실제로 다루게 되는 것은 더 구체적인 객체입니다.
Node 를 구현하는 객체는 Node 를 상속하는 더 구체적인 인터페이스도 함께 구현하기 때문입니다.
그 구체적인 인터페이스가 Document · DocumentType · DocumentFragment · Element ·
CharacterData · Attr 입니다. 이 상속 관계를 그림으로 보면 다음과 같습니다.
classDiagram
Node <|-- Document
Node <|-- DocumentType
Node <|-- DocumentFragment
Node <|-- Element
Node <|-- CharacterData
Node <|-- Attr
무엇이 무엇의 자식이 될 수 있는지도 명세가 정합니다. Document 는 트리 순서로
ProcessingInstruction 이나 Comment 를 0개 이상, DocumentType 을 최대 하나, 다시
ProcessingInstruction 이나 Comment 를 0개 이상, Element 를 최대 하나, 그리고 다시
ProcessingInstruction 이나 Comment 를 0개 이상 가질 수 있습니다. DocumentFragment 와
Element 는 Element 나 CharacterData 를 0개 이상 가집니다. 무엇이 무엇의 자식이 될 수
있고 몇 개까지인지를 그림으로 보면 다음과 같습니다.
erDiagram
Document ||--o{ ProcessingInstruction : "0개 이상"
Document ||--o{ Comment : "0개 이상"
Document ||--o| DocumentType : "최대 1개"
Document ||--o| Element : "최대 1개"
DocumentFragment ||--o{ Element : "0개 이상"
DocumentFragment ||--o{ CharacterData : "0개 이상"
Element ||--o{ Element : "0개 이상(자식 요소)"
Element ||--o{ CharacterData : "0개 이상"
그림의 ||--o{ 는 왼쪽은 하나, 오른쪽은 0개 이상이라는 뜻이고, ||--o| 는 왼쪽은 하나,
오른쪽은 최대 하나라는 뜻입니다. 이 그림은 무엇이 무엇의 자식이 될 수 있는지만 보여줍니다.
그 자식들이 나열되는 순서, 즉 트리 순서는 위 문단이 말한 그대로입니다.
DocumentType · CharacterData · Attr 은 자식을 갖지 않습니다. Attr 은 역사적인 이유로
트리에 참여하지만 null 이 아닌 부모도 자식도 갖지 않아서 언제나 혼자 트리를 이룹니다.
루트가 document(앞서 본 Document 인터페이스를 구현하는 노드)인 노드 트리를 문서 트리라고
부릅니다. 그 document 를 부모로 갖는 element(Element 인터페이스를 구현하는 노드)가 그
문서의 문서 요소입니다. 그런 element 가 없으면 null 입니다.
이 모델은 자료구조가 아닙니다. DOM Level 1 명세가 이 선을 직접 그었습니다. DOM 은 자료구조의 묶음이 아닙니다. 인터페이스를 명세하는 객체 모델입니다. 명세에 실린 부모·자식 관계 그림은 프로그래밍 인터페이스가 정의하는 논리적 관계입니다. 특정한 내부 자료구조의 표현이 아닙니다.
출처 문서
정본은 WHATWG(Web Hypertext Application Technology Working Group)가 내는 「DOM Standard」입니다.
상태는 Living Standard 이고, 판 번호 대신 갱신 날짜를 답니다. 문서 머리에
DOM — Living Standard — Last Updated 18 July 2026 이라고 적혀 있습니다.
앞판은 W3C(World Wide Web Consortium)가 낸 권고입니다.
| 문서 | 판 | 상태 |
|---|---|---|
| Document Object Model (DOM) Level 1 Specification | Version 1.0 | W3C Recommendation, 1 October 1998 |
| Document Object Model (DOM) Level 3 Core Specification | Version 1.0 | W3C Recommendation, 07 April 2004 |
| DOM Standard | 판 번호 없음 | Living Standard, 상시 갱신 |
Level 1 의 상태 문단은 이 문서가 W3C 회원과 관계자들의 검토를 거쳐 디렉터의 승인을 받은 W3C 권고라고 적습니다. 안정된 문서라서 참조 자료로 쓰거나 다른 문서에서 규범적 참조로 인용할 수 있다고도 적습니다. Level 3 Core 는 W3C 의 DOM Activity 산출물로 나온 권고입니다. 이 문서가 다루지 않는 이전 판인 Core Level 2 위에 쌓아 올린 판이라고 스스로 밝힙니다.
이 표에 없는 판이 하나 더 있었습니다. Level 3 Core 다음, 지금의 DOM Standard 로 흡수되기 전입니다.
이름은 DOM4 입니다. DOM4 판이 마지막 판 번호였다는 것은 지금 그 주소의 서버 응답으로 확인됩니다.
DOM4 권고가 있던
www.w3.org/TR/dom41/ 주소로 요청을 보내면 지금은 301 영구 이동으로 www.w3.org/TR/dom/ 로
넘어갑니다. 거기서 다시 307 리다이렉트로 WHATWG 의 DOM Standard 로 한 번 더 넘어갑니다. DOM4 는
독립된 판 번호 문서로는 더 이상 남아 있지 않습니다.
flowchart TD
D4["DOM4 (TR/dom41)"] -->|301 영구 이동| TD["TR/dom"]
TD -->|307 리다이렉트| WS["DOM Standard (dom.spec.whatwg.org)"]
두 기관의 관계는 2019년 양해각서가 정했습니다. HTML 과 DOM 은 주로 WHATWG 에서 Living Standard 명세 절차를 따라 개발한다고 적혀 있습니다. W3C 는 WHATWG 의 검토 초안에 의견을 냅니다. 그것이 W3C 권고가 되도록 승인할 의도라고도 적혀 있습니다. 그 경로는 후보 권고(Candidate Recommendation, CR)에서 제안 권고(Proposed Recommendation, PR)를 거쳐 권고(Recommendation, REC)에 이르는 W3C 절차 그대로입니다. 설계 목표는 W3C 의 CR·PR·REC 와 WHATWG 의 검토 초안이 같은 문서가 되는 것이라고 못 박았습니다. WHATWG 검토 초안이 그 절차를 지나며 이름만 바뀔 뿐, 서로 다른 문서로 갈라지는 것이 아니라는 뜻입니다. 그 승인 경로를 그림으로 보면 다음과 같습니다.
flowchart TD
RD["WHATWG 검토 초안"] -->|같은 문서, 이름만 바뀜| CR["W3C 후보 권고(CR)"]
CR -->|W3C 절차대로 진행| PR["W3C 제안 권고(PR)"]
PR -->|W3C 절차대로 진행| REC["W3C 권고(REC)"]
폐기 관계
이 표준의 §11 Historical 이 빠져나간 이름을 모아 둡니다. 제거된 인터페이스로
DOMConfiguration · DOMError · DOMErrorHandler · DOMImplementationList ·
DOMImplementationSource · DOMLocator · DOMObject · DOMUserData · Entity ·
EntityReference · MutationEvent · MutationNameEvent · NameList · Notation ·
RangeException · TypeInfo · UserDataHandler 이 적혀 있습니다. 인터페이스 멤버도 같이
빠졌습니다. Attr.isId · Document.createEntityReference() · Document.xmlVersion ·
DocumentType.entities · Element.setIdAttribute() · Node.isSupported ·
Node.getUserData() · Text.replaceWholeText() 같은 것들입니다. 이 목록에 있는 이름을 지금
코드나 문서에서 보면, 최신 표준이 아니라 옛 판을 근거로 삼고 있다는 신호입니다. 옛 권고의 절
번호를 인용해도 마찬가지입니다 — 지금 표준에 없는 이름을 근거로 들게 됩니다.
요구 강도
DOM 명세 본문에는 RFC(Request for Comments) 2119 나 RFC 8174 를 걸어 요구 강도를 정의하는 적합성 절(Conformance)이 보이지 않습니다. 두 RFC 는 이 명세가 직접 인용하는 근거가 아니라, 표준 문서 일반이 MUST·SHOULD 같은 낱말을 어떻게 정의하는지 보여주는 참고 자료로만 남겨 둡니다.
RFC 2119 는 MUST 를 명세의 절대적 요구로 정의합니다. REQUIRED 와 SHALL 도 같은 뜻이라고 적습니다. RFC 8174 는 여기에 조건을 하나 붙였습니다. RFC 2119 는 이 낱말들이 "종종 대문자로 쓰인다" 고만 적어 뒀습니다. 그 탓에 소문자 must 나 should 를 어떻게 읽어야 하는지 혼란이 있었습니다. 그래서 대문자로 쓰인 쓰임만 그 특별한 뜻을 갖는다고 명확히 했다는 것입니다.
예시
마크업 한 조각과 그 노드 트리
명세가 §4.1 에서 드는 문서입니다.
<!DOCTYPE html>
<html class=e><head><title>Aliens?</title></head><body>Why yes.</body></html>
이것이 아래 트리로 표현됩니다.
flowchart TD
Document --> Doctype["Doctype: html"]
Document --> HTML["Element: html (class=e)"]
HTML --> Head["Element: head"]
HTML --> Body["Element: body"]
Head --> Title["Element: title"]
Title --> TextTitle["Text: Aliens?"]
Body --> TextBody["Text: Why yes."]
Document 아래 형제로 Doctype 과 최상위 Element(앞서 말한 문서 요소)가 나란히 있고, 그 Element 아래로 head 와 body 가 갈립니다. 트리의 잎은 전부 Text 노드입니다.
명세는 그 아래에 단서를 답니다. 「HTML 파싱이라는 마술」 때문에 ASCII(American Standard Code for Information Interchange, 미국 정보 교환 표준 부호) 공백 문자가 전부 Text 노드로 바뀌지는 않는다는 것입니다. 그 마술은 HTML 표준이 정하는, 공백을 처리하는 세부 규칙을 뜻합니다. 그 규칙은 이 문서의 범위 밖입니다. 결과만 보면 어떤 공백 문자는 Text 노드로 안 바뀌지만, 마크업이 들어가면 노드의 트리가 나온다는 개념 자체는 분명합니다.
interface Node 선언
명세는 인터페이스를 IDL(Interface Definition Language, 인터페이스 정의 언어) 선언으로 못 박습니다.
Node 선언의 일부입니다.
[Exposed=Window]
interface Node : EventTarget {
const unsigned short ELEMENT_NODE = 1;
readonly attribute unsigned short nodeType;
readonly attribute DOMString nodeName;
readonly attribute boolean isConnected;
readonly attribute Document? ownerDocument;
readonly attribute Node? parentNode;
readonly attribute Element? parentElement;
[SameObject] readonly attribute NodeList childNodes;
readonly attribute Node? firstChild;
readonly attribute Node? nextSibling;
[CEReactions] attribute DOMString? textContent;
[CEReactions, NewObject] Node cloneNode(optional boolean subtree = false);
};
값이 여기서 정해집니다. ELEMENT_NODE 가 1 이라는 것, nodeType 이 읽기 전용이라는 것,
cloneNode 의 subtree 인자 기본값이 false 라는 것이 전부 이 선언에 적혀 있습니다.
parentNode · firstChild · nextSibling · childNodes 는 상세에서 말한 트리 관계를 그대로
속성 이름으로 드러냅니다. 그리고 Node 는 EventTarget 을 상속합니다. 대괄호로 묶인
[Exposed=Window] · [SameObject] · [CEReactions, NewObject] 같은 표기는 IDL 이 선언에
붙이는 확장 속성이고, DOMString 은 문자열 타입입니다. 이 문서는 그 확장 속성 하나하나의
규칙까지는 다루지 않습니다.
선택자로 노드를 골라내는 호출
믹스인은 여러 인터페이스가 함께 갖다 쓰는 선언 조각입니다. IDL 문법에서 다른 인터페이스가
includes 로 그 선언을 가져다 씁니다. ParentNode 믹스인이 선택자(셀렉터, selector)로 노드를
찾는 메서드를 선언하고, Document · DocumentFragment · Element 가 이 믹스인을 includes 로
가져다 씁니다. 이 관계를 그림으로 보면 다음과 같습니다.
classDiagram
class ParentNode {
<<mixin>>
querySelector()
querySelectorAll()
}
ParentNode <|.. Document : includes
ParentNode <|.. DocumentFragment : includes
ParentNode <|.. Element : includes
interface mixin ParentNode {
Element? querySelector(DOMString selectors);
[NewObject] NodeList querySelectorAll(DOMString selectors);
};
node.querySelector(selectors) 는 node 의 자손 가운데 selectors 에 들어맞는 첫 element 를
돌려줍니다. 메서드 단계는 selectors 문자열을 이 node 를 기준점으로 놓고 그 아래 노드들과
맞춰 보고, 그 첫 결과를 돌려주는 것입니다. 결과가 빈 목록이면 null 을 돌려줍니다.
삽입 순서가 만드는 관찰 결과
명세의 예제 하나가 실제 호출과 그 결과를 함께 보여줍니다.
const h1 = document.querySelector('h1');
const fragment = new DocumentFragment();
const script = fragment.appendChild(document.createElement('script'));
const style = fragment.appendChild(document.createElement('style'));
script.innerText = 'console.log(getComputedStyle(h1).color)';
// Logs 'rgb(255, 0, 0)'
style.innerText = 'h1 {color: rgb(255, 0, 0);}';
document.body.append(fragment);
스크립트가 rgb(255, 0, 0) 을 찍습니다. 명세는 그 이유를 순서대로 설명합니다. 먼저 노드를
트리에 매다는 삽입 알고리즘이 돌아 script 요소와 style 요소를 문서에 차례로 삽입합니다. 이
삽입 알고리즘과는 별개로, HTML 표준이 정하는 삽입 단계가 삽입된 요소마다 돕니다. script
요소에 대해서는 아무 일도 하지 않습니다. style 요소에 대해서는 그 스타일 규칙을 문서에
즉시 적용합니다. 그다음 HTML 표준이 정하는 연결 후 단계가 script 요소에 대해 돌아 스크립트를
실행합니다. 그 스크립트가 방금 적용된 스타일 규칙을 곧바로 관찰합니다. 이 순서를 그림으로
보면 다음과 같습니다.
sequenceDiagram
participant I as DOM 삽입 알고리즘
participant H as HTML 표준
participant S as script 요소
participant St as style 요소
participant D as 문서
I->>S: 삽입
I->>St: 삽입
H->>S: 삽입 단계 실행
Note right of S: 아무 일도 하지 않음
H->>St: 삽입 단계 실행
St->>D: 스타일 규칙 즉시 적용
H->>S: 연결 후 단계 실행
S->>D: 적용된 스타일 관찰
배경
스크립트가 브라우저마다 따로 놀았습니다. DOM 은 JavaScript 스크립트와 Java 프로그램이 웹 브라우저 사이에서 이식 가능하도록 만들려는 명세로 출발했습니다. 직계 조상은 "Dynamic HTML" 이었습니다. 처음에는 대체로 브라우저를 염두에 두고 생각된 것이었습니다.
W3C 에 DOM 작업반이 꾸려졌습니다. 참여자는 브라우저 밖으로 넓어졌습니다. HTML 이나 XML(Extensible Markup Language, 확장 가능 마크업 언어) 편집기와 문서 저장소를 만드는 벤더들이 합류했습니다. 이들 가운데 여럿은 XML 이 만들어지기 전에 SGML(Standard Generalized Markup Language, 표준 일반화 마크업 언어)로 일한 쪽이었습니다. 그 결과 DOM 은 SGML Groves 와 HyTime 표준의 영향을 받았습니다.
첫 판이 그 조상을 전부 담지는 않았습니다. Level 1 명세는 자신이 "Dynamic HTML" 의 강한 영향을 받았지만 그것을 전부 구현하지는 않는다고 적습니다. 특히 이벤트가 아직 정의되지 않았다고 밝힙니다. 지금의 Living Standard 가 이벤트와 활동의 중단을 노드 트리와 나란히 정하는 것과 견주면, 무엇이 나중에 채워졌는지가 그 문장에 남아 있습니다.
이 계보를 그림으로 보면 다음과 같습니다.
flowchart TD
DHTML["Dynamic HTML"] -->|직계 조상, 일부만 구현| L1["DOM Level 1"]
Groves["SGML Groves"] -->|영향, W3C DOM 작업반 합류 경유| L1
HyTime["HyTime 표준"] -->|영향, W3C DOM 작업반 합류 경유| L1
L1 -->|이벤트 · 활동의 중단 보강| LS["지금의 Living Standard"]
관련 항목
트리를 이루는 인터페이스
EventTarget · Node · Document · DocumentType · DocumentFragment · ShadowRoot · Element · Attr · NamedNodeMap · CharacterData · Text · CDATASection · ProcessingInstruction · Comment · DOMImplementation
트리를 훑고 지켜보는 인터페이스
NodeList · HTMLCollection · DOMTokenList · Range · NodeIterator · TreeWalker · NodeFilter · MutationObserver · MutationRecord · XPathResult · XSLTProcessor
이벤트와 중단
Event · CustomEvent · AbortController · AbortSignal
경계를 나눠 갖는 이웃 명세
HTML · HTML 파싱 · 직렬화 · CSS(Cascading Style Sheets) · CSSOM(CSS Object Model) · 셀렉터
이 표준을 구현하고 활용하는 기술
브라우저 · 사용자 에이전트 · 렌더링 · 프론트엔드 · 서버 사이드 렌더링 · 접근성
이 표준을 관리하고 설명하는 조직
다른 이름: Document Object Model · 문서 객체 모델 · DOM Standard