JavaScript 독학 가이드 7 - DOM 조작 기초
드디어 화면에 뭔가 보이는 걸 만들 차례예요! 지금까지는 콘솔에만 출력했는데, 이제 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>
실행 결과:
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-color→backgroundColorfont-size→fontSize
속성(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 독학 가이드 시리즈:
← 블로그 목록으로