16. DOM

16-1. ๋”(DOM)์˜ ๊ธฐ๋ณธ ๊ฐœ๋…

16-1-1. DOM์˜ ์—ญํ• ๊ณผ ๊ธฐ๋ณธ ๊ตฌ์กฐ

DOM(Document Object Model)์€ ๋ฌธ์„œ๊ฐ์ฒด๋ชจ๋ธ๋กœ ๊ฐ„๋‹จํžˆ ๋งํ•˜๋ฉด, ์›น ๋ฌธ์„œ(HTML, XML)๋ฅผ ์ œ์–ดํ•˜๊ธฐ ์œ„ํ•œ ์ธํ„ฐํŽ˜์ด์Šค(API)์ด๋‹ค. ์ž๋ฐ”์Šคํฌ๋ฆฝํŠธ ์–ธ์–ด๋กœ ์š”์†Œ ๋‚ด์˜ ํ…์ŠคํŠธ๋ฅผ ๋ถˆ๋Ÿฌ์˜ค๊ฑฐ๋‚˜, ์Šคํƒ€์ผ(CSS)์„ ๋™์ ์œผ๋กœ ๋ณ€๊ฒฝํ•˜๋Š” ๋“ฑ ์›น ๋ฌธ์„œ๋ฅผ ๊ฐ์ฒดํ™”ํ•˜๋Š” ๊ฒƒ์„ ๋งํ•œ๋‹ค. ๋”์˜ ๊ตฌ์„ฑ์š”์†Œ๋Š” ์•„๋ž˜ ๊ทธ๋ฆผ๊ณผ ๊ฐ™์ด ํŠธ๋ฆฌ ํ˜•ํƒœ ๊ตฌ์กฐ๋กœ ํ‘œํ˜„๋œ๋‹ค.
notion imagenotion image
์ด ๊ตฌ์กฐ๋ฅผ ๋” ํŠธ๋ฆฌ, ๊ฐ๊ฐ์˜ ์š”์†Œ๋ฅผ ๋…ธ๋“œ๋ผ๊ณ  ํ•œ๋‹ค. html์ด ๋…ธ๋“œ ํŠธ๋ฆฌ์˜ ์ตœ์ƒ์œ„์— ์žˆ๊ณ , root ๋…ธ๋“œ๋ผ๊ณ  ํ•œ๋‹ค. ์•„๋ž˜ ์ฝ”๋“œ๋ฅผ ํ†ตํ•ด ๋ณด๋ฉด, ๊ธฐ๋ณธ ๊ตฌ์กฐ๋ฅผ ํ™•์ธํ•  ์ˆ˜ ์žˆ๋‹ค.
<!DOCTYPE html> <html lang="ko"> <head> <meta charset="UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>test</title> </head> <body> <h1>hello world</h1> <p>์•ˆ๋…•ํ•˜์„ธ์š”.</p> </body> </html>
  • ๋ฌธ์„œ ๋…ธ๋“œ(Document Node): ๋ฌธ์„œ ์ „์ฒด๋ฅผ ๋‚˜ํƒ€๋‚ด๋ฉฐ, ๋” ํŠธ๋ฆฌ์˜ ์ตœ์ƒ์œ„์— ์œ„์น˜ํ•˜๊ณ , ์ตœ์ƒ์œ„ ๋…ธ๋“œ๋ฅผ root ๋…ธ๋“œ๋ผ๊ณ  ํ•œ๋‹ค. html ํƒœ๊ทธ๋ฅผ ๋‚˜ํƒ€๋‚ธ๋‹ค. head์™€ body ์ž์‹ ๋…ธ๋“œ๊ฐ€ ์žˆ๋‹ค.
  • ์š”์†Œ ๋…ธ๋“œ(Element Node): HTML ์š”์†Œ๋ฅผ ๋‚˜ํƒ€๋‚ด๋ฉฐ, ๋ฌธ์„œ์˜ ๊ตฌ์กฐ๋ฅผ ํ˜•์„ฑํ•œ๋‹ค. head, title, h1, p ๋“ฑ์ด ์š”์†Œ ๋…ธ๋“œ์ด๋‹ค. ๋‹ค๋ฅธ ์š”์†Œ๋ฅผ ์ž์‹์œผ๋กœ ๊ฐ€์งˆ ์ˆ˜ ์žˆ๋‹ค.
  • ํ…์ŠคํŠธ ๋…ธ๋“œ(Text Node): HTML ์š”์†Œ ์•ˆ์— ์žˆ๋Š” ํ…์ŠคํŠธ๋ฅผ ๋‚˜ํƒ€๋‚ธ๋‹ค. <h1>hello world</h1>, <p>์•ˆ๋…•ํ•˜์„ธ์š”.</p> ์š”์†Œ ๋…ธ๋“œ์— ์‹ค์ œ ํ…์ŠคํŠธ๊ฐ€ ํ…์ŠคํŠธ ๋…ธ๋“œ์ด๋‹ค.
  • ์†์„ฑ(Attribute): HTML ์š”์†Œ์˜ ์†์„ฑ์„ ๋‚˜ํƒ€๋‚ด๋ฉฐ, ์š”์†Œ์˜ ์ถ”๊ฐ€ ์ •๋ณด๋ฅผ ์ œ๊ณตํ•œ๋‹ค. ์˜ˆ๋ฅผ ๋“ค์–ด img ์š”์†Œ์˜ src๋‚˜ alt ์†์„ฑ์„ ๋งํ•œ๋‹ค.
