JavaScript 독학 가이드 7 - DOM 조작 기초

learning by Seven Fingers Studio 16분
JavaScriptDOM웹개발HTMLquerySelector프로그래밍

드디어 화면에 뭔가 보이는 걸 만들 차례예요! 지금까지는 콘솔에만 출력했는데, 이제 JavaScript로 웹 페이지를 직접 바꿔볼 거예요. 버튼 누르면 텍스트 바뀌고, 색깔 변하고, 요소 사라지고 나타나는 거 전부 할 수 있습니다.

DOM이 뭔가요?

DOM(Document Object Model)은 HTML 문서를 JavaScript가 이해할 수 있게 만든 객체 모델이에요. HTML의 모든 태그가 JavaScript 객체로 변환돼요.

<!DOCTYPE html>
<html>
<head>
    <title>테스트</title>
</head>
<body>
    <h1 id="title">안녕하세요</h1>
    <p class="content">DOM 조작을 배워봅시다</p>
</body>
</html>

이 HTML이 브라우저에 로드되면 JavaScript로 모든 요소에 접근할 수 있어요.

요소 찾기

getElementById

ID로 요소를 찾습니다.

<h1 id="title">제목</h1>

<script>
let title = document.getElementById("title");
console.log(title); // <h1 id="title">제목</h1>
</script>

실행 결과:

> console.log(title)
<h1 id="title">제목</h1>

querySelector (추천!)

CSS 선택자로 찾습니다. 가장 먼저 발견된 하나만 반환해요.

<h1 class="title">제목1</h1>
<h2 class="title">제목2</h2>

<script>
let title = document.querySelector(".title");
console.log(title); // <h1 class="title">제목1</h1> (첫 번째만)

let h2 = document.querySelector("h2");
console.log(h2); // <h2 class="title">제목2</h2>
</script>

querySelectorAll

조건에 맞는 모든 요소를 찾습니다.

<p class="text">첫 번째</p>
<p class="text">두 번째</p>
<p class="text">세 번째</p>

<script>
let texts = document.querySelectorAll(".text");
console.log(texts); // NodeList [p, p, p]

texts.forEach(text => {
    console.log(text.textContent);
});
// 출력:
// 첫 번째
// 두 번째
// 세 번째
</script>

내용 변경하기

textContent

텍스트만 변경합니다.

<p id="message">안녕하세요</p>

<script>
let message = document.querySelector("#message");
message.textContent = "반갑습니다!";
// 화면에 "반갑습니다!"로 바뀜
</script>

실행 결과:

안녕하세요반갑습니다!

textContent로 텍스트가 변경되었습니다

innerHTML

HTML 태그까지 변경할 수 있어요.

<div id="content">원래 내용</div>

<script>
let content = document.querySelector("#content");
content.innerHTML = "<strong>강조된 텍스트</strong>";
// 화면에 굵은 글씨로 "강조된 텍스트" 표시
</script>

실행 결과:

원래 내용강조된 텍스트

innerHTML로 HTML 태그가 포함된 내용이 렌더링되었습니다

주의: 사용자 입력을 innerHTML에 넣으면 XSS 공격 위험이 있어요!

스타일 변경하기

style 속성

<p id="text">스타일 변경 테스트</p>

<script>
let text = document.querySelector("#text");
text.style.color = "red";
text.style.fontSize = "24px";
text.style.backgroundColor = "yellow";
</script>

실행 결과:

스타일 변경 테스트

style 속성으로 색상, 크기, 배경색이 변경되었습니다

주의: CSS 속성명은 camelCase로 씁니다.

  • background-colorbackgroundColor
  • font-sizefontSize

속성(Attribute) 다루기

<img id="photo" src="old.jpg" alt="이전 사진">

<script>
let photo = document.querySelector("#photo");

// 속성 읽기
console.log(photo.src); // "old.jpg"
console.log(photo.alt); // "이전 사진"

// 속성 변경
photo.src = "new.jpg";
photo.alt = "새 사진";

// getAttribute/setAttribute
photo.setAttribute("width", "300");
console.log(photo.getAttribute("width")); // "300"
</script>

클래스 다루기

classList

<style>
.highlight {
    background-color: yellow;
    font-weight: bold;
}
.large {
    font-size: 24px;
}
</style>

<p id="text">텍스트</p>

<script>
let text = document.querySelector("#text");

// 클래스 추가
text.classList.add("highlight");

// 클래스 제거
text.classList.remove("highlight");

// 클래스 토글 (있으면 제거, 없으면 추가)
text.classList.toggle("highlight");

// 클래스 포함 여부 확인
console.log(text.classList.contains("highlight")); // true or false

