문서 객체 모델


학습 목표

- 문서 객체와 문서 객체 모델의 개념을 이해합니다.

- 문서 객체를 선택하고 조작할 수 있습니다.

- 이벤트의 종류를 알아보고 문서 객체에 이벤트를 연결합니다.


Preview


HTML 태그를 자바스크립트에서 이용할 수 있게 객체로 만든 것을 문서 객체라고 합니다. 따라서 자바스크립트에서 문서 객체를 사용하면 HTML 태그를 생성 - 제거하거나 조작할 수 있습니다. 또 문서 객체를 사용해 마우스를 클릭하거나 키보드를 누르는 등 이벤트에 반응할 수 있습니다.


1. 문서 객체 모델 관련 용어


웹 브라우저에 HTML 파일을 끌어다 놓으면 웹 브라우저는 HTML 파일을 분석하고 화면에 표시 합니다. 이때 웹 브라우저가 HTML 파일을 분석하고 표시하는 방식을 문서 객체 모델이라고 합니다.


문서 객체 모델을 본격적으로 살펴보기 전에 관련 용어붙처 정리하겠습니다. 이 장에서는 태그 문서 객체, 노드 라는 용어를 사용합니다. 간단한 HTML 페이지 코드를 보면서 하나씩 살펴봅시다.


<!DOCTYPE html>

<html>

<head>

<title>Document object Model</title>

<script>


</script>

</head>

<body>

<h1>header</h1>

<p>Lorem ipsum dolor amet</p>

</body>

</html>


이 코드에서 h1 또는 p를 태그라고 합니다. 지금까지 여러 번 사용한 용어이므로 별도로 설명하지 않습니다.

이러한 HTML 태그를 자바스크립트에서 사용할 수 있는 객체로 만든 것을 문서 객체라고 합니다. 따라서 문서 객체를 조작한다는 말은 태그를 조작한다는 말과 같습니다. 즉, 문서 객체를 조작하면 태그 내부의 글자, 스타일, 속성을 변경할 수 있습니다. HTML에서 요소라고 하는 것을 자바스크립트에서는 문서 객체라고 합니다.


"어떻게 자바스크립트에서 문서 객체를 조작하나요?"


이것이 이 장에서 배울 내용입니다. 계속해서 용어를 살펴보겠습니다. 이 코드를 트리 형태로 나타내면 [그림 10-1]과 같습니다. 이 때 존재하는 각 요소를 노드라고 하며, 요소 노드 와 텍스트 노드로 구분합니다. 반면 화면에 출력되는 문자열인 Lorem ipsum dolor amet 등은 텍스트 노드라고 합니다.


[그림 10-1] 노드


HTML 페이지에는 h1처럼 텍스트 노드를 갖는 태그도 있지만, 다음과 같이 텍스트 노드를 갖지 않는 태그도 있습니다.


<br />

<hr />

<img src="rintiantta.png" />


웹 페이지를 처음 실행할 때 HTML 페이지에 작성한 태그를 읽어 문서 객체를 생성하는 것을 '문서 객체를 정적으로 생성한다'고 표현합니다. 반면 프로그램 실행 중에 자바스크립트를 사용해 문서 객체를 생성하는 것을 '문서 객체를 동적으로 생성한다'고 표현합니다.


문서 객체 모델은 웹 브라우저마다 미세한 차이가 있습니다. 웹 브라우저별로 문서 객체 모델을 다루면 너무 방대하므로 인터넷 익스플로러 9이상과 다른 웹 브라우저를 기준으로 살펴봅니다.


2. 웹 페이지 생성 순서


본격적으로 살펴보기 전 반드시 짚고 넘어갈 사항이 있습니다. 바로 웹브라우저가 웹 페이지를 실행하는 순서입니다. 결론부터 말하면 웹 브랑줘는 HTML 코드를 위쪽에서 아래쪽으로 실행합니다. 예제로 실행 순서를 살펴보겠습니다. [기본 예제 10-1]에서는 HTML 페이지 내부에  alert() 함수를 사용해 중간중간 실행 흐름을 끊었습니다.


기본 예제 10-1 웹 페이지 실행 순서


1. HTML 페이지 만들기 실행 순서를 확인할 HTML 페이지를 작성합니다.