์ฆ‰, ๋ชจ๋“  html ์š”์†Œ๋Š” ๋…ธ๋“œ๋ผ๊ณ  ์ƒ๊ฐํ•˜๋ฉด ๋œ๋‹ค. ๋ชจ๋“  ๋…ธ๋“œ๋Š” ๋ถ€๋ชจ ๋…ธ๋“œ์™€ ์ž์‹ ๋…ธ๋“œ ๊ฐ„์˜ ๊ณ„์ธต๊ตฌ์กฐ๋ฅผ ํ˜•์„ฑํ•˜๊ณ , ๊ฐ ์š”์†Œ์™€ ํ•ด๋‹น ์š”์†Œ์˜ ์†์„ฑ์„ ๊ฐ์ฒด๋กœ ํ‘œํ˜„ํ•œ๋‹ค.
์ด ๊ฐ์ฒด๋Š” ํ”„๋กœํผํ‹ฐ๋‚˜ ๋ฉ”์„œ๋“œ๋ฅผ ํ†ตํ•ด์„œ ์ž๋ฐ”์Šคํฌ๋ฆฝํŠธ ์–ธ์–ด๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ํŽ˜์ด์ง€ ๋™์ž‘์„ ์ฒ˜๋ฆฌํ•  ์ˆ˜ ์žˆ๋‹ค. ์›นํŽ˜์ด์ง€์—์„œ ๋ฐœ์ƒํ•˜๋Š” ์ด๋ฒคํŠธ(ํด๋ฆญ, ์ž…๋ ฅ, ๋งˆ์šฐ์Šค ์ด๋™) ๋“ฑ์„ ๊ฐ์ง€ํ•˜๊ณ , ์ œ์–ดํ•  ์ˆ˜ ์žˆ๋‹ค.
๋ธŒ๋ผ์šฐ์ €์—์„œ ์ œ๊ณตํ•˜๋Š” ๊ธฐ๋Šฅ์ด๊ณ , API๊ธฐ ๋•Œ๋ฌธ์— ์ž๋ฐ”์Šคํฌ๋ฆฝํŠธ๋ฅผ ์‚ฌ์šฉํ•ด์„œ ์ œ์–ดํ•  ์ˆ˜ ์žˆ๋Š” ๋Œ€์ƒ์ผ ๋ฟ์ด๊ณ , ๋‹ค๋ฅธ ์–ธ์–ด๋„ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ ๊ฐ–์ถฐ์ง€๋ฉด ์กฐ์ž‘ํ•  ์ˆ˜ ์žˆ๋‹ค. DOM์€ ์ด๋ ‡๊ฒŒ ์›น ํŽ˜์ด์ง€์˜ ๊ตฌ์กฐ๋ฅผ ํ”„๋กœ๊ทธ๋ž˜๋ฐ์ ์œผ๋กœ ์ ‘๊ทผํ•  ์ˆ˜ ์žˆ๊ฒŒ ํ•ด์„œ, ์›น ์ ‘๊ทผ์„ฑ์„ ๊ฐœ์„ ํ•˜๊ณ  ์›น ํ‘œ์ค€์„ ์ค€์ˆ˜ํ•˜๋Š” ๋ฐ ๋„์›€์„ ์ค€๋‹ค. ์Šคํฌ๋ฆฐ ๋ฆฌ๋”์™€ ๊ฐ™์€ ๋ณด์กฐ ๊ธฐ์ˆ ์„ ์‚ฌ์šฉํ•˜๋Š” ์‚ฌ์šฉ์ž๊ฐ€ ์›น ํŽ˜์ด์ง€๋ฅผ ๋” ์‰ฝ๊ฒŒ ์ดํ•ดํ•˜๊ณ  ์ƒํ˜ธ์ž‘์šฉํ•  ์ˆ˜ ์žˆ๋„๋ก ํ•˜๊ธฐ๋•Œ๋ฌธ์— ๋”์„ ์ดํ•ดํ•˜๊ณ  ์ž˜ ๋‹ค๋ค„์•ผ ํ•œ๋‹ค.
์•„๋ž˜ ๋‚ด์šฉ๋ถ€ํ„ฐ ๋”์— ์–ด๋–ป๊ฒŒ ์ ‘๊ทผํ•˜๊ณ , ์ฒ˜๋ฆฌํ•˜๋Š”์ง€ ํ•ต์‹ฌ ๋‚ด์šฉ์„ ๋‹ค๋ค„๋ณธ๋‹ค.
ย 

16-2. ๋” ์กฐ์ž‘๊ณผ ๋ณ€ํ˜•

16-2-1. ์š”์†Œ ์„ ํƒ๊ณผ ๋ณ€๊ฒฝ