// 여러 클래스 추가
text.classList.add("highlight", "large");
</script>

실행 결과:

원본

텍스트

classList.add("highlight", "large")

텍스트

classList로 여러 클래스를 동적으로 추가/제거할 수 있습니다

요소 생성/삭제

요소 생성

// 새 요소 만들기
let newDiv = document.createElement("div");
newDiv.textContent = "새로 만든 div";
newDiv.classList.add("box");

// body에 추가
document.body.appendChild(newDiv);

요소 삭제

<div id="remove-me">삭제될 요소</div>

<script>
let element = document.querySelector("#remove-me");
element.remove(); // 요소 삭제
</script>

실전 예제

1. 버튼 클릭으로 텍스트 변경

<!DOCTYPE html>
<html>
<body>
    <h1 id="title">안녕하세요</h1>
    <button id="changeBtn">텍스트 변경</button>

    <script>
        let title = document.querySelector("#title");
        let btn = document.querySelector("#changeBtn");

        btn.onclick = function() {
            title.textContent = "반갑습니다!";
        };
    </script>
</body>
</html>

실행 결과:

안녕하세요

버튼을 클릭하면 제목이 "반갑습니다!"로 변경됩니다

2. 다크모드 토글

<!DOCTYPE html>
<html>
<head>
    <style>
        body.dark {
            background-color: #222;
            color: #fff;
        }
    </style>
</head>
<body>
    <h1>다크모드 테스트</h1>
    <button id="toggleBtn">다크모드 전환</button>

    <script>
        let btn = document.querySelector("#toggleBtn");

        btn.onclick = function() {
            document.body.classList.toggle("dark");
        };
    </script>
</body>
</html>

실행 결과:

다크모드 테스트

라이트 모드

다크모드 테스트

다크 모드

classList.toggle()로 다크모드를 쉽게 구현할 수 있습니다

3. 항목 추가 리스트

<!DOCTYPE html>
<html>
<body>
    <input type="text" id="itemInput" placeholder="항목 입력">
    <button id="addBtn">추가</button>
    <ul id="list"></ul>

    <script>
        let input = document.querySelector("#itemInput");
        let addBtn = document.querySelector("#addBtn");
        let list = document.querySelector("#list");

        addBtn.onclick = function() {
            let text = input.value;
            if (text) {
                let li = document.createElement("li");
                li.textContent = text;
                list.appendChild(li);
                input.value = ""; // 입력창 비우기
            }
        };
    </script>
</body>
</html>

실행 결과:

  • 사과
  • 바나나
  • 딸기

입력한 텍스트가 리스트에 동적으로 추가됩니다 (createElement + appendChild)

4. 이미지 갤러리

<!DOCTYPE html>
<html>
<body>
    <img id="mainImage" src="image1.jpg" width="400">
    <div>
        <button onclick="changeImage('image1.jpg')">이미지 1</button>
        <button onclick="changeImage('image2.jpg')">이미지 2</button>
        <button onclick="changeImage('image3.jpg')">이미지 3</button>
    </div>

    <script>
        function changeImage(imageName) {
            let img = document.querySelector("#mainImage");
            img.src = imageName;
        }
    </script>
</body>
</html>

자주 하는 실수

1. 요소를 찾기 전에 접근

// 틀림: HTML 로드 전에 실행
let title = document.querySelector("#title");

// 맞음: HTML 로드 후 실행
window.onload = function() {
    let title = document.querySelector("#title");
};

// 또는 script를 body 맨 아래에 배치

2. querySelector vs querySelectorAll 헷갈림

// querySelector는 하나만 반환
let item = document.querySelector(".item");
item.style.color = "red"; // OK

// querySelectorAll은 NodeList 반환
let items = document.querySelectorAll(".item");
items.style.color = "red"; // 에러! forEach 써야 함

items.forEach(item => {
    item.style.color = "red"; // 맞음
});

3. textContent vs innerHTML

let div = document.querySelector("#div");

// textContent는 HTML 태그를 텍스트로 취급
div.textContent = "<strong>텍스트</strong>";
// 화면: <strong>텍스트</strong> (그대로 보임)

// innerHTML은 HTML로 해석
div.innerHTML = "<strong>텍스트</strong>";
// 화면: 텍스트 (굵게 표시됨)

다음 단계

다음 글에서는 이벤트 처리를 배웁니다. 클릭, 마우스 움직임, 키보드 입력 등 사용자 동작에 반응하는 방법을 알아볼 거예요.

DOM 조작은 웹 개발의 핵심이에요. 이제부터 진짜 웹사이트 만드는 느낌이 날 겁니다!


JavaScript 독학 가이드 시리즈:

← 블로그 목록으로