[코드 10-1 기본 HTML 페이지 생성


<!DOCTYPE html>

<html>

<head>

<title>Document Object Model</title>

<script>alert('Process - 0')</script>

</head>

<body>

<h1>Process - 1</h1>

<script>alert('Process - 2')</script>

<h2>Process - 2</h2>

</body>

</html>


2. 첫 번째 알림창 닫기 처음 실행하면 문자열 'Process - 0'을 출력하는 경고창이 나타납니다. 경고창을 닫습니다.


3. 두 번째 알림창 닫기 웹 브라우저가 코드를 아래로 읽으며 h1 태그 내부의 문자열 'Process - 1'을 출력합니다. 이어서 그 아래의 코드를 읽으며 'Process -2' 경고창을 출력합니다.


4. 세 번째 알림창 닫기 다시 HTML 페이지를 읽으며 h2 태그내부의 문자열 'Process -2'를 출력합니다. 마찬가지로 그 아래의 코드를 읽으며 'Process -3' 경고창을 출력합니다.


HTML 페이지의 생성 순서는 굉장히 중요합니다.다음 예제에서 왜 중요한지 알아보겠습니다.


기본 예제 10-2 문서 객체 조작 방법


1. 문서 객체 사용 오류

웹 페이지 코드를 다음 코드처럼 작성한다고 합시다. 아직 배우지 안은 코드도 있지만 주석을 보면 어떠한 기능을 수행하는지 알 수 있겠죠? script 태그를 읽는 시점에 h1과 h2 태그는 생성되지 않았습니다. 따라서 이러한 순서로 코드를 작성하면 오류가 발생합니다.


<!DOCTYPE html>

<html>

<head>

<title>Document Object Model</title>

<script>

// h1 태그의 배겨 ㅇ색상을 변경합니다.

document.queryselector('h1').style.backgroundColor = 'red';


// h2 태그의 글자 색상을 변경합니다.

document.querySelector('h2').style.color = 'red';

</script>

</head>

<body>

<h1>Process - 1</h1>

<h2>Process - 2</h2>

</body>

</html>


2. 해결 방법 1: script 태그 위치 이동하기 가장 간단한 해결 방법은 다음 코드처럼 script 태그를 제목 태그들 아래에 삽입하는 것입니다. 하지만 HTML 페이지가 방대해졌을 때 유지 보수하기가 어렵습니다.


[코드 10-3] script 태그 아래 삽입


<!DOCTYPE html>

<html>

<head>

<title>Document Object Model</title>

</head>

<body>

<h1>Process - 1</h1>

<h2>Process - 2</h2>

<script>

// h1 태그의 배경 색상을 변경합니다.

document.querySelector('h1').style.backgroundcolor = 'red';

// h2 태그의 글자 색상을 변경합니다.

document.queryselector('h2').style.color = 'red';

</script>

</body>

</html>


3. 해결 방법 2 : 이베네트 활용하기 다음 절에서 배울 이벤트 기능ㅇ늘 사용합니다. 아직 이벤트가 무엇인지 잘 몰라도 '이벤트'ㄴ은 이러한 이유 때문에 사용하는구나 하고 생각하기 바랍니다.


[코드 10-4]


<!DOCTYPE html>

<html>

<head>

<title>Document Object Model</title>

<script>

window.onload = function () {

// h1 태그의 배경 색상을 변경합니다.

document.querySelector('h1').style.backgroundColor = 'red';

// h2 태그의 글자 색상을 변경합니다.

document.querySelector('h2').style.color = 'red';

};


</script>

</head>

<body>

<h1>Process - 1</h1>

<h2>Process - 2</h2>

</body>

</html>


NOTE_ script 태그의 위치


script 태그를 head 태그 내부에 삽입하는 것과 body 태그 아래에 삽입하는 것에 논쟁이 뜨겁습니다. head 태그 내부에 넣으면 코드를 보기 쉬우므로 유지 보수가 용이합니다. 반면 body 태그 아래에 넣으면 HTML 페이지가 빠르게 나타는 것처럼 보일 수 있습니다.


" 왜 빨리 불러오는 것처럼 보이나요?"


예를 들어 [코드 10-5]처럼 head 태그 내부에 있다면 위쪽에서부터 script 태그를 차근차근 읽기 시작합니다. 각각의 외부 슼느립트 파일의 용량이 크거나 사용자의 인터넷 속도가 느리다면 하얀 화면 상태로 몇 초 정도 있다가 글자가 나타납니다.


[코드 10-5] script 태그를 먼저 실행하는 웹 페이지


<!DOCTYPE html>

<html>

<head>

<title>Document Object Model</title>

<script src="jquery.js"></script>

<script src="jquery.masonry.js"></script>

<script src="jquery.rint.js"></script>

<script src="jquery.rint.graphics.js"></script>

<script src="jquery.rint.util.js"></script>

<script>

window.onload = function () { };

</script>

</head>

<body>

<h1>Header - 1</h1>

<h2>Header - 2</h2>

</body>

</html>


하지만 모든 script 태그를 [코드 10-3]처럼 body 태그의 맨 아래쪽에 넣는다면 script 태그 실행 전에 화면이 먼저 구성됩니다. 따라서 사용자는 웹페이지를 실행하자마자 빠르게 요소가 표시되는 것을 볼 수 있습니다.

가끔 스마트폰에서 웹 페이지로 접속하면 분명 화면은 모두 떴는데도 '로딩 중'이라는 메시지가 계속 나타날 때가 있습니다. 이는 script 태그를 아래에 삽입했기 때문에 요소를 모두 출력한 이후에 script 태그를 읽어서 발생합니다.


현재는 AMD(Asynchronous Module Definition)기술을 사용해 head 태그 내부에 script 태그를 입력해도 웹 페이지를 빠르게 표시할 수 있습니다.(CPU 회사 아닙니다.)


웹 페이지의 생성 순서를 길게 다루었지만 어렵지는 않았을 것입니다.


3. 문서 객체 선택


이미 존재하는 HTML 태그를 자바스크립트에서 문서 객체로 변환하는 것을 '문서 객체를 선택한다'고 표현합니다.


"문서 객체를 선택해 무엇을 하나요?"


문서 객체를 선택하면 자바스크립트를 사용해 실행 중에 내부 글자를 변경하거나 스타일을 변경할 수 있습니다. 내용을 진행하면서 자세히 살펴보겠습니다.


3.1 1개의 문서 객체 선택

문서 객체를 선택하는 가장 기본적인ㅇ 방법은 [표 10-1]의 메소드를 사용하는 것입니다. query Selector() 메소드는 HTML5에서 추가된 기능이므로 구 버전의 인터넷 익스플로러에서는 사용할 수 없습니다.


[표 10-1] 1개의 문서 객체를 선택하는 메소드

메소드 

설명 

documentj.getElementByld(아이디) 

아이디를 사용해 문서 객체 선택 

document.querySelector(선택자) 

선택자를 사용해 문서 객체 선택 



NOTE_ 이전에 스타일 시트를 다루면서 '스타일시트를 사용할 때는 id 속성이 중복되어도 문제가 없지만 자바스크립트에서는 문제가 생긴다'고 했습니다. 자바슼느립트에서 id 속성을 중복했을 때가 문제가 되는 부분이 바로 getElementByld)() 메소드입니다.