DOM์—์„œ ๊ฐ๊ฐ์˜ ์š”์†Œ๋ฅผ ์„ ํƒํ•˜๊ณ , ์กฐ์ž‘ํ•˜๋Š” ๋ฐฉ๋ฒ•์€ document ๊ฐ์ฒด์— ๋‹ค์–‘ํ•œ ๋ฉ”์„œ๋“œ, ํ”„๋กœํผํ‹ฐ๋ฅผ ํ†ตํ•ด์„œ ์ ‘๊ทผํ•  ์ˆ˜ ์žˆ๋‹ค. ๊ฐ ์š”์†Œ๋ฅผ ์„ ํƒํ•˜๋ฉด ํ•ด๋‹น ์š”์†Œ ๋‚ด์šฉ์— ์†์„ฑ๊ฐ’ ๋ณ€๊ฒฝ, ํ…์ŠคํŠธ ๋‚ด์šฉ ๋ณ€๊ฒฝ, ์Šคํƒ€์ผ ์ง€์ • ๋ฐ ๋ณ€๊ฒฝ ๋‹ค์–‘ํ•œ ์กฐ์ž‘์ด ๊ฐ€๋Šฅํ•˜๋‹ค.
๋จผ์ € ๋Œ€ํ‘œ์ ์œผ๋กœ ์ œ์ผ ๋งŽ์ด ์“ฐ์ด๋Š” ๋ฉ”์„œ๋“œ๋Š” document.querySelector() ๊ฐ€ ์žˆ๋‹ค.
<h1>hello</h1> <h2 class='title'>world</h2> <script> const h1 = document.querySelector('h1'); const h2 = document.querySelector('.title'); h1.innerHTML = '<p>bye</p>'; </script>
document.querySelector๋Š” ํ•œ๊ฐ€์ง€ ์š”์†Œ๋ฅผ ๋ถˆ๋Ÿฌ์˜ค๊ณ , ๋ณ€์ˆ˜์— ์ €์žฅํ•œ๋‹ค. ๊ฐ™์€ ์š”์†Œ๊ฐ€ ๋งŽ์€ ๊ฒฝ์šฐ ์ฒซ ๋ฒˆ์งธ ์š”์†Œ๋ฅผ ๋ถˆ๋Ÿฌ์˜จ๋‹ค. ์š”์†Œ๋ฅผ ๋ถˆ๋Ÿฌ์˜ฌ ๋•Œ class๋Š” .(์˜จ์ )์„, id๋Š” #(์ƒต)์„ ์š”์†Œ ์•ž์— ๋ถ™์—ฌ์ค€๋‹ค. innerHTML ํ”„๋กœํผํ‹ฐ๋Š” html ์š”์†Œ ์ž์ฒด๋ฅผ ์„ ํƒํ•˜๊ณ , ์ถ”๊ฐ€ํ•  ๋•Œ ์ฃผ๋กœ ์‚ฌ์šฉํ•œ๋‹ค. h1 ํƒœ๊ทธ ๋‚ด์— p ํƒœ๊ทธ๊ฐ€ ์ถ”๊ฐ€๋˜๊ณ , ํ…์ŠคํŠธ ๋‚ด์šฉ์ด bye๋กœ ๋ณ€๊ฒฝ๋˜๋Š” ๊ฒƒ์ด๋‹ค. ์ด๋ ‡๊ฒŒ ๋ฉ”์„œ๋“œ์™€ ํ”„๋กœํผํ‹ฐ๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ๋”์— ์ ‘๊ทผํ•˜๊ณ  ์†์„ฑ ๋ณ€๊ฒฝ์„ ๊ฐ„๋‹จํ•˜๊ฒŒ ์กฐ์ž‘ํ•  ์ˆ˜ ์žˆ๋‹ค.
ย 
querySelector()๊ฐ€ ํ•˜๋‚˜์˜ ์„ ํƒ์ž(์š”์†Œ)๋งŒ ๋ถˆ๋Ÿฌ์˜ฌ ์ˆ˜ ์žˆ์–ด, ์ผ์น˜ํ•˜๋Š” ์š”์†Œ๊ฐ€ ์—ฌ๋Ÿฌ ๊ฐœ์ผ ๊ฒฝ์šฐ ์‚ฌ์šฉํ•˜๋Š” ๋ฉ”์„œ๋“œ๋Š” document.querySelectorAll() ์ด ์žˆ๋‹ค.
<p>์•ˆ๋…•ํ•˜์„ธ์š”.</p> <p>์•ˆ๋…•ํ•˜์„ธ์š”.</p> <p>์•ˆ๋…•ํ•˜์„ธ์š”.</p> <script> document.querySelectorAll('p').forEach(item => { item.textContent = '์•ˆ๋…•ํžˆ๊ฐ€์„ธ์š”'; }) </script>
querySelectorAll() ์€ ์ผ์น˜ํ•˜๋Š” ๋ชจ๋“  ์š”์†Œ๋ฅผ ๋ถˆ๋Ÿฌ์˜ฌ ์ˆ˜ ์žˆ๋‹ค.
querySelectorAll()์€ NodeList๋กœ ๋ฐ˜ํ™˜๋˜๋ฉฐ, ๋ฐฐ์—ด์ด ์•„๋‹Œ ์œ ์‚ฌ ๋ฐฐ์—ด ๊ฐ์ฒด์ด๋‹ค. ๋”ฐ๋ผ์„œ textContent๋ฅผ ์ง์ ‘ ์‚ฌ์šฉํ•  ์ˆ˜ ์—†๊ณ , forEach() ๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ querySelectorAll๋กœ ์„ ํƒํ•œ ๋ชจ๋“  <p> ์š”์†Œ์— ๋Œ€ํ•ด ๋ฐ˜๋ณตํ•˜๊ณ , ๊ฐ ์š”์†Œ์˜ textContent๋ฅผ ๋ณ€๊ฒฝํ•ด์•ผ ํ•œ๋‹ค. textContent ํ”„๋กœํผํ‹ฐ๋Š” ์š”์†Œ์˜ ๋‚ด์šฉ์„ ๋ณ€๊ฒฝํ•  ๋•Œ ์‚ฌ์šฉํ•œ๋‹ค. h1 ํƒœ๊ทธ ๋‚ด์— ํ…์ŠคํŠธ๋ฅผ โ€˜byeโ€™๋กœ ๋ณ€๊ฒฝํ•œ ๊ฒƒ์ด๋‹ค.
ย 
์ด์™ธ์—๋„ id ๊ฐ’์„ ๋ถˆ๋Ÿฌ์˜ค๋Š” document.getElementById ๋ฉ”์„œ๋“œ์™€ class ๊ฐ’์„ ๋ถˆ๋Ÿฌ์˜ค๋Š” document.getElementsByClassName ๋ฉ”์„œ๋“œ๊ฐ€ ์žˆ๋‹ค.
<div id='wrap'></div> <h1 class='logo'></h1> <script> const div = document.getElementById('wrap'); const logo = document.getElementsByClassName('logo'); console.log(div) console.log(logo) // <div id='wrap'></div> // HTMLCollectionย [h1.logo] </script>
๋ฉ”์„œ๋“œ ๋™์ž‘๋ฐฉ์‹์— ๋”ฐ๋ฅธ ์ฐจ์ด๋กœ ๊ฒฐ๊ณผ๊ฐ€ ๋‹ค๋ฅธ ๊ฒƒ์„ ๋ณผ ์ˆ˜ ์žˆ๋‹ค. getElementById ๋ฉ”์„œ๋“œ๋Š” ๋ฌธ์„œ ๋‚ด ๊ณ ์œ ํ•œ id๋ฅผ ๊ฐ€์ง„ ์š”์†Œ๋ฅผ ํ•˜๋‚˜๋งŒ ๋ถˆ๋Ÿฌ์™€์„œ <div>์š”์†Œ ์ž์ฒด๊ฐ€ ์ถœ๋ ฅ ๋˜๋Š” ๊ฒƒ์„ ๋ณผ ์ˆ˜ ์žˆ๋‹ค.
๋ฐ˜๋ฉด getElementsByClassName ๋ฉ”์„œ๋“œ๋Š” ํด๋ž˜์Šค์ด๋ฆ„๊ณผ ์ผ์น˜ํ•˜๋Š” ๋ชจ๋“  ์š”์†Œ๋ฅผ ์„ ํƒํ•˜์—ฌ ๋ชจ๋“  ์š”์†Œ๋ฅผ ๋ฐฐ์—ดํ˜•ํƒœ์˜ HTMLCollection ์œผ๋กœ ์ถœ๋ ฅํ•œ๋‹ค.
ย 
  • ์š”์†Œ์˜ ์†์„ฑ๊ฐ’์„ ๋ณ€๊ฒฝ,์ถ”๊ฐ€ํ•˜๋Š” ๋ฉ”์„œ๋“œ setAttribute()
