본문 바로가기

Programming/javascript

[7~8일차] Do it! 자바스크립트 입문 / 08 웹 문서를 다루는 방법, 문서 객체 모델(DOM)

전구 모양(💡) 이모티콘은 공부하면서 깨달은 부분을 적어두었습니다.

< 08-1 문서 객체 모델이란? >

- 문서 객체 모델(DOM) : Document Object Model

  : 웹 문서의 모든 요소를 자바스크립트를 이용하여 조작할 수 있도록

    객체를 사용해 문서를 해석하는 방법

 

- DOM을 사용하지 않고 상세 설명 가리기

  : html 태그 중 가리고 싶은 게 있다면 CSS로 처리

    => 관리가 번거롭고 어려움

// html 상세 설명 부분을 가리고 싶다면?
<h3>상세 설명</h3>
<p>2차 세계대전 이후 설립된 게뎁 농장은 유기농 인증 농장으로 여성의 고용 창출과 지역사회 발전에 기여하며 3대째 이어져 내려오는 오랜 역사를 가진 농장입니다. 게뎁 농장은 SCAA 인증을 받은 커피
 품질관리 실험실을 갖추고 있어 철처한 관리를 통해 스페셜티 커피를 생산합니다.</p>
      


// CSS로 처리
<h3 style="visibility: hidden">상세 설명</h3>
<p style="visibility: hidden">2차 세계대전 이후 설립된 게뎁 농장은 유기농 인증 농장으로 여성의 고용 창출과 지역사회 발전에 기여하며 3대째 이어져 내려오는 오랜 역사를 가진 농장입니다. 게뎁 농장은 SCAA 인증을 받은 커피
품질관리 실험실을 갖추고 있어 철처한 관리를 통해 스페셜티 커피를 생산합니다.</p>

 

 

 

- 콘솔 창에 document 입력 후 확인하기

  => 자바스크립트에서 웹 문서의 소스 전부를 인식할 수 있기 때문에 수정도 가능

  => document도 수많은 DOM 요소 중 하나

 

 

 

- DOM 트리 - DOM 구조는 나무처럼 생겼다

  * DOM은 body를 부모 요소로 h1, p를 자식 요소로 이해하고 구조화함

    => DOM 트리(Tree)라고 칭함

 

- DOM 트리는 가지와 노드로 표현

  * 노드(Node) : 웹 문서에 있는 요소나 속성을 나타냄

  * 가지 : 노드와 노드 사이의 연결 관계

 

- DOM 트리는 웹 문서의 모든 것을 표현

  예) HTML의 요소가 품고 있는 텍스트, 이미지 등

 

- DOM 트리는 웹 문서의 요소를 다음과 같이 표현

  * 웹 문서의 태그는 요소(Element) 노드로 표현
  * 태그가 품고 있는 텍스트는 해당 요소 노드(태그)의 자식 노드인 텍스트(Text) 노드로 표현
  * 태그의 속성은 모두 해당 요소 노드(태그)의 자식 노드인 속성(Attribute) 노드로 표현
  * 주석은 주석(Comment) 노드로 표현

 

 

- DOM 트리 살펴보기     [Live DOM Viewer]

  => 위 링크로 접속해서 DOM 트리가 만들어지는 과정을 확인할 수 있음

 

  * 보라색 : 태그 요소

    #text : 텍스트 노드

    텍스트 노드에 값이 없는 것 : 줄 바꿈

               실시간으로 DOM 트리 확인                                                       DOM 트리로 표현(줄바꿈 노드는 생략)                                 

  * html 노드 : root element이면서 다른 요소 노드가 뻗어 나가기 시작하는 노드

                   루트 노드(Root Node)라고 부름

 

 

 

 

 

 

< 08-2 DOM 요소에 접근하기 >

- DOM 요소에 접근한다 : 자바스크립트로 프로그램에 사용할 요소에 접근하는 것

 

- CSS는 선택자(Selector) 개념이 존재

  : HTML 요소의 스타일을 선택하여 수정할 때 CSS 선택자 사용

  💡 어떤 요소에 CSS를 변경할 것인지 그 요소를 선택할 때 사용하는 것

// ┌ 선택자(Selector)
   p { visibility : hidden; color: blue }

 

- CSS 선택자의 종류

  1) id 선택자

     : 해당 태그의 id 속성

     * id 속성 값은 한 문서 안에서 유일하기 때문에 자주 사용

     => getElementById()로 DOM 요소에 접근