기본 예제 10-3 하나의 문서 객체 선택


1. get ElementByld() 메소드 사용하기 간단하게 getElementByld() 메소드를 사용해 보겠습니다. id 속성을 사용해 문서 객체를 선택하고 스타일과 내부 글자를 조작합니다.


[코드 10-6] id 속성을 사용한 1개의 문서 객체 선택


<!DOCTYPE html>

<html>

<head>

<title>DOM basic</title>

<script>

// 이벤트를 연결합니다.

window.onloiad = function () {

// 문서 객체를 선택합니다.

var header = document.getElementByld('header');


// 문서 객체를 조작합니다.

header.sytle.color = 'orange';

header.style.background = 'red';

header.innerHTML = 'From JavaScript';

};

</script>

</head>

<body>

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

</body>

</html>


2. querySelector() 메소드 사용하기 querySelector() 메소드도 getElementByld() 메소드와 사용 방법이 같습니다.다만 id 속성 대신에 선택자를 입력합니다.


[코드 10-7] 선택자를 사용한 1개의 문서 객체 선택


<!DOCTYPE html>

<html>

<head>

<title>DOM Basic</title>

<script>

// 이벤트를 연결합니다.

widnow.onload = function() {

// 문서 객체를 선택합니다.

var header = docment.querySelector('h1');


// 문서 객체를 조작합니다.

header.style.color = 'orange';

header.style.background = 'red';

header.innerHTML = 'From JavaScript';

};