<input type='text'/> <script> const input = document.querySelector('input'); input.setAttribute('type', 'checkbox'); </script>
setAttribute(name, value) ์ง€์ •๋œ ์š”์†Œ์˜ ์†์„ฑ๊ฐ’์„ ๋ณ€๊ฒฝํ•œ๋‹ค.ย ๊ธฐ์กด ์š”์†Œ์˜ ์†์„ฑ์ด ์—†๋‹ค๋ฉด, ์ง€์ •๋œ ์ด๋ฆ„๊ณผ ๊ฐ’์œผ๋กœ ์ƒˆ ์†์„ฑ์ด ์ถ”๊ฐ€๋œ๋‹ค. type์ด text์—์„œ checkbox๋กœ ๋ณ€๊ฒฝ๋œ๋‹ค.
ย 
  • ์š”์†Œ์˜ ์†์„ฑ๊ฐ’์„ ๊ฐ€์ ธ์˜ค๋Š” ๋ฉ”์„œ๋“œ getAttribute()
<div id='wrap'></div> <script> const id = document.getElementById('wrap'); id.getAttribute('id'); // 'wrap' </script>
getAttribute('id') ๋กœ ์“ฐ๋ฉด ์–ธ๋œป getElementById() ๋ฉ”์„œ๋“œ์™€ ๋น„์Šทํ•ด ๋ณด์ด์ง€๋งŒ, ์š”์†Œ์˜ ์†์„ฑ๊ฐ’์„ ๊ฐ€์ ธ์˜ฌ ๋•Œ ์‚ฌ์šฉํ•œ๋‹ค. ๋”ฐ๋ผ์„œ ์†์„ฑ๊ฐ’ โ€˜wrapโ€™๋งŒ ์ถœ๋ ฅํ•˜๋Š” ๊ฒƒ์„ ๋ณผ ์ˆ˜ ์žˆ๋‹ค.
getElementById() ๋Š” ํ•˜๋‚˜๋ฟ์ธ id ์š”์†Œ๋ฅผ ์ง์ ‘ ์„ ํƒํ•˜๋Š” ๊ฒƒ์ด๋‹ค.
ย 
  • ์š”์†Œ์˜ ํƒœ๊ทธ๋ช…์„ ๋ถˆ๋Ÿฌ์˜ค๋Š” ๋ฉ”์„œ๋“œ getElementsByTagName(tagname)
  • ์š”์†Œ์˜ ํŠน์ • ์†์„ฑ์„ ๋ณ€๊ฒฝํ•˜๋Š” ๋ฉ”์„œ๋“œ element.attribute = value
<img src='logo.jpg' alt='' /> <script> const image = document.getElementByTagName('img'); image.src = 'new_logo.png'; </script>
getElementsByTagName() ๋ฉ”์„œ๋“œ๋Š” ํƒœ๊ทธ ๋ช…์œผ๋กœ ์š”์†Œ๋ฅผ ๋ถˆ๋Ÿฌ์˜จ๋‹ค. ํƒœ๊ทธ ๋ช…๊ณผ ์ผ์น˜ํ•˜๋Š” ๋ชจ๋“  ์š”์†Œ๋ฅผ ์„ ํƒํ•˜๊ธฐ ๋•Œ๋ฌธ์— ์ž˜ ์‚ฌ์šฉ๋˜์ง€ ์•Š๋Š”๋‹ค. ํ•„์š”ํ•œ ์š”์†Œ์— ๋Œ€ํ•œ ์„ ํƒ์ž๋ฅผ ๋ถˆ๋Ÿฌ์˜ค๋ ค๋ฉด id๋‚˜ class๋ฅผ ๋ถˆ๋Ÿฌ์˜ค๋Š” ๋ฉ”์„œ๋“œ๋ฅผ ์‚ฌ์šฉํ•˜๋Š”๊ฒŒ ๋” ์ •ํ™•ํ•˜๊ณ  ์•ˆ์ „ํ•˜๋‹ค.
image.src = 'new_logo.png' ์š”์†Œ์˜ ํŠน์ • ์†์„ฑ์„ ๋ณ€๊ฒฝํ•  ์ˆ˜ ์žˆ์–ด ํ•ด๋‹น ์ฝ”๋“œ๋Š” ์ด๋ฏธ์ง€์š”์†Œ์˜ โ€˜srcโ€™ ์†์„ฑ์„ ๋ณ€๊ฒฝํ•œ๋‹ค. ์ฃผ๋กœ ํด๋ฆญ ์ด๋ฒคํŠธ, ์• ๋‹ˆ๋ฉ”์ด์…˜ ํšจ๊ณผ๋ฅผ ๋งŒ๋“ค ๋•Œ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋‹ค.
ย 

16-2-2. ๋™์ ์œผ๋กœ ์š”์†Œ ์ƒ์„ฑ ๋ฐ ์ œ๊ฑฐ

  • ๋™์ ์œผ๋กœ ์š”์†Œ ์ƒ์„ฑ
