반응형
노드(node)란?
- HTML 문서 객체 모델(DOM, Document Object Model)은 노드라고 불리는 계층적 단위에 정보를 저장하고 있는데, HTML DOM은 이러한 노드들을 정의하고 그들 사이의 관계를 설명해 주는 역할을 한다.
- HTML 문서의 정보는 노드들의 집합이며 노드 간의 관계를 보여주는 노드 트리(node tree)라고 불리는 계층적 구조에 저장되는데, 노드 트리는 노드들의 집합이며 노드 간의 관계를 보여준다.
- 노드 트리는 최상위 레벨인 루트 노드(root node)로부터 시작하여 가장 낮은 레벨인 텍스트 노드까지 뻗어 내려가는데, 자바스크립트에서는 HTML DOM을 이용하여 노드 트리에 포함된 모든 노드에 접근할 수 있다.
노드의 종류
- W3C HTML DOM 표준에 따르면, HTML 문서의 모든 것은 노드다.
- 문서 노드(document node) : HTML 문서 전체를 나타내는 노드
- 요소 노드(element node) : 모든 HTML 요소는 요소 노드이며, 속성 노드를 가질 수 있는 유일한 노드
- 속성 노드(attribute node) : 모든 HTML 요소의 속성은 속성 노드이며, 요소 노드에 관한 정보를 가지고 있지만 해당 요소 노드의 자식 노드(child node)에는 포함되지 않음.
- 텍스트 노드(text node) : HTML 문서의 모든 텍스트는 텍스트 노드
- 주석 노드(comment node) : HTML 문서의 모든 주석은 주석 노드
노드 간의 관계
- 노드 트리의 가장 상위에는 단 하나의 루트 노드(root node)가 존재하며, 루트 노드를 제외한 모든 노드는 단 하나의 부모 노드(parent node)만을 가진다.
- 모든 요소 노드는 자식 노드(child node)를 가질 수 있으며, 형제 노드(sibling node)란 같은 부모 노드를 가지는 모든 노드를 가리킨다.
- 조상 노드(ancestor node)란 부모 노드를 포함해 계층적으로 현재 노드보다 상위에 존재하는 모든 노드를 가리키며, 자손 노드(descendant node)란 자식 노드를 포함해 계층적으로 현재 노드보다 하위에 존재하는 모든 노드를 가리킨다.
노드로의 접근
getElementsByTagName() 메소드를 이용하는 방법
- getElementsByTagName() 메소드는 HTML 특정 태그 이름을 가지는 모든 요소를 노드 리스트의 형태로 반환하므로 이 메소드가 반환하는 노드 리스트를 이용하면 원하는 노드에 접근할 수 있다.
// 모든 <li> 요소선택
var selectedItem = document.getElementsByTagName("li");
// item() 메소드는 해당 HTML 객체 집합에서 전달받은 인덱스에 해당하는 요소 반환
for (var i = 0; i < selectedItem.length; i++) {
selectedItem.item(i).style.color = "red"; // 선택된 모든 요소 글자색 변경
}
노드 간의 관계를 이용하여 접근하는 방법
- HTML DOM에서 노드 간의 관계는 다음과 같은 프로퍼티로 정의되는데, 아래와 같은 프로퍼티를 이용하여 원하는 노드에 손쉽게 접근할 수 있다.
- parentNode : 부모 노드
- childNodes : 자식 노드 리스트
- firstChild : 첫 번째 자식 노드
- lastChild : 마지막 자식 노드
- nextSibling : 다음 형제 노드
- previousSibling : 이전 형제 노드
노드에 대한 정보
- 노드에 대한 정보는 다음과 같은 프로퍼티를 통해 접근할 수 있으며, 이 프로퍼티들은 특별히 다른 인터페이스를 이용하지 않고도 해당 노드의 정보에 직접 접근할 수 있는 방법을 제공한다.
nodeName
- nodeName 프로퍼티는 노드 고유의 이름을 저장하므로 수정할 수 없는 읽기 전용 프로퍼티며, 요소 노드의 nodeName 프로퍼티는 언제나 해당 HTML 요소의 태그 이름을 대문자로 저장한다.
// HTML 문서의 모든 자식 노드 중에서 두 번째 노드의 이름을 선택
// HTML 문서의 첫 번째 자식 노드는 <!DOCTYPE html>, 두 번째 자식 노드는 <html>
document.getElementById("document").innerHTML = document.childNodes[1].nodeName; // HTML
// html 노드의 모든 자식 노드 중에서 첫 번째 노드의 이름을 선택
// <html>노드의 첫 번째 자식 노드는 <head>
document.getElementById("html").innerHTML = document.childNodes[1].childNodes[0].nodeName; // HEAD
nodeValue
- nodeValue 프로퍼티는 노드의 값을 저장한다.
- innerHTML 프로퍼티를 사용하여 손쉽게 HTML 요소의 내용(content)에 접근하거나 변경할 수 있지만, innerHTML 프로퍼티 대신에 firstChild.nodeValue를 사용해도 같은 결과를 얻을 수 있다.
// 아이디가 heading인 요소의 첫 번째 자식 노드의 노드값을 선택
var headingText = document.getElementById("heading").firstChild.nodeValue;
document.getElementById("text1").innerHTML = headingText;
document.getElementById("text1").firstChild.nodeValue = headingText;
nodeType
- nodeType 프로퍼티는 노드 고유의 타입을 저장하므로, 수정할 수 없는 읽기 전용 프로퍼티다.
// 아이디가 heading인 요소의 첫 번째 자식 노드의 타입을 선택
var headingType = document.getElementById("heading").firstChild.nodeType;
document.getElementById("head").innerHTML = headingType; // 3
document.getElementById("document").innerHTML = document.nodeType; // 9
빈 텍스트 노드의 처리
- 현재 대부분의 주요 웹 브라우저는 모두 W3C DOM 모델을 지원하지만 그 처리 방식에 있어 약간씩의 차이가 있다.
- 예를 들어, 띄어쓰기와 줄 바꿈을 파이어폭스나 기타 브라우저들에서는 텍스트 노드(text node)로 취급하지만 익스플로러는 텍스트 노드로 취급하지 않으므로, 자식 노드나 형제 노드를 이용하여 원하는 노드에 접근하려면 브라우저 간에 차이가 발생한다.
- 브라우저간의 차이를 없애는 가장 손쉬운 방법은 nodeType 프로퍼티를 사용하여 선택된 요소의 타입을 검사하는 것이다.
/* 마지막 자식 노드 찾은 후 찾은 노드 타입이 요소 노드가 아니면 그 앞의 노드를 다시 검사 */
var lastNode;
function findLastChild(parentNode) {
lastNode = parentNode.lastChild;
while (lastNode.nodeType != 1) {
lastNode = lastNode.previousSibling;
}
}
function printLastChild() {
var parentNode = document.getElementById("parentNode");
findLastChild(parentNode);
document.getElementById("nodename").innerHTML = lastNode.nodeName;
}
노드 리스트(node list)
- 노드 리스트는 getElementsByTagName() 메소드나 childNodes 프로퍼티의 값으로 반환되는 객체로, HTML 문서와 같은 순서로 문서 내의 모든 노드를 리스트 형태로 저장하고 있다.
- HTML DOM에서 각 요소 노드 다음에는 별도의 텍스트 노드가 존재하며, 리스트의 각 노드는 0부터 시작하는 인덱스를 이용하여 접근할 수 있다.
/* 각 요소 노드 다음에 또 다른 텍스트 노드가 존재할 경우 */
<ul id="list">ul 요소 다음의 텍스트
<li>첫 번째 아이템이에요!</li>첫 번째 li 요소 다음의 텍스트
<li>두 번째 아이템이에요!</li>두 번째 li 요소 다음의 텍스트
<li>세 번째 아이템이에요!</li>세 번째 li 요소 다음의 텍스트
</ul>
<script>
// 아이디가 list인 요소의 모든 자식 노드들을 선택
var listItems = document.getElementById("list").childNodes;
// 자식 노드들 중 첫번째 노드값 출력 - 'ul 요소 다음의 텍스트'
document.write(listItems[0].nodeValue);
// 자식 노드들 중 두번째 노드의 자식노드 중 첫번째 노드값 출력 - '첫 번째 아이템이에요!'
document.write(listItems[1].firstChild.nodeValue);
// 자식 노드들 중 세번째 노드값 출력 - '첫 번째 li 요소 다음의 텍스트'
document.write(listItems[2].nodeValue);
</script>
- 노드 리스트 객체는 리스트에 노드를 추가하거나 삭제되면 자신의 상태 정보를 스스로 갱신하므로, length 프로퍼티 값은 언제나 노드 리스트가 저장하고 있는 노드들의 총 개수를 나타낸다
// 모든 <li> 요소들을 선택
var listItems = document.getElementsByTagName("li");
// 모든 자식 노드들의 개수 반환
document.getElementById("text").innerHTML =
"이 노드 리스트의 길이는 " + listItems.length + "개 입니다.<br>";
// 모든 자식 노드들의 글자색을 변경
function changeTextColor() {
for (var i = 0; i < listItems.length; i++) {
listItems[i].style.color = "orange";
}
}
노드의 추가
appendChild() 메소드
- appendChild() 메소드는 새로운 노드를 해당 노드의 자식 노드 리스트(child node list)의 맨 마지막에 추가한다.
function appendNode() {
// 아이디가 list인 요소 선택
var parent = document.getElementById("list");
// 아이디가 item인 요소 선택
var newItem = document.getElementById("item");
// 해당 요소의 맨 마지막 자식 노드로 추가
parent.appendChild(newItem);
}
insertBefore() 메소드
- insertBefore() 메소드는 새로운 노드를 특정 자식 노드 바로 앞에 추가한다.
- 기준 자식 노드에 null 값을 전달하면 새로운 노드는 자식 노드 리스트의 맨 마지막 노드로 추가되므로, appendChild() 메소드와 완전히 같은 동작을 한다.
- 새로운 자식 노드 : 자식 노드 리스트(child node list)에 새롭게 추가할 자식 노드를 전달한다.
- 기준 자식 노드 : 새로운 노드를 삽입할 때 기준이 되는 노드로, 이 노드 바로 앞에 새로운 노드가 추가된다.
부모노드.insertBefore(새로운자식노드, 기준자식노드);
function appendNode() {
// 아이디가 list인 요소를 선택
var parent = document.getElementById("list");
// 아이디가 criteria인 요소를 선택
var criteriaItem = document.getElementById("criteria");
// 아이디가 item인 요소를 선택
var newItem = document.getElementById("item");
// 해당 노드를 기준이 되는 자식 노드의 바로 앞에 추가
parent.insertBefore(newItem, criteriaItem);
}
insertData() 메소드
- insertData() 메소드는 텍스트 노드의 텍스트 데이터에 새로운 텍스트를 추가한다.
- 오프셋(offset) : 오프셋 값은 0부터 시작하며, 기존 텍스트 데이터의 몇 번째 위치부터 추가할지를 전달한다.
- 새로운 데이터 : 새로이 삽입할 텍스트 데이터를 전달한다.
텍스트노드.insertData(오프셋, 새로운데이터);
// 아이디가 text인 요소의 텍스트 노드를 선택
var text = document.getElementById("text").firstChild;
function appendText() {
// 텍스트 노드의 6번째 문자부터 나른한이란 텍스트를 추가
text.insertData(6, " 나른한 ");
}
노드의 생성
요소 노드의 생성
- createElement() 메소드를 사용하여 새로운 요소 노드를 만들 수 있다.
function createNode() {
// 기준이 되는 요소로 아이디가 text인 요소를 선택
var criteriaNode = document.getElementById("text");
// 새로운 <p> 요소를 생성
var newNode = document.createElement("p");
newNode.innerHTML = "새로운 단락입니다.";
// 새로운 요소를 기준이 되는 요소 바로 앞에 추가
document.body.insertBefore(newNode, criteriaNode);
}
속성 노드의 생성
- createAttribute() 메소드를 사용하여 새로운 속성 노드를 만들 수 있다.
- 만약 같은 이름의 속성 노드가 이미 존재하면 기존의 속성 노드는 새로운 속성 노드로 대체되고, 이미 존재하는 요소 노드에 속성 노드를 생성하고자 할 때에는 setAttribute() 메소드를 사용할 수 있다.
function createNode() {
// 아이디가 text인 요소를 선택
var text = document.getElementById("text");
// 새로운 style 속성 노드를 생성
var newAttribute = document.createAttribute("style");
newAttribute.value = "color:red";
// 해당 요소의 속성 노드로 추가
text.setAttributeNode(newAttribute);
}
텍스트 노드의 생성
- createTextNode() 메소드를 사용하여 새로운 텍스트 노드를 만들 수 있다.
function createNode() {
// 아이디가 text인 요소를 선택
var elementNode = document.getElementById("text");
// 새로운 텍스트 노드를 생성
var newText = document.createTextNode("새로운 텍스트에요!");
// 해당 요소의 자식 노드로 추가
elementNode.appendChild(newText);
}
노드의 제거
removeChild() 메소드
- removeChild() 메소드는 자식 노드 리스트에서 특정 자식 노드를 제거한다.
- 성공적으로 노드가 제거되면 제거된 노드를 반환하고, 노드가 제거될 때에는 제거되는 노드의 모든 자식 노드들도 다 같이 제거된다.
// 아이디가 "list"인 요소를 선택
var parent = document.getElementById("list");
// 아이디가 "item"인 요소를 선택
var removedItem = document.getElementById("item");
// 지정된 요소를 삭제
parent.removeChild(removedItem);
removeAttribute() 메소드
- removeAttribute() 메소드는 속성 이름을 이용하여 특정 속성 노드를 제거한다.
// 아이디가 text인 요소를 선택
var text = document.getElementById("text");
// 해당 요소의 style 속성을 제거
text.removeAttribute("style");
노드의 복제
cloneNode() 메소드
- cloneNode() 메소드는 기존의 존재하는 노드와 똑같은 새로운 노드를 생성하여 반환한다.
- 자식 노드 복제 여부 : 전달된 값이 true이면 복제되는 노드의 모든 속성 노드와 자식 노드도 같이 복제하며, false이면 속성 노드만 복제하고 자식 노드는 복제하지 않는다.
복제할노드.cloneNode(자식노드복제여부);
function cloneElement() {
// 아이디가 "list"인 요소를 선택
var parent = document.getElementById("list");
// 아이디가 "item"인 요소를 선택
var originItem = document.getElementById("item");
// 해당 노드를 복제하여 리스트의 맨 마지막에 추가
parent.appendChild(originItem.cloneNode(true));
}
노드의 조작
요소 노드의 텍스트
- 요소 노드는 자신이 직접 텍스트값을 가지지는 않고 요소 노드의 텍스트는 요소 노드의 자식 노드인 텍스트 노드에 저장되므로, 요소 노드의 텍스트 값을 확인하거나 변경하고자 할 때는 요소 노드에 포함된 텍스트 노드에 접근해야 한다.
텍스트 노드의 값 변경
- nodeValue 프로퍼티를 사용하여 텍스트 노드의 값을 변경할 수 있다.
// 아이디가 text인 요소를 선택
var para = document.getElementById("text");
function changeText() {
para.firstChild.nodeValue = "텍스트 변경 완료!";
}
속성 노드의 값 변경
- 속성 노드는 nodeValue 프로퍼티뿐만 아니라 setAttribute() 메소드를 사용하여 값을 변경할 수 있다.
- setAttribute() 메소드는 속성값을 변경하려는 속성이 존재하지 않으면, 먼저 해당 속성을 생성한 후에 속성값을 설정한다.
var para;
function changeAttribute() {
// 모든 <p> 요소중에서 첫 번째 요소에 클래스 속성값으로 para를 설정
// 클래스가 설정되면 해당 클래스에 설정되어 있던 스타일이 자동으로 적용
document.getElementsByTagName("p")[0].setAttribute("class", "para");
}
요소 노드의 교체
- replaceChild() 메소드를 사용하면 기존의 요소 노드를 새로운 요소 노드로 교체할 수 있다.
- 새로운 자식 노드 : 자식 노드 리스트에 새롭게 추가할 요소 노드를 전달한다.
- 기존 자식 노드 : 자식 노드 리스트에서 제거할 요소 노드를 전달한다.
교체할노드 = 부모노드.replaceChild(새로운자식노드, 기존자식노드);
/* 자식 노드 중 첫번째 요소 삭제, 그 대신에 세번째 요소를 첫번째 요소 자리에 삽입 */
var parent = document.getElementById("parent"); // 부모 노드를 선택
var first = document.getElementById("first");
var third = document.getElementById("third");
function changeNode() {
// first 요소를 삭제하고, 그 대신 third 요소를 삽입
parent.replaceChild(third, first);
}
텍스트 노드의 데이터 교체
- replaceData() 메소드를 사용하면 텍스트 노드의 텍스트 데이터를 바꿀 수 있다.
- 오프셋(offset) : 오프셋 값은 0부터 시작하며, 기존 텍스트 데이터의 몇 번째 문자부터 교체할지를 전달한다.
- 교체할 문자 수 : 기존 텍스트 노드의 데이터로부터 교체할 총 문자 수를 전달한다.
- 새로운 데이터 : 새로이 삽입할 텍스트 데이터를 전달한다.
텍스트노드.replaceData(오프셋, 교체할문자수, 새로운데이터);
// 아이디가 text인 요소의 텍스트 노드를 선택
var text = document.getElementById("text").firstChild;
function changeText() {
// 텍스트 노드의 7번째 문자부터 4개의 문자를 저녁 7로 교체
text.replaceData(7, 4, "저녁 7");
}
Reference
반응형
'Language > JavaScript' 카테고리의 다른 글
[Javascript] 자바스크립트 브라우저 객체 모델 - Location 객체 (0) | 2023.08.04 |
---|---|
[Javascript] 자바스크립트 브라우저 객체 모델 - Window 객체 (0) | 2023.08.04 |
[Javascript] 자바스크립트 문서 객체 모델 - DOM 선택, 변경, 메소드 (0) | 2023.08.04 |
[Javascript] 자바스크립트 호스트 객체 - 전역 객체 (0) | 2023.08.02 |
[Javascript] 자바스크립트 표준 객체 - RegExp 객체와 메소드 (0) | 2023.08.02 |