본문 바로가기
인천일보아카데미/- 학습일지

[학습일지]JAVA교육일지 20일차

by w1z 2022. 5. 31.

12장 문서 객체 모델과 이벤트 다루기

12.1) 문서 객체 모델

  • 문서 객체 모델(DOM) : 웹 브라우저에 표시되는 HTML 문서 구조를 객체화한 모델 구조
  • 웹 브라우저는 생성한 문서 객체 모델을 통해 HTML 문서의 구성요소를 객체로 인식할 수 있음
  • 자바스크립트도 웹 브라우저의 문서 객체 모델을 조작해 웹 브라우저에 표시되는 HTML 문서 구조를 변경하거나 새로운 구성 요소를 추가하는 등의 작업을 할 수 있음

12.1.1 문서 객체 모델이 생성되는 방식

  • 웹 브라우저가 HTML 문서를 해석, 해석한 HTML 문서 구조를 객체로 변환하는 방식으로 생성됨, 생성한 문서 객체 모델을 웹 브라우저에 표시
  • 웹 브라우저에 표시되는 HTML 문서는 내부적으로 문서 객체 모델을 해석해서 보이게 됨
  • DOM트리 : HTML 문서 기반으로 생성, HTML 문서의 각 구성 요소는 노드가 됨

ex)

- 노드(node) : document 객체 하위에 트리형태로 구성되는 각각의 HTML 태그 요소, 속성, 텍스트, 주석 등

- 루트 노드(root node) : DOM 트리의 가장 꼭대기(최상위)에 있는 노드, document는 객체임으로 루트노드는 html

- 각 노드는 부모, 자식, 형제 관계가 형성됨

12.1.2 노드 타입 살펴보기

  • HTML 구성 요소에 따라 노드의 타입이 다름

* 주요 노드 타입

타입
설명
문서 노드(Node.DOCUMENT_NODE)
최상위 document 객체의 노드 타입
요소 노드(Node.ELEMENT_NODE)
h1, p 태그와 같은 요소의 노드 타입
속성 노드(Node.ATTRIBUTE_NODE)
href, src와 같은 속성의 노드 타입
텍스트 노드(Node.TEXT_NODE)
텍스트에 해당하는 노드 타입
주석 노드(Node.COMMENT_NODE)
주석에 해당하는 노드 타입
  • 문서 객체 모델은 CSS를 포함하지 않기 때문에 CSS 관련 노드타입은 없음

12.2) 노드 선택하기

  • JS로 웹브라우저에 표시되는 HTML 문서를 조작하려면 문서 객체 모델을 조작해야함
  • 문서 객체 모델은 window 객체의 document 객체를 사용해 조작
  • document 객체로 조작하려는 DOM의 노드를 선택
  • JS는 주로 요소 노드를 선택해 조작

12.2.1 속성으로 노드 선택하기

  • document 객체는 트리를 탐색하면서 원하는 노드를 선택할 수 있는 속성 제공

* 속성 구분

- 모든 노드 탐색 : 노드 타입을 구분하지 않고 탐색할 수 있는 속성

- 요소 노드 탐색 : 요소 노드 타입만 탐색할 수 있는 속성

구분
속성
설명
모든 노드 탐색
parentNode
부모 노드 반환
childNodes
모든 자식 노드 반환
firstChild
첫 번째 자식 노드 반환
lastChild
마지막 자식 노드 반환
previousSibling
이전 형제 노드 반환
nextSibling
다음 형제 노드 반환
요소 노드 탐색
parentElement
부모 요소 노드 반환
children
자식 요소 노드 반환
firstElementChild
첫 번째 자식 요소 노드 반환
lastElementChild
마지막 자식 요소 노드 반환
previousElementSibling
이전 요소 노드 반환
nextElementSibling
다음 요소 노드 반환
  • 노드 탐색 속성은 연속으로 사용할 수 있음

ex) document.childNodes[1].firstElementChild.firstElementChild.nextElementSibling;

12.2.2 메서드로 노드 선택하기

DOM트리가 복잡하면 원하는 노드를 찾기 어려워서, 일반적으로 요소노드를 바로 선택할 수 있는 메서드를 이용한 노드선택 방법과 조합해서 사용

* 속성값과 태그명 사용하기 - get 메서드

