📌 [모던 자바스크립트 13주 뿌시기] 39. DOM
![](/assets/img/JavaScript/2022-11-10/bookcover.png)
39. DOM
DOM
은 HTML 문서의 계층적 구조와 정보를 표현하며 이를 제어할 수 있는 API, 즉 프로퍼티와 메서드를 제공하는 트리 자료구조이다.
노드
HTML 요소와 노드 객체
HTML 문서를 구성하는 개별적인 요소를 의미
<div class="box">hello</div>
<div>
: 시작태그
class
: 어트리뷰트
box
: class라는 어트리뷰트의 값
hello
: 콘텐츠
</div>
: 종료태그
HTML 요소는 렌더링 엔진에 의해 파싱되어 DOM을 구성하는 요소 노드 객체로 변환된다.
어트리뷰트 > 어트리뷰트 노드
HTML 요소의 콘텐츠 > 텍스트 노드
HTML 요소는 중첩 관계에 의해 계층적인 부자관계가 형성되고 이러한 관계를 반영한 모든 노드 객체들을 트리 자료로 구성한다.
트리 자료구조란?
- 노드들의 계층 구조로 이루어진 자료구조이다.
- 부모와 자식 노드로 계층적 구조를 표현하는 비선형 자료구조이다.
- 하나의 최상위 노드에서 시작한다.
- 최상위 노드는 부모 노드가 없고 루트 노드라고 부르기도 한다.
- 자식 노드가 없는 노드는 리프 노드라고 한다.
정리하자면 DOM
은 노드 객체의 트리로 구조화되어 있기 때문에 DOM 트리
라고 부르기도 한다.
노드 객체의 타입
노드 객체는 12가지의 종류가 있고 상속 구조를 갖는다. 아래에는 12가지 타입 중 중요한 4가지에 대해 기술했다.
문서 노드
- DOM 트리 최상위에 존재하는 루트 노드이며
document
객체를 가리킴 document
는 HTML 문서 전체를 가리킴, 따라서 문서 노드는document
로 참조 가능.document
는 DOM 트리의 루트 노드이다. 따라서document
는 DOM 트리에 접근하기 위한 진입점과 같다.- HTML 문서당
document
객체는 유일하다.
요소 노드
- HTML 요소를 가리키는 객체
- 문서의 구조를 표현한다.
어트리뷰트 노드
- HTML 요소의 어트리뷰트를 가리키는 객체
- 어트리뷰트 노드는 부모 노드와 연결된 것이 아닌, 요소 노드에 연결되어 있다.
- 어트리뷰트 노드에 접근하기 위해서는 먼저 요소 노드에 접근해야 한다.
텍스트 노드
- HTML 요소의 텍스트를 가리키는 객체
- 문서의 정보를 표현한다.
- 요소 노드의 자식 노드이다.
- 자식 노드가 없는 리프 노드이다. 그러므로 DOM 트리의 최종단이다.
- 테긋트 노드에 접근하기 위해스는 먼저 요소 노드에 접근해야 한다.
노드 객체의 상속 구조
DOM은 HTML 문서를 제어할 수 있는 API(프로퍼티, 메서드)를 제공한다.
API를 통해 노드의 부모, 형제, 자식을 탐색하고 어트리뷰트와 텍스트를 조작할 수 있다.
DOM 노드 객체는 표준 빌트인 객체가 아닌 브라우저 환경에서 추가적으로 제공하는 호스트 객체이지만, JavaScript 객체이므로 프로토타입에 의한 상속 구조를 가진다.
공통된 기능일수록 프토로타입 체인 상위에 위치하고 개별적인 고유 기능인 경우에는 프로토타입 체인 하위에 위치하여 필요한 기능을 제공한다.
정리하자면 DOM은 HTML 문서의 계층적 구조와 정보를 노드로 표현하고 이를 프로퍼티와 메서드의 집합인 DOM API로 제공한다. DOM API를 사용하여 HTML 구조와 내용, 스타일 등을 동적으로 조작할 수 있다.
요소 노드 취득
HTML을 조작하기 위해서는 요소 노드를 취득하는 과정이 필요하다.
id를 이용한 요소 노드 취득
Document.prototype.getElementById
메서드는 인수로 전달한 id 어트리뷰트 값을 갖는 하나의 요소 노드를 탐색하여 반환한다.
id 값은 HTML 문서 내에서 유일한 값이어야 한다.
그러나 중복된 id 값을 가져도 에러가 발생하지 않으므로 중복된 id 값을 가지는 요소가 여러 개 존재할 수 있다.
id가 중복된 값이 여러 개 존재할 경우, Document.prototype.getElementById
메서드는 해당 id 값을 가지는 첫 번째 요소 노드만 반환한다.
<body>
<ul>
<li id="banana">Apple</li>
<li id="banana">Banana</li>
<li id="banana">Orange</li>
</ul>
<script>
const banana = document.getElementById('banana'); // 첫 번째 li 요소가 반환된다.
const isNull = document.getElementById('test'); // 요소가 존재하지 않는 경우, null 반환
</script>
</body>
HTML 요소에 id 어트리뷰트를 부여하면 id 값과 동일한 이름의 전역 변수가 선언되고 해당 노드 객체가 할당된다.
그러나 id 값과 동일한 변수가 이미 선언되어 있는 경우에는 재할당되지 않는다.
<body>
<div id="boxId"></div>
<script>
const test = document.getElementById('boxId');
console.log(boxId === test); // true
delete boxId;
console.log(boxId); // <div id="boxId"></div>
</script>
</body>
태그 이름을 이용한 요소 노드 취득
Document.prototype/Element.prototype.getElementsByTagName
메서드는 모든 요소 노드를 탐색하여 반환한다.
여러 개의 요소 노드 객체를 갖는 DOM 컬렉션 객체인 HTMLCollectiom
객체를 반환한다.
여러 개의 값을 반환받기 위해서는 배열이나 객체와 같은 자료구조에 담아 반환되므로 getElementsByTagName
메서드가 반환하는 HTMLCollectiom
객체는 유사 배열 객체이며 이터러블이다.
모든 요소를 취득하기 위해서는 인수로 *
를 전달하면 된다.
const $all = document.getElementsByTagName('*');
인수로 전돨된 태그 이름을 갖는 요소가 없는 경우 빈 HTMLCollection
객체를 반환한다.
class를 이용한 요소 노드 취득
Document.prototype/Element.prototype.getElementsByClassName
메서드는 인수로 전달한 class 어트리뷰트 값을 갖는 모든 요소 노드를 탐색하여 반환한다.
getElementsByTagName
와 동일하게 여러 개의 요소 노드 객체를 갖는 DOM 컬렉션 객체인 HTMLCollectiom
객체를 반환한다.
인수로 전돨된 태그 이름을 갖는 요소가 없는 경우 빈 HTMLCollection
객체를 반환한다.
CSS 선택자를 이용한 요소 노드 취득
Document.prototype/Element.prototype.querySelector
메서드는 인수로 전달한 CSS 선택자를 만족시키는 하나의 요소 노드를 탐색하여 반환한다.
- 인수로 전달한 CSS 선택자를 만족시키는 요소 노드가 여러 개인 경우 첫 번째 요소만 반환한다.
- 인수로 전달한 CSS 선택자를 만족시키는 요소 노드가 존재하지 않는 경우 null을 반환한다.
- 인수로 전달한 CSS 선택자가 문법에 맞지 않는 경우
DOMException
에러가 발생한다.
Document.prototype/Element.prototype.querySelectorAll
메서드는 인수로 전달한 CSS 선택자를 만족시키는 모든 요소 노드를 탐색하여 반환한다.
여러 개의 요소 노드 객체를 갖는 DOM 컬렉션 객체인 NodeList
객체를 반환한다. 이는 유사 배열 객체이며 이터러블이다.
- 인수로 전달한 CSS 선택자를 만족시키는 요소 노드가 존재하지 않는 경우 빈 NodeList 객체를 반환한다.
- 인수로 전달한 CSS 선택자가 문법에 맞지 않는 경우
DOMException
에러가 발생한다.
그래서 뭘 쓰는게 좋은지?
속도: getElementById
, getElementBy***
> querySelector
, querySelectorAll
편의성: getElementById
, getElementBy***
< querySelector
, querySelectorAll
id 어트리뷰트가 있는 요소 노드를 취득하는 경우는 getElementById
를 쓰되, 그 외의 경우는 querySelector
, querySelectorAll
를 사용하는 것을 권장한다.
특정 노드를 취득할 수 있는지 확인하는 방법
Element.prototype.matches
메서드는 인수로 전달한 CSS 선택자를 통해 특정 요소를 취득할 수 있는지 확인한다.
HTMLCollection과 NodeList
HTMLCollection
과NodeList
는 DOM 컬렉션 객체로, 유사 배열 객체이며 이터러블이다.for ... of
문법으로 순회가 가능하며 스프레드 문법을 통해 간단하게 배열로 변환할 수 있다.HTMLCollection
과NodeList
는 실시간성을 띄는 객체이다. 단,NodeList
는 대부분의 경우 실시간으로 반영하지 않고 과거의 정적 상태를 유지하는 non-live 객체로 동작한다.
live 객체로 동작하는 특성은 개발자의 예상과 다르게 동작할 수 있기 때문에 HTMLCollection
이나 NodeList
객체를 배열로 변환하여 사용하는 것을 권장한다.
두 객체 모두 유사 배열 객체이면서 이터러블이기 때문에 스프레드 문법이나 Array.from
메서드를 사용하여 간단히 배열로 변환할 수 있다.
노드 탐색
요소 노드를 취득한 후, 취득한 요소 노드를 기점으로 DOM 트리를 재탐색할 수 있다.
DOM 트리 상의 노드를 탐색할 수 있도록 Node
, Element
인터페이스는 트리 탐색 프로퍼티를 제공한다.
![](/assets/img/JavaScript/2023-02-04/DomNavigation.png)
노드 탐색 프로퍼티는 모두 접근자 프로퍼티지만 setter
없이 getter
만 존재하여 참조만 가능한 읽기 전용 접근자 프로퍼티다.
공백 텍스트 노드
HTML 요소 사이의 스페이스, 탭, 줄바꿈(개행) 등의 공백 문자는 텍스트 노드를 생성한다. 이를 공백 텍스트 노드라 한다.
공백 텍스트 노드를 의식하고 노드를 탐색할 때 주의하여야 한다.
자식 노드 탐색
Node.prototype.childNodes
: 자식 노드를 모두 탐색하여 NodeList
에 담아 반환한다. NodeList
는 텍스트 노드도 포함되어 있을 수 있다.
Element.prototype.children
: 자식 노드 중에서 요소 노드만 모두 탐색하여 HTMLCollection
에 담아 반환한다. 텍스트 노드가 포함되지 않는다.
Node.prototype.firstChild
: 첫 번째 자식 노드를 반환한다. Node.prototype.lastChild
: 마지막 자식 노드를 반환한다.
Element.prototype.firstElementChild
: 첫 번째 자식 요소 노드를 반환한다. Element.prototype.lastElementChild
: 마지막 자식 요소 노드를 반환한다.
자식 노드 존재 확인
Node.prototype.hasChildNodes
메서드를 사용하여 자식 노드가 존재하면 true
, 자식 노드가 존재하지 않으면 false
를 반환받을 수 있다.
이는 텍스트 노드를 포함하여 자식 노드의 존재를 확인하는데, 텍스트 노드가 아닌 요소 노드가 존재하는지 확인하려면 children.length
혹은 childElementCount
를 사용하면 된다.
요소 노드의 텍스트 노드 탐색
요소 노드의 텍스트 노드는 요소 노드의 자식 노드기 때문에 firstChild
프로퍼티로 접근할 수 있다.
firstChild
프로퍼티는 첫 번째 자식 노드를 반환한다.
부모 노드 탐색
Node.prototype.parentNode
를 통해 부모 노드를 탐색할 수 있다.
텍스트 노드는 DOM 트리의 최종단 리프 노드이므로 부모 노드인 경우는 없다.
형제 노드 탐색
Node.prototype.previousSibling
: 부모 노드가 같은 형제 노드중에서 자신의 이전 형제 노드를 탐색하여 반환한다. 이는 요소 노드거나 텍스트 노드일 수 있다.
Node.prototype.nextSibling
: 부모 노드가 같은 형제 노드중에서 자신의 다음 형제 노드를 탐색하여 반환한다. 이는 요소 노드거나 텍스트 노드일 수 있다.
Element.prototype.previousElementSibling
: 부모 노드가 같은 형제 요소 노드 중에서 자신의 이전 형제 요소 노드를 탐색하여 반환한다. 요소 노드만 반환한다.
Element.prototype.nextElementSibling
: 부모 노드가 같은 형제 요소 노드 중에서 자신의 다음 형제 요소 노드를 탐색하여 반환한다. 요소 노드만 반환한다.
노드 정보 취득
다음은 노드 객체에 대한 정보를 취득하기 위한 프로퍼티이다.
Node.prototype.nodeType
: 노드 객체의 종류, 즉 노드 타입을 나타내는 상수를 반환한다.
- Node.ELEMENT_NODE: 노드 타입을 나타내는 상수 1을 반환
- Node.TEXT_NODE: 노드 타입을 나타내는 상수 3을 반환
- Node.DOCUMENT_NODE: 노드 타입을 나타내는 상수 9를 반환
Node.prototype.nodeName
: 노드의 이름을 문자열로 반환한다.
- 요소 노드: 대문자 문자열로 태그 이름(
UL
,LI
등)을 반환 - 텍스트 노드: 문자열
#text
를 반환 - 문서 노드: 문자열
#document
를 반환
요소 노드의 텍스트 조작
nodeValue
Node.prototype.nodeValue
프로퍼티는 setter
와 getter
모두 존재하는 접근자 프로퍼티다.
nodeValue
프로퍼티를 참조하는 경우 노드 객체의 값을 반환한다.
노드 객체의 값 = 텍스트 노드의 텍스트
<body>
<div id="foo">Hello</div>
<script>
// 문서 노드의 nodeValue 프로퍼티를 참조한다.
console.log(document.nodeValue); // null
// 요소 노드의 nodeValue 프로퍼티를 참조한다.
const $foo = document.getElementById('foo');
console.log($foo.nodeValue); // null
// 텍스트 노드의 nodeValue 프로퍼티를 참조한다.
const $textNode = $foo.firstChild;
console.log($textNode.nodeValue); // Hello
</script>
</body>
요소 노드의 텍스트를 변경하는 방법
- 텍스트를 변경할 요소 노드를 취득한 후 취득한 요소 노드의 텍스트 노드를 탐색한다. 텍스트 노드는 요소 노드의 자식 노드이므로
firstChild
프로퍼티를 사용하여 탐색한다. - 탐색한 텍스트 노드의
nodeValue
프로퍼티를 사용하여 텍스트 노드의 값을 변경한다.
textContent
Node.prototype.textContent
프로퍼티는 setter
와 getter
모두 존재하는 접근자 프로퍼티다.
요소 노드의 텍스트와 모든 자손 노드의 텍스트를 모두 취극하거나 변경한다.
요소 노드의 textContent
프로퍼티를 참조하면 요소 노드의 콘텐츠 영역 내의 태그를 모두 반환한다.
nodeValue
와 textContent
, 둘 다 텍스트를 취득할 수 있지만 노드의 nodeValue
프로퍼티는 null
을 반환하고 텍스트 노드의 nodeValue
프로퍼티를 참조할 때만 텍스트 노드의 값을 반환한다.
innerText
는 textContent
프로퍼티와 유사한 동작을 하지만, 아래와 같은 이유로 사용하지 않는 것이 좋다.
- CSS에 영향을 받는다. 즉,
visibility
가hidden
인 요소는 텍스트를 반환하지 않는다. - CSS에 영향을 받기 때문에
textContent
보다 속도가 느리다.
DOM 조작
DOM 조작: 새로운 노드를 생성하여 DOM에 추가하거나 기존 노드를 삭제 또는 교체하는 것
삭제, 교체 과정에서 리플로우와 리페인트가 발생하므로 성능 저하에 영향을 주므로 주의해야 한다.
innerHTML
getter
,setter
모두 존재하는 접근자 프로퍼티다.- innerHTML 프로퍼티를 참조하면 요소 노드의 콘텐츠 영역 내에 포함된 모든 HTML 마크업을 문자열로 반환한다.
- innerHTML 프로퍼티에 문자열을 할당하면 기존 모든 자식 노드가 삭제되고 할당한 문자열에 포함된 HTML 마크업이 파싱되어 DOM에 반영된다.
- 이는 크로스 사이트 스크립팅 공격(XSS)에 취약하다는 단점이 있다.
insertAdjacentHTML 메서드
Element.prototype.insertAdjacentHTML(position, DOMString)
메서드는 기존 요소를 제거하지 않으면서 위치를 지정해 새로운 요소를 삽입한다.
첫 번째 인수를 통해 위치를 설정하고 두 번째 인수를 통해 HTML 마크업 문자열을 전달하여 DOM에 반영한다.
다음은 첫 번째 인수로 위치를 설정할 수 있는 문자열이다.
beforebegin
, afterbegin
, beforeend
, afterend
{beforebegin}<div>{afterbegin}content{beforeend}</div>{afterend}
innerHTML
과 마찬가지로 크로스 사이트 스크립팅 공격에 취약하다.
노드 생성과 추가
요소 노드 생성
Document.prototype.createElement(tagName)
메서드는 요소 노드를 생성하여 반환한다.
매개변수에는 태그 이름을 나타내는 문자열을 전달한다.
DOM에 추가되지는 않지만 요소 노드를 생성한다. DOM에 추가하고 싶다면 별도의 처리가 필요하다.
텍스트 노드 생성
Document.prototype.createTextNode(text)
메서드는 텍스트 노드를 생성하여 반환한다.
매개변수에는 텍스트 노드의 값으로 사용할 문자열 전달한다.
createElement
와 마찬가지로 텍스트 노드를 생성하지만 요소 노드에 추가하지는 않는다.
텍스트 노드를 요소 노드의 자식 노드로 추가
Node.prototype.appendChild(childNode)
메서드는 매개변수 childNode
에게 인수로 전달한 노드를 appendChild
메서드를 호출한 노드의 마지막 자식 노드로 추가한다.
요소 노드를 DOM에 추가
Node.prototype.appendChild
메서드를 사용하여 위 과정에서 생성한 요소 노드를 DOM에 추가할 수 있다.
DOM에 추가하는 과정에서 리플로우와 리페인트가 실행된다.
복수의 노드 생성과 추가
여러 번 DOM을 변경하는 것보다 한 번에 변경하는 것이 성능 최적화에 좋기 때문에 복수의 노드를 추가할 때는 반복해서 DOM에 반영하는 것보다 복수의 노드를 한 번에 반영하는 것이 좋다.
이를 위해 DocumentFragment
노드를 통해 해결할 수 있는데 이는 문서, 요소, 어트리뷰트, 텍스트 노드와 같은 노드 객체의 일종으로 부모 노드가 없기 때문에 기존 DOM과는 별도로 존재한다는 특징이 있다.
즉, DocumentFragment
에 복수의 노드를 수정한 후 이를 DOM에 추가하면 단 한 번의 DOM 접근을 통해 수정할 수 있다.
노드 삽입
마지막 노드로 추가
Node.prototype.appendChild
메서드는 인수로 전달받은 노드를 자신을 호출한 노드의 마지막 자식 노드로 DOM에 추가한다.
지정한 위치에 노드 삽입
Node.prototype.insertBefore(newNode, childNode)
메서드는 첫 번째 인수로 전달받은 노드를 두 번째 인수로 전달받은 노드 앞에 삽입한다.
두 번째 인수로 전달받은 노드는 반드시 insertBefore
메서드를 호출한 노드의 자식 노드여야 한다.
이를 어길 경우, DOMException
에러가 발생한다.
노드 이동
DOM에 이미 존재하는 노드를 appendChild
혹은 insertBefore
메서드를 사용하여 DOM에 다시 추가할 경우 노드가 이동한다.
노드 복사
Node,prototype.cloneNode([deep: true | false])
메서드는 노드의 사본을 생성하여 반환한다.
true
나 false
를 인수로 전달하면 깊은 복사 혹은 얕은 복사 여부를 결정할 수 있다.
노드 교체
Node.prototype.replaceChild(newChild, oldChild)
메서드는 자신을 호출한 노드의 자식 노드를 다른 노드로 교체한다.
newChild
: 교체할 새로운 노드
oldChild
: 이미 존재하는 교체될 노드
즉, oldChild
노드를 newChild
노드로 교체하는 메서드다.
교체 후, oldChild
노드는 DOM에서 제거된다.
노드 삭제
Node.prototype.removeChild(child)
메서드는 child 매개변수에 인수로 전달한 노드를 DOM에서 삭제한다.
어트리뷰트
어트리뷰트 노드와 attributes 프로퍼티
요소는 여러 개의 어트리뷰트(속성)를 가질 수 있다.
HTML 문서가 파싱될 때 HTML 요소의 어트리뷰트는 어트리뷰트 노드로 변환되어 요소 노드와 연결되는데 이때 HTML 어트리뷰트 당 하나의 어트리뷰트 노드가 생성된다.
모든 어트리뷰트 노드의 참조는 NamedNodeMap
객체에 담겨 요소 노드의 attributes 프로퍼티에 저장된다.
어트리뷰트 노드 > 요소 노드의 Element.prototype.attributes
프로퍼티로 취득할 수 있다.
HTML 어트리뷰트 조작
attributes
프로퍼티는 getter
만 존재하는 읽기 전용 접근자 프로퍼티다.
Element.prototype.getAttribute/setAttribute
메서드를 통해 요소 노드에서 직접 HTML 어트리뷰트 값을 취득하거나 변경할 수 있다.
어트리뷰트 값을 참조하려면 getAttribute
를 사용하고 값을 변경하려면 setAttribute
를 사용하면 된다.
HTML 어트리뷰트 vs DOM 프로퍼티
HTML 어트리뷰트
- HTML 어트리뷰트의 역할은 HTML 요소의 초기 상태를 지정하는 것.
- HTML 어트리뷰트 값은 HTML 요소의 초기 상태를 의미하고 이는 변하지 않음.
- 요소 노드는 초기 상태와 최신 상태를 관리해야 하기 때문에 초기 상태는 어트리뷰트 노드가 관리하고 최신 상태는 DOM 프로퍼티가 관리한다.
DOM 프로퍼티
- 사용자가 입력한 최신 상태는 DOM 프로퍼티가 관리한다.
- DOM 프로퍼티는 사용자의 입력에 의한 상태 변화에 반응하여 언제나 최신 상태를 유지함
HTML 어트리뷰트, DOM 프로퍼티 대응관계
id
어트리뷰트와id
프로퍼티는 1:1 대응 및 동일한 값 연동input
요소의value
어트리뷰트(초기 상태)는value
프로퍼티(최신 상태)와 1:1 대응.class
어트리뷰트는className
,classList
와 대응for
어트리뷰트는htmlFor
프로퍼티와 1:1 대응td
요소의colspan
어트리뷰트는 대응하는 프로퍼티 존재 XtextContent
프로퍼티는 대응하는 어트리뷰트 존재 X- 어트리뷰트의 이름은 대소문자 구분 X, 프로퍼티 키는 카멜 케이스
data 어트리뷰트와 dataset 프로퍼티
data
어트리뷰트와 dataset
프로퍼티를 사용하면 HTML 요소에 정의한 사용자 정의 어트리뷰트와 자바스크립트 간 데이터를 교환할 수 있다.
data
어트리뷰트의 값은 HTMLElement.dataset
프로퍼티를 통해 취득 가능.
dataset
프로퍼티는 DOMStringMap
객체를 반환한다.
DOMStringMap
객체는 data
어트리뷰트의 data- 접두사 다음에 붙인 임의의 이름을 카멜 케이스로 변환한 프로퍼티를 가지고 있기 때문에 이를 통해 data
어트리뷰트의 값을 취득 및 변경할 수 있다.
스타일
인라인 스타일 조작
HTMLElement.prototype.style
프로퍼티는 setter
와 getter
모두 존재하는 접근자 프로퍼티이다.
요소 노드의 인라인 스타일을 취득/추가/변경한다.
style
프로퍼티를 참조할 경우, CSSStyleDeclaration
타입 객체를 반환한다.
CSSStyleDeclaration
객체의 프로퍼티는 카멜 케이스를 따른다.
클래스 조작
HTML 요소의 class
어트리뷰트를 조작하기 위해서는 class
어트리뷰트에 대응하는 요소 노드의 DOM 프로퍼티를 사용한다.
class
어트리뷰트에 대응하는 DOM 프로퍼티는 class
가 아닌 className
과 classList
이다.
요소에 적용되어 있는 CSS 스타일 참조
요소에 적용되어 있는 CSS 스타일 참조를 위해 getComputedStyle
메서드를 사용한다.
window.getComputedStyle(element[, pseudo])
메서드는 첫 번째 인수(element)로 전달한 요소 노드에 적용되어 있는 평가된 스타일을 CSSStyleDeclaration
객체에 담아 반환한다.
출처
위키북스, 『모던 자바스크립트 Deep Dive』, 이웅모
https://www.tutorialstonight.com/js/js-dom-navigation