본문 바로가기
Front/JavaScript

[JavaScript] DOM(Document Object Model)

by 시월해 2021. 4. 26.

DOM(Document Object Model : 문서 객체 모델)
웹 화면에 보이는 요소를 조작하기 위한 기능으로 가득 찬 라이브러리 덩어리.
웹 브라우저가 HTML 페이지에 접근하는 방법을 정의한 API임.
- DOM에서 제공하는 일반적인 기능은 여러 개의 DOM 객체로 나눠 구성되어 있음.
- DOM은 정의부분(명세서)와 구현부분으로 나누어져 있음.

- 정의부분인 명세서에는 웹 페이지 문서를 조작할 때 지켜야 할 약속(규칙, 규약)이 명시되어 있는 문서일 뿐 실제 동작하는 구현 소스코드는 전혀 존재하지 않음. 텅 빈 상자와도 같음. 그리고 이 명세서를 만드는 곳이 바로 웹 관련 표준을 정의하는 협회인 W3C임. 구현부분은 바로 브라우저 내부에 존재함.
- 브라우저 제작사(IE, Chrome, Firefox, Safari)는 DOM에 명시되어 있는 인터페이스에 맞춰 자신들만의 특화된 고유 기술을 이용해 독자적으로 기능을 구현함.
- IDL(Interface Definition Language)은 DOM의 정의부분을 만들 때 사용하는 인터페이스 정의 전용 언어임. 프로그래밍 언어 중 하나이며, 고유의 문법이 있음.