<h1 id="heading">에디오피아 게뎁</h1>

콘솔창에서 확인 가능

 

 

  2) class 선택자

     : getElementsByClassName()로 DOM 요소에 접근

       => class 선택자는 id 선택자와 다르게 웹 문서 안에서 여러 번 사용 가능

 

     * 만약 1개의 요소만 접근하고 싶다면 배열의 인덱스 사용

 

 

  3) 태그 선택자

     : id나 class 선택자가 없는 DOM 요소에 접근할 때 사용   

     : getElementsByTagName()으로 DOM 요소에 접근

       => 함수명에 s가 붙는다면 웹 문서 안에서 여러 번 사용 가능하단 의미

 

    

  4) 다양한 방법으로 찾아주는 함수 : querySelector(), querySelectorAll()

      * id, class 값, 태그 이름 다 사용 가능

        => 입력 방식만 다름

              ⓐ id : id 값 앞에 샾(#)

              ⓑ class : class값 앞에 마침표(.)

              ⓒ 태그 : 기호 없이 태그 이름만 사용

              ※ querySelector()와 함께 class 선택자, 태그 이름을 사용할 때는

                 여러 요소 중 첫 번째 요소에만 접근 가능

        => 두 함수는 접근하는 DOM 요소 개수에만 차이가 있을 뿐 사용 방법은 같음

// getElementById() 와 querySelector()로 id값을 사용한 예제
document.getElementById("container")
document.querySelector("#container")

 

 

 

 

- getElementById()와 querySelector() 차이

  : getElementById()는 단순히 id 선택자를 사용해서 요소에 접근하지만

    querySelector()는 id 선택자뿐만 아니라 querySelector("#container > ui")처럼

    둘 이상의 선택자를 사용해서 요소에 접근 가능!

 

 

 

 

 

< 08-3 웹 요소의 태그 속성 가져와서 수정하기 >

- DOM 요소의 속성 노드에 접근하는 방법 알아보기

  : 속성 노드에 접근하면 HTML 요소의 속성 값을 원하는 값으로 수정 가능!

 

 

 

[ HTML 태그 속성을 가져오거나 수정하는 함수 - getAttribute(), setAttribute() ]

- getAttribute() : 해당 요소에 지정된 값을 반환

- setAttribute() : 해당 요소에 속성 값 설정(세팅)

 

 

 

 

 

< 08-4 DOM에서 이벤트 처리하기 >

- 이벤트 처리 방법 복습하기

  1) HTML 태그 안에서 이벤트 처리기 연결하기 (잘 사용하지 않음!)

     예) changPic() 이란 함수가 미리 선언했다면 해당 태그 안에 실행할 함수 추가

// 누르면 changePic() 함수 실행
<img id="pic" src="images/girl.png" onclick="changePic()">

     => 이 방법은 이벤트나 연결 함수를 바꾸려면 HTML 소스를 수정해야 함

          또 하나의 요소에 하나의 이벤트 처리기만 사용 가능

 

  2) DOM 요소에 이벤트 처리기 연결하기

      * 이벤트 처리기를 자바스크립트 소스에서 실행

      * HTML 태그와 뒤섞이지 않고 자바스크립트 소스를 사용한다는 점은 좋지만

        역시 하나의 요소에 하나의 이벤트 처리만 가능

<div id="container">
	<img id="pic" src="images/girl.png" alt="">
</div>
<script>		
	var pic = document.querySelector('#pic');
	pic.onclick = changePic;    // pic 요소를 누르면 changePic() 실행
        
	function changePic() {			
		pic.src = "images/boy.png";
	}
</script>

 

 

 

[ 실습 - addEventListener()로 여러 이벤트를 한 번에 처리하기 ]

- addEventListener() : 이벤트가 발생한 요소에 이벤트 처리기를 연결해 주는 함수

                              웹 문서뿐만 아니라 Document 객체나 Window 객체 어디에서든 사용 가능