์ƒˆ๋กœ์šด HTML ์š”์†Œ๋ฅผ ๋™์ ์œผ๋กœ ์ƒ์„ฑํ•˜๋Š” ๋ฉ”์„œ๋“œ document.Element(tagName) @
์œ„์— ํ”„๋กœํผํ‹ฐ๋กœ ๋™์ ์œผ๋กœ ์ƒ์„ฑํ•  ์ˆ˜ ์žˆ์ง€๋งŒ, ๋ธŒ๋ผ์šฐ์ € ํ˜ธํ™˜์„ฑ ์ธก๋ฉด์—์„œ ๋Œ€๋ถ€๋ถ„ ์ผ๋ฐ˜์ ์ธ ๊ฒฝ์šฐ๋Š” document.Element() ๋ฅผ ์‚ฌ์šฉํ•œ๋‹ค.
const text = document.createElement('p');
์ƒ์„ฑํ•  html ์š”์†Œ ํƒœ๊ทธ ๋ช…์„ ๋„ฃ์–ด์ฃผ๋ฉด ๋œ๋‹ค. ์ฃผ๋กœ ์‚ฌ์šฉ์ž๊ฐ€ ๋ฒ„ํŠผ์„ ํด๋ฆญํ•ด์„œ ์ƒˆ๋กœ์šด ์•„์ดํ…œ์„ ์ถ”๊ฐ€ํ•˜๊ฑฐ๋‚˜, ์ž…๋ ฅ์— ๋”ฐ๋ผ ์ƒˆ๋กœ์šด ๋ฆฌ์ŠคํŠธ๋ฅผ ๋งŒ๋“ค ๋•Œ ๋งŽ์ด ์‚ฌ์šฉ๋œ๋‹ค.
ย 
  • ํ…์ŠคํŠธ ๋…ธ๋“œ ์ƒ์„ฑ
์ƒˆ๋กœ์šด ํ…์ŠคํŠธ ๋…ธ๋“œ๋ฅผ ๋™์ ์œผ๋กœ ์ƒ์„ฑํ•˜๋Š” ๋ฉ”์„œ๋“œ document.createTextNode('์ถ”๊ฐ€ํ•˜๋Š” ํ…์ŠคํŠธ')
const text = document.createTextNode('hello world!');
document.createTextNode() ๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด ํ…์ŠคํŠธ ๋‚ด์šฉ์„ ์กฐ์ž‘ํ•  ์ˆ˜ ์žˆ์–ด ์ž…๋ ฅ ํ•„๋“œ๊ฐ’์„ ๋ฐ”๊พธ๊ณ , ์—๋Ÿฌ๋ฉ”์‹œ์ง€๋ฅผ ๋งŒ๋“ค ๋•Œ ์œ ์šฉํ•˜๊ฒŒ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋‹ค.
ย 
  • ํŠน์ • ์š”์†Œ ์ž์‹์œผ๋กœ ์ถ”๊ฐ€
๋ถ€๋ชจ๋…ธ๋“œ๋ฅผ ํ†ตํ•ด ์ž์‹ ๋…ธ๋“œ๋ฅผ ์ถ”๊ฐ€ํ•˜๋Š” ๋ฉ”์„œ๋“œ appendChild(newNode)
<ul></ul> <script> const ul = document.querySelector('ul'); const li = document.createElement('li'); ul.appendChild(li) </script>
๋ฉ”์„œ๋“œ๋ฅผ ํ˜ธ์ถœํ•  ๋•Œ ์ถ”๊ฐ€ํ•˜๋Š” ๋…ธ๋“œ๋ฅผ ์ธ์ž๋กœ ์ „๋‹ฌํ•˜๋ฉด, ์ด ๋…ธ๋“œ๊ฐ€ ํŠน์ • ์š”์†Œ์˜ ์ž์‹ ๋…ธ๋“œ๋กœ ์ถ”๊ฐ€๋œ๋‹ค. ์œ„ ์˜ˆ์ œ๋Š” HTML์˜ ul ์š”์†Œ๋ฅผ ๋ถˆ๋Ÿฌ์˜ค๊ณ , ๋™์ ์œผ๋กœ li ์š”์†Œ๋ฅผ ์ƒ์„ฑํ•œํ›„ appendChild() ๋กœ ul์˜ ์ž์‹์œผ๋กœ li๋ฅผ ์ถ”๊ฐ€ํ•œ ๊ฒƒ์„ ๋ณผ ์ˆ˜ ์žˆ๋‹ค. ์ด์ฒ˜๋Ÿผ ๋ถ€๋ชจ ๋…ธ๋“œ์˜ ์ž์‹ ๋…ธ๋“œ๋กœ ์ถ”๊ฐ€๋˜๊ณ , ํ•˜๋‚˜์˜ ๋…ธ๋“œ๋งŒ ์ถ”๊ฐ€ํ•  ์ˆ˜ ์žˆ๋‹ค. ์—ฌ๋Ÿฌ ์š”์†Œ๋ฅผ ๋™์‹œ์— ์ถ”๊ฐ€ํ•˜๊ณ  ์‹ถ์œผ๋ฉด append() ๋ฉ”์„œ๋“œ๋ฅผ ์‚ฌ์šฉํ•ด์•ผ ํ•œ๋‹ค.
ย 
  • ํŠน์ • ๋…ธ๋“œ๋ฅผ ์ถ”๊ฐ€ํ•˜๋Š” ๋ฉ”์„œ๋“œ append()
ํ•˜๋‚˜ ์ด์ƒ์˜ ๋…ธ๋“œ ๋˜๋Š” ํ…์ŠคํŠธ๋ฅผ ํŠน์ • ์š”์†Œ ๋…ธ๋“œ์— ์ถ”๊ฐ€ํ•œ๋‹ค. ์—ฌ๋Ÿฌ ์š”์†Œ๋ฅผ ๋™์‹œ์— ์ถ”๊ฐ€ํ•  ์ˆ˜ ์žˆ๊ณ , ์š”์†Œ์˜ ์ˆœ์„œ๋ฅผ ์ง€์ •ํ•  ์ˆ˜ ์žˆ๋‹ค.
const parent = document.getElementById('wrap'); const child1 = document.createElement('div'); const child2 = document.createElement('h1'); const text = document.createTextNode('hello world!'); parent.append(child1, child2, text);
ย 
  • ๋™์ ์œผ๋กœ ์š”์†Œ ์ œ๊ฑฐ