(참고 : http://www.w3.org/TR/DOM-Level-2-HTML/html.html#ID-22445964)  

 

- 눈에 보이진 않지만 사실 브라우저에 출력된 웹 페이지는 온통 DOM 객체로 구성되어 있음.

 

- DOM 객체는 텍스트와 이미지, 하이퍼링크, 폼 엘리먼트 등의 각 문서 엘리먼트를 나타냄.

 

- 자바스크립트 코드에서는 동적인 HTML을 만들어내기 위해 DOM 객체에 접근하여 조작할 수 있음.

 

- 문서 객체 : 자바스크립트에서 이용할 수 있는 객체.
* 노드 : - HTML 웹 페이지 구성 요소의 가장 작은 단위를 말함. 
           - 문서를 이루는 모든 요소를 통합해서 부르는 용어. 즉, HTML 페이지의 각 요소(태그)들. 주석도 노드에 속함.
           - 브라우저는 이런 노드로 가득찬 웹 페이지를 읽어들여 해석한 후, 각 노드에 접근해 제어할 수 있는 DOM 객체를 생성함. 
* 요소(element) : <시작태그>텍스트</끝태그>
* 텍스트 노드 : 요소 안에 있는 글자. innerHTML과 관계가 있음.

 

- 노드, 스타일, 속성, 이벤트, 위치 및 크기들을 다룰 수 있는 다양한 기능이 포함되어 있음.

 

- DOM 객체가 생성되는 순서를 자세히 살펴 보면, 웹브라우저는 가정 먼저 최상위에 해당하는 HTMLDocument 쿨래스의 객체를 생성함. 이후에 생성되는 모든 DOM 객체는 HTMLDocument 객체의 자식 객체로 만들어 짐.

 

- 보통 DOM 방식은 트리 구조임. 브라우저가 웹 페이지를 처리하는 과정을 살펴보면 먼저 브라우저는 문서 정보에 쉽게 접근하고 조작하고자 HTML 웹 페이지를 읽은 후 파싱 단계를 거침. 이 후 DOM 객체로 변환(트리구조) 후 화면에 출력을 함.

 

예를 들어 웹 페이지에 <img src="test.jpg">태그 노드가 있다면 브라우저에 의해 HTMLImageElement라는 DOM 객체가 생성이 됨. 이 객체는 다른 DOM 객체와는 다르게 이미지를 읽어들이는 특별한 기능이 있어서 실행 시에 "test.jpg" 라는 외부 이미지 파일을 읽어 들이게 됨. 즉, 문서 상의 노드는 "브라우저이군. 이 노드를 보고 알맞은 DOM 객체를 생성해 주세요" 라는 의미일 뿐, 모든 작업은 브라우저에서 만들어낸 DOM 객체로 처리를 하게 됨.

  <브라우저가 웹 페이지를 처리하는 과정>
  

1. 웹 페이지 읽기
     - 먼저 브라우저는 HTML 페이지를 읽음.
  

2. 파싱 단계
     - 이어서 파싱(parsing) 단계를 거쳐서 웹 페이지 내용을 해석하게 됨.

     - 작성한 마크업 태그와 1:1 매칭이 되는 DOM 클래스 객체를 생성하게 됨.
     - 생성된 객체는 저마다 고유한 기능을 하게 됨. 

 

 좀 더 자세하게 설명을 한다면 웹 브라우저가 HTML 페이지를 읽은 후 파싱 단계에서 <div> 태그를 만나게 되면 HTMLDivElement 라는 클래스의 인스턴스(객체)를 생성하게 되고, <img> 태그를 만나면 HTMLImageElement 라는 클래스의 인스턴스를 생성하게 된다는 의미.
 정리를 한다면 HTML 페이지에 작성하는 마크업은 웹브라우저에게 알려주는 일종의 DOM 클래스의 메타 정보임. 브라우저는 이 마크업 태그와 1:1로 매칭되는 DOM 클래스의 객체를 생성해서 보관을 하고 있게 됨.
  

3. 출력
     - 마지막으로 웹 브라우저는 생성한 DOM 객체를 가지고 우리가 보고 있는 웹 페이지 화면을 만들게 됨.

 


Node 객체
- Node 객체는 노드를 조작하기 위한 가장 기본적인 프로퍼티와 메서드가 정의되어 있는 Node 인터페이스를 구현한 객체. Node 객체에서 제공하는 기능을 이용하면 노드 타입을 파악하거나 부모, 형제 그리고 자식 노드를 알아내서 접근하거나, 또는 자식 노드를 추가, 삭제, 교체를 할 수 있음. Node 객체는 DOM 객체 가운데 가장 최상위 객체이자 모든 하위 노드 객체들이 상속을 받는 객체임.

 

Element 객체
- Element는 노드 중 주석 노드와 텍스트 노드를 제외한 나머지 노드를 통합해서 부르는 용어.
    - Element 객체 역시 노드의 한 종류이며 Element 인터페이스를 구현한 객체임.
      또, Element 객체는 Node 객체의 자식이므로 Node 객체가 가지고 있는 기능을 모두 사용할 수 있음.
    - Element 객체의 주요 기능으로는 태그 이름이 담긴 프로퍼티와 속성(Attribute)을 알아내고 설정하는 기능과 이벤트를 추가하거나 삭제하거나 발생시키는 기능이 있음.
           
HTMLElement 객체
    - HTMLElement는 오직 HTML 문서에만 있는 노드를 통합해서 부르는 말.
    - HTMLElement 객체에는 Element 객체의 기능 외에도 오직 HTML 페이지의 p, div 태그와 같은 HTML 태그에서만 쓸 수 있는 공통적인 속성과 기능이 포함이 되어 있음.
    - HTMLElement 객체는 HTMLDivElement, HTMLImageElement, HTMLBodyElement와 같은 객체의 부모 객체이기도 함.
    
Document 객체
    - Document 객체 역시 Node 객체의 하위 객체이며 HTML 문서와 xml 문서의 루트 객체로 엘리먼트 노드와 이벤트, 속성 노드, 텍스트 노드, 주석 등의 노드를 생성하는 기능, id, className, tagName으로 특정 노드를 찾는 기능, 이벤트를 발생시키고 등록시키는 이벤트 기능까지 갖춘 아주 중요한 객체임.
    
HTMLDocument 객체
    - HTMLDocument 객체는 HTML 문서 전용 Document 객체임. body와 같은 HTML 문서전용 프로퍼티와 메서드가 포함되어 있음. HTML 페이지 로딩 후 파싱 단계에서 만들어진 html, head, body 객체를 비롯해서 페이지에 작성된 태그와 일대일로 매칭되는 모든 Node 객체를 가지고 있는 객체이기도 함. 

 


<DOM을 공부하면서 알아야 할 내용>


1. 노드 다루기
   - 문서에서 특정 태그 이름을 지닌 노드 찾기
   - 특정 노드의 자식 노드에서 특정 태그 이름을 지닌 노드 찾기
   - 문서에서 특정 클래스가 적용된 노드 찾기
   - 문서에서 특정 id를 가진 노드 찾기
   
   - 자식 노드 찾기
   - 부모 노드 찾기
   - 형제 노드 찾기
   
   - document.createElement() 메서드를 사용해서 노드 생성 및 추가하기
   - HTMLElement.innerHTML 프로퍼티를 사용해서 노드 생성 및 추가하기
   - Node.cloneNode() 메서드를 사용해서 노드 생성 및 추가하기
   - 노드 삭제하기
   - 노드 이동시키기
   
   - 텍스트 노드 생성 및 추가하기
   - 텍스트 노드 내용 변경하기
   
2. 스타일 다루기
   - 스타일 속성값 구하기
   - 스타일 속성값 설정하기
   - 스타일 속성 제거하기
   
3. 속성 다루기
   - 속성값 구하기
   - 속성값 설정하기
   - 속성 제거하기
   
4. 이벤트 다루기
   - 이벤트 리스너 추가하기
   - 이벤트 리스너 삭제하기
   - 이벤트 발생시키기
   - 사용자 정의 이벤트 만들기


기본 요소(태그) 생성 방법

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
<script type="text/javascript">

	// 현재 문서의 body 태그를 읽고 난 후에 자바스크립트를 실행하라는 의미.
	onload = function() {
		
		// 요소(태그)를 생성하는 방법
		// 형식) createElement(tagName);
		// 형식) createTextNode(text) : 텍스트 노드를 생성하는 메서드.
		let h1_element = document.createElement("h1");
		
		let textNode = document.createTextNode("Hello.. DOM");
		
		// 텍스트노드를 h1태그에 자식으로 추가
		h1_element.appendChild(textNode);
		
		// 실제로 문서의 body에 h1 요소를 추가해 주면 된다.
		document.body.appendChild(h1_element);
	}


</script>
</head>
<body>
	
</body>
</html>


이미지 태그 생성 방법1

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
<script type="text/javascript">

	onload = function() {
		
		// 이미지 태그를 만들어 보자.
		let imgNode = document.createElement("img");
		
		// 이미지 태그에 이미지를 넣으려면  src 속성이 지정이 되어야 함.
		imgNode.src = "../images/mango.jpg";
		imgNode.width = "200";
		imgNode.height = "200";
		
		// 해당 이미지 노드를 문서의 본문에 추가시키자.
		document.body.appendChild(imgNode);
	}


</script>
</head>
<body>

</body>
</html>

이미지 태그 생성 방법2

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
<script type="text/javascript">

	onload = function() {
		let imgNode = document.createElement("img");
		
		imgNode.setAttribute("src", "../images/apple.jpg");
		imgNode.setAttribute("width", 200);
		imgNode.setAttribute("height", 200);
		
		document.body.appendChild(imgNode);
		
	}

</script>
</head>
<body>

</body>
</html>

 


문서의 요소를 가져오는 방법 - 3가지
1. getElementById(id) 를 이용하는 방법

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
<script type="text/javascript">

	onload = function() {
		// 1. getElementById(id) 를 이용하는 방법
		let header1 = document.getElementById("header_1");
		let header2 = document.getElementById("header_2");
		
		// 문서 객체의 속성을 변경해 보자.
		header1.innerHTML = "header_1 id를 가진 요소";
		header2.innerHTML = "header_2 id를 가진 요소";
		
	}

</script>
</head>
<body>

	<h1 id="header_1">Header1</h1>
	<h1 id="header_2">Header2</h1>
	
</body>
</html>

 2. getElementsByTagName(tagName)을 이용하는 방법

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
<script type="text/javascript">

	onload = function() {
		// 2. getElementsByTagName(tagName)을 이용하는 방법
		//    ==> tagName과 일치하는 요소를 배열로 가져오는 메서드.
		
		let headers = document.getElementsByTagName("h1");
		
		// headers[0].innerHTML = "getElementsByTagName()";
		// headers[1].innerHTML = "getElementsByTagName()";
		
		for(let i=0; i<headers.length; i++) {
			headers[i].innerHTML = "getElementsByTagName()";
		}
	}



</script>
</head>
<body>

	<h1>Header1</h1>
	<p>header1 내용</p>
	
	<hr>
	
	<h1>Header2</h1>
	<p>header2 내용</p>
	
</body>
</html>

 3. querySelector(선택자) 를 이용하는 방법

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
<script type="text/javascript">

	onload = function() {
		// 3. querySelector(선택자) 를 이용하는 방법
		// querySelector(선택자)
		// ==> 선택자로 가장 처음 선택되는 문서의 요소를 가져오는 메서드.
		// querySelectorAll(선택자)
		// ==> 선택자로 선택된 문서의 요소 전체를 배열로 가져오는 메서드.
		
		let header1 = document.querySelector("#header_1");
		let header2 = document.querySelector("#header_2");
		
		header1.innerHTML = "header_1 id를 가진 요소";
		header2.innerHTML = "header_2 id를 가진 요소";
	}

</script>
</head>
<body>

	<h1 id="header_1">Header1</h1>
	<h1 id="header_2">Header2</h1>
	
</body>
</html>


태그 가져와서 요소 설정하기 응용1

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
<script type="text/javascript">

	onload = function() {
		let header = document.getElementById("header");
		
		// h1 태그의 문서의 요소를 바꾸어 보자.
		header.style.border = "1px solid red";
		header.style.color = "blue";
		header.style.fontStyle = "italic";
		header.innerHTML = "방가방가";
	}

</script>
</head>
<body>

	<h1 id="header">Header</h1>
	
</body>
</html>


태그 가져와서 요소 설정하기 응용2

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
<script type="text/javascript">

	onload = function() {
		let header = document.getElementById("header");
		
		// 이벤트 처리 작업
		header.onclick = function() {
			alert("글자를 클릭 하셨군요!!!");
			header.innerHTML = "글자 변경";
		}
	}


</script>
</head>
<body>

	<h1 id="header">Header</h1>
	
</body>
</html>

 


태그 가져와서 요소 설정하기 응용3

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
<script type="text/javascript">


	onload = function() {
		document.getElementById("btnChannel1").onclick = function() {
			let myDiv = document.getElementById("myDiv");
			myDiv.style.backgroundColor = "yellow";
			myDiv.style.width = "100px";
			
			document.getElementById("str").style.color = "red";
		}
	}

	function go_change() {
		alert("이벤트 예제입니다");
	}


</script>
</head>
<body>

	<div id="myDiv" style="height: 100px;">
		<span id="str">안녕</span>하세요!!!
	</div>
	
	<input type="button" id="btnChannel1" value="스타일변경">
	<input type="button" id="btnChannel2" 
			value="스타일변경" onclick="go_change()">
</body>
</html>

 


특정 요소(태그)를 노드에 추가하기

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
<script type="text/javascript">

	onload = function() {
		
		let pNode = document.createElement("p");
		let textNode1 = 
				document.createTextNode("DOM을 이용한 p 태그");
		pNode.appendChild(textNode1);
		
		let hrNode = document.createElement("hr");
		// hr 요소에 title 속성을 추가하는 방법
		hrNode.setAttribute("title", "DOM을 이용한 수평선");
		
		// 추가된 요소들을 문서의 body에 추가해 주자.
		document.body.appendChild(pNode);
		document.body.appendChild(hrNode);
		
	}

</script>
</head>
<body>

	<br> <br> <br>
	
	<hr title="직접 태그를 이용하여 생성된 수평선">
	
	<br> <br> <br>
	
	<!-- 
		[문제] 해당 위치에 <p> 태그와 <hr> 태그를
		      DOM을 이용하여 생성하여 화면에 보여주세요.
	 -->
	 
</body>
</html>


특정 요소(태그)를 노드에 추가한 뒤 요소의 속성을 변경하기

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
<script type="text/javascript">

	onload = function() {
		// p 태그를 만들어 보자.
		let pNode = document.createElement("p");
		
		// p 태그에 들어갈 텍스트노드를 만들어 보자.
		let txtNode = document.createTextNode("안녕하세요");
		
		// p 태그에 텍스트노드를 추가하는 방법.
		pNode.appendChild(txtNode);
		
		
		let myDiv = document.getElementById("myDiv");
		
		myDiv.appendChild(pNode);
		
		myDiv.style.color = "blue";
		
	}

</script>
</head>
<body>

	<div id="myDiv">
		<!-- 
			[문제] 아래와 같이 DOM을 이용하여 화면을 만들어 보세요.
			
			<p>안녕하세요</p>
		
		    조건) "안녕하세요" 라는 글자는 파란색으로 처리
	 	-->
	
	</div>
	
</body>
</html>


요소에 이벤트 추가하기

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
<script type="text/javascript">

	onload = function() {
		let button = document.getElementById("btn");
		
		button.onclick = function() {
			let text = 
					document.getElementById("text1").value;
			
			if(text == "") {
				alert("내용을 입력하세요...");
			}else {
				document.getElementById("text2").value = text;
			}
		}
	}



</script>
</head>
<body>

	<div align="center">
		<h2>[문제] 버튼을 클릭하면 첫번째 텍스트 창에 입력된 내용을
		                    두번째 텍스트 창으로 복사해 보자.</h2>
		
		<input type="text" id="text1"><br>
		<input type="text" id="text2"><br>
		<input type="button" id="btn" value="복사">
	</div>
	
</body>
</html>


특정 요소 제거

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
<script type="text/javascript">

	onload = function() {
		let header2 = document.getElementById("header_2");
		
		// 특정 요소를 제거하는 방법
		document.body.removeChild(header2);
	}


</script>
</head>
<body>

	<h1 id="header_1">Header1</h1>
	<h1 id="header_2">Header2</h1>
	
</body>
</html>