</script>

</head>

<body>

<h1>Header</h1>

<h1>Header</h1>

<h1>Header</h1>

</body>

</html>


querySelector()는 문서 객체 하나를 선택하는 메소드입니다. 따라서 이름이 같은 선택자가 여러 개라면 가장 처음에 등장하는 것을 선택합니다.


3.2 여러 개의 문서 객체 선택


여러 개의 문서 객체를 선택할 때는 [표 10-2]의 메소드를 사용합니다.


표 10-2 여러 개의 문서 객체를 선택하는 메소드


메소드 

설명 

document.getElementsByName(이름) 

name 속성으로 여러 개의 문서 객체 선택 

document.getElementsByClassName(클래스)

class 속성으로 여러 개의 문서 객체 선택 

document.querySelectorAll(선택자) 

선택자로 여러 개의 문서 객체 선택 


어떠한 속성으로 문서 객체를 선택하는지만 다를 뿐 사용 방법은 모두 같습니다. [표 10-2]의 메소드를 사용해 문서 객체를 선택하면 배열의 형태로 문서 객체가 반환됩니다.



기본 예제 10-4 여러 개의 문서 객체 선택


사용 방법이 같으므로 querySelectorAll() 메소드만 살펴보겠습니다. [코드 10-7]과 달리 여러 개의 문서 객체를 선택해 조작할 수 있습니다.


[코드 10-8] 선택자를 사용한 여러 개의 문서 객체 선택


<!DOCTYPE html>

<html>

<head>

<title>DOM Basic</title>

<script>

// 이벤트를 연결합니다.

window.onload = function () {

// 문서 객체를 선택합니다.

var headers = document.querySelectorAll('h1');


for (var i = 0; i < headers.length; i++) {

// 변수를 선언합니다.

var header = headers[i];

// 문서 객체를 조작합니다.

header.style.color = 'orange';

header.style.background = 'red';

header.innerHTML = 'from JavaScript';

}

};

</script>

</head>

<body>

<h1>Header</h1>

<h1>Header</h1>

<h1>Header</h1>

</body>

</html>


4. 문서 객체 조작


선택한 문서 객체의 글자, 스타일, 속성 등을 조작할 수 있습니다. 어떻게 바꾸는지 문서 객체 조작 방법을 차근차근 살펴보겠습니다.


4.1 글자 조작


문서 객체 내부에 있는 글자를 조작할 때는 [표 10-3]의 속성을 사용합니다. 이 중 textContent 속성은 인터넷 익스플로러 9 이상에서 사용할 수 있습니다.


[표 10-3] 글자 조작 속성


속성

설명 

textContent

일반 글자 형식의 문서 객체 내부 글자 

innerHTML  

HTML 형식의 문서 객체 내부 글자 



기본 예제 10-5 내부 글자 변경


textContent 속성을 사용해 문서 객체 내부의 글자를 변경할 수 있습니다. 코드를 실행하면 입력한 글자가 body 태그에 바로 들어갑니다.


[코드 10-9] 일반 글자 형식으로 내부 글자 변경


<!DOCTYPE html>

<html>

<head>

<title>DOM Basic</title>

<script>

     // 이벤트를 연결합니다.

window.onload = function () {

// 변수를 선언합니다.

var output = '';

for (var i = 0; i < 10; i++) {

output += '<h1>Header - ' + i + '</h1> ';

}


// 문서 객체 내부의 글자를 변경합니다.

document.body.textContent = output;

};

</script>

</head>

<body>

</body>
</html>


기본 예제 10-6 태그 내부 글자 변경


이번에는 innerHTML 속성으로 생성한 문자열을 넣어 보겠습니다. textContent 속성과 달리 HTML 태그가 적용됩니다.


[코드 10-10] html 태그를 적용해 내부 글자 변경


<!DOCTYPE html>

<html>

<head>

<title>DOM Basic</title>

<script>

// 이벤트를 연결합니다.

window.onload = function () {

// 변수를 선언합니다.

var output = '';

for (var i = 0; i < 10; i++) {

output += 'h1>Header - ' + i + '<h1>';

}


// 문서 객체 내부의 글자를 변경합니다.

document.body.innerHTML = output;

};