//                    ┌ ⓐ 이벤트 유형         ┌ ⓒ 캡쳐 여부
pic.addEventListener("mouseover", "changePic", false);
//                                 └ ⓑ 함수

  ⓐ 이벤트 유형 : 처리할 이벤트 유형 지정

                        단, 이 함수에서 이벤트 유형을 지정할 때는 'on'을 붙이지 않고

                        'click'이나 'mouseover'처럼 이벤트 이름만 사용

 

  ⓑ 함수 : 이벤트가 발생했을 때 실행할 명령을 나열하거나 따로 함수를 만들었다면 함수명 지정

  ⓒ 캡처 여부 : 기본값 false, 이벤트를 캡쳐링 하는지 여부를 지정

      * 이벤트 캡쳐링(true) : DOM의 부모 노드에서 자식 노드로 이벤트가 전달되는 것

      * 이벤트 버블링(false) : DOM의 자식 노드에서 부모 노드로 이벤트가 전달되는 것 

 

※ 이벤트 캡쳐링과 버블링의 차이

더보기

💡 궁금해서 직접 찾아본 내용이나 지금 공부 단계에선 중요치 않은 내용이므로 스킵하셔도 됩니다.


이벤트 캡쳐링 : 최상위 요소 -> 최하위 요소까지 이벤트가 전달되는 방식
이벤트 버블링 : 해당 요소 -> 최상위 요소까지 이벤트가 전달되는 방식

WC3에서 명시한 그림


이벤트 캡쳐링과 버블링은 이벤트 시작점 -> 도착점만 다를 뿐
이벤트가 상위 또는 하위 한 방향으로 전달된다.

그럼 이 이벤트들은 언제 사용할까?
한 가지 동작으로 여러 요소에 적용시킬 때 사용하면 됩니다.
예를 들어 <td>Over the River, Charlie</td> 를 클릭했을 때
해당 태그 ~ 상위 태그들까지 bold 처리를 하고 싶다! << 이런 식으로
상위/하위 요소들에게 영향을 주는 이벤트를 처리할 때 사용하면 됩니다.

만약 특정 요소까지 접근하지 못하게 하길 원한다면
event.stopPropagation()를 이용해서 처리하면 됩니다.
예)
<tr onclick="alert('버블링은 여기까지 못 옴');">
    <td onclick="event.stopPropagation()">Over the River, Charlie</td>
</tr>

 

 

 

 

 

< 08-5 웹 요소의 스타일 가져와서 수정하기 >

- DOM으로 CSS 속성에 접근하고 수정하기

  * 자바스크립트로 특정 웹 요소에 접근하는 방법을 응용하면

    웹 요소에서 사용한 CSS 속성에 접근, 수정 모두 가능!

 

- 웹 요소를 화면에 표시하기/감추기

  * display와 visibility 차이

  설정 공통점 차이점
display display: none 화면에서 감추기 요소가 차지하던 공간도 사라짐
visibility  visibility: hidden 요소가 차지하던 공간은 안 사라짐

가운데 요소에 dispaly: none을 적용한 모습 (공간 유지 X)
가운데 요소에 visibility: hidden을 적용한 모습 (공간 유지 O)

 

 

 

 

 

 

< 08-6 DOM에 요소 추가하기 >

- 실습 : 참가 신청 명단 표시하기

  : 07장에서는 배열을 이용한 내용이지만

    이 장에서는 DOM에 노드를 추가하는 방법을 사용

 

- DOM에 새로운 노드를 추가하는 방법

  * 어떤 소스를 추가할 것인지 고려

추가할 태그의 각 요소 파악하기

 

- 새로운 노드를 만들거나 부모 노드에 연결할 때 사용하는 함수들 

  함수 설명
1 createElement() 새 요소 노드 만들기
2-1 createTextNode() 텍스트 내용이 있다면 텍스트 노드 만들기
appendChild() 텍스트 노드를 요소 노드에 자식 노드로 추가
2-2 createAttribute() 요소에 속성이 있다면 속성 노드 만들기
setAttributeNode() 속성 노드를 요소 노드에 연결
3 appendChild() 새로 만든 요소 노드를 부모 노드에 추가

 

 

- 웹 문서에 새로운 노드 추가하기

  1) 요소 노드 만들기

      * 가장 먼저 할 일!!

      * createElement() 사용

// 입력해도 아직은 보이지 않음
var newP = document.createElement("p");

 

 

  2) 텍스트 노드 만들기

      * 요소에 추가할 텍스트 입력

      * createTextNode() 사용

// 아직은 화면에 출력되는 내용 없음
var newText = document.createTextNode("주문이 완료되었습니다.");

 

 

  3) 자식 노드로 추가하기

      * 1, 2번은 각 노드로 존재 (아직 트리형태 X)

      * appendChild() 사용

      * 자식 노드를 여러개 추가한다면 appendChild()를 사용해서 연결하는 노드는

        자식 노드 중 맨 끝에 추가됨

