본문 바로가기
혼공학습단 11기(完)

[혼공스] 07 - 1 '문서 객체 조작하기' 정리(1)

by jaeheon0520 2024. 1. 31.

 

오늘은 07 - 1장의 내용을 정리해 보자.

 

07 - 1장의 제목은 '문서 객체 조작하기'로, 화면에 글자 또는 그림 등을 출력하는 방법을 설명하고 있다.

 

화면을 구성하는 기본 내용이니 잘 익혀두어야 한다.

 

그럼 정리 시작!

 

INTRO

HTML 페이지에 있는 html, head, body, title, h1, div, span 등을 HTML 언어에서는 요소(element)라고 부른다. 그리고 자바스크립트에서는 이를 문서 객체(document object)라고 부른다. 따라서 '문서 객체를 조작한다'는 말은 'HTML 요소들을 조작한다'는 의미이다.

 

element & document object

 

문서 객체를 조합해서 만든 전체적인 형태를 문서 객체 모델(DOM, Document Objects Model) 이라고 부른다.

 

DOMContentLoaded 이벤트

문서 객체를 조작할 때는 DOMContedLoaded 이벤트를 사용한다. 왜 이 코드를 사용해야 할까?

 

document.addEventListener('DOMContentLoaded', () => {	
    // 문장
})

 

HTML 페이지는 코드를 위에서 아래로 차례대로 실행한다. 만약 body 태그가 생성되기 이전인 head 태그에서 body 태그에 무언가를 출력하려고 하면 어떻게 될까? 분명 문제가 발생한다.

 

문제가 발생하는 코드를 살펴보자. 이 코드에 아직 배우지 않은 document.body.innerHTML 코드가 등장한다. 이 코드는 문서(document)의 바디(body) 안에 있는 HTML 코드(innerHTML)를 자바스크립트로 조작할 수 있게 해주는 코드이다.

 

<!DOCTYPE html>
<html lang="en">
<head>
    <title>DOMContentLoaded</title>
    <script>
        // HTML 태그를 쉡게 만들 수 있는 콜백 함수를 선언한다.
        const h1 = (text) => `<h1>${text}</h1>`
    </script>
    <script>
        document.body.innerHTML += h1('1번째 script 태그') // body 태그가 생성되기 이전에 script 태그로 body 태그를 조작한다
        // 앞에서 선언한 h1 함수를 실행합니다.
    </script>
</head>
<body>
    <script>
        document.body.innerHTML += h1('2번째 script 태그')
    </script>
    <h1>1번째 h1 태그</h1>
    <script>
        document.body.innerHTML += h1('3번째 script 태그')
    </script>
    <h1>2번째 h2 태그</h1>
</body>
</html>

 

실행결과

 

화면에 문자열들이 나타나는데, body 태그가 생성되기 이전에 head 태그 안의 script 태그에서 body 태그를 조작하던 부분(<h1>1번째 script 태그</h1>를 출력하는 부분)은 화면에 출력되지 않았다. 정리하면 기본적으로 head 태그 내부에 script 태그를 배치하면 body 태그에 있는 문서 객체에 접근할 수 없다.

 

head 태그 내부의 script 태그에서 body 태그에 있는 문서에 접근하려면 화면에 문서 객체를 모두 읽어들일 때 까지 기다려야 한다.

 

DOMContentLoaded 이벤트는 웹 브라우저가 문서 객체를 모두 읽고 나서 실행하는 이벤트이다. 다음과 같이 코드를 구성하면 DOMContentLoaded 상태가 되었을 때 콜백 함수를 호출한다.

 

<!DOCTYPE html>
<html lang="en">
<head>
    <title>DOMContentLoaded</title>
    <script>
        // DOMContentLoaded 이벤트를 연결한다.
        document.addEventListener('DOMContentLoaded', () => {
        const h1 = (text) => `<h1>${text}</h1>`
        document.body.innerHTML += h1('DOMContentLoaded 이벤트 발생') // 문서 객체를 모두 읽어들이면(DOMContentLoaded) 이 콜백 함수가 실행된다.
    })
    </script>
</head>
<body>
   
</body>
</html>

 

실행결과

 

코드를 실행하면 script 태그가 body 태그 이전에 위치해도 문제없이 코드가 실행된다.

 

TIP! addEventListener() 메소드

