DOM
Document Object Model
도구
브라우저가 읽어 들인 웹 문서를 코드에서 찾고 고칠 수 있도록 객체 구조로 바꿔 놓은 것입니다.
등장 배경
초창기 웹에서 화면은 한 번 그려지면 끝이었습니다. 서버가 보낸 문서를 브라우저가 그대로 펼쳐 놓았고, 그 안의 무엇 하나를 바꾸려면 주소를 다시 요청해 문서 전체를 새로 받아야 했습니다. 목록에서 항목 하나를 지우는 일에도 화면이 하얗게 깜빡이며 처음부터 다시 그려졌습니다.
브라우저 회사들이 각자 방법을 내놓으면서 상황이 더 꼬였습니다. 한쪽은 문서 안의 요소를 한 가지 이름으로 꺼내게 했고 다른 쪽은 전혀 다른 이름을 썼습니다. 같은 기능을 만들려면 지금 어느 브라우저에서 돌고 있는지 먼저 판별한 뒤 두 벌의 코드를 각각 짜 두어야 했습니다. 스크립트 첫머리가 브라우저를 가려내는 분기로 시작하는 것이 그 시절의 흔한 풍경이었습니다.
그래서 문서를 코드에서 다루는 방식을 표준으로 하나 정했습니다. 브라우저가 문서를 읽어 들이면 정해진 규격의 객체 묶음으로 만들어 두고, 코드는 어느 브라우저에서 돌든 같은 이름으로 그 묶음을 다루게 한 것입니다. 이 규격과 그 결과물을 함께 가리키는 말이 DOM 입니다. 자바스크립트가 화면을 바꾼다는 말은 실제로는 이 묶음을 고친다는 뜻입니다.
해결하는 문제
글자로 적힌 문서를 코드가 다룰 수 있는 물건으로 바꿔 줍니다. 브라우저는 받아 온 HTML 을 위에서부터 읽으면서 요소 하나하나를 객체로 만들고, 그것들을 포함 관계에 따라 나무 모양으로 잇습니다. 문서가 맨 위에 있고 그 아래 본문이 있고 본문 아래 목록이 있고 목록 아래 항목들이 달리는 식입니다.
이 구조 덕분에 코드가 할 수 있는 일이 셋으로 정리됩니다.
- 찾기 — 조건에 맞는 요소를 골라냅니다. 고유한 이름표가 붙은 요소 하나를 집을 수도 있고, 특정 표시가 붙은 요소를 전부 모을 수도 있습니다.
- 고치기 — 찾은 요소의 글자를 바꾸거나 속성을 바꾸거나, 새 요소를 만들어 원하는 자리에 끼우거나, 있던 요소를 떼어 냅니다. 고친 결과는 그 자리에서 화면에 반영됩니다.
- 듣기 — 요소에 사건을 기다리는 함수를 걸어 둡니다. 이 버튼이 눌리면 저 함수를 실행하라는 식이고, 클릭·입력·스크롤 같은 것이 사건에 해당합니다.
페이지덱의 문서 목록에서 항목 하나를 지우는 장면이 이 셋을 한 번에 보여 줍니다. 휴지통 아이콘에 사건을 걸어 두고, 눌리면 서버에 삭제를 요청하고, 성공 응답이 오면 그 항목에 해당하는 요소만 떼어 냅니다. 나머지 항목과 스크롤 위치는 그대로 남습니다. 문서 전체를 다시 받던 시절이라면 같은 일에 화면 전체가 다시 그려졌습니다.
한 가지 더 있습니다. 브라우저가 만들어 둔 이 구조는 원본 문서와 따로 놉니다. 서버가 보낸 문서에는 항목이 열 개로 적혀 있어도, 코드가 하나를 떼어 내면 지금 화면의 구조에는 아홉 개만 남습니다. 화면에 보이는 것은 언제나 이 구조 쪽이고 원본 파일이 아닙니다.
대안
코드에서 이 구조를 손으로 직접 만지는 대신 쓰는 방법이 몇 가지 있습니다. 어느 쪽을 택하든 마지막에 이 구조가 바뀐다는 사실은 같고, 누가 그 일을 하느냐만 달라집니다.
- 화면을 조각으로 나눠 라이브러리에 맡기기 — 컴포넌트를 쓰는 방식입니다. 무엇을 어떻게 고칠지 적는 대신 지금 화면이 어떤 모습이어야 하는지를 적어 두면, 라이브러리가 이전 모습과 견줘 달라진 부분만 골라 대신 고칩니다. 사람이 고치는 순서를 놓치는 실수가 줄어듭니다.
- 서버에서 미리 그려 보내기 — 서버 렌더링입니다. 첫 화면에 필요한 문서를 서버가 완성해 내려보내므로 브라우저는 받자마자 구조를 만들어 보여 줍니다. 대신 그렇게 받은 화면에 동작을 입히는 하이드레이션 과정이 따로 필요합니다.
- 아예 건드리지 않기 — 접었다 펴는 메뉴나 마우스를 올렸을 때의 변화처럼 눈에 보이는 상태만 달라지는 일은 CSS로 처리할 수 있습니다. 코드가 개입하지 않으니 더 빠르고 덜 깨집니다.
세 가지 모두 이 구조를 없애지는 못합니다. 라이브러리도 결국 같은 이름으로 요소를 만들고 떼어 내며, 서버가 보낸 문서도 브라우저에 닿으면 같은 구조로 변환됩니다. 그래서 화면이 왜 느린지, 왜 안 바뀌는지를 따질 때는 한 겹 아래의 이 구조를 보게 됩니다.
실무 용례
"이건 DOM 을 직접 만지지 말고 상태로 관리하죠."
화면을 손으로 고치지 말고 값이 바뀌면 라이브러리가 알아서 고치게 하자는 제안입니다.
"목록이 3천 개라 DOM 노드가 너무 많아요. 보이는 것만 그립시다."
요소가 늘어난 만큼 브라우저가 계산할 것도 늘어 느려졌으니 화면에 들어온 부분만 만들자는 뜻입니다.
"콘솔에서 DOM 열어 보면 그 속성이 빠져 있어요."
브라우저 개발자 도구로 지금 화면의 구조를 들여다보니 원본 문서에 있어야 할 값이 없다는 말입니다.
페이지덱에서는 태오가 화면이 느리다는 제보를 받았을 때 여기부터 봅니다. 개발자 도구를 열어 지금 만들어져 있는 요소가 몇 개인지 세고, 조작 한 번에 그중 몇 개가 다시 계산되는지를 확인합니다. 문서 목록 화면에서 항목 하나를 열 때마다 목록 전체가 다시 그려지고 있었던 적이 있는데, 원인은 서버도 네트워크도 아니고 바뀌지 않은 항목까지 손대고 있던 코드였습니다.
흔한 오해
DOM 을 자바스크립트의 일부로 아는 경우가 많습니다. 늘 자바스크립트로 다루다 보니 그 언어의 문법처럼 보이는 것입니다. 실제로는 브라우저가 바깥에 내어 주는 별개의 규격이고, 자바스크립트는 그것을 부르는 언어 중 하나일 뿐입니다. 이 구분을 모르면 서버에서 자바스크립트를 돌릴 때 같은 코드가 동작하지 않는 이유를 못 찾습니다. 그 환경에는 문서도 브라우저도 없으니 다룰 구조 자체가 없습니다.
DOM 을 만지면 무조건 느리다는 말도 자주 들립니다. 성능 이야기에서 늘 함께 나오는 이름이라 그렇게 굳었습니다. 하지만 요소 하나를 고치는 일 자체는 빠르고, 느려지는 것은 고친 직후에 화면 계산 결과를 다시 읽는 일을 반복할 때입니다. 항목 100개의 높이를 하나씩 읽고 하나씩 고치기를 번갈아 하면 브라우저가 100번 다시 계산합니다. 무조건 피해야 할 것으로 외워 두면 읽기와 쓰기를 나눠 모으기만 해도 해결될 문제에 라이브러리를 새로 들이게 됩니다.
자주 헷갈리는 용어
| 용어 | 무엇인가 | DOM 과의 차이 |
|---|---|---|
| HTML | 문서의 구조를 적어 둔 텍스트 | 브라우저에 건네는 원본이 HTML 이고, 그것을 읽어 만든 객체 구조가 DOM 입니다. 원본 파일을 고쳐도 이미 떠 있는 화면은 바뀌지 않고, 화면 쪽 구조를 고쳐도 원본 파일은 그대로입니다 |
같이 보면 좋은 페이지
마지막 업데이트 2026-09-16