newP.appendChild(newText);	// newP(부모)-newText(자식)

 

     * 1번에서 만든 <p>는 웹 문서의 <body> 안에 추가해야 함

document.body.appendChild(newP);

 

 

  4) 속성 노드 만들기

      * createAttribute() 사용

      * 텍스트 노드를 만들어 웹 문서에 추가해 놓았다면 더 간단히 속성 추가 가능!

var attr = document.createAttribute("class");	// class 속성 추가
attr.value="accent";	// class 이름 추가


// 만약 텍스트 노드를 만들어 웹 문서에 추가했다면
// 더 간단히 속성 추가 가능!
newP.setAttribute("class", "accent");

 

 

  5) 속성 노드 연결하기

      * setAttributeNode() 사용

newP.setAttributeNode(attr);

 

 

 

[ 실습 - 참가 신청 명단 프로그램 만들기 ]

- 1단계 : 버튼에 이벤트 함수 지정하기

  * onclick()에 return false; 추가하는 이유 : 원래 버튼의 기능(서버 전송)을 사용하지 않겠다는 의미

 

- 2단계 : 이벤트 함수 정의하기

  * p 요소 만들기 → 텍스트 필드 내용 가져오기 → 새 텍스트 노드 만들기 → 텍스트 노드(자식)와 p 노드(부모) 연결

    → #nameList 가져오기 → p 노드(자식)와 nameList 노드(부모) 연결 → 텍스트 필드 비우기

 

- 3단계 : 웹 브라우저에서 확인하기

 

 

 

 

 

< 08-7 추가한 노드 순서 바꾸거나 삭제하기 >

- 노드 리스트(Node List)

  : querySelectorAll()를 사용해 여러 개의 노드를 한꺼번에 가져오면 여러 개의 요소 노드가 한꺼번에 저장되는 것

    예) 웹 페이지의 p 노드 3개

    => 이 노드들에 접근하려면 인덱스를 사용

// 웹 페이지의 <p> 요소 가져오기
document.querySelectorAll("p");

// <p> 요소 중 첫번째 가져오기
document.querySelectorAll("p")[0];

 

 

- DOM 트리를 활용해 원하는 노드 다루기

  1) 자식 노드 확인하기

      * hasChildNodes() 사용

        => 자식 노드가 있다면 true, 자식 노드가 없다면 false 반환

 

  2) 자식 노드에 접근하기

      * childNodes 사용 

         => 요소 노드뿐만 아니라 태그와 태그 사이의 줄 바꿈

              빈 텍스트 노드인 자식 노드로 인식함

인덱스 0, 2, 4, 6은 줄바꿈이나 빈 텍스트로 인식

 

 

 

      * 요소에만 접근하려면 children 속성 사용하기

        => 요소 노드, 텍스트 노드, 주석 노드까지 모두 접근 가능

             만약 자식 노드 중에서 텍스트 노드와 주석 노드는 필요하지 않다면

             children 속성을 사용하면 됨!

 

  3) 원하는 위치에 노드 삽입하기

      * insertBefore() 사용

        : 부모 노드에 자식 노드를 추가할 때 기준이 되는 노드를 지정하고

          그 앞에 자식 노드를 추가 가능

var nameList = document.querySelector("#nameList");	// #nameList 가져옴
nameList.insertBefore(nameList.children[2], nameList.children[0]);
//                    └ 추가할 노드         └ 기준 노드

 

 

  4) 특정 노드 삭제하기

      * removeChild() 사용

        : 부모 노드에서 자식 노드를 삭제하는 함수

          괄호 안에는 삭제하려는 자식 노드가 들어감

      * 노드는 스스로 자신을 삭제할 수 없음

        => 먼저 부모 노드를 찾아 접근한 후 부모 노드에서 삭제해야 함

      * parentNode : 부모 노드를 찾는 속성 

var firstDel = document.querySelectorAll(".del")[0]; // 클래스명이 del인 첫번째 요소
var firstP = document.querySelectorAll("p")[0];	     // p요소들 중 첫번째 요소
firstP.removeChild(firstDel);	// 첫번째 p 요소에 있는 클래스명이 del인 첫번째 요소 삭제