Knowledge Map

DOM 접근 본문

WEB/JAVASCRIPT

DOM 접근

2016. 3. 13. 17:29

DOM 이란 무엇인가?

DOM은 HTML에 대한 매핑 레이아웃 모델이자 자바스크립트가 HTML에서 특정작업을 할 수 있는 수단이다. 

DOM은 HTML도 아니고 자바스크립트도 아니지만 세가지는 서로 긴밀하게 연결되어야 있다. 이것은 엘리먼트의 조합(객체)이자 그러한 객체를 표시하는 순서(모델)이며 자바스크립트에서 제공하는 다양한 메소드를 이용해 돌아다니는 동안 전체 구조(문서)의 일부를 추가, 삭제, 수정하는 무한한 접저을 제공한다. HTML은 문서이며 문서안에는 수많은 객체로 구성돼 있다. 이러한 객체는 특정순서(모델)로 나타난다.


DOM트리

DOM은 웹 브라우저에서부터 시작한다. 웹사이트를 방문할 때 브라우저는 HTML을 문서로 렌더링하고 각 엘리먼트를 통해 읽으며, 그것들을 사용자에게 보여준다. 이 과정은 문서에 대한 초기 모델이 만들어지고 저장되어 개별 엘리먼트에 접근하기 위해 그러한 작업을 모두 다시 해야할 필요가 없다.


1
2
3
4
5
6
7
8
9
10
11
12
<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8">
    <title>기초적인 DOM예제</title>
</head>
<body>
    <h1>Hello World!</h1>
    <p> 이 문서가 <strong> 대단히 기초적인 HTML 문서이지만</strong>
        실질적으로 문서객체모델의 상세 예제로도 사용된다. </p>
</body>
</html>
cs


DOM은 노드(node)라고 하는 항목으로 구성되는데, 노드는 부모, 자식, 형제를 가질수 있으며 여기에 따라 트리상의 위치가 결정된다.

DOM에서 노드라고 부르는 실제로 다양한 유형의 엘리먼트에 해당한다.

  -  문서 노드(document node) : 전체 부모 노드. 문서에서 노드를 접근하고 싶을 때마다 트리를 타고 내려가서 노드와 상호작용하기에 앞서 먼저 문서노드를 거쳐야 한다.

  -  엘리먼트 노드(element node) : HTML 엘리먼트를 나타내는 노드

  -  텍스트 노드(text node) : 텍스트를 나타내는 노드

  -  속성 노드(attribute node) : 속성을 나타내는 노드



엘리먼트노드 : 문서의 상당부분을 차지, 노드를 탐색하는 기초가 된다. 이 노드는 문서의 대부분을 차지하며, 트리와 유사한 구조를 만들어낸다.



DOM에서 엘리먼트 노드를 강조한 그림, 문서의 대부분을 차지한다.


텍스트 노드

DOM에 위치하는 방식을 비롯해 엘리먼트 노드와 같은 자바스크립트 메소드를 이용해 노드에 접근한다는 점에서 텍스트 노드는 엘리먼트 노드와 비슷하다. 하지만 가장 주목할 만한 차이점은 생김새다. 엘리먼트 노드는 각진 괄호 <> 에 담겨있다. 텍스트 노드는 그렇지 않으며 엘리먼트 노드 사이에 위치한다. 텍스트 노드는 자식을 가질 수 없다. 









속성노드 : 속성 노드는 엘리먼트노드와 전혀 다른 종류의 노드이자 중요한 노드이다. 속성 노드도 자식을 가질수 없으며 속성 노드 자체도 엘리먼트 노드의 자식 엘리먼트가 아니다. 늘 엘리먼트 노드에 첨가되기 때문에 구조상 엘리먼트 노드 아래의 DOM 구조에 위치하기는 하지만 전혀 다른 방식으로  취급하고 접근한다. 자체적인 메소드가 없다. 기본적인 자바스크립트 메소드를 이용해 속성 근처에 도달할 수는 있지만 그 이후에는 속성 안으로 진입하려면 특별한 메소드를 사용해야 한다.





엘리먼트 노드 사용

DOM에 뭔가가 나열돼 있으면 자바 스크립트를 이용해 그러한 노드에 접근해서 저장하거나 수정할 수 있다.


ID를 이용한 엘리먼트 선택