메서드 형식
getElementById(<id 속성값>)
id 속성값과 일치하는 요소 노드를 1개만 선택
getElementsByClassName(<class 속성값>)
class 속성값과 일치하는 요소 노드를 모두 선택
getElemenetsByTagName(<태그명>)
태그명과 일치하는 요소 노드를 모두 선택
  • 각 메서드는 매개변수로 class 속성값, id 속성값, HTML 태그명을 전달받아 노드 선택

ex)

<body> <h1 id="title">title</h1> <p class="text">text-1</p> <p class="text">text-2</p> <script> // id 속성값이 title인 요소 노드 1개 선택하기 const el = document.getElementById("title"); console.log(el); // class 속성값이 text인 요소 노드 모두 선택하기 const classEl = document.getElementsByClassName("text"); console.log(classEl); // p 태그에 해당하는 요소 노드 모두 선택하기 const tagEls = document.getElementsByTagName("p"); console.log(tagEls); </script> </body>

- getElementById( ) 메서드로 선택하는 요소 노대는 무조건 1개이기 때문에 해당하는 요소 하나만 보여줌

- 다른 두 메서드는 HTMLCollection 객체로 여러 요소를 한꺼번에 선택

- HTMLCollection 객체는 유사 배열, 배열의 인덱스 요소에 하나씩 접근 가능

ex)

<script> const classEl = document.getElementsByClassName("text"); console.log(classEl[0]); console.log(classEl[1]); const tagEls = document.getElementsByTagName("p"); console.log(tagEls[0]); console.log(tagEls[1]); </script>

* CSS 선택자 사용하기 - query 메서드

  • document 객체의 메서드 중에는 매개변수로 CSS 선택자를 전달받아서 노드를 선택하는 메서드도 있음
메서드 형식
설명
querySelector(<CSS 선택자>)
매개변수로 넘어오는 CSS 선택자에 해당하는 노드를 1개만 선택
querySelectorAll(<CSS 선택자>)
매개변수로 넘어오는 CSS 선택자에 해당하는 노드를 모두 선택,
노드를 2개 아싱 선택할 때 사용

ex)

<body> <div class="box-1"> <p class="text">text-1</p> <p class="text">text-2</p> </div> <div class="box-2"> <p class="text">text-3</p> <p class="text">text-4</p> </div> </body> 1. class 속성값이 box-1인 요소 노드를 선택하려면? querySelector( ) 메서드 이용 <script> const el = document.querySelector(".box-1"); </script> 2-1. class 속성값이 box-1인 요소의 하위에 있는 p태그 선택? getElementsByClassName( ) 메서드 활용 <script> const el = document.getElementsByClassName("box-1")[0].children; console.log(el); </script> 2-2. CSS 선택자를 사용하는 querySelectorAll( ) 메서드 활용 <script> const el = document.querySelectorAll(".box-1 .text"); console.log(el); </script>
  • 메서드의 매개변수가 CSS선택자를 전달하니 더 간단하게 우너하는 노드 선택 가능
  • 여러 개의 노드는 선택할 때 getElementsByClassName() 메서드와 getElementsByTagName() 메서드는 HTMLCollection객체에 담아 반환 / querySelectorAll() 메서드는 NodeList 객체에 담아 반환함

12.3) 노드 조작하기

12.3.1 콘텐츠 조작하기

선택된 노드가 요소 노드라면 콘텐츠 조작 속성으로 조작 가능

* 요소 노드의 콘텐츠 조작 속성

속성
설명
textContent
요소 노드의 모든 텍스트에 접근
innerText
요소 노드의 텍스트 중 웹 브라우저에 표시되는 텍스트에만 접근
innerHTML
요소 노드의 텍스트 중 HTML 태그를 포함한 텍스트에만 접근
ex) <p id="title">Hello, <span style="display:none">Javascript!</span></p> - 콘텐츠 조작 속성으로 접근했을 때 각 속성이 가져오는 콘텐츠는 다음과 같음 document.getElementById("title").textContent; // Hello, Javascript! document.getElementById("title").innerText; // Hello, document.getElementById("title").innerHTML; // Hello, <span style="display:none">Javascript!</span>
  • 콘텐츠 조작 속성은 접근한 노드의 콘텐츠를 가져올 뿐만 아니라 속성에 값을 할당하면 각 노드의 콘텐츠를 바꿀 수도 있음
