본문 바로가기

개발자노트/우아한 테코톡 감상

[10분 테코톡] 🕶 곤이의 DOM&BOM

1. 웹 구성 요소

HTML - 뼈대 ( 제목 / 이미지/ 표 등을 정의 ) , 구조와 의미를 부여하는 정적언어

           - 웹의 전체적인 구조를 담당함

 

CSS - 옷 (색상 , 레이아웃, 폰트 등을 지정), 콘텐츠를 꾸미는 정적 언어

         - 웹의 시각적인 표면을 담당함

 

JS - 기능 , HTML의 정적이고 단조로운 한계를 극복하기 위해 만들어진 언어

      - 웹 문서를 더욱 동적으로 처리할 수 있도록 도와줌

 

 

JS는 어떻게 확장자가 다른 HTML과 CSS파일의 내용을 읽고 수정할 수 있을까??

해답은 2번 DOM에 있음

 

 

2. DOM (Document Object Model)

- 문서에 대한 모든 내용을 담고 있는 객체

- 텍스트 파일로 만들어진 문서를 브라우저가 이해할 수 있는 구조로 구성한 것

- HTML 요소 간의 부자관계를 반영하여 모든 노드들을 트리구조로 구성한 것

- HTML, XML 문서의 프로그래밍 interface

- 문서의 구조화된 표현(structured representation)을 제공하여 프로그래밍 언어가

   DOM 구조에 접근할 수 있는 방법을 제공하여, 문서구조, 스타일, 내용 등을 변경할 수 있게 도움

 

이러한 HTML요소들이 들어있는 HTML 문서를 렌더링 엔진이 파싱하여

다음과 같이 노드객체로 구성된 트리 구조를 가진 DOM을 생성함

 

이처럼 DOM은 노드 객체의 계층적인 구조로 구성됨, 노트 객체는 각각 종류가 있고 상속 구조를 가짐

 

이 중 가장 중요한 노드타입 4가지에 대해서 알아볼 것임

 

 

1) 문서노드 (document node)

- DOM 트리의 최상위에 존재하는 루트 노드로서 document 객체를 가리킴

- HTML 문서당 document 객체는 유일함

- DOM 트리의 루트 노드이므로 DOM 트리의 노드들에 접근하기 위한 진입점 역할을 함

- 즉, 요소, 어트리뷰트, 텍스트 노드에 접근하려면 문서 노드를 통해야 함

 

2) 요소노드 (element node)

- HTML 요소를 가리키는 객체

- HTML 요소 간의 중첩에 의해 부자관계를 가지며, 이 부자관계를 통해 정보를 구조화함

- 즉 , 요소노드는 문서의 구조로 표현함

 

3) 어트리뷰트노드 (atrribute node)

- HTML 요소으 어트리뷰트를 가르키는 객체임

- 어트리뷰트노드는 지정된 HTML 요소의 요소 노드와 형제 관계를 가짐 (but 부모노드와는 연결 x) 

- 어트리뷰트노드에 접근하여 어트리뷰트를 참조하거나 변경하려면 먼저 형제 노드인 요소노드에 접근해야함

 

 

4) 텍스트노드 (text node)

- HTML 요소의 텍스트를 가리키는 객체임

- 문서의 정보를 표현함

- 텍스트노드는 요소노드의 자식노드이며, 자식노드를 가질 수 없는 노드임

- 텍스트노드에 접근하려면 먼저 부모노드만 요소노드에 접근해야함

- 자식을 가질 수 없기 때문에 DOM 트리의 최종단

 

 

노드객체도 자바스크립트객체 임으로 프로토타입에 의한 상수 구조를 가짐

노드 객체의 상속 구조

EventTarget - 이벤트와 관련된,

                       예를 들어 addEventListener와 removerEventListener와 같은 기능을 제공함

                       따라서 사실상 모든 HTML요소에 addEventListener를 추가할 수 있음

 

Node(인터페이스) - parent 노드나 child 노드 등과 같은 노드 관련 기능은 노드 인터페이스에서 제공함

                             

input 요소 노드 객체의 특성을 예로 들은 설명
상속확인

 

 

 

3. DOM API

- DOM은 브라우저에서 제공하는 API 중 하나

- DOM API를 이용해 자바스크립트로 웹 페이지를 동적으로 조작할 수 있음

- 대표적인 DOM API : document.querySelector()

                                    Node.appendChild()

                                    Node.removeChilde()

 

 