HTML 표준에는 엘리먼트 ID값이 문서 내에서 유일해야 한다고 명시한다. 그러한 이유로 ID를 문서의 접근 지점으로 이용하는 것은 가장 효율적이고 바람직하다. 엘리먼트 노드에 빠르게 접근하기 위해 별도의 ID를 지정해야 할 때도 있다. 성능 측면에서는 이 방법이 가장 빠르다. ID속성을 이용하고 있지만 이 시점에서 속성 노드가 아닌 엘리먼트 노드에 접근하는 것이다. ID 속성의 내용(header, homelink)에 접근하는 것이라면 속성노드이겠지만 그렇지 않기에 여전히 엘리먼트 노드에 머무르는 것이다.

getElementById는 모든 브라우저에서 지원한다.

HTML에서 ID를 사용하는 것은 자바스크립트 성능에도 좋을 뿐더러 스타일을 적용할 때 CSS에도 좋고 구체적이어서 좋다. ID는 스크린 리더나 시각적인 장애가 있는 사용자를 위해 어딘가로 곧바로 이동하거나 '콘텐츠로 이동' 링크를 만들 때 접근성 향상 기능에 사용될 수도 있다.



1
2
3
4
5
6
7
8
<div id="header">
    <h1><a href="/" id="homelink">제목 사이트</a></h1>
</div>
 
<script>
document.getElementById("header");
document.getElementById("homelink");
</script>
cs



태그 이름을 이용한 엘리먼트 선택

한개 이상의 엘리먼트가 필요하거나 엘리먼트 그룹이 필요할 때가 있다. 이러한 경우 getElementsByTagName()을 이용하면 된다.

주의할 건 getElementsByTagName에서 element는 s가 붙는다는 것이다. 주의하자.


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8">
    <title>기초적인 DOM예제</title>
</head>
<body>
    <h1>Hello World!</h1>
    <p>콘텐트 단락1</p>
    <p>콘텐트 단락2</p>
    <p>콘텐트 단락3</p>
    <p>콘텐트 단락4</p>
    <p>콘텐트 단락5</p>

 
<script>
    document.getElementsByTagName("p");
    document.getElementsByTagname("p").length//3을 반환
    if(document.getElementsByTagName("p").length> 0){
    //0보다 크면 작업이 진행됨
    }
</script>

</body>
</html>d
cs


이렇게 하면 NodeList 라는 DOM 객체가 반환된다. NodeList는 엘리먼트의 원래 순서가 유지되는 노드의 컨렉션을 반환한다. NodeList는 엘리먼트의 목록이며, 각 엘리먼트는 페이지에 나타나는 원래 순서를 유지한다. 엘리먼트가 나타나는 순서가 중요한 이유는 항목이 무작위로 섞여있을 경우 엘리먼트가 필요할 때 엘리먼트에 접근하기가 굉장히 어려워질 것이기 때문이다.  NodeList를 확보하고나면 NodeList의 길이를 확인하고 싶을 것이다. NodeList의 길이를 확인하면 스크립트 블록이 실행하기 전에 사용가능한 값이 얼마나 있는지 확인할 수 있다.


NodeList에서 원하는 항목을 꺼내는 것은 상당히 쉽다. 이렇게 하는데는 두 가지 상법이 있다.


ㅇitem메소드 사용

ㅇ배열 문법 사용


두방법 모두 같은 값을 반환하므로 NodeList에서 엘리먼트에 접근하는 방법은 선호의 문제이다. NodeList와 배열은 0에서부터 시작한다. 


1
2
3
4
5
6
7
8
9
<script>
//item메소드를 이용한 첫번째, 두번째 단락 선택
document.getElementsByTagName("p").item(0);
document.getElementsByTagName("p").item(1);
 
//배열 문법을 이용한 두 번째 단락 선택
document.getElementsByTagName("p")[0];
document.getElementsByTagName("p")[1];
</script>
cs


클래스를 이용한 엘리먼트 선택

최근에 자바스크립트에 엘리먼트의 클래스로 엘리먼트를 선택하는 방법이 마련되었다.

getElementsByClassName() 메소드이다. 이것은 getElementsByTagName() 메소드와 ㅣ비슷하게 NodeList를 만들어내고 그것에 접근한다는 점에서는 비슷하지만 조합해서 사용할수 있다.


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
<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8">
    <title>기초적인 DOM예제</title>