<p id="textContent"></p> <p id="innerText"></p> <p id="innerHTML"></p> <script> document.querySelector("#textContent").textContent = `<strong>textContent</strong> 속성`; document.querySelector("#innerText").innerText = `<strong>innerText</strong> 속성`; document.querySelector("#innerHTML").innerHTML = `<strong>innerHTML</strong> 속성`; </script>

- innerHTML 속성에 값 할당 : 태그로 인식해 노드의 콘텐츠에 적용

- textContent 속성과 innerText 속성은 단순 텍스트 취급, 값을 그대로 노드 콘텐츠에 넣음

12.3.2 스타일 조작하기

선택된 노드가 요소 노드라면 style 속성으로 요소에 스타일(CSS) 지정 가능

(형식) <노드>.style.<css 속성명> = <속성값> ;

ex) p 태그의 텍스트 색상을 빨간색으로 변경하고 싶다면

- querySelector( ) 메서드로 조작하고 싶은 노드 선택

- 선택한 노드에 style 속성으로 조작하고 싶은 css 속성명 적고, 적용하고 싶은 css 속성값 할당

<p id="text">text</p> <script> const pEl = document.querySelector("p"); // 노드 선택하기 pEl.style.color = "red"; </script>

※ 주의할 점 : background-color 처럼 속성명에 대시(-)가 있는 속성은 JS에서 뺄셈연산자(-)로 인식. backgroundColor 처럼 카멜표기법으로 작성해야함.

12.3.3 클래스 속성 조작하기

JS로 class 속성을 조작해 스타일 적용가능

선택한 요소 노드에 class 속성을 지정할 때는 classList 속성의 add( ), remove( ), toggle( ) 메서드 사용

(형식)
<노드>.classList.add("class 속성값"); // 추가
<노드>.classList.remove("class 속성값"); // 삭제
<노드>.classList.toggle("class 속성값"); // 추가와 삭제 반복

ex)

<style> .red-color{ color:red; } .fz20{ font-size:20px; } </style> (중략) <p id="text">text</p> <script> const pEl = document.querySelector("#text"); // 노드 선택하기 pEl.classList.add("red-color"); pEl.classList.add("fz20"); </script>

- classList 속성의 add( ) 메서드로 class 속성값 추가, 콤마(,)로 구분하여 여러 개를 한번에 추가 할 수 있음

- 적용된 class 속성값을 삭제하고 싶을 때는 classList의 remove( ) 메서드 사용

- toggle( ) 메서드는 add( ) 메서드와 remove( ) 메서드 반복 호출

12.3.4 데이터 속성 조작하기

  • data-* 속성 : HTML5에 추가된 속성, 사용자가 원하는 속성을 추가할 수 있는 사용자 정의(custom) 속성
  • data-* 속성은 JS의 dataset 속성을 자용해 조작
  • dataset 속성은 HTML 문서에서 data-*속성을 가져오거나 지정

ex) data-* 속성이 적용된 HTML 요소 노드를 선택해 data 속성값 출력

<button data-cnt="10">가방 구매</button> <button data-cnt="0">신발 구매</button> <script> const buttonEls = document.querySelectorAll("button"); buttonEls.forEach((el) => { console.log(el.dataset); }) </script>

- querySelectorAll( ) 메서드로 button 태그에 해당하는 노드 한 번에 선택

- forEach( ) 메서드로 반복해서 각 노드에 접근한 뒤, dataset 속성으로 data-cnt 정보를 가져와 출력

- 실행결과를 보면 dataset 속성으로 노드의 data-* 속성에 대한 정보를 가져와 DOMStringMap객체에 담겨 반환됨

- 정확하게 data-cnt 속성의 값만 가져오고 싶으면 다음처럼 객체 속성에 접근하는 방법 사용

<script> const buttonEls = document.querySelectorAll("button"); buttonEls.forEach((el) => { console.log(el.dataset.cnt); }) </script> 실행결과) 10 0

- 속성에 값을 항당하면 data-*의 속성값을 바꿀 수도 있음