</script>

</head>

<body>

</body>

</html>



textcontent와 innerHTML 속성 모두 태그 내부의 글자를 변경할 때 사용ㄴ합니다. 하지만 HTML 태그 형태의 문자열을 입력할 때는 차이가 있으니 주의하기 바랍니다.


NOTE_ 구 버전의 인터넷 익스플로러에서는 textContent 속성을 지원하지 않으므로 대개 innerHTML 속성을 사용합니다. 이때 HTML 태그로 사용하는 글자를 넣고 싶다면 글자 태그를 배우면서 살펴본 &nbsp; 등 특수 문자를 사용합니다.


4.2 스타일 조작


태그의 스타일 속성을 조작하는 것은 이전 절에서 잠시 살펴보았습니다. 다음 코드처럼 문서 객체의 style 속성을 변경하면 됩니다.


var header = document.getelementByld('header');

header.style.color = 'red';


스타일시트에서 사용하던 스타일 속성 이름을 그대로 입력하면 된다고 생각할 수 있습니다. 하지만 자바스크립트는 특수 문자 '-'을 식별자에 사용할 수 없으므로 다음 코드처럼 입력하면 오류를 출력합니다.


var header = document.getElementByld('header');

header.style.background-color = 'red';


따라서 '-'으로 연결된 속성은 다음 코드처럼 끊겨진 단어의 첫 글자를 대문자로 변경해야 합니다.


var header = document.getElementById('header');

header.style.backgroundcolor = 'red';


이 방법을 적용해 [표10-4]처럼 스타일시트의 스타일 속성을 자바스크립트의 스타일 식별자로 변환할 수 있습니다.


표 10-4 스타일 식별자 전환


스타일시트의 스타일 속성 

자바스크립트의 스타일 식별자 

background-image 

backgroundimage 

background-color 

backgroundColor 

box-sizng

boxSizing 

list-style 

listStyle 



NOTE_ 문자열을 사용한 스타일 속성 접근


문자열을 사용해 스타일 속성ㄴ에 접근할 때는 다음 두 가지 방법을 모두 사용할 수 있습니다.

① document.body.style['backgroundColor'] = 'red';

② document.body.style'[background-Color'] = 'red';


기본 예제 10-7 스타일 조작


간단한 내용이므로 조금만 살펴보면 쉽게 이해할 수 있을 것입니다. 다음 코드의 실행 결과를 예측해 봅니다.


[코드 10-11] 스타일 조작으로 그레이디언트 출력


<!DOCTYPE html>

<html>

<head>

<title>DOM Basic</title>

<script>

// 이벤트를 연결합니다.

window.onload =function () {

// 문서 객체를 추가합니다.

var output = '';

for (var i = 0; i < 256; i++) {

output += '<div></div>';

}

docment.body.innerHTML = output;


// 문서 객체를 선언합니다.

var div = divs[i];


// 스타일을 적용합니다.

div.style.height = '2px';

div.style.background = 'rgb(' + i + ',' + i + ',' + i + ')';

}

};

</script>

</head>

<body>



</body>

</html>


256개의 div 태그가 위쪽에서 아래쪽으로 그레이디언트를 형성합니다.


4.3 속성 조작


이제 문서 객체의 속성을 조작하는 방법을 알아보겠습니다. 문서 객체의 속성을 조작할 때는 [표 10-5]의 메소드를 사용합니다.


표 10-5 문서 객체의 속성 조작 메소드


메소드 

설명 

setAttribute(속성 이름, 속성값) 

속성 지정 

getAttribut(속성 이름)

속성 추출 


웹 표준에서 지정한 속성은 다음 방법으로 곧바로 접근할 수도 있습니다. 웹 표준에서 지원하지만 웹 브라우저 제조사가 구현을 못했다면 접근하지 못할 수도 있습니다.


image.src = 'rint.png'

alert(image.src)


웹 표준에서 지정하지 않은 속성에 접근할 때는 setAttribute ()와 getAttribute () 메소드를 사용합니다. 웹 표준에서 지정하지 않은 속성이 있다는 것에 의문이 생길 수 있습니다. 예를 들어 [그림 10-2]는 jQuery Mobile 코드의 일부 입니다. 여기서 data-role은 웹 표준에서 지정하는 속성이 아닙니다. 문자열 'date-'로 시작하는 것을 사용자 지정 속성이라고 하는데, 반드시 속성 조작 메소드를 사용해서 접근해야 합니다.