DOM API 노드 취득

노드취득 메서드

- getElement로 시작하는 둘은 html 컬렉션을 말하고 

  querySelecAll은 노드 리스트를 반환함

 

- 컬렉션과 노드리스트의 공통점은 DOM API가 여러개의 결과값을 반환하기 위한 DOM 컬렉션 객체라는 것

 

- 또한 이들은 유사배열객체 이면서 이터러블

  유사배열객체: length를 가지고 있어서 인덱싱을 할 수 있고 for문을 사용할 수 있음

  이터러블 :for of 반복문을 사용할 수 있고, 스프레드 연산자를 사용할 수 있으며 배열 디스트럭처링 할 수 있음

  그러나, 배열이 아닌 유사배열이기 때문에 둘 다 배열에서 제공하는 Map, filter, reduce와 같은 메소드 사용이 불가능함

 

- html 컬렉션은 노드객체 상태를 실시간으로 반영하는 라이브객체임

  알아서 노드를 취득한 후에도 DOM이 변경되면 자동으로 값을 변경해줌

  반면, NodeList는 특별한 상황을 제외하면 대부분의 경우 과거 정적인 상태를 유지하는 Non-live 객체임

 

- html 컬렉션은 forEach를 사용할 수가 없지만, 

  Node-List의 경우 Node List 프로토타입이 forEach를 지원하기 때문에 사용할 수 있음

 

- 중요한 점은 둘 다 for문을 사용해서 반복문을 수행할 수 있지만,

  노드객체의 상태변경과 상관없이 안전하게 DOM 컬렉션을 사용하려면,

  둘 다 객체를 스프레드연산자를 통해 배열로 변환하여 사용하는 것이 좋음

  ==> 배열이 제공하는 다양한 메소드를 사용할 수 있어서 좋음

 

 

DOM API 노드 추가

 

✔ innerHTML

장점

- 쉽고 간단하게 새로운 요소를 추가할 수 있다

단점

- 기존 요소노드의 모든 자식노드를 제거하고 할당한 HTML 마크업 문자열을 파싱하여 DOM을 변경함

- 요소와 요소 사이에 새로운 요소를 삽입하기 어려움

- 크로스 사이트 스크립팅 공격에 취약함

innerHTML 사용법 , 상이 아닌 하로 해야 처리시간 빠름, 변수를 만들어서..

insertAdjacentHTML

장점

- 기존 요소를 제거하지 않으면서 위치를 지정해 추가 가능

- 기존 자식을 모두 제거하고 자식을 새로 생성하는 innerHTML보다 빠름

 

단점

- 크로스 사이트 스크립팅 공격에 취약함

 

insertAdjacentHTML 성능차이

 

 

appendChile

장점

- 기존요소를 제거하지 않으면서 위치를 지정해 추가 가능함

- innerHTML과 insertAdjacenHTML과 비교하여 보안이슈가 없음

 

단점

- 자식 노드를 생성해야함

appendChile 성능

 

속도 : insertAdjacentHTML & appendChile

편의성 : insertAdjacentHTML

보안성 : appendChile

== DOM 조작을 최소화는 성능향상과 연관이 있다.

 

 

 

4. 렌더링 과정

 

렌더링과정

- 브라우저의 랜더링 엔진은 클라이언트가 서버로부터 요청한 HTML부터 순차적으로 파싱하며 DOM을 생성해 나감

 

- 이 때 렌더링 엔진은 DOM을 생성해 나가다가

 

- CSS를 로드하는 링크태그나 스타일태그를 만나면 CSSOM을 생성하게됨

 

- CSSOM은 DOM과 비슷한 트리 구조의 오브젝트 모델임

 

- UCSS 파싱을 완료하면 HTML 파싱이 중단된 지점부터 다시 HTML을 파싱하기 때문에 DOM 생성을 재개함

 

- DOM과 CSS생성이 끝나면 이 둘을 합쳐 랜더트리를 구성

 

- 랜더트리는 랜더링을 위한 트리구조이기 때문에 랜더링에 포함되지 않는 노드들 

  예를 들어 metaTag, scriptTag, CSS, 즉 디스플레이 등과 같은 것들은 제외하고 구성이 됨

 

- CSS 파싱 과정과 마찬가지로 렌더링 엔진은 HTML을 한줄씩 순차적으로 파싱하며

  DOM을 생산하다가 스크립트 태그를 만나면 DOM 생성을 일시중단함

 

