Language/JavaScript [JavaScript] 노드
  • 728x90
    반응형

     

     

     

     

    노드(node)

    HTML DOM은 노드(node)라고 불리는 계층적 단위에 정보를 저장하고 있다.

    HTML DOM은 이러한 노드들을 정의하고, 그들 사이의 관계를 설명해 주는 역할을 한다.

     

     

    HTML 문서의 정보는 노드 트리(node tree)라고 불리는 계층적 구조에 저장된다.

    이러한 노드 트리는 노드들의 집합이며, 노드 간의 관계를 보여준다.

     

    노드 트리는 최상위 레벨인 루트 노드(root node)로 부터 시작하여, 가장 낮은 레벨인 텍스트 노드까지 뻗어 내려간다.

    자바스크립트에서는 HTML DOM을 이용하여 노드 트리에 포함된 모든 노드에 접근할 수 있다.

     

     

     

    노드의 종류

    W3C HTML DOM 표준에 따르면, HTML 문서의 모든 것은 노드이다.

     

    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)란 자식 노드를 포함해 계층적으로 현재 노드보다 하위에 존재하는 모든 노드를 가리킨다.

     

     

    노드로의 접근

    HTML 문서에서 HTML DOM 노드에 접근하는 방법은 다음과 같다.

     

    1. getElementsByTagName() 메소드를 이용하는 방법
    2. 노드 간의 관계를 이용하여 접근하는 방법

     

     

     

    getElementsByTagName() 메소드를 이용하는 방법

    getElementsByTagName() 메소드는 특정 태그 이름을 가지는 모든 요소를 노드 리스트의 형태로 반환한다.

    따라서 이 메소드가 반환하는 노드 리스트를 이용하면 원하는 노드에 접근할 수 있다.

     

     

     

    노드 간의 관계를 이용하여 접근하는 방법

    HTML DOM에서 노드 간의 관계는 다음과 같은 프로퍼티로 정의된다.

     

    1. parentNode : 부모 노드
    2. childNodes : 자식 노드 리스트
    3. firstChild : 첫 번째 자식노드
    4. lastChild : 마지막 자식 노드
    5. nextSibling : 다음 형제 노드
    6. previousSibling : 이전 형제 노드

     

    위와 같은 프로퍼티를 이용하여 원하는 노드에 손쉽게 접근할 수 있다.

     

     

     

    노드에 대한 정보

    노드에 대한 정보는 다음과 같은 프로퍼티를 통해 접근할 수 있다.

     

    1. nodeName
    2. nodeValue
    3. nodeType

    이 프로퍼티들은 특별히 다른 인터페이스를 이용하지 않고도, 해당 노드의 정보에 직접 접근할수 있는 방법을 제공한다.

     

     

     

    nodeName

    nodeName 프로퍼티는 노드 고유의 이름을 저장하므로, 수정할 수 없는 읽기 전용 프로퍼티이다.

     

    요소 노드의 nodeName 프로퍼티는 언제나 해당 HTML 요소의 태그 이름을 대문자로 저장한다.

     

    노드 프로퍼티 값
    문서 노드(document node) #doeument
    요소 노드(element node) 태그 이름(영문자로 대문자)
    속성 노드(attribute node) 속성 이름
    텍스트 노드(text node) #text

     

    🔔 예제)

    <!DOCTYPE html>
    <html lang="ko">
    <head>
        <meta charset="UTF-8">
        <title>JavaScript Node Access</title>
    </head>
    <body>
        <h1>nodeName 프로퍼티</h1>
        <p id="document"></p>
        <p id="html"></p>    
        <script>
            // HTML 문서의 모든 자식 노드 중에서 두 번째 노드의 이름을 선택함.
            document.getElementById("document").innerHTML = document.childNodes[1].nodeName;            // HTML
            
            // html 노드의 모든 자식 노드 중에서 첫 번째 노드의 이름을 선택함.
            document.getElementById("html").innerHTML = document.childNodes[1].childNodes[0].nodeName;    // HEAD
       </script>
    </body>
    </html>

     

    실행 결과

    nodeName 프로퍼티

     

    위의 예제에서 HTML 문서의 첫 번째 자식 노드는 <!DOCTYPE html>이며, 두 번째 자식 노드는 <html>이다. 또한, <html> 노드의 첫 번째 자식 노드는 <head>이며, 세 번째 자식 노드는 <body>이다.

     

     

     

    nodeValue

    nodeValue 프로퍼티는 노드의 값을 저장한다.

     

    노드 프로퍼티 값
    요소 노드(element node) undefined
    속성 노드(attribute node) 해당 속성의 속성값
    텍스트 노드(text node) 해당 텍스트 문자열

     

    🔔 예제)

    <!DOCTYPE html>
    <html lang="ko">
    <head>
        <meta charset="UTF-8">
        <title>JavaScript Node Access</title>
    </head>
    <body>
        <h1 id="heading">nodeValue 프로퍼티</h1>
        <p id="text1">텍스트</p>
        <p id="text2">텍스트</p>    
        <script>
            // 아이디가 "heading"인 요소의 첫 번째 자식 노드의 노드값을 선택함.
            var headingText = document.getElementById("heading").firstChild.nodeValue;
            
            document.getElementById("text1").innerHTML = headingText;
            document.getElementById("text2").firstChild.nodeValue = headingText;
       </script>
    </body>
    </html>
     

    실행 결과

    nodeValue 프로퍼티

    텍스트

    텍스트

     

    지금까지 innerHTML 프로퍼티를 사용하여 손쉽게 HTML 요소의 내용(content)에 접근하거나, 내용을 변경할 수 있었다.

    이러한 innerHTML 프로퍼티 대신에 firstChild.nodeValue를 사용해도 같은 결과를 얻을 수 있다.

     

     

     

    nodeType

    nodeType 프로퍼티는 노드 고유의 타입을 저장하므로, 수정할 수 없는 읽기 전용 프로퍼티이다.

     

    대표적인 HTML 노드별 nodeType 프로퍼티 값은 다음과 같다.

     

    노드 프로퍼티 값
    요소 노드(element node) 1
    속성 노드(attribute node) 2
    텍스트 노드(text node) 3
    주석 노드(comment node) 8
    문서 노드(document node) 9

     

    🔔 예제)

    <!DOCTYPE html>
    <html lang="ko">
    <head>
        <meta charset="UTF-8">
        <title>JavaScript Node Access</title>
    </head>
    <body>
        <h1 id="heading">nodeType 프로퍼티</h1>
        <p id="head"></p>
        <p id="document"></p>    
        <script>
            // 아이디가 "heading"인 요소의 첫 번째 자식 노드의 타입을 선택함.
            var headingType = document.getElementById("heading").firstChild.nodeType;
            
            document.getElementById("head").innerHTML = headingType;            // 3
            document.getElementById("document").innerHTML = document.nodeType;    // 9
       </script>
    </body>
    </html>

     

    실행 결과

    nodeType 프로퍼티

     

     

     

     

    빈 텍스트 노드의 처리

    현재 대부분의 주요 웹 브라우저는 모두 W3C DOM 모델을 지원하지만, 그 처리 방식에 있어 약간씩의 차이가 있다.

    그중에서도 가장 큰 차이점은 띄어쓰기와 줄 바꿈을 처리하는 방식이다.

     

    파이어폭스나 기타 브라우저들은 띄어쓰기나 줄 바꿈을 텍스트 노드(text node)로 취급한다.

    하지만 익스플로러는 띄어쓰기나 줄 바꿈을 텍스트 노드로 취급하지 않는다.

     

    따라서 자식 노드나 형제 노드를 이용하여 원하는 노드에 접근하려고 하면 브라우저 간에 차이가 발생하게 된다.

    이 차이를 없애는 가장 손쉬운 방법은 nodeType 프로퍼티를 사용하여 선택된 요소의 타입을 검사하는 것이다.

     

    🔔 예제)

    <!DOCTYPE html>
    <html lang="ko">
    <head>
        <meta charset="UTF-8">
        <title>JavaScript Node Access</title>
    </head>
    <body>
        <h1>빈 텍스트 노드의 처리</h1>
        <div id="parentNode">
            <p><span>첫 번째 단락</span> 입니다.</p>
            <p>두 번째 단락 입니다.</p>
        </div>
        <button onclick="printLastChild()">마지막 자식 노드 찾기!</button>
        <p id="nodename"></p>
        
        <script>
            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;
            }
       </script>
    </body>
    </html>

     

    실행 결과

    빈 텍스트 노드의 처리

    첫 번째 단락 입니다.

    두 번째 단락 입니다.

     

    위의 예제에서 마지막 자식 노드를 찾은 후에, 찾은 노드의 타입이 요소 노드가 아니면 그 앞의 노드를 다시 검사한다.

    이 방식을 사용하면 모든 브라우저에서 마지막 자식 노드로 같은 요소 노드를 선택할 수 있게 된다.

     

     

     

    노드 리스트(node list)

    노드 리스트는 getElementsByTagName()  메소드나 childNodes 프로퍼티의 값으로 반환되는 객체이다.

    이 객체는 HTML 문서와 같은 순서로 문서 내의 모든 노드를 리스트 형태로 저장하고 있다.

     

    리스트의 각 노드는 0부터 시작하는 인덱스를 이용하여 접근할 수 있다.

     

    🔔 예제)

    <!DOCTYPE html>
    <html lang="ko">
    <head>
        <meta charset="UTF-8">
        <title>JavaScript Node List</title>
    </head>
    <body>
        <h1>노드 리스트</h1>
        <ul id="list">
            <li>첫 번째 아이템이에요!</li>
            <li>두 번째 아이템이에요!</li>
            <li>세 번째 아이템이에요!</li>
        </ul>
        <script>
            // 아이디가 "list"인 요소의 모든 자식 노드들을 선택함.
            var listItems = document.getElementById("list").childNodes;
            // 자식 노드들 중 첫 번째 li 요소의 내용을 변경함.
            listItems[1].firstChild.nodeValue = "HTML 요소의 내용을 변경했어요!";
       </script>
    </body>
    </html>

     

    실행 결과

    노드 리스트

    • 첫 번째 아이템이에요!
    • 두 번째 아이템이에요!
    • 세 번째 아이템이에요!

     

     

    위의 예제에서 자식 노드 중 첫 번째 <li>요소를 선택할 때 인덱스로 0이 아닌 1을 사용한다.

    그 이유는 HTML DOM에서 각 요소 노드 다음에는 별도의 텍스트 노드가 존재하기 때문이다. 따라서 아이디가 "list"인 요소의 자식 노드 리스트의 첫 번째 노드에는 아이디가 "list"인 요소 다음에 존재하는 텍스트 노드가 저장된다.

     

    다음 예제는 이러한 요소 노드 사이에 존재하는 텍스트 노드를 확인하는 예제이다.

     

    🔔 예제)

    <!DOCTYPE html>
    <html lang="ko">
    <head>
        <meta charset="UTF-8">
        <title>JavaScript Node List</title>
    </head>
    <body>
        <h1>노드 리스트의 텍스트 노드</h1>
        <ul id="list">ul 요소 다음의 텍스트
            <li>첫 번째 아이템이에요!</li>첫 번째 li 요소 다음의 텍스트
            <li>두 번째 아이템이에요!</li>두 번째 li 요소 다음의 텍스트
            <li>세 번째 아이템이에요!</li>세 번째 li 요소 다음의 텍스트
        </ul>
        <script>
            // 아이디가 "list"인 요소의 모든 자식 노드들을 선택함.
            var listItems = document.getElementById("list").childNodes;
            // 자식 노드들 중 첫 번째 노드의 값을 출력함.
            document.write(listItems[0].nodeValue + "<br>");
            // 자식 노드들 중 두 번째 노드의 자식 노드 중 첫 번째 노드의 값을 출력함.
            document.write(listItems[1].firstChild.nodeValue + "<br>");
            // 자식 노드들 중 세 번째 노드의 값을 출력함.
            document.write(listItems[2].nodeValue);
       </script>
    </body>
    </html>

     

    실행 결과

    노드 리스트의 텍스트 노드

      ul 요소 다음의 텍스트
    • 첫 번째 아이템이에요!
    • 첫 번째 li 요소 다음의 텍스트
    • 두 번째 아이템이에요!
    • 두 번째 li 요소 다음의 텍스트
    • 세 번째 아이템이에요!
    • 세 번째 li 요소 다음의 텍스트

     

     

    위의 예제는 각 요소 노드 다음에 또 다른 텍스트 노드가 존재함을 보여준다.

    따라서 노드 리스트에 인덱스를 이용하여 접근할 때는 이러한 텍스트 노드의 존재를 반드시 염두해 두어야 한다.

     

    노드 리스트 객체는 리스트에 노드를 추가하거나 삭제되면 자신의 상태 정보를 스스로 갱신한다.

    따라서 이 객체의 length 프로퍼티 값은 언제나 노드 리스트가 저장하고 있는 노드들의 총 개수를 나타낸다.

     

    🔔 예제)

    <!DOCTYPE html>
    <html lang="ko">
    <head>
        <meta charset="UTF-8">
        <title>JavaScript Node List</title>
    </head>
    <body>
        <h1>노드 리스트의 length 속성</h1>
        <ul id="list">
            <li>첫 번째 아이템이에요!</li>
            <li>두 번째 아이템이에요!</li>
            <li>세 번째 아이템이에요!</li>
        </ul>
        <p id="text"></p>
        <button onclick="changeTextColor()">글자색 변경!</button>
        <script>
            var listItems = document.getElementsByTagName("li");    // 모든 <li> 요소들을 선택함.
            document.getElementById("text").innerHTML = 
                "이 노드 리스트의 길이는 " + listItems.length + "개 입니다.<br>";    // 모든 자식 노드들의 개수를 반환함.
    
            function changeTextColor() {
                for (var i = 0; i < listItems.length; i++) {
                listItems[i].style.color = "orange";    // 모든 자식 노드들의 글자색을 변경함.
                }
            }
       </script>
    </body>
    </html>

     

    실행 결과

    노드 리스트의 length 속성

    • 첫 번째 아이템이에요!
    • 두 번째 아이템이에요!
    • 세 번째 아이템이에요!

     

     

     

    728x90
    반응형

    'Language > JavaScript' 카테고리의 다른 글

    [JavaScript] 노드의 조작  (0) 2018.10.22
    [JavaScript] 노드의 관리  (0) 2018.10.22
    [JavaScript] DOM 요소  (0) 2018.10.22
    [JavaScript] DOM / Document 객체  (0) 2018.10.19
    [JavaScript] Array 객체 / 메소드  (0) 2018.10.19
상단으로