DOM이란(Document Object Model)
문서 객체 모델(Document Object Model, 이하 DOM)은 HTML, XML 문서의 프로그래밍 인터페이스이다. DOM
은 문서의 구조화된 표현을 제공하며 프로그래밍 언어가 DOM
구조에 접근할 수 있도록 해주는 매우 중요한 역할이다. DOM
은 nodes와 objects로 문서를 표현한다. 따라서 개발자들은 DOM
에 접근하여 구조를 바꾸거나 스타일과 내용 등을 변경하고 이벤트를 연결시키는 등의 다양한 작업을 수행할 수 있다.
내가 이해한 내용을 쉽게 풀어보자면 DOM
은 웹 페이지의 요소들을 프로그래밍 언어로 제어, 조작할 수 있도록 존재하는 객체 형식의 모델이다. 우리가 JavaScript로 구현한 모든 동작들이 DOM
을 조작하기 위함이다. JavaScript는 브라우저가 읽고 ~작업을 할 수 있는 언어라면, DOM
은 바로 이 ~작업이 이루어지는 장소인 것이다.
DOM의 활용 방법
DOM
은 프로그래밍 언어가 DOM
에 접근하고 수정할 수 있도록 방법을 제공한다고 했다. 어떻게? 일반적으로는 프로퍼티와 메서드를 가지고 있는 JavaScript 객체로 제공한다. 이것이 DOM API
이다. 정적인 웹 페이지에 접근해서 동적으로 변경하기 위해서는 메모리상의 DOM
을 변경해야 하는데, 이를 조작하는데 필요한 것이 DOM API
라고 생각하면 된다.
DOM은 어떻게 생겼을까?
브라우저는 HTML 문서를 로드하고 해당 문서에 대한 모델을 메모리에 생성한다. 이때 생성되는 트리 모양의 모델이 DOM tree
이다. DOM
은 HTML 문서의 구조를 트리 형태로 표현하는 계층 구조를 가지고 있다. 하나의 최상위 노드(root)에서 시작해 자식 노드들을 가지며, 각 노드는 웹 페이지의 요소, 속성 또는 텍스트와 같은 정보를 나타낸다.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1" />
<title>DOM</title>
</head>
<body>
<h1 style="color: blue;">Document Object Model</h1>
</body>
</html>
해당 HTML 문서를 작성하여 브라우저가 로드 후 *파싱하면 아래와 같은 트리 구조, 즉, DOM tree
모델을 생성하게 된다. document
노드가 최상위, 밑으로 element
노드가 오며 이어 text
노드와 attribute
노드가 오는 계층 구조임을 알 수 있다.
document node (문서 노드)
DOM
의 최상위 노드이며, DOM tree
에 접근하기 위한 시작점이다. HTML 문서 전체를 나타내는 노드이다.
- 문서 구조 표현: HTML 문서의 구조를 표현하는 데 사용된다. HTML 문서의 모든 요소, 속성, 텍스트, 주석 등이 이 노드 아래에 계층 구조로 포함된다.
- 전역 설정과 속성: 문서 수준의 속성과 설정을 포함한다. 문서의 기본 언어, 문자 인코딩, 제목 및 메타데이터 등을 말한다.
- 문서 객체에 접근:
window
객체의document
프로퍼티로 바인딩(연결)이 되어 있어window.document
,document
로 참조해 사용할 수 있다.
var documentNode = document; // document node에 접근
documentNode.title = "새로운 제목"; // document node의 속성에 접근 (예: 제목 변경)
// 기존: DOM
// 변경: 새로운 제목
element 노드 (요소 노드)
모든 HTML 요소(body
, h2
, div
등의 태그)를 나타내는 노드이다. 이러한 노드들은 웹 페이지의 구조를 표현하며, 계층구조로 연결되어 있다. 또한, 속성 노드(id
, class
, src
, href
등)를 포함하는 노드이며 요소 노드는 다른 요소 노드를 자식 요소로 포함할 수 있다.
attribute node (속성 노드)
모든 HTML 요소의 속성을 나타내는 노드이다. 요소 노드에 대한 정보를 가지고 있다. 각 속성은 속성 이름과 해당 값을 가진다.
- 이름과 값: 예를 들어
<img src=”sample.jpg”>
요소의src
속성 노드는 “src”라는 이름과 “sample.jpg”라는 값을 가진다. - 속성 노드 접근: 해당 속성의 값을 읽거나 변경할 수 있다. 이를 통해 HTML 요소의 속성을 조작할 수 있다.
- 읽기 및 쓰기: 요소의 속성 값을 얻거나 변경할 때 사용하는 메서드
getAttribute
와setAttribute
가 있다.
<img src="sample.jpg" id="logo" />
var image = document.getElementById("logo"); // id가 logo인 요소에 접근
var srcAttribute = image.getAttribute("src"); // "src" 속성 값 접근
console.log(srcAttribute); // "sample.jpg"
image.setAttribute("src", "new-image.jpg"); // "src" 속성 값 변경
console.log(srcAttribute); // "new-image.jpg"
text node (텍스트 노드)
HTML 요소 내에 표시되는 텍스트를 나타내는 요소이다. 텍스트 노드 자체는 자식 노드를 가지는 것이 불가능하다. 즉, DOM
의 최하위 노드라고 할 수 있다.
- 텍스트 내용: 실제 텍스트 내용을 포함한다. 예를 들어
<p>
요소의 텍스트 내용텍스트입니다.
는 텍스트 노드에 저장된다. - 엔터 및 공백 문자 포함: 줄 바꿈, 공백, 탭과 같은 공백 문자를 포함한다.
- 부모 요소와 연결: 텍스트 노드는 특정 HTML 요소의 자식 노드로 연결된다.
- 텍스트 노드 접근: 텍스트 노드에 접근하고 내용을 읽거나 변경할 수 있다.
DOM
에서 텍스트 노드를 다룰 때 주로textContent
및innerText
프로퍼티를 사용한다.
<p id="paragraph">텍스트입니다.</p>
var paragraph = document.getElementById("paragraph"); // id가 paragraph인 요소에 접근
var textNode = paragraph.firstChild; // text 노드에 접근
console.log(textNode.textContent); // "텍스트입니다."
textNode.textContent = "업데이트 된 텍스트입니다.";
console.log(textNode.textContent); // "업데이트 된 텍스트입니다."
그렇다면 우리가 DOM
에 접근하여 수행한 작업들을 브라우저는 어떻게 화면에 보여주는 것일까? 브라우저의 핵심 기능과 렌더링 과정에 대해서 알아보자.
요청과 응답
브라우저의 핵심 기능은 필요한 리소스(HTML, CSS, JavaScript, 이미지, 폰트 등)를 서버에 요청(Request)하고 서버로부터 응답(Response) 받아 브라우저에 렌더링하는 것이다.
요청
사용자가 브라우저 주소창에 URL
을 입력하고 엔터 키를 누르면, 해당 URL 서버로 요청을 보낸다. 예를 들어 https://google.com
을 입력하면 해당 google.com
서버로 요청을 보낸다. 이때 명확히 리소스를 요청하는 내용이 없지만 일반적으로 서버는 루트 요청에 대해 index.html
을 응답하는 것이 기본 설정이다.
만약, 다른 정적 파일을 서버에 요청하려면 브라우저 주소창에 https://www.google.com/images/searchbox/desktop_searchbox_sprites318_hr.webp
처럼 요청할 정적 파일의 경로와 파일 이름을 URI의 호스트 뒤 패스에 기술하여 서버에 요청한다. 그럼 서버는 루트 폴더의 images/searchbox
폴더 내에 있는 정적 파일 desktop_searchbox_sprites318_hr.webp
을 응답할 것이다.
응답
응답은 개발자 도구의 Network 탭에서 확인할 수 있다. 위에서 보낸 루트 요청에 대한 정보와 서버의 응답을 살펴보자. 아래 그림을 보면 index.html(www.google.com)
뿐만 아니라 JavaScript, 이미지, CSS 파일들도 응답되었다. 내가 요청한 건 루트 요청 뿐인데?
이는 브라우저 렌더링 엔진이 HTML을 *파싱하는 도중에 외부 리소스를 로드하는 태그, 즉 <link>
, <img>,
<script>
등을 만나면 HTML의 파싱이 일시 중지되고 해당 리소스 파일을 서버로 요청하기 때문이다.