[javascript] 문서 객체 모델(DOM)과 노드, 그리고 태그의 이해

Document Object Model, 줄여서 DOM(돔이라고 읽음), 한글로는 문서 객체 모델이라고 합니다.

HTML, 또는 XML 페이지의 구조와 요소들을 제어할 수 있도록 제공하는 프로그래밍 인터페이스, 또는 구조화된 데이터를 말합니다.

자바스크립트는 이 프로그래밍 인터페이스(API)인 DOM에 접근할 수 있으며, DOM 생성 후, 화면에 웹페이지가 표시되기 전에 DOM을 제어할 수도 있습니다.

웹브라우저로 웹사이트의 특정 페이지에 접속할 경우 웹브라우저는 HTML 문서를 읽습니다. 그리고 CSS와 여러가지 컨텐츠 파일들도 함께 읽습니다.

그리고 HTML과 CSS, 그리고 컨텐츠 파일들을 조합해 웹 페이지를 브라우저 화면에 표시합니다.

웹브라우저는 이 과정을 2단계로 나누어서 실행합니다.

먼저 HTML 파일을 읽어 문서의 구조를 파악하고, 트리 형태로 된 데이터 구조를 만듭니다.

이것이 DOM 입니다. DOM이 일단 완성되고 나면, 자바스크립트와 같은 프로그래밍 언어가 DOM을 제어할 수 있게 됩니다.

웹브라우저가 화면에 웹페이지를 표시하는 단계로 넘어가기 전에 실행되는 자바스크립트가 DOM을 제어합니다.

DOM 제어가 끝나면 웹브라우저는 DOM 구조를 기반으로 화면에 웹페이지를 그리는 과정을 진행합니다. 

이 그리는 과정을 렌더링(Rendering) 이라고 합니다.

렌더링에는 CSS 파일의 화면 배치와 속성에 대한 정보를 정보를 사용합니다.

이 과정에서 웹브라우저는 DOM과 마찬가지로 CSS를 읽어 CSSOM(Cascading Style Sheet Object Model) 을 생성합니다.

CSS를 구조화 된 데이터 형태로 생성한 것입니다.

DOM 과 CSSOM을 조합해 화면에 표시할 최종 구조를 만듭니다. 이것이 렌더트리입니다.

렌더트리를 기초로 화면에 HTML 페이지를 그립니다.

배치가 되면서 컨텐츠 파일들 또한 비동기로 읽어서 HTML 페이지의 맞는 위치에 배치를 합니다.

렌더링 과정은 전적으로 웹브라우저의 몫입니다.

DOM의 구조는 표준으로 정해져 있기 때문에 모두 같은 구조를 가지지만, DOM을 웹브라우저 화면에 어떻게 표시할 것이냐는 웹브라우저 고유의 방식을 따릅니다.

여기서 브라우저간 호환성 문제가 발생합니다.

실제로 다른 렌더링 엔진(렌더링을 구현한 모듈)을 쓰는 구글 크롬과, 모질라 파이어폭스는 같은 HTML 페이지를 화면에 표시할 때 미세하게 다르게 표현되는 부분이 있습니다.

대부분은 HTML 규격에 세세하게 정해지지 않은 부분들을 각자 알아서 구현하면서 나타나는 차이지만, DOM이 같다고 웹브라우저 화면에도 100% 같은 화면이 보이는 것은 아닙니다.

다소 복잡해 보이지만

HTML 문서를 구조화한 데이터인 DOM과, CSS를 구조화한 데이터인 CSSOM을 조합해서 웹페이지를 웹브라우저 화면에 그립니다.

DOM 완성 후 화면에 표시되기 전에, 또는 표시 후에 자바스크립트로 DOM을 제어할 수 있습니다.

DOM의 구조와 노드, 태그의 이해

HTML 문서는 태그를 사용해 문서의 내용을 표현합니다.

그리고 HTML 문서는 최상위인 <html></html> 태그로부터 시작해 부모 자식 관계를 가지는 1개의 트리 구조를 가집니다.

DOM은 이 트리구조인 HTML 태그 구조를 데이터 구조로 표현한 것입니다.

DOM 에서는 HTML의 태그 1개에 해당하는 것을 노드라고 하며, 부모 자식 관계로 노드들을 트리 구조로 표현한 것을 노드 트리(Node Tree)라고 합니다.

DOM 과 HTML의 이런 트리 구조는 매우 유사하고, 언뜻 1:1 로 매칭이 될 것 같지만, 둘에는 여러가지 차이점이 있습니다.

1.

DOM 은 유효하지 않은 HTML 태그를 교정해서 DOM 트리 구조로 표현할 수 있는 형태로 보정합니다.

문서로 존재하는 HTML 페이지는 HTML 문서 구조에서 필수로 있어야 하는 태그가 없을 수도 있고, 끝나는 태그가 없는 태그가 있을 수도 있습니다.

웹브라우저는 DOM을 생성하면서 이런 HTML 페이지의 구조적인 문제점 교정해서 구조적으로 문제가 없는 DOM을 생성합니다.

HTML 페이지는 문제가 있을 수 있지만, 생성된 DOM은 완전한 형태의 구조를 가지게 됩니다.

2.

자바스크립트는 DOM을 제어하는 것이지, HTML 페이지의 태그를 제어하는 것이 아닙니다.

자바스크립트를 이용해 태그를 추가하거나 특정 트리 구조를 다른 위치로 옮기는 것은 모두 DOM을 변경하는 것입니다.

DOM 생성이 완료되기 전까지 자바스크립트는 동작하지 않습니다.

자바스크립트로 HTML 페이지의 구조를 수정할 수 있다는 것은 DOM이 이미 완성되어 있는 것입니다.

3.

노드와 태그는 다른 것이다. 

자주 혼동하지만 노드와 태그는 완전히 다른 것입니다.

노드는 DOM의 요소 1개를 말하고, 태그는 HTML 페이지의 태그 요소 1개를 말합니다.

노드는 태그일 수도 있고, 태그가 아닐 수도 있습니다.

노드는 태그의 수퍼셋과 같은 개념이라고 이해하면 됩니다.

노드는 태그(엘리먼트) 노드 외에 제어를 위한 특수 문자나, 또는 웹브라우저에서 렌더링 되지 않는 시각적이지 않은 요소들을 모두 각각의 노드로 표현합니다.

4.

DOM 에는 CSS 에 연관된 내용이 없습니다.

CSS는 CSSOM으로 표현하며, 둘은 완전히 분리된 데이터 구조입니다.

웹브라우저 개발자 도구에서 HTML 구조를 표현할 때 일부 CSS 요소들이 보이는 것은 시각적인 편의를 위한 것이지, 실제 그 데이터가 DOM에 있기 때문이 아닙니다.

대표적으로 :before, :after 와 같은 CSS 가상 요소가 있습니다.

웹브라우저 개발자도구의 데이터 구조는 DOM과 CSSOM이 모두 생성된 후에 그 구조에 접근하는 것으로 이해를 해야 합니다.