๋ถ€๋ชจ ๋…ธ๋“œ๋ฅผ ํ†ตํ•ด ์ž์‹ ๋…ธ๋“œ๋ฅผ ์ œ๊ฑฐํ•˜๋Š” ๋ฉ”์„œ๋“œ removeChild(child)
๋ถ€๋ชจ ๋…ธ๋“œ์—์„œ ๋ฉ”์„œ๋“œ๋ฅผ ํ˜ธ์ถœํ•˜๊ณ , ์ธ์ž๋กœ ์ž์‹๋…ธ๋“œ๋ฅผ ์ง€์ •ํ•˜๋ฉด ์ž์‹ ๋…ธ๋“œ๊ฐ€ ์ œ๊ฑฐ๋œ๋‹ค.
<ul> <li></li> </ul> <script> const ul = document.querySelector('ul'); const li = document.querySelector('li'); ul.removeChild(li); </script>
HTML์˜ ul๊ณผ li ์š”์†Œ๋ฅผ ๋ถˆ๋Ÿฌ์˜ค๊ณ , removeChild() ๋กœ ul ์š”์†Œ์˜ ์ž์‹ ์š”์†Œ์ธ li๋ฅผ ์ œ๊ฑฐํ•œ๋‹ค. ์ž์‹ ์š”์†Œ๋ฅผ ์ง์ ‘ ์ง€์ •ํ•˜์ง€ ์•Š๊ณ , ํŠน์ • ๋ถ€๋ชจ ๋…ธ๋“œ์—์„œ ํ•˜๋‚˜์˜ ์ž์‹ ๋…ธ๋“œ๋ฅผ ์ œ๊ฑฐํ•  ๋•Œ ์‚ฌ์šฉ๋œ๋‹ค.
ย 
  • ํŠน์ • ๋…ธ๋“œ๋ฅผ ์ œ๊ฑฐํ•˜๋Š” ๋ฉ”์„œ๋“œ remove()
ํ•ด๋‹น ๋…ธ๋“œ ์ž์ฒด์—์„œ ๋ฉ”์„œ๋“œ๋ฅผ ํ˜ธ์ถœํ•˜์—ฌ ํ•ด๋‹น ๋…ธ๋“œ๋ฅผ ์ œ๊ฑฐํ•œ๋‹ค. ๋…ธ๋“œ๊ฐ€ ์—ฌ๋Ÿฌ ๊ฐœ์ผ ๊ฒฝ์šฐ ๊ฐ๊ฐ remove() ๋ฉ”์„œ๋“œ๋ฅผ ํ˜ธ์ถœํ•˜๋ฉด ๋œ๋‹ค.
const ul = document.querySelector('ul'); ul.remove();
ย 

16-2-3. DOM ๋…ธ๋“œ ํƒ์ƒ‰

  • ๋…ธ๋“œ ์‚ฌ์ด์˜ ๊ด€๊ณ„
notion imagenotion image
๋” ํŠธ๋ฆฌ์˜ ๋…ธ๋“œ๋Š” root ๋…ธ๋“œ <html>์ œ์™ธํ•˜๊ณ , ๊ณ„์ธต๊ตฌ์กฐ๋กœ ๊ฐ ํ•˜๋‚˜์˜ ๋ถ€๋ชจ์™€ ์—ฌ๋Ÿฌ ๊ฐœ์˜ ์ž์‹์„ ๊ฐ€์ง„๋‹ค. ๊ฐ™์€ ๋ถ€๋ชจ ๋…ธ๋“œ์˜ ๊ด€๊ณ„๋ฅผ sibling์ด๋ผ๊ณ  ํ•œ๋‹ค. DOM ํŠธ๋ฆฌ์˜ ๊ณ„์ธต๊ด€๊ณ„๋ฅผ ํƒ์ƒ‰ํ•˜๋Š” ํ”„๋กœํผํ‹ฐ๊ฐ€ ์žˆ๊ณ , ์ด ํ”„๋กœํผํ‹ฐ๋กœ DOM ํŠธ๋ฆฌ ๊ฐ ๋…ธ๋“œ๋ฅผ ํƒ์ƒ‰ํ•  ์ˆ˜ ์žˆ๋‹ค.
ย 
  • ๋…ธ๋“œ๋ฅผ ํƒ์ƒ‰ํ•˜๋Š” ํ”„๋กœํผํ‹ฐ