document.addEventListener('DOMContentLoaded', () => {})는 이후 나오는 대부분의 코드에서 사용된다. 이 코드는 "document라는 문서 객체의 DOMContentLoaded 이벤트가 발생했을 때, 매개변수로 지정한 콜백 함수를 실행해라"는 의미이다. 조만간 다시 살펴볼 예정이다.

 

문서 객체 가져오기

본격적으로 문서 객체와 관련된 내용을 하나하나 살펴보자.

 

document.body 코드를 사용하면 문서의 body 요소를 읽어들일 수 있다. 이 외에도 HTML 문서에 있는 head 요소와 title 요소 등은 다음과 같은 방법으로 읽어들일 수 있다.

 

document.head
document.body
document.title

 

이는 웹 브라우저의 자바스크립트가 "당연히 있겠지"라고 전제하고 만든 속성이다. 우리가 head 요소과 body 요소 내부에 만든 다른 요소들은 다음과 같은 별도의 메소드를 사용해서 접근한다.

 

document.querySelector(선택자)
document.querySelectorAll(선택자)

 

선택자 부분에는 CSS 선택자를 입력한다. CSS 선택자는 매우 다양하다.  자주 사용하는 기본적인 CSS 선택자는 다음과 같다.

 

이름 선택자 형태 설명
태그 선택자 태그 특정 태그를 가진 요소를 추출한다.
아이디 선택자 #아이디 특정 ID 속성을 가진 요소를 추출한다.
클래스 선택자 .클래스 특정 class 속성을 가진 요소를 추출한다.
속성 선택자 [속성 = 값] 특정 속성을 갖고 있는 요소를 추출한다.
후손 선택자 선택자_A 선택자_B 선택자_A 아래에 있는 선택자_B를 선택.

 

querySelector() 메소드와 querySelectorAll() 메소드를 살펴보자. querySeletor() 메소드는 요소 하나만 추출하고, querySelectorAll() 메소드는 문서 객체 여러 개를 추출한다. 

 

다음은 querySelector() 메소드를 사용해서 h1 태그를 추출하고 조작하는 예이다.

 

<script>
    document.addEventListener('DOMContentLoaded', () => {
    	// 요소를 읽어들인다.
        const header = document.querySelector('h1') // h1 태그 이름으로 요소를 선택한다
        
        // 텍스트와 스타일을 변경한다
        header.textContent = 'HEADERS'
        header.style.color = 'white'
        header.style.backgroundColor = 'black'
        header.style.padding = '10px'
    })
</script>
<body>
	<h1></h1>
</body>

 

실제 h1 태그에는 내용을 입력하지 않았지만, 자바스크립트쪽에서 문서 객체를 조작했으므로 코드를 실행하면 다음과 같이 출력한다.

 

querySelector() 활용하기

 

다음은 querySelectorAll() 메소드이다. 문서 객체 여러 개를 배열로 읽어들이는 함수이다. 따라서 내부의 요소에 접근하고 활용하려면 반복을 돌려야 한다. 일반적으로 forEach() 메소드를 사용해서 반복을 돌린다. 

 

<script>
    document.addEventListener('DOMContentLoaded', () => {
    	// 요소를 읽어들인다.
        const headers = document.querySelectorAll('h1') // 태그 이름으로 요소를 선택한다.
        
        // 텍스트와 스타일을 변경한다.
        headers.forEach((header) => {
        	header.textContent = 'HEADERS'
            header.style.color = 'white'
            header.style.backgroundColor = 'black'
            header.style.padding = '10px'
        })
    })
</script>
<body>
    <h1></h1>
    <h1></h1>
    <h1></h1>
    <h1></h1>
</body>

 

querySelectorAll() 활용하기

 

글자 조작하기

지금까지 살펴본 예제들에서 innerHTML 속성과 textContent 속성을 사용해서 문서 객체 내부의 글자를 조작해봤다.

 

속성 이름 설명
문서 객체.textContent 입력된 문자열을 그대로 넣습니다
문서 객체.innerHTML 입력된 문자열을 HTML 형식으로 넣습니다

 

textContent 속성은 입력된 문자열을 그대로 넣어주고, innerHTML 속성은 입력된 문자열을HTML 형식으로 넣어준다. 다음 예제를 통해 살펴보자.

 

