일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | ||||
4 | 5 | 6 | 7 | 8 | 9 | 10 |
11 | 12 | 13 | 14 | 15 | 16 | 17 |
18 | 19 | 20 | 21 | 22 | 23 | 24 |
25 | 26 | 27 | 28 | 29 | 30 | 31 |
- React
- Flipper
- reactnative
- 타입스크립트
- ios
- Android
- 자바스크립트
- 자료구조와알고리즘
- slice
- react-hook-form
- react-native-vision-camera
- 크라코
- 모던자바스크립트
- 리액트
- 파스에러
- 유니온타입
- javascript
- 프로그래머스
- craco
- sort( )
- react-native-camera-roll
- react-native-image-picker
- Typescript
- 제네릭타입
- js
- 배열
- 코드숨
- 리액트네이티브
- react-native
- 리액트쿼리
- Today
- Total
KassyLog
[모던자바스크립트]Dom 본문
브라우저 렌더링 엔진은 HTML 문서를 파싱하여 브라우저가 이해할 수 있는 자료구조인 DOM을 생성한다.
DOM은 HTML 문서의 계층적 구조와 정보를 표현하며 이를 제어할 수 있는 API, 즉 프로퍼티와 메서드를 제공하는 트리 자료구조다.
HTML 요소와 노드 객체
HTML 요소는 HTML 문서를 구성하는 개별적인 요소를 의미한다.
HTML 요소는 렌더링 엔진에 의해 파싱되어 DOM을 구성하는 요소 노드 객체로 변환된다.
HTML 요소와 노드 객체
노드 객체들로 구성된 트리 자료구조를 DOM이라 한다. DOM 트리라고 부르기도 한다.
노드 객체의 상속 구조
DOM은 DOM을 제어할 수 있는 API, 즉 프로퍼티와 메서드를 제공하는 트리 자료구조이다.
DOM을 구성하는 노드 객체는 브라우저 환경에서 제공하는 호스트 객체다.
노드 객체도 자바스크립트 객체이므로 프로토타입에 의한 상속 구조를 갖는다. 노드 객체의 상속 구조는 다음과 같다.
노드 객체는 Object, EventTarget, Node 인터페이스를 상속받는다.
예를들어 input 요소 노드 객체를 보자. input 요소 노드 객체는 HTMLInputElement, HTMLEIement, Element, Node, EventTarget, Object의 prototype에 바인딩되어 있는 프로토타입 객체를 상속받는다.
즉 input 요소 노드 객체는 프로토타입 체인에 있는 모든 프로토타입의 프로퍼티나 메서드를 상속 받아 사용할 수 있다.
배열이 객체인 동시에 배열인 것처럼 input 요소 노드 객체도 다음과 같이 다양한 특성을 갖는 객체이며, 이러한 특성을 나타내는 기능들을 상속을 통해 제공받는다.
input 요소 노드 객체의 특성 | 프로토타입을 제공하는 객체 |
객체 | Object |
이벤트를 발생시키는 객체 | EventTarget |
트리 자료구조의 노드 객체 | Node |
브라우저가 렌더링할 수 있는 웹 문서의 요소(HTML, XML, SVG)를 표현하는 객체 | Element |
웹 문서의 요소 중에서 HTML 요소를 표현하는 객체 | HTMLElement |
HTML 요소 중에서 input 요소를 표현하는 객체 | HTMLInputElement |
정리하자면 DOM은 HTML 문서의 계층적 구조와 정보를 표현하는 것은 물론 노드 객체의 종류, 즉 노드 타입에 따라 필요한 기능을 프로퍼티와 메서드의 집합인 DOM API로 제공한다. 이 DOM API를 통해 HTML의 구조나 내용 또는 스타일 등을 동적으로 조작할 수 있다.
요소 노드 취득
HTML의 구조나 내용 또는 스타일 등을 동적으로 조작하려면 먼저 요소 노드를 취득해야 한다.
DOM은 요소 노드를 취득할 수 있는 다양한 메서드를 제공한다.
id를 이용한 요소 노드 취득
Document.prototype.getElementById 메서드는 인수로 전달한 id 어트리뷰트 값을 갖는 하나의
요소 노드를 탐색하여 반환한다. id값은 HTML 문서 내에서 유일한 값이어야 하지만,
여러 개 존재하더라도 에러가 발생하지 않기 때문에 관리를 잘 해야한다.
인수로 전달된 id값을 갖는 첫 번째 요소 노드가 반환한다. (id 값이 중복되더라도 첫 번째 id값만 반환)
요소가 존재하지 않는 경우 null을 반환한다.
태그 이름을 이용한 요소 노드 취득
Document.prototype/Element.prototype.getElementsByTagName 메서드는 인수로 전달한 태그 이름을 갖는 모든 요소 노드들을 탐색하여 반환한다.
getElementsByTagName 메서드가 반환하는 DOM 컬렉션 객체인 HTMLCollection 객체는 유사 배열 객체이면서 이터러블이다.
class를 이용한 요소 노드 취득
Document.prototype/Element.prototype.getElementsByClassName 메서드는 인수로 전달한 class 어트리뷰트 값을 갖는 모든 요소 노드들을 탐색하여 반환한다.
querySelector / querySelectorAll
Document.prototype/Element.prototype.querySelector 메서드는 인수로 전달한 CSS 선택자를 만족시키는 하나의 요소 노드를 탐색하여 반환한다.
Document.prototype/Element.prototype.querySelectorAll 메서드는 인수로 전달한 CSS 선택자를 만족시키는 모든 요소 노드를 탐색하여 반환한다. querySelectorAll 메서드는 여러 개의 요소 노드 객체를 갖는 DOM 컬렉션 객체인 NodeList 객체를 반환한다. NodeList 객체는 유사 배열 객체이면서 이터러블이다.
HTMLCollection과 NodeList
DOM 컬렉션 객체인 HTMLCollection과 NodeList는 DOM API가 여러 개의 결과값을 반환하기 위한
DOM 컬렉션 객체이다. HTMLCollection과 NodeList는 모두 유사 배열 객체이면서 이터러블이다.
따라서 for...of 문으로 순회할 수 있으며 스프레드 문법을 사용하여 간단히 배열로 변환할 수 있다.
HTMLCollection과 NodeList의 중요한 특징은 노드 객체의 상태 변화를 실시간으로 반영하여 살아 있는 객체라는 것이다.
HTMLCollection은 언제나 live 객체로 동작한다. NodeList는 특정 경우에만 live 객체로 동작한다.
HTMLCollection 객체는 실시간으로 노드 객체의 상태 변경을 반영하기 때문에 for 문 순회를 통해 상태를 변경할 때는 주의해야 한다.
또한 querySelectorAll이 반환하는 NideList 객체는 실시간으로 노드 객체의 상태 변경을 반영하지 않는 객체로 querySelectorAll을 활용하여 해결할 수도 있다.
하지만 childNodes 프로퍼티가 반환하는 NodeList 객체는 HTMLCollection 객체와 동일하게 실시간 객체로 동작하므로 주의가 필요하다.
따라서 노드 객체의 상태 변경과 상관없이 안전하게 DOM 컬렉션을 사용하려면 HTMLCollection이나 NodeList 객체를 배열로 변환하여 사용하는 것을 권장한다. 또한 고차 함수를 사용하여 순회한다.
textContent
Node.prototype.textContent 프로퍼티는 setter와 getter 모두 존재하는 접근자 프로퍼티로서 요소 노드의 텍스트와 모든 자손 노드의 텍스트를 모두 취득하거나 변경한다.
innerHTML
Element.prototype.innerHTML 프로퍼티는 setter와 getter 모두 존재하는 접근자 프로퍼티로서 요소 노드의 HTML 마크업을 취득하거나 변경한다.
textContent 프로퍼티는 HTML 마크업을 무시하고 텍스트만 반환하지만 innerHTML 프로퍼티는 HTML 마크업이 포함된 문자열을 그대로 반환한다. 또한 마크업 태그를 삽입할 수도 있다.
innerHTML으로 문자열을 할당하면 문자열에 포함되어 있는 HTML 마크업이 파싱되어 요소 노드의 자식 노드로 DOM에 반영된다. 이때 사용자로부터 입력받은 데이터를 그대로 innerHTML 프로퍼티에 할당하는 것은 크로스 사이트 스크립팅 공격(XXS)에 취약하므로 위험하다. 마크업 내에 자바스크립트 악성 코드가 포함되어 있다면 파싱 과정에서 그대로 실행될 가능성이 있기 때문이다.
HTML5는 innerHTML 프로퍼티에 삽입된 script 자바스크립트 코드를 실행하지 않는다. 따라서 HTML5를 지원하는 브라우저에서는 동작하지 않는다. 하지만 다른 방식으로 공격을 할 수 있다. innerHTML 프로퍼티를 사용한 DOM 조작은 구현이 간단하고 직관적인 장점이 있지만 크로스 사이트 스크립팅 공격에 취약한 단점도 있다.
노드 생성과 추가
Document.prototype.createElement(tagName) 메서드는 요소 노드를 생성하여 반환한다.
createElement 메서드의 메개변수 tagName에는 태그 이름을 나타내는 문자열을 인수로 전달한다.
노드 삽입
Node.prototype.appendChild 메서드는 인수로 전달받은 노드를 자신을 호출한 노드의 마지막 자식 노드로 DOM에 추가한다. 이때 노드를 추가할 위치를지정할 수 없고 언제나 마지막 자신 노드로 추가한다.
Node.prototype.inserBefore(newNode, childNode) 메서드는 첫 번째 인수로 전달받은 노드를 두 번째 인수로 전달받은 노드 앞에 삽입한다.
노드 이동
DOM에 이미 존재하는 노드를 appendChild 또는 insertBefore 메서드를 사용하면 DOM에 다시 추가하면 현재 위치에서 노드를 제거하고 새로운 위치에 노드를 추가한다. 즉, 노드가 이동한다.
노드 복사
Node.prototype.clibeNode([deep : true | false]) 메서드는 노드의 사본을 생성하여 반환한다.
매게변수 deep에 true를 인수로 전달하면 노드를 깊은 복사하여 모든 자손 노드가 포함된 사본을 생성하고, false를 인수로 전달하거나 생략하면 얕은 복사하여 노드 자신만의 사본을 생성한다. 이때 텍스트 노드도 자손 노드이므로 텍스트 노드도 복사되지 않는다.
노드 교체
Node.prototype.replaceChild(newChild, oldChild) 메서드는 자신을 호출한 노드의 자식 노드를 다른 노드로 교체한다. 첫 번째 매개변수 newChild에는 교체할 새로운 노드를 인수로 전달하고, 두 번째 매개변수 oldChild에는 이미 존재하는 교체될 노드를 인수로 전달한다.
노드 삭제
Node.prototype.removeChild(child) 메서드는 child 매개변수에 인수로 전달한 노드를 DOM에서 삭제한다.
어트리뷰트
HTML 문서의 구성 요소인 HTML 요소는 여러 개의 어트리뷰트(속성)을 가질 수 있다. HTML 요소의 동작을 제어하기 위한 추가적인 정보를 제공하는 HTML 어트리뷰트는 HTML 요소의 시작 태그에 어트리뷰트 이름 = 어티르뷰트 값 형식으로 정의한다.
HTML 어트리뷰트 vs DOM 프로퍼티
요소 노드 객체에는 HTML 어트리뷰트에 대응하는 프로퍼티가 존재한다. 이 DOM 프로퍼티들은 HTML 어트리뷰트 값을 초기값으로 가지고 있다. HTML 어트리뷰트의 역할은 HTML 요소의 초기 상태를 지정하는 것이다. 즉, HTML 어트리뷰트 값은 HTML 요소의 초기 상태를 의미하며 이는 변하지 않는다. DOM 프로퍼티의 역할은 사용자의 입력에 의한 상태 변화에 반응하여 언제나 최신 상태를 유지한다.
요소 노드는 2개의 상태를 가진다. 즉 초기 상태와 최신 상태를 관리해야 한다.
요소 노드의 초기 상태는 어트리뷰트 노드가 관리하며, 노드의 최신 상태는 DOM 프로퍼티가 관리한다.
data 어트리뷰트와 dataset 프로퍼티
data 어트리뷰트와 dataset 프로퍼티를 사용하면 HTML 요소에 정의한 사용자 정의 어트리뷰트와 자바스크립트 간에 데이터를 교환할 수 있다. data 어트리뷰트는 data-user-id, data-role과 같이 data- 접두사 다음에 임의의 이름을 붙여 사용한다.
data 어트리뷰트 값은 HTMLElement.dataset 프로퍼티로 취득할 수 있다. data 어트리뷰트의 data- 접두사 다음에 붙인 임의의 이름을 카멜 케이스로 변환한 프로퍼티를 가지고 있다. 이 프로퍼티로 data 어트리뷰트의 값을 취득하거나 변경할 수 있다.
*참고자료
[JavaScript DeepDive] 39장_DOM
브라우저 렌더링 엔진은 HTML 문서를 파싱하여 브라우저가 이해할 수 있는 자료구조인 DOM을 생성한다. DOM은 HTML 문서의 계층적 구조와 정보를 표현하며 이를 제어할 수 있는 API, 즉 프로퍼티와 메
ghost4551.tistory.com
'javascript' 카테고리의 다른 글
[모던 자바스크립트]Set과 Map (0) | 2023.04.09 |
---|---|
[모던 자바스크립트]비동기 프로그래밍 (0) | 2023.04.09 |
리플로우와 리페인트 (0) | 2023.03.16 |
[모던 자바스크립트]브라우저의 렌더링 과정 (0) | 2023.03.09 |
[모던 자바스크립트]Date (0) | 2023.02.28 |