- ๋‹จ์ผ ๋…ธ๋“œ
ํ”„๋กœํผํ‹ฐ
์„ค๋ช…
parentNode
์š”์†Œ์˜ ๋ถ€๋ชจ ๋…ธ๋“œ๋ฅผ ์ ‘๊ทผํ•œ๋‹ค.
childNodes
์š”์†Œ์˜ ๋ชจ๋“  ์ž์‹ ๋…ธ๋“œ๋ฅผ ์ ‘๊ทผํ•œ๋‹ค. NodeList๋กœ ๊ฐ์ฒด๋กœ ๋ฐ˜ํ™˜๋œ๋‹ค.
firstChild
์ž์‹ ๋…ธ๋“œ์—์„œ ์ฒซ๋ฒˆ์งธ ์ž์‹ ๋…ธ๋“œ๋ฅผ ์ ‘๊ทผํ•œ๋‹ค.
lastChild
์ž์‹ ๋…ธ๋“œ์—์„œ ๋งˆ์ง€๋ง‰ ์ž์‹ ๋…ธ๋“œ๋ฅผ ์ ‘๊ทผํ•œ๋‹ค.
nextSibling
๋ถ€๋ชจ ๋…ธ๋“œ์˜ ๋ชจ๋“  ์ž์‹ ๋…ธ๋“œ์ค‘ ์ž์‹  ๋‹ค์Œ์— ์žˆ๋Š” ๋…ธ๋“œ๋ฅผ ์ ‘๊ทผํ•œ๋‹ค.
previousSibling
๋ถ€๋ชจ ๋…ธ๋“œ์˜ ๋ชจ๋“  ์ž์‹ ๋…ธ๋“œ์ค‘ ์ž์‹  ์ด์ „์— ์žˆ๋Š” ๋…ธ๋“œ๋ฅผ ์ ‘๊ทผํ•œ๋‹ค.
children
์š”์†Œ์˜ ์ž์‹ ๋…ธ๋“œ ๋ชฉ๋ก์— ์ ‘๊ทผํ•œ๋‹ค. childNodes ์™€ ๋‹ค๋ฅด๊ฒŒ ํ…์ŠคํŠธ ๋…ธ๋“œ๋ฅผ ๊ฑด๋„ˆ๋›ด๋‹ค.
์ž์ฃผ ์‚ฌ์šฉ๋˜๋Š” parentNode ํ”„๋กœํผํ‹ฐ๋Š” ํŠน์ • ๋…ธ๋“œ์˜ ๋ถ€๋ชจ๋ฅผ ์ฐพ๊ธฐ ์œ ์šฉํ•˜์—ฌ ๋ถ€๋ชจ ์š”์†Œ์˜ ๋‚ด์šฉ์„ ๋ณ€๊ฒฝํ•˜๋Š” ๋“ฑ ๋‹ค์–‘ํ•œ ์ž‘์—…์„ ์ˆ˜ํ–‰ํ•  ์ˆ˜ ์žˆ๋‹ค.
<div id='parent'> <div id='child'></div> </div> <script> const child = document.getElementById('child'); const parent = child.parendNode; </script>
DOM ํƒ์ƒ‰์„ ํ†ตํ•ด ์›น์˜ ๊ตฌ์กฐ๋ฅผ ์ดํ•ดํ•˜๊ณ , ์›ํ•˜๋Š” ์š”์†Œ์— ์ ‘๊ทผํ•˜๋Š” ๊ฒŒ ๊ฐ„ํŽธํ•˜๊ณ  ํšจ๊ณผ์ ์œผ๋กœ ์ œ์–ดํ•  ์ˆ˜ ์žˆ๋‹ค.
๊ทธ๋Ÿฌ๋‚˜ DOM ๋…ธ๋“œ ํƒ์ƒ‰์€ ์„ฑ๋Šฅ์— ์˜ํ–ฅ์„ ๋ฏธ์น˜๊ธฐ ๋•Œ๋ฌธ์—, ๊ฐ€๋Šฅํ•˜๋ฉด ์ตœ์ ํ™”๋œ ์ฟผ๋ฆฌ๋ฉ”์„œ๋“œ querySelector ๋˜๋Š” getElementById ๋ฅผ ์‚ฌ์šฉํ•˜๊ณ , ๋ฐ˜๋ณต์ ์ธ ํƒ์ƒ‰์€ ์ฃผ์˜ํ•ด์•ผ ํ•œ๋‹ค.
ย 

16-2-4. ์Šคํƒ€์ผ ๋ณ€๊ฒฝ๊ณผ ํด๋ž˜์Šค ์กฐ์ž‘

  • DOM ์š”์†Œ์˜ CSS ์Šคํƒ€์ผ ํ”„๋กœํผํ‹ฐ๋ฅผ ๋ณ€๊ฒฝํ•˜๋Š” ๋ฐฉ๋ฒ• element.style.property = value
โ€˜propertyโ€™๋Š” ์Šคํƒ€์ผ ์†์„ฑ์˜ ์ด๋ฆ„์ด๊ณ , โ€˜valueโ€™๋Š” ์†์„ฑ์— ์ ์šฉํ•  ๊ฐ’์ด๋‹ค.
const div = document.querySelector('div'); div.style.backgroundColor = 'red';
div ์š”์†Œ๋ฅผ ๋ถˆ๋Ÿฌ์˜ค๊ณ , ๋ฐฑ๊ทธ๋ผ์šด๋“œ ์Šคํƒ€์ผ ํ”„๋กœํผํ‹ฐ๋ฅผ ๋ณ€๊ฒฝํ•œ ๊ฒƒ์ด๋‹ค. style์€ DOM ์š”์†Œ์˜ ์Šคํƒ€์ผ ๊ฐ์ฒด์ด๋ฉฐ, โ€˜backgroundColorโ€™๋Š” ์Šคํƒ€์ผ ์†์„ฑ์˜ ์ด๋ฆ„์œผ๋กœ ์นด๋ฉœ ์ผ€์ด์Šค๋กœ ์ž‘์„ฑํ•ด์•ผ ํ•˜๊ณ , โ€˜redโ€™๋Š” ์†์„ฑ์— ์ ์šฉํ•  ๊ฐ’์ด๋‹ค.
๋™์ ์œผ๋กœ ์Šคํƒ€์ผ์„ ๋ณ€๊ฒฝํ•ด์•ผ ํ•  ๋•Œ ์˜ˆ๋ฅผ ๋“ค์–ด, ๋ฒ„ํŠผ ํด๋ฆญํ•  ๋•Œ ์Šคํƒ€์ผ์„ ๋ณ€๊ฒฝํ•˜๊ฑฐ๋‚˜ ์• ๋‹ˆ๋ฉ”์ด์…˜ ํšจ๊ณผ๋ฅผ ์ฃผ๋Š” ๋“ฑ ์ด๋ฒคํŠธ๋ฆฌ์Šค๋„ˆ ํด๋ฆญ ์ด๋ฒคํŠธ์™€ ๊ฐ™์ด ์“ฐ์ด๊ณ , ์ž์ฃผ ์‚ฌ์šฉ๋œ๋‹ค.
ย 
  • ์š”์†Œ์˜ ์ƒˆ๋กœ์šด ํด๋ž˜์Šค๋ฅผ ์ถ”๊ฐ€ํ•˜๋Š” ๋ฉ”์„œ๋“œ element.classList.add(className)