<body>

<div data-role="page">

<div data-role="header"></div>

<div data-role="content">


</div>

<div data-role="footer"></div>

</div>

</body>


[그림 10-2] jQuery Mobile 코드


기본 예제 10-8 문서 객체 속성 조작


1. img 태그 속성 조작하기    다음 코드는 간단한 속성 조작 방법을 사용ㄴ해 img 태그의 src, width, height 속성을 변경합니다. img 태그에는 id 속성을 제외한 다른 속성은 부여하지 않았습니다. 하지만 자바스크립트의 문서 객체 코드에서 src 속성 등을 지정하므로 출력 결과처럼 이미지가 나타납니다.


[코드 10-12] img 태그 속성 조작


<!DOCTYPE html>

<html>

<head>

<title>DOM Basic</title>

<script>

// 이벤트를 연결합니다.

window.onload = function () {

// 변수를 선언합니다.

var image = document.getElementById('image');


// 속성을 변경합니다.

image.src = 'http://p9;acehold.it/300x200';

image.width = 300;

image.height = 200;

};

</script>

</head>

<body>

<img id="image" />

</body>

</html>


2. body 태그의 속성 조작하기

다음 코드는 body 태그에 data-custom 속성을 지정한 후 속성을 다시 추출해서 출력합니다. 웹 표준에서 지정하고 있지 않은 속성이므로 속성 조작 메소드를 사용합니다.


코드 10-13 body 태그 속성 조작


<!DOCTYPE html>

<html>

<head>

<title>DOM Basic</title>

<script>

// 이벤트를 연결합니다.

window.onload = function () {

// 속성을 지정합니다.

document.body.setAttribute('data-custom', 'value');


// 속성을 추출합니다.

var datacustom = document.body.getAttribute('data-custom');

alert(dataCustom);

};

</script>


</head>

<body>

</body>

</html>



코드를 실행하고 검사를 사용해서 살펴보면 [그림 10-3]처럼 body 태그에 data-custom 속성이 추가되어 있습니ㅏㄷ. 다른 속성도 이 방법으로 지정하고 추출합니다.


<!DOCTYPE html>

<html>

<head>...</head>

<body data-custom="value"></body>

</html>


[그림 10-3] 검사로 속성 조작 확인


기본 예제 10-9 문서 객체를 사용한 시계


지금까지 다룬 예제들이 정ㅈ덕이었다면, 문서 객체를 정리하는 의미로 1초 단위로 현재 시계를 표시하는 시계를 만들어 보겠습니다. 간단한 예제이지만, 왜 문서 객체를 사용하는지 알수 있습니다.


setInterval() 함수를 사용해 1초마다 clock 문서 객체의 innerHTML 속성을 현재 시간으로 변경합니다.

setInterval() 함수는 12장에서 자세히 다룹니다. 지금은 단위 시간마다 함수를 실행한다고 이해하면 됩니다.


[코드 10-14] 문서 객체를 사용한 시간 표시


<!DOCTYPE html>

<html>
<head>

<title>Clock</title>

<script>

// 이벤트를 연결합니다.

window.onload = function () {

// 문서 객체를 선택합니다.

var clock = document.getelementById('clock');


// 1초마다 함수를 실행합니다.

setInterval(function () {

var now = new Date();

clock.innerHTML = noew.toString();

}, 1000);

};
</script>

</head>

<body>

<h1 id="clock"></h1>

</body>

</html>


지금까지 모든 내용을 제대로 따라 했다면 jQuery Mobile도 쉽게 익힐 수 있을 것입니다. 간단한 라이브러리이므로 별도로 공부하기 바랍니다.



'프로그래밍 > Javascript' 카테고리의 다른 글

jQuery 라이브러리 설정  (0) 2017.08.14
문서 객체 모델 - 이벤트  (0) 2017.08.11
자바스크립트 - 객체  (0) 2017.08.08
자바스크립트 - 함수  (0) 2017.08.07
자바스크립트 - 반복문  (0) 2017.08.07
TAGS.

Comments