<script> const buttonEls = document.querySelectorAll("button"); buttonEls.forEach((el) => { el.dataset.cnt = 50; // data-cnt의 값을 50을 변경 }) </script>

12.3.5 메서드로 속성 조작하기

  • 모든 속성을 전체적 조작 가능한 메서드

* 속성 조작 메서드

메서드 형식
설명
<노드>.getAttribute("속성명");
선택된 요소노드의 속성값 가져옴
<노드>.setAttribute("속성명", "속성값");
속성값 설정
<노드>.removeAttribute("속성명");
속성 삭제

ex) getAttribute( ) 메서드 : 속성값을 가져오고 싶을 때 사용

길벗

- querySelector( ) 메서드로 a태그에 해당하는 요소노드 선택

- getAttribute( ) 메서드로 href 속성값을 가져옴

- 개발자 도구 콘총창을 보면 href의 속성값이 출력됨

ex) setAttribute( ) : 속성값을 새로 설정하고 싶을 때 사용

길벗

- setAttribute( ) 메서드로 href 속성값 새로 설정

- a태그의 텍스트를 바꾸기 위해 innerText 속성값 사용

- 바꾼 속성값을 적용해 새 창으로 열리게 하고 싶으면 setAttribute() 메서드로 target 속성값을 _blank 로 지정

  • getAttribute( ) 메서드와 setAttribute( ) 메서드는 모든 속성의 상위 메서드 → classList속성, dataset속성으로 하는 조작 전부 가능

※ classList 속성과 setAttribute( ) 메서드

- classList 속성으로 class속성값을 추가,삭제하면 기존에 있던 class 속성값을 보존하면서 추가,삭제

- setAttribute( ) 메서드는 속성값을 아예 새로 설정, 기존 class 속성값 보존하지 않음

- classList 속성의 remove( ) 메서드와 removeAttribute( ) 메서드에서도 똑같이 적응됨

12.4) 노드 추가/삭제하기

DOM트리에서 새로운 노드를 생성하고, 생성한 노드를 기존 DOM트리와 연결하면 동적으로 새로운 요소를 화면에 추가할 수 있음

12.4.1 노드 추가하기

화면에 새로운 요소 추가 : DOM트리에 새로운 노드를 생성 - 생성한 노드를 기존 DOM 트리 노드와 연결

* 노드 추가 메서드

구분
메서드
설명
노드 생성
createElement()
요소 노드 생성
createTextNode()
텍스트 노드 생성
createAttribute()
속성 노드 생성
노드 연결
<기준 노드>.appendChild(<자식 노드>)
기준 노드에 자식 노드 연결
<기준 노드>.setAttributeNode(<속성 노드>)
기준 노드에 속성 노드 연결
  • DOM트리의 주축 노드는 요소 노드, 일반적으로 DOM트리에 새로운 노드를 연결할 때는 요소노드를 먼저 생성

ex)

<!DOCTYPE html> <html> <head> <title>Create Node</title> </head> <body> <script></script> </body> </html> <script> // 요소 노드 생성하기 (DOM트리와 연결되지 않은 새로운 요소 노드) const aEl = document.createElement("a"); // 생성된 노드를 기존 DOM트리와 연결, 앞서 생성한 a요소 노드를 body 요소 노드의 자식 노드로 연결 document.body.appendChild(aEl); /* 단순 요소 노드 연결으로는 웹브라우저에 아무것도 표시되지 않아서 보통은 텍스트 노드도 함께 연결 텍스트 노드를 생성한 후, querySelector()메서드로 a요소노드를 선택해 appendChile() 메서드로 연결 */ const txtEl = document.createTextNode("길벗"); document.querySeletor("a").appendChile(txtEl); </script>
  • hn, p, span,i 태그처럼 일반적으로 텍스트가 필요한 요소들은 텍스트 노드만 생성하고 연결해도 충분함
  • a 태그, img 태그처럼 별도의 속성이 필요한 요소들은 속성 노드까지 생성해 연결해야 함
  • 주의! 속성 노드는 a 요소 노드의 자식노드로 추가하는 것이 아님

12.4.2 노드 삭제하기

  • removeChild( ) 메서드 사용 : 부모 노드에 연결된 자식 노드를 삭제
(형식) <부모 노드>.removeChild(<자식 노드>)
  • 삭제 노드는 항상 부모 노드에서 removeChile( ) 메서드를 사용해야함
  • 따라서, 부모 노드를 반환하는 parentNode 속성으로 부모노드에 접근해서 삭제

ex) p 요소 노드를 찾아서 삭제하는 코드

text 1

길벗 수코딩

ex) DOM트리를 순회하면서 a 태그에 해당하는 요소 노드를 모두 삭제하는 코드

text 1

길벗 수코딩