<style> .active { color: red; } </style> <body> <button id='btn'>์•ˆ๋…•ํ•˜์„ธ์š”</button> <script> const btn = document.getElementById('btn'); btn.addEventListener('click', ()=> { btn.classList.add('active'); }); </script> </body>
element.classList ๋Š” ์—˜๋ ˆ๋จผํŠธ์˜ ํด๋ž˜์Šค ๋ชฉ๋ก์— ์ ‘๊ทผํ•˜๋Š” ๊ฐ„ํŽธํ•œ ๋ฐฉ๋ฒ•์œผ๋กœ, ์ฝ๊ธฐ ์ „์šฉ ํ”„๋กœํผํ‹ฐ์ด๋‹ค.
๋ฒ„ํŠผ ์š”์†Œ๋ฅผ ๋ถˆ๋Ÿฌ์˜ค๊ณ , ๋ฒ„ํŠผ์„ ํด๋ฆญํ•˜๋ฉด โ€˜activeโ€™ํด๋ž˜์Šค๊ฐ€ ์ถ”๊ฐ€๋˜์„œ ์Šคํƒ€์ผ ์ปฌ๋Ÿฌ ์ƒ‰์ƒ์ด ๋ณ€๊ฒฝ๋œ๋‹ค.
add() ๋ฉ”์„œ๋“œ๋Š” ํด๋ž˜์Šค๋ฅผ ์ถ”๊ฐ€ํ•˜๋Š” ๋ฉ”์„œ๋“œ๋กœ ํด๋ž˜์Šค ์ด๋ฆ„์„ ์ธ์ˆ˜๋กœ ๋ฐ›๋Š”๋‹ค. ์ถ”๊ฐ€ํ•  ํด๋ž˜์Šค๊ฐ€ ์—ฌ๋Ÿฌ ๊ฐœ๋ผ๋ฉด btn.classList.add('active','show','toggle') ์ด๋Ÿฐ ์‹์œผ๋กœ ํ•œ๊บผ๋ฒˆ์— ์—ฌ๋Ÿฌ ๊ฐœ๋ฅผ ํ˜ธ์ถœํ•˜๋ฉด ๋œ๋‹ค.
์ด๋ฒคํŠธ๋ฆฌ์Šค๋„ˆ addEventListener ๋“ฑ๋ก์€ ์ด๋ฒคํŠธ ๋ชฉ์ฐจ์—์„œ ๋‹ค๋ฃฐ ์˜ˆ์ •์œผ๋กœ ํด๋ฆญํ•  ๋•Œ ์Šคํƒ€์ผ ๋ณ€๊ฒฝ ๋“ฑ DOM ์š”์†Œ์˜ ํด๋ž˜์Šค๋ฅผ ์กฐ์ž‘ํ•˜๋Š”๋ฐ ์ฃผ๋กœ ๊ฐ™์ด ์‚ฌ์šฉ๋œ๋‹ค.
ย 
  • ์š”์†Œ์—์„œ ํด๋ž˜์Šค๋ฅผ ์ œ๊ฑฐํ•˜๋Š” ๋ฉ”์„œ๋“œ element.classList.remove(className)
const btn = document.querySelector('.btn'); btn.addEventListener('click', ()=> { btn.classList.remove('btn'); });
โ€˜btnโ€™ ํด๋ž˜์Šค ์ด๋ฆ„์„ ๊ฐ€์ง„ ์š”์†Œ๋ฅผ ๋ถˆ๋Ÿฌ์˜ค๊ณ , ์š”์†Œ๋ฅผ ํด๋ฆญํ•  ๋•Œ โ€˜btnโ€™ ํด๋ž˜์Šค ์ด๋ฆ„์ด ์‚ญ์ œ๋œ๋‹ค. add() ๋ฉ”์„œ๋“œ์™€ ๋งˆ์ฐฌ๊ฐ€์ง€๋กœ ์‚ญ์ œํ•  ํด๋ž˜์Šค๊ฐ€ ์—ฌ๋Ÿฌ ๊ฐœ๋ผ๋ฉด btn.classList.remove('btn','show','toggle') ํ•œ๊บผ๋ฒˆ์— ์—ฌ๋Ÿฌ ๊ฐœ ํ˜ธ์ถœ์ด ๊ฐ€๋Šฅํ•˜๋‹ค.
ย 
  • ์š”์†Œ์— ํด๋ž˜์Šค๊ฐ€ ์—†์œผ๋ฉด ์ถ”๊ฐ€, ์žˆ์œผ๋ฉด ์ œ๊ฑฐ ํ•˜๋Š” ๋ฉ”์„œ๋“œ element.classList.toggle(className)
<div id='hello' class='toggle'>Hello</div> <div id='bye'>Bye</div> <script> const hello = document.getElementById('hello'); const bye = document.getElementById('bye'); hello.addEventListener('click', ()=>{ hello.classList.toggle('toggle'); }); bye.addEventListener('click', ()=>{ bye.classList.toggle('toggle'); }); </script>
๊ฐ๊ฐ์˜ div ์š”์†Œ๋ฅผ ๋ถˆ๋Ÿฌ์™€์„œ, ์š”์†Œ๋ฅผ ํด๋ฆญ ํ• ๋•Œ โ€˜toggleโ€™ํด๋ž˜์Šค ์ด๋ฆ„์ด ์žˆ๋‹ค๋ฉด ์‚ญ์ œ๋˜๊ณ , ์—†๋‹ค๋ฉด โ€˜toggleโ€™ํด๋ž˜์Šค๊ฐ€ ์ถ”๊ฐ€๋œ๋‹ค. โ€˜helloโ€™๋Š” ์ด๋ฏธ ์žˆ๊ธฐ ๋•Œ๋ฌธ์— ์ œ๊ฑฐ๋˜๊ณ , โ€˜byeโ€™๋Š” ์—†์œผ๋ฏ€๋กœ ํด๋ž˜์Šค๊ฐ€ ์ถ”๊ฐ€๋œ๋‹ค.