<script>
    document.addEventListener('DOMContentLoaded', () => {
    	const a = document.querySelector('#a') // 특정 아이디로 요소를 선택한다
        const b = document.querySelector('#b') // 특정 아이디로 요소를 선택한다
        
        a.textContent = '<h1>textContent 속성</h1>'
        b.innerHTML = '<h1>innerHTML 속성</h1>'
    })
</script>
<body>
    <div id='a'></div>
    <div id='b'></div>
</body>

 

글자 조작하기

 

코드를 실행하면 위와 같이 출력한다. textContent 속성의 경우는 글자가 그대로 들어갔지만, innerHTML 속성은 <h1>~<h1>을 h1 요소로 변환해서 들어갔다.

 

속성 조작하기

문서 객체의 속성을 조작할 때는 다음과 같은 메소드를 사용한다.

 

메소드 이름 설명
문서 객체.setAttribute(속성 이름, 값) 특정 속성에 값을 지정한다.
문서 객체.getAttribute(속성 이름) 특정 속성을 추출한다.

 

다음 코드는 img 태그의 src 속성을 조작해서 이미지를 출력하는 예시이다. 다음과 같은 형태로 URL을 입력하면 적절한 크기의 고양이 이미지를 얻을 수 있다. 

 

http://placekitten.com/너비/높이

 

 

<script>
    document.addEventListener('DOMContentLoaded', () => {
    	const rects = document.querySelectorAll('.rect') // 특정 클래스로 요소를 선택한다
        
        rects.forEach((rect, index) => {
        	const width = (index + 1) * 100 
            // index 값은 [0, 1, 2, 3]이 반복된다. 1을 더해서 [1, 2, 3, 4]가 반복되게 만들고
            // 100을 곱해서 너비가 [100, 200, 300, 400]이 되게 만들었다
            const src = `http://placekitten.com/${width}/250`
            rect.setAttribute('src', src) // src 속성에 값을 지정한다
    	})
    })
</script>
<body>
    <img class="rect">
    <img class="rect">
    <img class="rect">
    <img class="rect">
</body>

 

속성 조작하기

 

setAttribute() 와 getAttribute() 를 사용하지 않고도 다음과 같이 온점을 찍고 간단하게 사용할 수 있다.

rects.forEach((rect, index) => {
	const width = (index + 1) * 100
	const src = `http://placekitten.com/${width}/250`
    rect.src = src // 간단하게 사용한 예
})

 

스타일 조작하기

문서 객체의 스타일을 조작할 때는 style 속성을 사용한다. style 속성은 객체이며, 내부에는 속성으로 CSS를 사용해서 지정할 수 있는 스타일들이 있다. 이러한 속성에는 CSS로 입력할 때 사용하는 값과 같은 값을 입력한다.

 

style 객체 안에 들어있는 속성(css)

 

다만 그림을 보면 속성들의 이름이 CSS에서 사용할 때와 약간 다르다. 자바스크립트에서는 -기호를 식별자에 사용할 수 없으므로, 두 단어 이상의 속성은 다음과 같이 캐멀 케이스로 나타낸다. -기호를 제거하고, - 기호 뒤의 알파벳을 대문자로 변경한 형태이다.

 

(케멀케이스(CamelCase)란 단어의 첫 글자를 대문자로 쓰는 것을 말한다.)

 

CSS 속성 이름 자바스크립트 style 속성 이름
background-color backgroundColor
text-align textAlign
font-size fontSize

 

다음 코드는 25개의 div 태그를 조작해서 검은색에서 흰색으로 변화하는 그레디언트를 만드는 코드이다.

 

<script>
    document.addEventListener('DOMContentLoaded', () => {
    	const divs = document.querySelectorAll('body > div') // body 태그 아래에 있는 div 태그 선택
        
        divs.forEach((div, index) => { // div 개수만큼 반복하여 출력한다.
        	console.log(div, index)
            const val = index * 10 // index는 0부터 24까지 반복한다
        	div.style.height = `10px` // 크기를 지정할 때는 반드시 단위를 함께 붙여줘야 한다
            div.style.backgroundColor = `rgba(${val}, ${val}, ${val})`
        })
    })
</script>
<body>
    <div></div><div></div><div></div><div></div><div></div>
    <div></div><div></div><div></div><div></div><div></div>
    <div></div><div></div><div></div><div></div><div></div>
</body>

 

스타일 조작하기

 

내용이 많이 길어졌으므로 여기서 잠깐 쉬어가자!

 

오늘 하루도 쌓였다.