Romantic Developer : )
(Web JavaScript) 웹 자바스크립트 DOM (9) Node API 본문
(Web JavaScript) 웹 자바스크립트 DOM (9) Node API
Romantic_Developer 2018. 8. 7. 18:33안녕하세요, 영감을 주는 개발자 방민방민입니다.
오늘은 자바스크립트에서 Node 가 가지고 있는 다양한 기능을 활용할 수 있는 API 에 대하여 학습해 보고자 합니다. 노드는 웹 프로그램에서 엘리먼트들이 가지는 관계를 의미합니다. 자주 사용되는 이러한 node API 의 종류는 아래와 같습니다.
(출처 : 생활코딩)
- Node.childNodes
자식노드들을 유사배열에 담아서 리턴한다. - Node.firstChild
첫번째 자식노드 - Node.lastChild
마지막 자식노드 - Node.nextSibling
다음 형제 노드 - Node.previousSibling
이전 형제 노드
1.Node 관계 API
아래의 코드는 nodeAPI 를 활용하여 문서를 탐색하는것을 보여줍니다.
<body id="start"> <ul> <li><a href="./532">html</a></li> <li><a href="./533">css</a></li> <li><a href="./534">JavaScript</a> <ul> <li><a href="./535">JavaScript Core</a></li> <li><a href="./536">DOM</a></li> <li><a href="./537">BOM</a></li> </ul> </li> </ul> <script> var s = document.getElementById('start'); console.log(1, s.firstChild); // #text var ul = s.firstChild.nextSibling console.log(2, ul); // ul console.log(3, ul.nextSibling); // #text console.log(4, ul.nextSibling.nextSibling); // script console.log(5, ul.childNodes); //text, li, text, li, text, li, text console.log(6, ul.childNodes[1]); // li(html) console.log(7, ul.parentNode); // body </script> </body>
노드간의 관계를 파악하는 것은 쉽지 않습니다.
일단 모든 엘리먼트들은 id 값이 start 인 body 태그에 소속되어 있습니다.
script 코드를 보겠습니다.
변수 s 에 id값이 start 인 body 태그를 저장하였습니다. 이후 콘솔을 통해 어떤 노드가 출력되는지 확인하시기 바랍니다.
- s.firstChild 는 첫번째 자식인 text 를 출력합니다. 이는 <ul></ul>일 것 같지만, 그렇지 않고 #text 를 출력합니다. 그 이유는 <body> 태그와 <ul> 태그 사이에 있는 줄바꿈 text가 하나의 차일드로 취급되기 때문입니다.
- 변수 ul에 s.firstChild(#text).nextSibling를 담습니다. 같은 레벨을 갖는 다음 태그를 의미합니다. 여기에서는 <ul> 태그가 됩니다.
- ul.nextSibling 은 </ul> 뒤의 <script>가 될 것같지만, 두 태그 사이에 있는 줄바꿈 문자가 되기 때문에 또다시 #text 가 됩니다.
- ul.nextSibling.nextSibling 가 드디어 <script></script> 태그가 됩니다.
- ul.childNodes 는 ul에 속해있는 <li>태그 들과, 줄바꿈 문자가 됩니다. 그러므로 li 와 text 를 반복적으로 출력합니다.
- ul.childNodes[1] ul 에 속에있는 두번째 노드인 <li>html</li>가 됩니다.([0] 은 #text 일 것입니다.
- ul.parentNode 는 ul 의 부모 노드임으로 body 를 출력합니다.
2. Node 종류 API
아래의 코드를 먼저 실행해 보겠습니다.
<!DOCTYPE> <html> <head> </head> <body id="start"> <ul> <li><a href="./532">html</a></li> <li><a href="./533">css</a></li> <li><a href="./534">JavaScript</a> <ul> <li><a href="./535">JavaScript Core</a></li> <li><a href="./536">DOM</a></li> <li><a href="./537">BOM</a></li> </ul> </li> </ul> <script> for(var name in Node){ console.log(name, Node[name]); } </script> </body> </html>
이는 아래의 내용을 출력합니다.
jsPractice.html:20 ELEMENT_NODE 1 jsPractice.html:20 ATTRIBUTE_NODE 2 jsPractice.html:20 TEXT_NODE 3 jsPractice.html:20 CDATA_SECTION_NODE 4 jsPractice.html:20 ENTITY_REFERENCE_NODE 5 jsPractice.html:20 ENTITY_NODE 6 jsPractice.html:20 PROCESSING_INSTRUCTION_NODE 7 jsPractice.html:20 COMMENT_NODE 8 jsPractice.html:20 DOCUMENT_NODE 9 jsPractice.html:20 DOCUMENT_TYPE_NODE 10 jsPractice.html:20 DOCUMENT_FRAGMENT_NODE 11 jsPractice.html:20 NOTATION_NODE 12 jsPractice.html:20 DOCUMENT_POSITION_DISCONNECTED 1 jsPractice.html:20 DOCUMENT_POSITION_PRECEDING 2 jsPractice.html:20 DOCUMENT_POSITION_FOLLOWING 4 jsPractice.html:20 DOCUMENT_POSITION_CONTAINS 8 jsPractice.html:20 DOCUMENT_POSITION_CONTAINED_BY 16 jsPractice.html:20 DOCUMENT_POSITION_IMPLEMENTATION_SPECIFIC 32
이를 통해 각각의 노드들이 어떤 nodeName(이름), 과 어떤 nodeType(번호) 를 가지는지 조회할 수 있습니다.
예를 들어 ELEMENT 노드는 1번 노드타입을 가지고 있습니다. 우리가 기존에 배웠던 atrribute , text, document 등등의 노드들이 어떤 타입값을 갖고 있는지 확인 할 수 있습니다.
아래의 코드는 노드 네임을 활용한 재귀함수의 좋은 예입니다.
<!DOCTYPE> <html> <head> </head> <body id="start"> <ul> <li><a href="./532">html</a></li> <li><a href="./533">css</a></li> <li><a href="./534">JavaScript</a> <ul> <li><a href="./535">JavaScript Core</a></li> <li><a href="./536">DOM</a></li> <li><a href="./537">BOM</a></li> </ul> </li> </ul> <script> function traverse(target, callback){//익명함수 callback을 인자로 if(target.nodeType === Node.ELEMENT_NODE){//1 은 element node 를 나타냄 callback(target); var c = target.childNodes; for(var i = 0; i<c.length; i++){ traverse(c[i],callback); } } } traverse(document.getElementById('start'),function(elem){console.log(elem); }); </script> </body> </html>
이는 아래의 결과를 출력합니다.
즉 재귀함수를 통해 각각의 노드에 들려 그 내용을 출력하는 예제입니다.
재귀에 대한 내용은 프로그래밍적 부분이므로 차후에 다른 포스팅에서 설명하겠습니다.
여기에서는
3. Node 변경 API
먼저 노드를 추가하고 제거하는 등의 활용이 Node 변경 API 를 통하여 가능합니다.
노드의 추가와 관련된 API 는 아래와 같습니다. (출처 : 생활코딩)
- appendChild(child)
노드의 마지막 자식으로 주어진 엘리먼트 추가 - insertBefore(newElement, referenceElement)
appendChild와 동작방법은 같으나 두번째 인자로 엘리먼트를 전달 했을 때 이것 앞에 엘리먼트가 추가된다.
노드를 추가하기 위해서는 추가할 엘리먼트를 생성해야 하는데 이것은 document 객체의 기능이다. 아래 API는 노드를 생성하는 API이다.
- document.createElement(tagname)
엘리먼트 노드를 추가한다. - document.createTextNode(data)
텍스트 노드를 추가한다.
아래의 코드를 보도록 하겠습니다.
<!DOCTYPE> <html> <head> </head> <body> <ul id="target"> <li>HTML</li> <li>CSS</li> </ul> <input type="button" onclick="callAppendChild();" value="appendChild()"/> <input type="button" onclick="callInsertBefore();" value="callInsertBefor()"/> <script> function callAppendChild(){ var target = document.getElementById('target’);//target 노드를 저장 var li = document.createElement('li’);//li엘리먼트 생성 var text = document.createTextNode('JavaScript’);//text 노드 생성 li.appendChild(text);//li 엘리먼트에 text 노드를 차일드로 추가 target.appendChild(li);//li엘리먼트를 target 의 차일드노드로 추가 } function callInsertBefore(){ var target = document.getElementById('target’);//target 노드를 저장 var li = document.createElement('li’);//li 엘리먼트를 생성 var text = document.createTextNode('JQuery’);//text 노드 생성 li.appendChild(text);//text 노드를 li의 차일드로 추가 target.insertBefore(li,target.firstChild);//li 엘리먼트를 target 의 first Child 로 추가 } </script> </body> </html>
이는 아래의 결과를 출력합니다.
이와 같이 각각의 노드를 생성하여 appendChild() 의 경우 추가하고자 하는 노드를 가장 마지막 child로 더해주고 intertBefore()의 경우에는 추가하고자 하는 노드를 추가하는 노드를 인자로 주는 노드의 이전 노드로 저장합니다. 이 경우에는 (li, target.firstChild)를 주었기 때문에, 첫번째 자식노드인 HTML 이전에 추가되는것을 확인할 수 있습니다.
노드를 제거하고 바꾸는 코드도 존재합니다.(출처: 생활코딩)
노드 제거를 위해서는 아래 API를 사용한다. 이 때 메소드는 삭제 대상의 부모 노드 객체의 것을 실행해야 한다는 점에 유의하자.
노드의 제거는 위에서 말한것과 같이 반드시 부모 노드의 객체에서 실행해야합니다.
아래의 코드를 보겠습니다
<html> <!DOCTYPE> <html> <head> </head> <body> <ul id="target"> <li>HTML</li> <li>CSS</li> <li>JavaScript</li> </ul> <input type="button" onclick = "callRemoveChild()" value="callRemoveChild"> <script> function callRemoveChild(){ var target = document.getElementById('target'); target.parentNode.removeChild(target);//지우고자 하는 target 의 부모 노드에서 실행 } </script> </body> </html>
이 코드를 통해 버튼을 누르면, 전체 id 값이 target 을 갖는 해당 ul 엘리먼트 전부가 삭제됩니다. 그러므로 하위 li 엘리먼트인 HTML, CSS , JavaScript 가 모두 삭제됩니다.
이때, 삭제되는 코드를 보면, target.parentNode.removeChild(target) 로, target으로 하는 엘리먼트 노드의 부모 노드를 한번 호출하고, 그 부모노드에서 자식노드를 삭제할 수 있었습니다.
이는 많은 비판을 받고 있는 부분이기도 합니다. 지우고자 하는 노드를 바로 삭제할 수 없고, 부모노드를 알아야만 하는 구조이기 때문입니다. 그러나 이것은 설계상의 규약이기때문에 JS 를 공부하는 우리로써는 받아들여야 할 부분입니다.
아래는 노드를 변경하는 예제입니다.
<!DOCTYPE> <html> <head> </head> <body> <ul> <li>HTML</li> <li>CSS</li> <li id="target">JavaScript</li> </ul> <input type="button" onclick = "callReplaceChild()" value="callReplaceChild"> <script> function callReplaceChild(){ var a = document.createElement('a');//a 태그 엘리먼트를 생성 a.setAttribute('href','http://aaa.com');//a 태그의 속성중 href 를 변경 a.appendChild(document.createTextNode('web browser JavaScirpt'));//a 태그의 자식 택스트를 생성 var target = document.getElementById('target');//target 엘리먼트 지정 target.replaceChild(a,target.firstChild);//target 엘리먼트의 첫번째 자식을 변경 } </script> </body> </html>
주석에서 볼 수 있는 바와 같이 변경하고자 하는 앨리먼트의 부모노드에서 replaceChild(newNode,oldNode)를 해주면 해당 자식 엘리먼트가 변하는 것을 알 수 있습니다.
오늘은 Node API 라는 다소 어려운 내용을 정말 긴 포스팅으로 알아보았습니다.
API 를 통해 어떤 노드를 조회하고, 변경, 삭제 등을 하는 API 는 웹사이트의 프로그래밍 적인 동작에 있어서 매우 중요하다고 할 수 있습니다.
지금까지 영감을 주는 개발자 방민방민이었습니다! :)
'Romantic Developer > Web JavaScript' 카테고리의 다른 글
(Web JavaScript) 웹 자바스크립트 DOM (8) Element jQuery (0) | 2018.08.06 |
---|---|
(Web JavaScript) 웹 자바스크립트 DOM (7) 조회 API (0) | 2018.08.05 |
(Web JavaScript) 웹 자바스크립트 DOM (6) 식별자 API (0) | 2018.08.04 |
(Web JavaScript) 웹 자바스크립트 DOM (5) jQuery객체 (0) | 2018.08.03 |
(Web JavaScript) 웹 자바스크립트 DOM (4) HTML element (0) | 2018.08.02 |