</head>
<body>
    <h1>Hello World!</h1>
    <p class="dropcap huge">콘텐츠 단락</p>
    <p id="e" class="dropcap">콘텐츠<span class="huge">단락</span></p>
    <p class="dropcap">콘텐츠 단락</p>
    <!-- 
    첫번째 엘리먼트 : 두개의 클래스가 지정되어 있다.
    두번째 엘리먼트 : 클래스가 단락에 하나, 자식 span노드에 하나 지정
    세번째 엘리먼트 : 하나의 클래스가 지정
    -->
    
    <script>
        //dropcap이라는 클래스가 지정된 모든 엘리먼트를 반환
        document.getElementsByClassName("dropcap");
        //dropcap과 huge클래스가 함께 지정된 모든 엘리먼트를 반환
        document.getElementsByClassName("dropcap huge");
        //e 라는 ID가 지정된 엘리먼트 내에서 huge라는 클래스가 지정된 모든 엘리먼트를 반환
        document.getElementById("e").getElementsByClassName("huge");
    </script>
</body>
</html>
cs


getElementsByClassName 메소드는 자바스크립트에 상당히 최근에 추가된 기능이기 때문에 버전마다 지원되는 경우가 다르다.


인터넷 익스플로러 : 9.0 및 상위버전

파이어 폭스 : 3.0 및 상위버전

크롬 : 4.0 및 상위 버전

오페라 : 9.5 및 상위버전

사파리 : 3.1 및 상위버전


자바스크립트에서 CSS 선택자를 이용한 노드 선택

querySelector(), querySelectorAll()는 CSS 형태로 선택자를 취할 수 있다.

querySelector() : 발견한 첫 번째 엘리먼트만을 반환한다.

querySelectorAll() : NodeList를 반환한다.


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
<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8">
    <title>기초적인 DOM예제</title>
</head>
<body>
    <div id="header">
        <h1>querySelector 사용</h1>
    </div>
    
    <p class="dropcap huge">콘텐츠 단락</p>
    <p class="dropcap">콘텐츠 <span class="huge">단락</span></p>
    <p class="dropcap">콘텐츠 단락</p>
    
    <script>
    //ID가 header인 엘리먼트에 접근
    document.querySelector("#header");
    //droptcap 클래스가 지정된 첫 번째 엘리먼트에 접근
    document.querySelector(".dropcap");
    //"dropcap"이라는 클래스가 지정된 모든 단락에 접근 (NodeList 반환)
    document.querySelectorAll(".dropcap");
    //"dropcap"이나 "huge"이라는 클래스가 지정된 모든 엘리먼트에 접근
    document.querySelectorAll(".dropcap, .huge");
    //클래스가 지정된 모든 단락에 접근
    document.querySelectorAll("p[class]");
    </script>
</body>
</html>
cs


querySelector()는 자바스크립트 언어에서 굉장히 유연하고 강력한 메소드다.

이 메소드는 여러 개의 선택자, ID, 클래스, 속성, 심지어 CSS 갓아 클래스를 가지고 엘리먼트를 선택할 수 있다. 


해당 메소드는 

인터넷 익스플로러 : 8.0 및 상위버전

파이어폭스 : 3.5 및 상위버전

크롬 : 1 및 상위버전

오페라 : 10 및 상위버전

사파리 : 3.2 및 상위버전


selector은 자바스크립트에서 중요한 부분이다. 

querySelector() 같은 메소드는 직접 브라우저 통계를 확인하고 해당 메소드를 안심하고 사용할수 있는지 판단할 필요가 있다. 


속성 노드 사용

속성은 엘리먼트 노드안에 있지만 해당 노드의 자식으로 간지되지는 않으므로 엘리먼트 노드의 정보를 구하거나 수정하거나 제거하려면 특별한 메소드가 필요하다.


getAttribute()


setAttribute()


removeAttribute()


hasAttribute()


이러한 메소드에서는 모두 속성을 선택하고 값을 반환하므로 class="visible" --> class를 선택하고 "visible"이라는 값을 반환하는 식으로 된다. 속성을 구하고 변경하는 것은 웹애플리케이션을 작성하는데 중요하다.


'WEB > JAVASCRIPT' 카테고리의 다른 글

javascript 변수타입확인, 반올림, 날짜 설정, 삼항연산자  (0) 2016.05.24
location.replace  (0) 2016.05.18
아코디언  (0) 2016.04.18
자바스크립트 용어  (0) 2016.02.28
점진적 기능 향상  (0) 2016.02.27
Comments