자바스크립트를 이용한 DOM 액세스
순수한 자바스크립트나 제이쿼리를 이용해 화면 요소를 바꿀 때는 DOM을 순차적으로 조작합니다.
템플릿 만들기
먼저 간단한 동작을 시험해보기 위한 애플리케이션 템플릿을 만듭니다.
- 모형 (index.html)
<!DOCTYPE html>
<html>
<head>
<title>JavaScript에서의 DOM 조작</title>
<meta charset="UTF-8"/>
<link rel="stylesheet" href="src/style.css"/>
</head>
<body>
<h1 id = "title">Hello World!</h1>
<div class="container">
<p>영역 1입니다.</p>
</div>
<div class="container">
<p>영역 2입니다.</p>
</div>
</body>
</html>
- 템플릿 (styles.css)
.container{
border: solid 1px #ccc;
padding: 16px;
margin: 8px;
}
위 애플리케이션 템플릿을 화면에 표시한 결과는 다음과 같습니다.
이 화면에서 자바스크립트로 DOM을 얻어봅니다.
자바스크립트를 이용한 DOM 얻기
먼저 JS 파일을 만들어 로드해둡니다.
- 추가한 index.js 출력 테스트 (index.js)
console.log("test");
- index.js 추가 (index.html)
<!DOCTYPE html>
<html>
<head>
<title>JavaScript에서의 DOM 조작</title>
<meta charset="UTF-8"/>
<link rel="stylesheet" href="src/style.css"/>
</head>
<body>
<h1 id = "title">Hello World!</h1>
<div class="container">
<p>영역 1입니다.</p>
</div>
<div class="container">
<p>영역 2입니다.</p>
</div>
<script src="src/index.js"></script> <!-- 추가 -->
</body>
</html>
콘솔에 test라고 표시되었다면 정상적으로 로딩된 것입니다. 그럼 id를 지정해 요소를 얻어보겠습니다. 방법은 다음과 같습니다.
- id를 지정해 요소 얻기 (index.js)
// getElementById 사용
const title1 = document.getElementById("title");
console.log(title1);
// <h1 id="title">Hello World!!</h1>
// querySelector 사용
const title2 = document.querySelector("#title");
console.log(title2);
// <h1 id="title">Hello World!!</h1>
콘솔에서 확인하면 HTML 태그와 같은 것을 자바스크립트 변수로 얻었음을 알 수 있습니다. document는 DOM 트리의 엔트리포인트, getElementById는 id를 저장한 DOM을 얻는 방법입니다.
querySelector는 ( ) 안에 여러 셀러터(Selector)를 지정한 뒤 일치하는 첫 번째 요소를 반환합니다. 이렇게 얻은 DOM 요소를 앞으로 엘리먼트(Element)라고 부르겠습니다. 이외에도 클래스명을 이용해서 얻는 방법도 있습니다.
- 클래스명으로 엘리먼트 얻기 (index.js)
// getElementByClassName 사용
const containers = document.getElementsByClassName("container");
console.log(containers);
이때 다음과 같이 HTMLCollection에 여러 엘리먼트를 저장해 얻을 수 있습니다.
getElementsByClassName은 지정한 클래스명을 가진 요소를 얻습니다. class="container"를 가진 div 태그는 두 개 존재하며 위의 그림과 같이 두 개의 요소를 모두 얻었음을 확인할 수 있습니다. 이렇게 엘리먼트를 모아서 얻는 것도 가능합니다. 그리고 앞에서 설명한 querySelector를 이용해 클래스명으로 엘리먼트를 얻을 수도 있습니다.
- querySelector를 이용한 엘리먼트 얻기 (index.js)
// querySelector 사용
const container = document.querySelector(".container");
console.log(container);
클래스명일 때는 .를 붙입니다. querySelector는 가장 처음 일치한 요소를 반환하므로 여기에서는 다음과 같이 한 개의 엘리먼트를 얻습니다.
여러 엘리먼트를 얻을 수 있는 버전의 querySelector인 querySelectorAll도 있습니다.
- querySelectorAll을 이용한 엘리먼트 얻기
// querySelectorAll 사용
const containers2 = document.querySelectorAll(".container");
console.log(containers2)
기존 프론트엔드 개발에서는 이와 같이 먼저 조작 대상이 '무엇'인지 명시적으로 지정할 필요가 있었습니다. 그러나 id나 class, 태그명 및 계층 구조 등을 사용해서 조작 대상 DOM을 얻어야만 했는데 이는 버그를 쉽게 발생시키는 요인이기도 했습니다.
DOM 작성, 추가, 삭제
DOM 작성
자바스크립트 기능을 이용하면 지금까지 얻은 것과 같은 엘리먼트를 새롭게 작성할 수 있습니다. 예를 들어 다음과 같이 div의 엘리먼트를 생성할 수 있습니다.
- div 생성
const divEl = document.createElement("div");
console.log(divEl);
//<div></div>
createElement는 인수에 HTML 태그명을 문자열로 지정 가능하며 해당 태그의 엘리먼트를 작성합니다. 존재하지 않는 태그를 지정한 경우에는 HTMLUnKnownElement라는 명칭의 엘리먼트 같은 것을 생성할 수 있지만 구체적인 이용 방법은 없습니다.
- HTMLUnknownElement 생성
//존재하지 않는 태그명을 지정
const hi = document.createElement("hi);
console.log(hi);
//<hi></hi>
순수한 자바스크립트를 이용해 화면에 요소를 추가하는 경우에는 먼저 createElement로 DOM 요소를 작성하게 됩니다.
DOM 추가
획득 또는 작성한 엘리먼트에 대해 요소를 추가할 수 있습니다. 예를 들어 createElement로 작성한 div 태그 안에 p 태그를 추가할 때는 다음과 같이 기술합니다.
- div 태그 아래 p 태그 추가
//div 태그 생성
const divEl = document.createElement("div");
//p 태그 생성
const pEl = document.createElement("p");
//div 태그 아래 p 태그 추가
divEl.appendChild(pEl);
console.log(divEl);
콘솔에서 다음과 같은 결과를 확인할 수 있습니다.
이렇게 appendChild를 사용해 특정 엘리먼트 아래에 다른 엘리먼트를 추가할 수 있습니다. HTML을 계층 구조로 코딩하는 것과 같습니다. appendChild는 하위 요소의 맨 끝에 요소를 추가하기 때문에 자녀 요소가 여러 개일 경우 가장 마지막에 차례대로 추가됩니다.
- div 아래에 p 태그와 h2 태그를 추가
//div 태그 생성
const divEl = document.createElement("div");
//p 태그 생성
const pEl = document.createElement("p");
//h2 태그 생성
const h2El = document.createElement("h2");
//div 태그 아래 p 태그 추가
divEl.appendChild(pEl);
//div 태그 아래 h2 태그 추가
divEl.appendChild(h2El);
console.log(divEl);
콘솔에서 다음과 같은 결과를 확인할 수 있습니다.
나중에 추가한 h2 태그가 p 태그보다 뒤에 추가되는 것을 확인할 수 있습니다. 뒤가 아닌 앞에 추가하고 싶을 때는 prepend를 사용합니다.
이렇게 appendChild나 prepend를 이용함으로써 특정 DOM 아래에 다른 DOM을 추가할 수 있습니다.
- 이용할 HTML 파일 (index.html)
<!DOCTYPE html>
<html>
<head>
<title>JavaScript에서의 DOM 조작</title>
<meta charset="UTF-8"/>
<link rel="stylesheet" href="src/style.css"/>
</head>
<body>
<h1 id = "title">Hello World!</h1>
<div class="container">
<p>영역 1입니다.</p>
</div>
<div class="container">
<p>영역 2입니다.</p>
</div>
<script src="src/index.js"></script> <!-- 추가 -->
</body>
</html>
- 사용하는 js 파일 (index.js)
// 빈 파일
'영역 1입니다'라는 문자 아래에 버튼을 설정해봅니다. index.js를 수정해 화면을 읽을 때 코드가 실행되는 요소를 추가할 수 있습니다.
- 버튼 설정 (index.js)
// button 태그 생성
const buttonEl = document.createElement("button");
// 버튼 라벨 설정
buttonEl.textContent = "버튼";
// 영역 1의 div 태그 얻기
const divEl = document.querySelector(".container");
//div 태그 아래에 button을 추가
divEl.appendChild(buttonEl);
화면을 다시 로딩했을 때 다음과 같이 표시됩니다.
이와 같이 화면에서 얻은 엘리먼트에 추가로 메서드를 구현해 화면 표시를 변경할 수 있습니다.
DOM 삭제
삭제하는 경우에는 removeChild를 사용합니다. 다음은 앞의 HTML에서 'Hello Wolrd!!'라고 쓰인 h1 태그를 삭제하는 예입니다.
- h1 태그 삭제
// h1 태그 삭제
const h1El = document.getElementById("title");
//body 태그 얻기
const bodyEl = document.querySelector("body");
//body 태그 아래부터 삭제
bodyEl.removeChild(h1El);
화면을 표시하면 다음과 같이 Hello World! 문자가 사라집니다.
removeChild는 그 아래부터 지정된 엘리먼트를 삭제할 수 있는 것이 장점입니다. 특정 요소가 아니라 자녀 요소를 모두 삭제할 때는 textContent에 null을 지정하면 됩니다.
- body 아래 모두 삭제
//body 태그 얻기
const bodyEl = document.querySelector("body");
//body 태그 아래부터 삭제
bodyEl.textContent = null;
그러면 화면에는 아무것도 나타나지 않게 됩니다. 이렇게 특정 요소 아래 전체를 한 번에 삭제할 수도 있습니다.
새로운 엘리먼트를 만들거나, 추가하거나, 삭제해서 동적인 화면을 만들 수도 있습니다. HTML의 구조나 id, 클래스명과 자바스크립트 코드가 밀접하게 관련되어 있음을 알았을 것입니다.
자바스크립트를 이용해 DOM 조작하기
작성할 애플리케이션
프론트엔드만으로 동작하는 간단한 메도 애플리케이션을 작성해볼 것입니다.
사전 준비
먼저 자바스크립트를 제외한 코드 템플릿을 만듭니다.
- index.html
<!DOCTYPE html>
<html>
<head>
<title>간단 메모 애플리케이션</title>
<meta charset="UTF-8"/>
<link rel="stylesheet" href="src/style.css"/>
</head>
<body>
<h1 id = "title">간단 메모 애플리케이션</h1>
<input id="add-text"/>
<button id="add-button">추가</button>
<div class="container">
<p>메모 목록</p>
<ul id="memo-list"></ul>
</div>
<script src="src/index.js"></script> <!-- 추가 -->
</body>
</html>
- style.css
.container{
border: solid 1px #ccc;
padding: 16px;
margin: 8px;
}
li > div{
display: flex;
align-items: center
}
button {
margin-left: 16px;
}
- index.js
// 빈 파일
이 상태에서 자바스크립트를 이용한 DOM 조작 처리를 추가해봅니다.
자바스크립트 처리
- 처리 구현 (index.js)
//추가 버튼 클릭 시 실행하는 함수
const onClickedAdd = () => {
//텍스트 박스의 엘리먼트를 얻는다.
const textEl = document.getElementById("add-text");
//텍스트 박스의 값을 얻는다.
const text = textEl.value;
//텍스트 박스를 초기화한다(공백).
textEl.value = "";
//li 태그 생성
const li = document.createElement("li");
//div 태그 생성
const div = document.createElement("div");
//p 태그 생성(텍스트 박스의 문자 설정)
const p = document.createElement("p");
p.textContent = text;
//button 태그 생성(라벨: [삭제])
const button = document.createElement("button");
button.textContent = "삭제";
//버튼 클릭 시 행을 삭제하는 처리
button.addEventListener("click",() => {
//삭제 대상 행(li)을 얻는다.
//closest는 부모 요소와 일치하는 문자열을 찾는 메서드
const deleteTarget = button.closest("li");
//ul 태그 아래에서 앞서 특정한 행을 삭제
document.getElementById("memo-list").removeChild(deleteTarget);
});
//div 태그 아래에 p 태그와 button 태그 설정
div.appendChild(p);
div.appendChild(button);
//li 태그 아래에 div 태그 설정
li.appendChild(div);
//메모 목록 리스트에 li 태그 설정
document.getElementById("memo-list").appendChild(li);
};
//[추가] 버튼 클릭시 onClickAdd 함수를 실행하도록 등록
document
.getElementById("add-button")
.addEventListener("click",()=>onClickedAdd());
'모던 자바스크립트' 카테고리의 다른 글
모던 자바스크립트 기능 익히기 (2) | 2025.01.22 |
---|---|
모던 자바스크립트 기초 (2) | 2025.01.22 |