ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • DOM 을 좀 더 깊게 공부하자 !
    웹 브라우저 2023. 3. 7. 22:08

    브라우저의 렌더링 과정에서 브라우저가 html 통짜 텍스트 문서를 어떻게 DOM 트리로 파싱하는 지 알아보았다.

    이 DOM 이라는 자료구조에 대해 좀 더 자세히 이해하면 매우 좋다 !

    왜 ? 지금까지 이해한 것을 바탕으로 감히 생각해 보건데,

    프론트엔드의 대부분의 작업은 이 DOM 트리를 조작하는 일이다.

    바로 자바스크립트를 이용해서 ! (자바스크립트의 DOM API 를 이용해서)

    그렇다는 것은 DOM 트리를 얼마나 잘 이해하고 있냐는 프론트엔드의 실력과도 상관관계가 많이 있을 것이라 예측한다.

     

    자바스크립트 Deep Dive (나는 어느샌가 이것을 성경이라고 부르기 시작했다) 에는 DOM 을 거의 100페이지에 걸쳐서 길게 설명하는데, 나는 이것을 완벽하게 이해해서 최대한 압축한 글을 쓰려고 한다. 할 수 있다 !

     


    출처 : 모던 자바스크립트 Deep Dive: 자바스크립트의 기본 개념과 동작 원리 / 이웅모 지음

    DOM 노드

     

    DOM(Document Object Model) 은 HTML 문서의 계층적 구조와 정보를 표현하며 이를 제어할 수 있는 API, 즉 프로퍼티와 메서드를 제공하는 트리 자료구조다.

     

    DOM 의 정의는 이것이다. 그리고 이 DOM 트리의 각 노드에 대해 알아볼 것이다.

     

    우선 노드는 하나의 HTML 요소를 렌더링 엔진으로 파싱한 결과물이다.

    <div class="greeting">Hello</div>

    div : 태그, class="greeting : 어트리뷰트, Hello : 콘텐츠

    요소 노드 어트리뷰트 노드
    div, right->attribute_node, bottom->text_node class="greeting"
    텍스트 노드  
    "Hello"  

    1. 요소 노드에는 태그가 들어가며, 오른쪽 노드에 어트리뷰트 노드를, 아래쪽 자식 노드에 텍스트 노드를 연결한다.

    2. 컨텐츠 노드에는 텍스트 노드 뿐만 아니라 다른 HTML 요소를 파싱한 노드가 들어올 수 있다. (트리 중첩)

     

    노드 객체는 총 12개의 종류가 있는데, 그 중에서 중요한 4가지 노드 타입이 있다.

     

    1. 문서 노드 (document node)

    - DOM 트리의 루트 노드. document 객체를 가리킴. 전역 객체 window의 document 프로퍼티에 바인딩되어 있음.

     

    2. 요소 노드 (element node)

    - HTML 요소를 가리키는 객체. 위의 예시에 Hello 텍스트 대신 다른 HTML 요소 노드가 컨텐츠 노드로서 들어올 수 있고, 계속 자식을 연결해 트리 구조를 만듬.

     

    3. 어트리뷰트 노드 (attribute node)

    - HTML 요소의 어트리뷰트를 가리키는 객체. 부모 노드나 자식 노드가 없고, 오직 요소 노드와 연결되어 있다. 따라서 어트리뷰트를 참조하고 싶으면 그와 연결된 요소 노드에 접근해야 한다.

     

    4. 텍스트 노드 (text node)

    - 자식 노드를 가질 수 없는 리프 노드 (leaf node) 로, DOM 트리의 최종단.

     

     

    이제 노드 객체의 상속 구조에 대해 살펴볼 건데, 내가 TypeScript (이하 TS) 로 코드를 작성할 때 가장 애먹었던 부분이다. 어떤 노드를 인자로 넣은 함수를 만들고 싶은데, 노드 타입이 너무 많아서 정신이 나갈 뻔 했었다.

    그런데 사실 노드 타입은 나름 체계화된 상속 구조를 가지고 있었고, 이를 이해하고 나니 한결 타입을 파악하기 쉬워졌다.

     

    fig 1. 노드 객체의 상속 구조 (모던 자바스크립트 Deep Dive)

    이 것을 모르고 있을 땐 노드의 타입을 명시할 때 대체 EventTarget 으로 해야하는지, HTMLElement 로 해야 하는지, HTMLInputElement 로 해야 하는지, 세 개의 차이는 무엇인지 너무 헷갈렸었다. 사실상 필수 개념인데 이걸 모른 채로 개발을 한 셈.

     

    input 요소 노드 객체의 특성 프로토타입을 제공하는 객체
    객체 Object
    이벤트를 발생시키는 객체 EventTarget
    트리 자료구조의 노드 객체 Node
    브라우저가 렌더링할 수 있는 웹 문서의 요소를 표현하는 객체 Element
    웹 문서의 요소 중에서 HTML 요소를 표현하는 객체 HTMLElement
    HTML 요소 중에서 input 요소를 표현하는 객체 HTMLInputElement

     

    내가 작성한 노드 객체의 상속 구조를 확인하고 싶으면, 개발자 도구의 Element 패널 우측의 Properties 패널을 확인하면 된다.

     

    올바른 타입의 사용법을 정리하자면 이렇다.

    - 노드의 이벤트를 관리하고 싶을 때 : EventTarget 인터페이스 사용

    - 트리 탐색을 하고 싶을 때 : Node 인터페이스 사용 (자주 사용하진 않음, 리액트 훅에는 useRef 같은 좋은 기능도 있고 ..)

    - HTML 요소의 공통적인 기능을 관리하고 싶을 때 : HTMLElement 사용 (예를 들어 style 같은 것)

    - 요소 노드의 고유한 기능을 사용하고 싶을 때 :

      예를 들어 아주 빈번하게 사용하는 input 노드의 경우, HTMLInputElement 인터페이스를 정말 많이 사용한다. (입력칸에 들어온 input 요소의 값을 관리하거나 하는 등)

     

     

    딥다이브에는 querySelector 를 사용하거나, getElementById 등으로 요소 노드를 취득하는 방식을 소개하는데, 리액트를 사용할 경우 이런 방식은 거의 쓰지 않는 것 같다. DOM 을 조작하는 방식 또한, 바닐라JS 만 사용할 경우의 예시가 많아서, 패스. (바닐라JS만 사용해서 웹을 만들 일이 있을까 ?)

     

     

    이로써 DOM 트리의 노드에 대해서도 알아보았다 ! 이것들을 진작에 알고 있었다면 첫 웹 프로젝트를 할 때 훨씬 시간이 적게 들었을 텐데 .. 하지만 이제부터라도 알고 있다는 게 중요하다. 이제 시작이니까.

    댓글

Designed by Tistory.