DOM
은 문서 객체 모델로 HTML, XML 문서의 프로그래밍 인터페이스다. DOM
은 문서의 구조화된 표현을 제공하고 프로그래밍 언어가 DOM
구조에 접근할 수 있는 방법을 제공하여 문서의 구조, 스타일, 내용 등을 변경할 수 있게 한다.
현실에 있는 것을 특정 관점에서 보아 객체로 만드는 것을
추상화
또는모델링
이라고 한다.
이러한 과정을 거쳐 만들어진 객체는모델
이라고 부른다.
먼저 DOM은 JavaScript가 탄생하면서 같이 등장했다. 초창기에는 접근 가능한 태그도 많지 않았고 불편한 점도 많았지만 그에 따라 점차 발전하여 HTML 문서를 직접 수정까지 가능하게 되었다.
DOM트리
의 시작점은 document
로 문서 노드에 속한다.
문서 노드
는 최상위 노드로 모든 노드에 접근하기 위해서는 문서 노드를 통해야한다.
요소 노드
는 HTML태그 그 자체를 나타낸다. HTML 문서 구조를 그대로 표현한다고 할 수 있다.
또한 속성 노드
, 텍스트 노드
에 접근하려면 이 노드를 찾아야한다.
속성 노드
는 요소 노드
에 붙어있는 노드이고 태그에 정의되어 있는 속성을 나타낸다. 붙어있다고해서 자식 노드가 아님을 명심하자.
텍스트 노드
는 요소의 텍스트를 표현하고 자식 노드를 가질 수 없다. -> DOM Tree의 단말 노드
DOM Tree가 화면에 출력되는 과정을 알아보자
HTML
을 읽고 파싱한 후 DOM Tree
를 구성한다.Style Sheets
를 파싱하여 Style Rules
를 만들어 DOM 요소에 스타일을 입힌다.Attachment
라고 한다.Layout
을 통해 DOM 노드의 위치를 정해 Render Tree
를 만든다.Render Tree
가 완성되면 이 트리를 통해 실제 화면에 그린다.DOM
또는 Style
이 수정되면 이 프로세스를 다시 반복한다.<!DOCTYPE html>
<html>
<head></head>
<body>
<div>
<span class="span">Span1</span>
</div>
<div>
<span class="span">Span2</span>
</div>
<ul>
<li id="unique" class="list">list1</li>
<li class="list">list2</li>
<li class="list">list3</li>
</ul>
<p>Paragraph</p>
</body>
</html>
getElementById
DOM Tree에서 요소 노드를 id로 찾아 제일 먼저 찾은 요소 하나를 반환한다.
getElementsByClassName
DOM Tree에서 요소 노드를 class로 찾는다. 일치하는 모든 요소를 반환한다.
getElementsByTagName
DOM Tree에서 요소 노드를 태그 이름으로 찾는다. 일치하는 모든 요소를 반환한다.
querySelector
DOM Tree에서 요소 노드를 CSS Selector 문법으로 찾는다. 제일 먼저 찾은 요소 하나를 반환한다.
querySelectorAll
DOM Tree에서 요소 노드를 CSS Selector 문법으로 찾는다. 일치하는 모든 요소를 반환한다.
window.[id]
id가 있는 요소는 window 객체를 통해 찾을 수 있다. 여러개라면 리스트로 반환된다.
parentNode
선택한 요소 노드의 부모 노드를 불러온다. document는 최상위 노드이기 때문에 부모 노드는 null이다.
firstElementNode
선택한 요소 노드의 자식 요소 노드 중 첫 번째를 불러온다. 없을 경우 null을 반환한다. lastElementNode
도 사용 가능하다.
children
선택한 요소 노드의 자식 요소 노드를 불러온다. 없을 경우 빈 배열을 반환한다.
nextElementSibling
선택한 요소 노드의 다음 형제 요소 노드를 불러온다. 없을 경우 null을 반환한다.
previousElementSibling
선택한 요소 노드의 이전 형제 요소 노드를 불러온다. 없을 경우 null을 반환한다.
class 접근
선택한 요소 노드에서 className과 classList로 요소의 class 속성을 불러오고 변경할 수 있다.
hasAttribute
선택한 요소 노드에서 속성을 가지는지 확인 가능하다.
getAttribute
선택한 요소 노드에서 속성 값을 반환한다. 없다면 null을 반환한다.
setAttribute
선택한 요소 노드에서 속성을 정의한다.
removeAttribute
선택한 요소 노드에서 속성을 제거한다.
textContent
선택한 요소 노드에서 텍스트 노드에 접근하여 변경할 수 있다.
innerHTML
선택한 요소 노드 내부 HTML을 수정한다. XSS위험이 있다.
XSS(Cross Site Scripting)
웹 해킹 공격 중 하나로 게시판이나 웹 메일 등에 스크립트 코드를 삽입해 개발자가 구현하지 않은 기능이 작동하게 하는 치명적일 수 있는 공격이다.
createElement
요소 노드를 생성할 수 있다.
appendChild
선택한 요소 노드 마지막 자식 요소로 추가한다.
removeChild
선택한 요소 노드 자식 노드 중 해당하는 요소를 제거한다.
만약 여러개의 DOM 객체를 수정한다면 어떤 일이 발생할까?
예를 들어 100개의 DOM을 수정하면 최악의 경우 100번의 레이아웃과 렌더링을 하게된다.
이러한 경우 Virtual DOM
을 사용한다. 개발자가 코드를 하나하나 최적화 하는것은 쉽지 않고 대규모 어플리케이션의 경우 더욱 그렇다. virtual DOM
은 실제DOM Tree
를 자바스크립트 객체로 만든것으로 필요한 정보만 담아 만들어진다.
Event
나 DOM
이 수정되는 짧은 순간에 DOM
을 직접 수정하지 않고 virtual DOM
을 바뀐 부분만 수정한후 렌더링하면 브라우저 렌더링 프로세스가 줄어든다.
우리가 주로 사용하는 React.js
, Vue.js
가 virtual DOM
을 사용하고있다.
React 핵심 개발자에 따르면 React는 DOM보다 빠르다는 것은 미신일 뿐이고 유지보수에 용이한 애플리케이션을 만들도록 도와주고 대부분의 유스케이스에 충분히 빠를 뿐이라고 언급했다.
이는 페이지에 그려지는 DOM이 많을수록 느려지는 것은 같다는 뜻이다. 왜냐하면 (virtual DOM, DOM) 이 두가지를 탐색 해야하기 때문이다.
브라우저 렌더링 횟수를 줄여줄뿐 실제로는 더 느림
메모리도 그 만큼 더 사용하게 된다.
하지만, 일반적인 웹사이트에서 그정도의 성능 저하가 문제되는 경우는 드물고 빠른 개발을 위해 성능 최적화
보다 개발 편의성
이 더 중요할때가 많다. 그래서 virtual DOM
을 많이 사용한다.