- 브라우저는 자바 스크립트 코드를 실행하기 위해 렌더링엔진에서부터 자바스크립트 에닌으로

  제어권을 넘김, 이후 자바 스크립트 파싱과 실행이 종료되면

 

- 렌더링 엔진으로부터 다시 제어권을 넘겨 HTML파싱이 중단된 지점부터 DOM을 생성함

 

- 만약 자바스크립트코드에 의해 DOM이나 CSSOM이 이용되는 경우 DOM과 CSSOM을 다시 랜더 트리로 결합하고

  이를 기반으로 레이아웃과 패인트 과정을 거쳐 브라우저화면에 랜더링 되게 됨

  ==> 이를 리플로우와 리페인트라고 함

 

- CSS의 경우에서 알 수 있듯이 브라우저는 동기적으로

  즉, 위에서 아래 방향으로 순차적으로 HTML과 CSS, 자바스크립트를 파싱하고 실행함

  ==> 스크립트태그 위치에 따라 HTML파싱이 중단되어 DOM 생성이 지연될 수 있다는 것을 의미함

 

- 따라서 스크립트 태그의 위치는 중요한 의미를 가짐

 

- CSS관련 태그의 경우 상단에 위치하여 있음

   : 사용자가 흰 화면을 응시하는 시간을 줄이기 위해 (CSS는 렌더링 차단 리소스로 취급됨)

     Link를 이용하여 스타일시트를 다운받는 경우 최대한 빠르게 다운받기 위해

      => 브라우저는 모든 외부스타일시트가 다운로드 후 CSSOM트리가 구성될 때 까지 웹 페이지 렌더링을 차단

 

- 스크립트의 경우 하단에 위치함

   : HTML 파서는 script 태그를 만나면 파싱을 멈추고 스크립트를 읽기 때문에 웹페이지의 로딩이 그만큼 늦춰질 수 있음

     생성되지 않은 DOM노드를 읽거나 조작하는 것이 불가능하기 때문에 예상치 못한 오류가 발생할 수 있음

스크립트를 하단에 위치하는 이유

왼쪽의 경우처럼 스크립트 태그가 먼저 있어서 아직 DOM생성이 미처 완료되지 않은 상태인데, 

DOM을 호출하는 경우에 찾지 못한다는 것을 볼 수 있음

반면 오른쪽 코드는 DOM이 생성된 이후여서 정상적으로 노드요소를 확인하는 것을 볼 수 있음

 

 

 

5. 렌더링의 문제점

- 동적 UI관리에 약함

     ==> DOM 트리가 수정될 때마다 새로운 렌더트리와 레이아웃을 생성하고 Repaint함

- 단 하나의 요소가 바뀌어도 전체 페이지 정보를 갱신함

- 하나의 페이지에서 많은 동작이 이루어지는 SPA(Single Page Application)에서 비효율적임

 

이러한 문제를 개선하고자 등장한 것이 Virtual DOM

 

 

6. Virtual DOM

- 이전 DOM과 가상 DOM에 있는 내용을 비교하여 바뀐 부분만 실제 DOM에 적용함

- React에서는 변경된 부분 (diff)만을 계산하여 실제 DOM에 적용함

  ==> 결과적으로 브라우저는 불필요한 렌더링 횟수를 줄이고 한번만 렌더링 할 수 있음

 

 

 

7. BOM (Browser Object Model)

- 웹 브라우저 환경의 다양한 기능을 객체처럼 다루는 모델

- 대부분의 브라우저에서 구현되어 있지만, 정의된 표준이 없어 브라우저마다 세부사항이 다름

- Window 객체는 자바스크립트의 최상위 객체이다 전역객체이면서 모든 객체가 소속된 객체

- var 키워드로 선언한 일반 변수도 모두 window 객체의 속성이 됨

- 최상위 객체이기 때문에 생략이 가능

var 키워드로 선언한 일반 변수도 모두 window 객체의 속성이 됨,                                                        최상위 객체이기 때문에 생략이 가능

 

BOM의 대표적인 객체

 

- document 객체는 DOM 트리의 최상단 객체

  따라서 DOM은 BOM에 포함되는 관계임

  때문에 DOM api를 통해 노드 요소를 불러올 때 window.를 앞에 붙여도 정상적으로 실행되는 것을 확인할 수 있음

 

 

 

출처: https://www.youtube.com/watch?v=q1fQnGG1bgU