๋ณธ๋ฌธ์œผ๋กœ ๊ฑด๋„ˆ๋›ฐ๊ธฐ

DOM

DOM(Document Object Model)#

DOM tree#

2020-05-15-dom-image-0

DOM tree๋Š” ๋„ค ์ข…๋ฅ˜์˜ ๋…ธ๋“œ๋กœ ๊ตฌ์„ฑ๋œ๋‹ค.

  • ๋ฌธ์„œ ๋…ธ๋“œ(Document Node)

ํŠธ๋ฆฌ์˜ ์ตœ์ƒ์œ„์— ์กด์žฌํ•˜๋ฉฐ ๊ฐ๊ฐ ์š”์†Œ, ์–ดํŠธ๋ฆฌ๋ทฐํŠธ, ํ…์ŠคํŠธ ๋…ธ๋“œ์— ์ ‘๊ทผํ•˜๋ ค๋ฉด ๋ฌธ์„œ ๋…ธ๋“œ๋ฅผ ํ†ตํ•ด์•ผ ํ•œ๋‹ค. ์ฆ‰, DOM tree์— ์ ‘๊ทผํ•˜๊ธฐ ์œ„ํ•œ ์‹œ์ž‘์ (entry point)์ด๋‹ค.

  • ์š”์†Œ ๋…ธ๋“œ(Element Node)

์š”์†Œ ๋…ธ๋“œ๋Š” HTML ์š”์†Œ๋ฅผ ํ‘œํ˜„ํ•œ๋‹ค. HTML ์š”์†Œ๋Š” ์ค‘์ฒฉ์— ์˜ํ•ด ๋ถ€์ž ๊ด€๊ณ„๋ฅผ ๊ฐ€์ง€๋ฉฐ ์ด๋ถ€์ž ๊ด€๊ณ„๋ฅผ ํ†ตํ•ด ์ •๋ณด๋ฅผ ๊ตฌ์กฐํ™”ํ•œ๋‹ค. ๋”ฐ๋ผ์„œ ์š”์†Œ ๋…ธ๋“œ๋Š” ๋ฌธ์„œ์˜ ๊ตฌ์กฐ๋ฅผ ์„œ์ˆ ํ•œ๋‹ค๊ณ ๋ง ํ•  ์ˆ˜ ์žˆ๋‹ค. ์–ดํŠธ๋ฆฌ๋ทฐํŠธ, ํ…์ŠคํŠธ ๋…ธ๋“œ์— ์ ‘๊ทผํ•˜๋ ค๋ฉด ๋จผ์ € ์š”์†Œ ๋…ธ๋“œ๋ฅผ ์ฐพ์•„ ์ ‘๊ทผํ•ด์•ผ ํ•œ๋‹ค. ๋ชจ๋“  ์š”์†Œ ๋…ธ๋“œ๋Š” ์š”์†Œ๋ณ„ ํŠน์„ฑ์„ ํ‘œํ˜„ํ•˜๊ธฐ ์œ„ํ•ด HTMLElement ๊ฐ์ฒด๋ฅผ ์ƒ์†ํ•œ๊ฐ์ฒด๋กœ ๊ตฌ์„ฑ๋œ๋‹ค. (๊ทธ๋ฆผ: DOM tree์˜ ๊ฐ์ฒด ๊ตฌ์„ฑ ์ฐธ๊ณ )

  • ์–ดํŠธ๋ฆฌ๋ทฐํŠธ ๋…ธ๋“œ(Attribute Node)

์–ดํŠธ๋ฆฌ๋ทฐํŠธ ๋…ธ๋“œ๋Š” HTML ์š”์†Œ์˜ ์–ดํŠธ๋ฆฌ๋ทฐํŠธ๋ฅผ ํ‘œํ˜„ํ•œ๋‹ค. ์–ดํŠธ๋ฆฌ๋ทฐํŠธ ๋…ธ๋“œ๋Š” ํ•ด๋‹น ์–ดํŠธ๋ฆฌ๋ทฐํŠธ๊ฐ€ ์ง€์ •๋œ ์š”์†Œ์˜ ์ž์‹์ด ์•„๋‹ˆ๋ผ ํ•ด๋‹น ์š”์†Œ์˜ ์ผ๋ถ€๋กœ ํ‘œํ˜„๋œ๋‹ค. ๋”ฐ๋ผ์„œ ํ•ด๋‹น ์š”์†Œ ๋…ธ๋“œ๋ฅผ ์ฐพ์•„ ์ ‘๊ทผํ•˜๋ฉด ์–ดํŠธ๋ฆฌ๋ทฐํŠธ๋ฅผ ์ฐธ์กฐ, ์ˆ˜์ •ํ•  ์ˆ˜ ์žˆ๋‹ค.

  • ํ…์ŠคํŠธ ๋…ธ๋“œ(Text Node)

ํ…์ŠคํŠธ ๋…ธ๋“œ๋Š” HTML ์š”์†Œ์˜ ํ…์ŠคํŠธ๋ฅผ ํ‘œํ˜„ํ•œ๋‹ค. ํ…์ŠคํŠธ ๋…ธ๋“œ๋Š” ์š”์†Œ ๋…ธ๋“œ์˜ ์ž์‹์ด๋ฉฐ์ž์‹ ์˜ ์ž์‹ ๋…ธ๋“œ๋ฅผ ๊ฐ€์งˆ ์ˆ˜ ์—†๋‹ค. ์ฆ‰, ํ…์ŠคํŠธ ๋…ธ๋“œ๋Š” DOM tree์˜ ์ตœ์ข…๋‹จ์ด๋‹ค.

DOM Query / Traversing (์š”์†Œ๋กœ ์ ‘๊ทผ)#

ํ•˜๋‚˜์˜ ์š”์†Œ ๋…ธ๋“œ ์„ ํƒ(DOM Query)#

document.getElementById(id)#

  • id ์†์„ฑ ๊ฐ’์œผ๋กœ ์š”์†Œ ๋…ธ๋“œ๋ฅผ ํ•œ ๊ฐœ ์„ ํƒํ•˜์—ฌ ๋ฐ˜ํ™˜, ์—ฌ๋Ÿฌ ๋…ธ๋“œ๊ฐ€ ์žˆ๋Š” ๊ฒฝ์šฐ ์ฒซ๋ฒˆ์งธ์š”์†Œ๋งŒ ๋ฐ˜ํ™˜

  • HTMLElement๋ฅผ ์ƒ์†๋ฐ›์€ ๊ฐ์ฒด๋ฅผ ๋ฆฌํ„ดํ•œ๋‹ค.

๐Ÿ“Œ ์•„๋ž˜์˜ ์˜ˆ์ œ๋ถ€ํ„ฐ ๋ชจ๋‘ class="red" ์ธ ์š”์†Œ๋Š” ์ƒ‰์ƒ์ด red ๋ผ๋Š” css ์„ค์ •๊ณผ ๋‹ค์Œ์˜ html ์š”์†Œ๋“ค์„ ๊ณ ์ •ํ•ด๋†“๊ณ  ์‚ฌ์šฉํ•œ๋‹ค.

.red {    color: red;}
<h1>๋™๋ฌผ๋†์žฅ</h1><p class="dog">๊ฐ•์•„์ง€</p><ul>    <li id="cocker" class="red">์ฝ”์นด</li>    <li id="sichu" class="red">์‹œ์ธ„</li>    <li id="poodle" class="red">ํ‘ธ๋“ค</li></ul><p class="cat">๊ณ ์–‘์ด</p><ul>    <li id="sphinx" class="black">์Šคํ•‘ํฌ์Šค</li>    <li id="russian" class="black">๋Ÿฌ์‹œ์•ˆ</li>    <li id="persian" class="black">ํŽ˜๋ฅด์‹œ์•ˆ</li></ul>
const elem = document.getElementById('sphinx');elem.className = 'red';
  • ๊ฒฐ๊ณผ

2020-05-15-dom-image-1

document.querySelector(cssSelector)#

  • CSS ์„ ํƒ์ž๋กœ ์š”์†Œ ๋…ธ๋“œ ํ•œ ๊ฐœ ์„ ํƒํ•˜์—ฌ ๋ฐ˜ํ™˜, ์—ฌ๋Ÿฌ ๋…ธ๋“œ๊ฐ€ ์žˆ๋Š” ๊ฒฝ์šฐ ์ฒซ๋ฒˆ์งธ ์š”์†Œ๋งŒ ๋ฐ˜ํ™˜

  • HTMLElement๋ฅผ ์ƒ์†๋ฐ›์€ ๊ฐ์ฒด๋ฅผ ๋ฆฌํ„ดํ•œ๋‹ค.

const elem = document.querySelector('#sphinx');elem.className = 'red';

2020-05-15-dom-image-2

์—ฌ๋Ÿฌ ๊ฐœ์˜ ์š”์†Œ ๋…ธ๋“œ ์„ ํƒ(DOM Query)#

document.getElementsByClassName(class)#

  • class ์†์„ฑ ๊ฐ’์œผ๋กœ ์š”์†Œ ๋…ธ๋“œ๋ฅผ ๋ชจ๋‘ ์„ ํƒ ํ•œ๋‹ค. ๊ณต๋ฐฑ์œผ๋กœ ๊ตฌ๋ถ„ํ•˜์—ฌ ์—ฌ๋Ÿฌ class๋ฅผ์ง€์ •ํ•  ์ˆ˜ ์žˆ๋‹ค.

  • HTMLCollection ์„ ๋ฆฌํ„ดํ•œ๋‹ค. (live)

const elems = document.getElementsByClassName('black');for (let i = 0; i < elems.length; i++) {    elems[i].className = 'red';}
  • ๊ฒฐ๊ณผ

2020-05-15-dom-image-3

์œ„ ์˜ˆ์ œ์˜ ์‹คํ–‰ ๊ฒฐ๊ณผ๊ฐ€ ์ด์ƒํ•œ ๊ฒƒ์„ ๋ณผ ์ˆ˜ ์žˆ๋Š”๋ฐ, getElementsByClassName ๋ฉ”์†Œ๋“œ์˜๋ฐ˜ํ™˜๊ฐ’์ธ HTMLCollection์ด ์‹ค์‹œ๊ฐ„์œผ๋กœ Node์˜ ์ƒํƒœ ๋ณ€๊ฒฝ์„ ๋ฐ˜์˜ํ•˜๊ธฐ ๋•Œ๋ฌธ์ด๋‹ค.

์ฆ‰ loop๊ฐ€ ์‹คํ–‰๋˜๋ฉด์„œ, elems์˜ className ์กฐ๊ฑด์— ๋ถ€ํ•ฉ๋˜์ง€ ์•Š๋Š” ์š”์†Œ๋“ค์ด ์ œ๊ฑฐ๋˜๋ฉด์„œ elems ๋ฐฐ์—ด์˜ ๊ธธ์ด๊ฐ€ ๋ณ€๋™๋˜๊ธฐ ๋•Œ๋ฌธ์— ๋ฃจํ”„๊ฐ€ ์ œ๋Œ€๋กœ ์‹คํ–‰๋˜์ง€ ์•Š๋Š”๋‹ค.

์ด๋ฅผ ํ•ด๊ฒฐํ•˜๋Š” ๋ฐฉ๋ฒ•์€ ๋‹ค์Œ๊ณผ ๊ฐ™๋‹ค

  • ๋ฐ˜๋ณต๋ฌธ์„ ์—ญ๋ฐฉํ–ฅ์œผ๋กœ ๋Œ๋ฆฐ๋‹ค.

  • while ๋ฐ˜๋ณต๋ฌธ์„ ์‚ฌ์šฉํ•˜๋ฉด์„œ, elems์˜ ์š”์†Œ๊ฐ€ ๋‚จ์•„์žˆ์ง€ ์•Š์„ ๋•Œ๊นŒ์ง€ ๋ฐ˜๋ณตํ•œ๋‹ค.

const elems = document.getElementsByClassName('black');
while (elems.length > 0) {    // elems์— ์š”์†Œ๊ฐ€ ๋‚จ์•„ ์žˆ์ง€ ์•Š์„ ๋•Œ๊นŒ์ง€ ๋ฌดํ•œ๋ฐ˜๋ณต    elems[0].className = 'red';}
  • HTMLCollection์„ ๋ฐฐ์—ด๋กœ ๋ณ€๊ฒฝํ•œ๋‹ค. (๊ถŒ์žฅ)
const elems = document.getElementsByClassName('black');
[...elems].forEach((elem) => (elem.className = 'red'));
  • querySelectorAll ๋ฉ”์†Œ๋“œ๋ฅผ ์‚ฌ์šฉํ•œ๋‹ค.

2020-05-15-dom-image-4

document.getElementsByTagName(tagName)#

  • ์ง€์ •๋œ CSS ์„ ํƒ์ž๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ์š”์†Œ ๋…ธ๋“œ๋ฅผ ๋ชจ๋‘ ์„ ํƒํ•œ๋‹ค

  • NodeList(non-live) ๋ฅผ ๋ฆฌํ„ดํ•œ๋‹ค.

NodeList๋Š” HTMLCollection๊ณผ ๋‹ฌ๋ฆฌ non-live ์ด๊ธฐ ๋•Œ๋ฌธ์—, loop ์•ˆ์—์„œ length์˜ ๋ณ€ํ™”๊ฐ€ ์ผ์–ด๋‚˜์ง€ ์•Š๋Š”๋‹ค.

const elems = document.querySelectorAll('.black');elems.forEach((elem) => (elem.className = 'red'));

document.getElementsByTagName(tagName)#

  • ํƒœ๊ทธ ์ด๋ฆ„์œผ๋กœ ์š”์†Œ ๋…ธ๋“œ๋ฅผ ๋ชจ๋‘ ์„ ํƒํ•œ๋‹ค

  • HTMLCollection (live)์„ ๋ฆฌํ„ดํ•œ๋‹ค

const elems = document.getElementsByTagName('li');[...elems].forEach((elem) => (elem.className = 'red'));

DOM Traversing(ํƒ์ƒ‰)#

๊ธฐ์ค€์ด ๋˜๋Š” ๋…ธ๋“œ์™€ ๊ด€๊ณ„๋ฅผ ๊ฐ–๊ณ  ์žˆ๋Š” ๋…ธ๋“œ๋กœ ์ด๋™ํ•˜๋ฉด์„œ ํƒ์ƒ‰ํ•  ์ˆ˜ ์žˆ๋‹ค.

parentNode#

  • ๋ถ€๋ชจ ๋…ธ๋“œ๋ฅผ ํƒ์ƒ‰ํ•œ๋‹ค.

  • HTMLElement๋ฅผ ์ƒ์†๋ฐ›์€ ๊ฐ์ฒด๋ฅผ ๋ฆฌํ„ดํ•œ๋‹ค.

const elem = document.querySelector('#sphinx');elem.parentNode.className = 'red';

firstChild, lastChild#

  • ์ž์‹ ๋…ธ๋“œ๋ฅผ ํƒ์ƒ‰ํ•œ๋‹ค

  • HTMLElement๋ฅผ ์ƒ์†๋ฐ›์€ ๊ฐ์ฒด๋ฅผ ๋ฆฌํ„ดํ•œ๋‹ค.

const elem = document.querySelector('ul');elem.firstChild.className = 'black';elem.lastChild.className = 'black';

์œ„์˜ ์˜ˆ์ œ๋ฅผ ์‹คํ–‰ํ•ด๋ณด๋ฉด ์ž˜ ๋™์ž‘ํ•˜์ง€ ์•Š๋Š”๋ฐ, IE๋ฅผ ์ œ์™ธํ•œ ๋Œ€๋ถ€๋ถ„์˜ ๋ธŒ๋ผ์šฐ์ €๋“ค์ด ์š”์†Œ ์‚ฌ์ด์˜ ๊ณต๋ฐฑ ๋˜๋Š” ์ค„๋ฐ”๊ฟˆ ๋ฌธ์ž๋ฅผ ํ…์ŠคํŠธ ๋…ธ๋“œ๋กœ ์ทจ๊ธ‰ํ•˜์—ฌ ์ฒซ๋ฒˆ์งธ ์ž์‹ ๋…ธ๋“œ, ๋งˆ์ง€๋ง‰ ์ž์‹ ๋…ธ๋“œ๋ฅผ HTML ์š”์†Œ๋กœ ํŒ๋‹จํ•˜์ง€ ์•Š๊ธฐ ๋•Œ๋ฌธ์ด๋‹ค.

์ด๋ฅผ ํ•ด๊ฒฐํ•˜๋Š” ๋ฐฉ๋ฒ•์€ ๋‹ค์Œ๊ณผ ๊ฐ™๋‹ค.

  • HTML์˜ ๊ณต๋ฐฑ์„ ์ œ๊ฑฐํ•œ๋‹ค.
<ul>    <li id="cocker" class="red">์ฝ”์นด</li>    <li id="sichu" class="red">์‹œ์ธ„</li>    <li id="poodle" class="red">ํ‘ธ๋“ค</li></ul>
  • jQuery: .prev() ์™€ jQuery: .next() ๋ฅผ ์‚ฌ์šฉํ•œ๋‹ค.

  • ๋˜๋Š” firstElementChild, lastElementChild๋ฅผ ์‚ฌ์šฉํ•œ๋‹ค.

2020-05-15-dom-image-5

hasChildNodes()#

  • ์ž์‹ ๋…ธ๋“œ๊ฐ€ ์žˆ๋Š”์ง€ ํ™•์ธํ•˜๊ณ  Boolean ๊ฐ’์„ ๋ฐ˜ํ™˜ํ•œ๋‹ค.

childNodes#

  • ์ž์‹ ๋…ธ๋“œ์˜ ์ปฌ๋ ‰์…˜์„ ๋ฐ˜ํ™˜ํ•œ๋‹ค.

  • ํ…์ŠคํŠธ ์š”์†Œ๋ฅผ ํฌํ•จํ•œ ๋ชจ๋“  ์ž์‹ ์š”์†Œ๋ฅผ ๋ฐ˜ํ™˜ํ•œ๋‹ค.

  • NodeList(non-live)๋ฅผ ๋ฆฌํ„ดํ•œ๋‹ค.

children#

  • ์ž์‹ ๋…ธ๋“œ์˜ ์ปฌ๋ ‰์…˜์„ ๋ฐ˜ํ™˜ํ•œ๋‹ค. ์ž์‹ ์š”์†Œ ์ค‘์—์„œ Element type ์š”์†Œ ๋งŒ์„ ๋ฐ˜ํ™˜ํ•œ๋‹ค.

  • HTMLCollection(live)๋ฅผ ๋ฆฌํ„ดํ•œ๋‹ค.

const elem = document.querySelector('ul');
if (elem.hasChildNodes()) {    console.log(elem.childNodes);
    console.log(elem.children);    [...elem.children].forEach((el) => console.log(el));}

2020-05-15-dom-image-6

previousSibling, nextSibling#

  • ํ˜•์ œ ๋…ธ๋“œ๋ฅผ ํƒ์ƒ‰ํ•œ๋‹ค. text node๋ฅผ ํฌํ•จํ•œ ๋ชจ๋“  ํ˜•์ œ ๋…ธ๋“œ๋ฅผ ํƒ์ƒ‰ํ•œ๋‹ค.

  • HTMLElement๋ฅผ ์ƒ์†๋ฐ›์€ ๊ฐ์ฒด๋ฅผ ๋ฆฌํ„ดํ•œ๋‹ค.

previousElementSibling, nextElementSibling#

  • ํ˜•์ œ ๋…ธ๋“œ๋ฅผ ํƒ์ƒ‰ํ•œ๋‹ค. ํ˜•์ œ ๋…ธ๋“œ ์ค‘์—์„œ Element type ์š”์†Œ๋งŒ์„ ํƒ์ƒ‰ํ•œ๋‹ค.

  • HTMLElement๋ฅผ ์ƒ์†๋ฐ›์€ ๊ฐ์ฒด๋ฅผ ๋ฆฌํ„ดํ•œ๋‹ค.

DOM Manipulation (์กฐ์ž‘)#

๋…ธ๋“œ์— ๋Œ€ํ•œ ์ •๋ณด๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™์€ ํ”„๋กœํผํ‹ฐ๋ฅผ ํ†ตํ•ด ์ ‘๊ทผํ•  ์ˆ˜ ์žˆ๋‹ค.

nodeName#

๋…ธ๋“œํ”„๋กœํผํ‹ฐ ๊ฐ’
๋ฌธ์„œ ๋…ธ๋“œ(document node)#document
์š”์†Œ ๋…ธ๋“œ(element node)ํƒœ๊ทธ ์ด๋ฆ„(์˜์–ด๋กœ ๋Œ€๋ฌธ์ž)
์†์„ฑ ๋…ธ๋“œ(attribute node)์†์„ฑ ์ด๋ฆ„
ํ…์ŠคํŠธ ๋…ธ๋“œ(text node)#text

nodeType#

๋…ธ๋“œํ”„๋กœํผํ‹ฐ ๊ฐ’
์š”์†Œ ๋…ธ๋“œ(element node)1
์†์„ฑ ๋…ธ๋“œ(attribute node)2
ํ…์ŠคํŠธ ๋…ธ๋“œ(text node)3
์ฃผ์„ ๋…ธ๋“œ(comment node)8
๋ฌธ์„œ ๋…ธ๋“œ(document node)9

nodeValue#

๋…ธ๋“œํ”„๋กœํผํ‹ฐ ๊ฐ’
์š”์†Œ ๋…ธ๋“œ(element node)null
์†์„ฑ ๋…ธ๋“œ(attribute node)ํ•ด๋‹น ์†์„ฑ์˜ ์†์„ฑ ๊ฐ’
ํ…์ŠคํŠธ ๋…ธ๋“œ(text node)ํ•ด๋‹น ํ…์ŠคํŠธ ๋ฌธ์ž์—ด

ํ…์ŠคํŠธ ๋…ธ๋“œ์—์˜ ์ ‘๊ทผ/์ˆ˜์ •#

์š”์†Œ์˜ ํ…์ŠคํŠธ๋Š” ํ…์ŠคํŠธ ๋…ธ๋“œ์— ์ €์žฅ๋˜์–ด ์žˆ๋‹ค. ํ…์ŠคํŠธ ๋…ธ๋“œ์— ์ ‘๊ทผํ•˜๋ ค๋ฉด ๋‹ค์Œ์˜ ์ˆ˜์ˆœ์„ ๋”ฐ๋ผ์•ผ ํ•œ๋‹ค.

  1. ํ•ด๋‹น ํ…์ŠคํŠธ ๋…ธ๋“œ์˜ ๋ถ€๋ชจ ๋…ธ๋“œ๋ฅผ ์„ ํƒ

  2. firstChild ํ”„๋กœํผํ‹ฐ๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ํ…์ŠคํŠธ ๋…ธ๋“œ๋ฅผ ํƒ์ƒ‰

  3. ํ…์ŠคํŠธ ๋…ธ๋“œ์˜ nodeValue๋ฅผ ์ด์šฉํ•˜์—ฌ ํ…์ŠคํŠธ ์ทจ๋“

  4. nodeValue๋ฅผ ์ด์šฉํ•˜์—ฌ ํ…์ŠคํŠธ ์ˆ˜์ •

const elem = document.querySelector('ul');console.dir(elem); // HTMLElement: ulconsole.log(elem.nodeName); // ULconsole.log(elem.nodeType); // 1: Element nodeconsole.log(elem.nodeValue); // null
const firstDog = elem.firstElementChild;console.log(firstDog.nodeName); // LIconsole.log(firstDog.nodeType); // 1: Element nodeconsole.log(firstDog.nodeValue); // null
const textNode = firstDog.firstChild;console.log(textNode.nodeName); // #textconsole.log(textNode.nodeType); // 3: Text nodeconsole.log(textNode.nodeValue); // ์ฝ”์นดtextNode.nodeValue = 'ํฌ๋ฉ”๋ฆฌ์•ˆ';

2020-05-15-dom-image-7

2020-05-15-dom-image-8

์†์„ฑ ๋…ธ๋“œ์—์˜ ์ ‘๊ทผ/์ˆ˜์ •#

์†์„ฑ ๋…ธ๋“œ๋ฅผ ์กฐ์ž‘ํ•  ๋•Œ ๋‹ค์Œ ํ”„๋กœํผํ‹ฐ์™€ ๋ฉ”์†Œ๋“œ๋ฅผ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋‹ค.

className#

class ์†์„ฑ์˜ ๊ฐ’์„ ์ทจ๋“ ๋˜๋Š” ๋ณ€๊ฒฝํ•œ๋‹ค. className ํ”„๋กœํผํ‹ฐ์— ๊ฐ’์„ ํ• ๋‹นํ•˜๋Š” ๊ฒฝ์šฐ class ์†์„ฑ์ด ์—†์œผ๋ฉด class ์†์„ฑ์„ ์ƒ์„ฑํ•˜๊ณ  ์ง€์ •๋œ ๊ฐ’์„ ์„ค์ •ํ•œ๋‹ค. class ์†์„ฑ์˜ ๊ฐ’์ด ์—ฌ๋Ÿฌ ๊ฐœ์ผ ๊ฒฝ์šฐ ๊ณต๋ฐฑ์œผ๋กœ ๊ตฌ๋ถ„๋œ ๋ฌธ์ž์—ด์ด ๋ฐ˜ํ™˜๋˜๋ฏ€๋กœ String ๋ฉ”์†Œ๋“œ split(' ') ์„ ์‚ฌ์šฉํ•˜์—ฌ ๋ฐฐ์—ด๋กœ ๋ณ€๊ฒฝํ•˜์—ฌ ์‚ฌ์šฉํ•œ๋‹ค.

const elems = document.querySelectorAll('li');
[...elems].forEach((elem) => {    if (elem.className === 'red') {        elem.className = 'black';    }});

2020-05-15-dom-image-9

classList#

add, remove, item, toggle, contains, replace ๋ฉ”์†Œ๋“œ๋ฅผ ์ œ๊ณตํ•œ๋‹ค.

const elems = document.querySelectorAll('li');
[...elems].forEach((elem) => {    if (elem.classList.contains('black')) {        elem.classList.replace('black', 'red');    }});

2020-05-15-dom-image-10

id#

  • id ์†์„ฑ์˜ ๊ฐ’์„ ์ทจ๋“ ๋˜๋Š” ๋ณ€๊ฒฝํ•œ๋‹ค. id ์†์„ฑ์— ๊ฐ’์„ ํ• ๋‹นํ•˜๋Š” ๊ฒฝ์šฐ, id ์†์„ฑ์ด ์กด์žฌํ•˜์ง€ ์•Š์œผ๋ฉด id ์†์„ฑ์„ ์ƒ์„ฑํ•˜๊ณ  ์ง€์ •๋œ ๊ฐ’์„ ์„ค์ •ํ•œ๋‹ค.
const heading = document.querySelector('h1');
console.dir(heading);console.log(heading.firstChild.nodeValue);
heading.id = 'heading';console.log(heading.id); // heading

hasAttribute(attribute)#

  • ์ง€์ •ํ•œ ์†์„ฑ์„ ๊ฐ–๊ณ  ์žˆ๋Š”์ง€ ๊ฒ€์‚ฌํ•œ๋‹ค.

  • Return : Boolean

getAttribute(attribute)#

  • ์†์„ฑ์˜ ๊ฐ’์„ ์ทจ๋“ํ•œ๋‹ค

  • Return : String

setAttribute(attribute, value)#

  • ์†์„ฑ๊ณผ ์†์„ฑ์˜ ๊ฐ’์„ ์„ค์ •ํ•œ๋‹ค.

  • Return : undefined

removeAttribute(attribute)#

  • ์ง€์ •ํ•œ ์†์„ฑ์„ ์ œ๊ฑฐํ•œ๋‹ค

  • Return : undefined

const elems = document.querySelectorAll('li');
elems.forEach((elem) => {    if (elem.hasAttribute('class')) {        console.log(elem.getAttribute('id'));    }});
const sphinx = document.getElementById('sphinx');sphinx.setAttribute('class', 'red');
const sichu = document.getElementById('sichu');sichu.removeAttribute('class');console.log(sichu.hasAttribute('class'));

2020-05-15-dom-image-11

HTML ์ฝ˜ํ…์ธ  ์กฐ์ž‘(Manipulation)#

textContent#

์š”์†Œ์˜ ํ…์ŠคํŠธ ์ฝ˜ํ…์ธ ๋ฅผ ์ทจ๋“ ๋˜๋Š” ๋ณ€๊ฒฝํ•œ๋‹ค. ์ด ๋•Œ ๋งˆํฌ์—…์€ ๋ฌด์‹œ๋˜๊ธฐ ๋•Œ๋ฌธ์— ul.textContent = '<h1>Heading</h1>' ์ฒ˜๋Ÿผ ๋งˆํฌ์—…์„ ํฌํ•จ์‹œํ‚ค๋ฉด ๋ฌธ์ž์—ด๋กœ ์ธ์‹๋˜์–ด๊ทธ๋Œ€๋กœ ์ถœ๋ ฅ๋œ๋‹ค.

const ul = document.querySelector('ul');console.log(ul.textContent);
const cocker = document.getElementById('cocker');console.log(cocker.textContent);
cocker.textContent += '์Šค ํŒŒ๋‹ˆ์—˜';console.log(cocker.textContent);
cocker.textContent = '<li>์ฝ”์นด์Šค ํŒŒ๋‹ˆ์—˜</li>';console.log(cocker.textContent);

2020-05-15-dom-image-12

innerText#

innerText ํ”„๋กœํผํ‹ฐ๋กœ๋„ ํ…์ŠคํŠธ ์ฝ˜ํ…์ธ ์— ์ ‘๊ทผํ•  ์ˆ˜ ์žˆ๋‹ค. ํ•˜์ง€๋งŒ ๋น„ํ‘œ์ค€์ด๊ณ , CSS ์ˆœ์ข…์ ์ด๋ผ, CSS์— ์˜ํ•ด ๋น„ํ‘œ์‹œ ๋˜์–ด ์žˆ๋Š” ๊ฒฝ์šฐ ํ…์ŠคํŠธ๊ฐ€ ๋ฐ˜ํ™˜๋˜์ง€ ์•Š๋Š”๋‹ค. CSS๋ฅผ ๊ณ ๋ คํ•ด์•ผ ํ•˜๊ธฐ ๋•Œ๋ฌธ์— textContent ํ”„๋กœํผํ‹ฐ๋ณด๋‹ค ๋Š๋ฆฌ๋‹ค.

innerHTML#

ํ•ด๋‹น ์š”์†Œ์˜ ๋ชจ๋“  ์ž์‹ ์š”์†Œ๋ฅผ ํฌํ•จํ•˜๋Š” ๋ชจ๋“  ์ฝ˜ํ…์ธ ๋ฅผ ํ•˜๋‚˜์˜ ๋ฌธ์ž์—ด๋กœ ์ทจ๋“ํ•  ์ˆ˜ ์žˆ๋‹ค. ์ด ๋ฌธ์ž์—ด์€ ๋งˆํฌ์—…์„ ํฌํ•จํ•œ๋‹ค.

const ul = document.querySelector('ul');console.log(ul.innerHTML);
const cocker = document.getElementById('cocker');console.log(cocker.innerHTML);
cocker.innerHTML += '์Šค ํŒŒ๋‹ˆ์—˜';console.log(cocker.innerHTML);
cocker.innerHTML = '<li>์ฝ”์นด์Šค ํŒŒ๋‹ˆ์—˜</li>';console.log(cocker.innerHTML);

2020-05-15-dom-image-13

innerHTML ํ”„๋กœํผํ‹ฐ๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ๋งˆํฌ์—…์ด ํฌํ•จ๋œ ์ƒˆ๋กœ์šด ์š”์†Œ๋ฅผ DOM์— ์ถ”๊ฐ€ํ•  ์ˆ˜ ์žˆ๋‹ค .

const cocker = document.getElementById('cocker');cocker.innerHTML += '<li id="york" class="red">์š”ํฌ</li>';

2020-05-15-dom-image-14

ํ•˜์ง€๋งŒ ์ด๋ ‡๊ฒŒ ๋งˆํฌ์—…์ด ํฌํ•จ๋œ ์ฝ˜ํ…์ธ ๋ฅผ ์ถ”๊ฐ€ํ•˜๋Š” ๊ฒƒ์€ ํฌ๋กœ์Šค ์Šคํฌ๋ฆฝํŒ… ๊ณต๊ฒฉ์— ์ทจ์•ฝํ•˜๋‹ค

// ์—๋Ÿฌ ์ด๋ฒคํŠธ๋ฅผ ๋ฐœ์ƒ์‹œ์ผœ ์Šคํฌ๋ฆฝํŠธ๊ฐ€ ์‹คํ–‰๋˜๋„๋ก ํ•œ๋‹ค.elem.innerHTML = '<img src="#" onerror="alert(\\'XSS\\')">';

DOM ์กฐ์ž‘ ๋ฐฉ์‹#

innerHTML ํ”„๋กœํผํ‹ฐ๋ฅผ ์‚ฌ์šฉํ•˜์ง€ ์•Š๊ณ  ์ƒˆ๋กœ์šด ์ฝ˜ํ…์ธ ๋ฅผ ์ถ”๊ฐ€ํ•  ์ˆ˜ ์žˆ๋Š” ๋ฐฉ๋ฒ•์€ DOM์„์ง์ ‘ ์กฐ์ž‘ํ•˜๋Š” ๊ฒƒ์ด๋‹ค. ํ•˜๋‚˜์˜ ์š”์†Œ๋ฅผ ์ถ”๊ฐ€ํ•˜๋Š” ๊ฒฝ์šฐ ์‚ฌ์šฉํ•œ๋‹ค.

  1. ์š”์†Œ ๋…ธ๋“œ ์ƒ์„ฑ - createElement() ๋ฉ”์†Œ๋“œ๋ฅผ ์‚ฌ์šฉํ•ด์„œ ์ƒˆ๋กœ์šด ์š”์†Œ ๋…ธ๋“œ๋ฅผ ์ƒ์„ฑํ•œ๋‹ค. ๋ฉ”์†Œ๋“œ์˜ ์ธ์ž๋กœ ํƒœ๊ทธ ์ด๋ฆ„์„ ์ „๋‹ฌํ•œ๋‹ค.

  2. ํ…์ŠคํŠธ ๋…ธ๋“œ ์ƒ์„ฑ - createTextNode() ๋ฉ”์†Œ๋“œ๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ์ƒˆ๋กœ์šด ํ…์ŠคํŠธ ๋…ธ๋“œ๋ฅผ ์ƒ์„ฑํ•œ๋‹ค. ๊ฒฝ์šฐ์— ๋”ฐ๋ผ ์ƒ๋žตํ•  ์ˆ˜ ์žˆ์ง€๋งŒ, ์ƒ๋žตํ•˜๋Š” ๊ฒฝ์šฐ ์ฝ˜ํ…์ธ ๊ฐ€ ๋น„์–ด์žˆ๋Š” ์š”์†Œ๊ฐ€๋œ๋‹ค.

  3. ์ƒ์„ฑ๋œ ์š”์†Œ๋ฅผ DOM์— ์ถ”๊ฐ€ - appendChild() ๋ฉ”์†Œ๋“œ๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ์ƒ์„ฑ๋œ ๋…ธ๋“œ๋ฅผ DOM tree์— ์ถ”๊ฐ€ํ•œ๋‹ค. ๋˜๋Š” removeChild() ๋ฉ”์†Œ๋“œ๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ DOM tree์—์„œ ๋…ธ๋“œ๋ฅผ ์‚ญ์ œํ•  ์ˆ˜๋„ ์žˆ๋‹ค.

createElement(tagName)#

  • ํƒœ๊ทธ ์ด๋ฆ„์„ ์ธ์ž๋กœ ์ „๋‹ฌํ•˜์—ฌ ์š”์†Œ๋ฅผ ์ƒ์„ฑํ•œ๋‹ค.

  • Return : HTMLElement๋ฅผ ์ƒ์†๋ฐ›์€ ๊ฐ์ฒด

createTextNode(text)#

  • ํ…์ŠคํŠธ๋ฅผ ์ธ์ž๋กœ ์ „๋‹ฌํ•˜์—ฌ ํ…์ŠคํŠธ ๋…ธ๋“œ๋ฅผ ์ƒ์„ฑํ•œ๋‹ค.

  • Return : Text ๊ฐ์ฒด

appendChild(Node)#

  • ์ธ์ž๋กœ ์ „๋‹ฌํ•œ ๋…ธ๋“œ๋ฅผ ๋งˆ์ง€๋ง‰ ์ž์‹ ์š”์†Œ๋กœ DOM ํŠธ๋ฆฌ์— ์ถ”๊ฐ€ํ•œ๋‹ค.

  • Return : ์ถ”๊ฐ€ํ•œ ๋…ธ๋“œ

removeChild(Node)#

  • ์ธ์ž๋กœ ์ „๋‹ฌํ•œ ๋…ธ๋“œ๋ฅผ DOM ํŠธ๋ฆฌ์— ์ œ๊ฑฐํ•œ๋‹ค.

  • Return : ์ œ๊ฑฐํ•œ ๋…ธ๋“œ

// ํƒœ๊ทธ ์ด๋ฆ„์„ ์ธ์ž๋กœ ์ „๋‹ฌํ•˜์—ฌ ์ƒˆ๋กœ์šด ์š”์†Œ ์ƒ์„ฑconst newDog = document.createElement('li');
// ํ…์ŠคํŠธ ๋…ธ๋“œ๋ฅผ ์ƒ์„ฑconst newText = document.createTextNode('ํฌ๋ฉ”๋ฆฌ์•ˆ');
// ํ…์ŠคํŠธ ๋…ธ๋“œ๋ฅผ newDog์˜ ์ž์‹์œผ๋กœ DOM ํŠธ๋ฆฌ์— ์ถ”๊ฐ€newDog.appendChild(newText);
const container = document.querySelector('ul');
// newElem์„ container์˜ ์ž์‹์œผ๋กœ DOM ํŠธ๋ฆฌ์— ์ถ”๊ฐ€. ๋งˆ์ง€๋ง‰ ์š”์†Œ๋กœ ์ถ”๊ฐ€๋œ๋‹ค.container.appendChild(newDog);
const removeDog = document.getElementById('sichu');
// container์˜ ์ž์‹์ธ removeElem ์š”์†Œ๋ฅผ DOM ํŠธ๋ฆฌ์—์„œ ์ œ๊ฑฐํ•œ๋‹คconsole.log(container.removeChild(removeDog));

2020-05-15-dom-image-15

insertAdjacentHTML(position, string)#

์ธ์ž๋กœ ์ „๋‹ฌํ•œ ํ…์ŠคํŠธ๋ฅผ HTML๋กœ ํŒŒ์‹ฑํ•˜๊ณ , ๊ทธ ๊ฒฐ๊ณผ๋กœ ์ƒ์„ฑ๋œ ๋…ธ๋“œ๋ฅผ DOM ํŠธ๋ฆฌ์˜ ์ง€์ •๋œ ์œ„์น˜์— ์‚ฝ์ž…ํ•œ๋‹ค. ์ฒซ๋ฒˆ์งธ ์ธ์ž๋Š” ์‚ฝ์ž… ์œ„์น˜, ๋‘๋ฒˆ์งธ ์ธ์ž๋Š” ์‚ฝ์ž…ํ•  ์š”์†Œ๋ฅผ ํ‘œํ˜„ํ•œ๋ฌธ์ž์—ด์ด๋‹ค. ์ฒซ๋ฒˆ์งธ ์ธ์ž๋กœ ์˜ฌ ์ˆ˜ ์žˆ๋Š” ๊ฐ’์€ ์•„๋ž˜์™€ ๊ฐ™๋‹ค.

  • beforebegin

  • afterbegin

  • beforeend

  • afterend

<!-- beforebegin --><p>    <!-- afterbegin -->    foo    <!-- beforeend --></p><!-- afterend -->
const dogList = document.querySelector('ul');dogList.insertAdjacentHTML('afterbegin', '<li id="york" class="dog">์š”ํฌ</li>');dogList.insertAdjacentHTML(    'beforeend',    '<li id="dober" class="dog">๋„๋ฒ ๋ฅด๋งŒ</li>',);

2020-05-15-dom-image-16

innerHTML vs DOM ์กฐ์ž‘ ๋ฐฉ์‹ vs insertAdjacentHTML()#

innerHTML#

์žฅ์ ๋‹จ์ 
DOM ์กฐ์ž‘ ๋ฐฉ์‹์— ๋น„ํ•ด ๋น ๋ฅด๊ณ  ๊ฐ„ํŽธํ•˜๋‹ค.XSS๊ณต๊ฒฉ์— ์ทจ์•ฝ์ ์ด ์žˆ๊ธฐ ๋•Œ๋ฌธ์— ์‚ฌ์šฉ์ž๋กœ ๋ถ€ํ„ฐ ์ž…๋ ฅ๋ฐ›์€ ์ฝ˜ํ…์ธ (untrusted data: ๋Œ“๊ธ€, ์‚ฌ์šฉ์ž ์ด๋ฆ„ ๋“ฑ)๋ฅผ ์ถ”๊ฐ€ํ•  ๋•Œ ์ฃผ์˜ํ•˜์—ฌ์•ผ ํ•œ๋‹ค.
๊ฐ„ํŽธํ•˜๊ฒŒ ๋ฌธ์ž์—ด๋กœ ์ •์˜ํ•œ ์—ฌ๋Ÿฌ ์š”์†Œ๋ฅผ DOM์— ์ถ”๊ฐ€ํ•  ์ˆ˜ ์žˆ๋‹ค.ํ•ด๋‹น ์š”์†Œ์˜ ๋‚ด์šฉ์„ ๋ฎ์–ด ์“ด๋‹ค. ์ฆ‰, HTML์„ ๋‹ค์‹œ ํŒŒ์‹ฑํ•œ๋‹ค. ์ด๊ฒƒ์€ ๋น„ํšจ์œจ์ ์ด๋‹ค.
์ฝ˜ํ…์ธ ๋ฅผ ์ทจ๋“ํ•  ์ˆ˜ ์žˆ๋‹ค.

DOM ์กฐ์ž‘ ๋ฐฉ์‹#

์žฅ์ ๋‹จ์ 
ํŠน์ • ๋…ธ๋“œ ํ•œ ๊ฐœ(๋…ธ๋“œ, ํ…์ŠคํŠธ, ๋ฐ์ดํ„ฐ ๋“ฑ)๋ฅผ DOM์— ์ถ”๊ฐ€ํ•  ๋•Œ ์ ํ•ฉํ•˜๋‹ค.innerHTML๋ณด๋‹ค ๋Š๋ฆฌ๊ณ  ๋” ๋งŽ์€ ์ฝ”๋“œ๊ฐ€ ํ•„์š”ํ•˜๋‹ค.

insertAdjacentHTML()#

์žฅ์ ๋‹จ์ 
๊ฐ„ํŽธํ•˜๊ฒŒ ๋ฌธ์ž์—ด๋กœ ์ •์˜๋œ ์—ฌ๋Ÿฌ ์š”์†Œ๋ฅผ DOM์— ์ถ”๊ฐ€ํ•  ์ˆ˜ ์žˆ๋‹ค.XSS๊ณต๊ฒฉ์— ์ทจ์•ฝ์ ์ด ์žˆ๊ธฐ ๋•Œ๋ฌธ์— ์‚ฌ์šฉ์ž๋กœ ๋ถ€ํ„ฐ ์ž…๋ ฅ๋ฐ›์€ ์ฝ˜ํ…์ธ (untrusted data: ๋Œ“๊ธ€, ์‚ฌ์šฉ์ž ์ด๋ฆ„ ๋“ฑ)๋ฅผ ์ถ”๊ฐ€ํ•  ๋•Œ ์ฃผ์˜ํ•˜์—ฌ์•ผ ํ•œ๋‹ค.
์‚ฝ์ž…๋˜๋Š” ์œ„์น˜๋ฅผ ์„ ์ •ํ•  ์ˆ˜ ์žˆ๋‹ค.

๊ฒฐ๋ก #

innerHTML๊ณผ insertAdjacentHTML()์€ ํฌ๋กœ์Šค ์Šคํฌ๋ฆฝํŒ… ๊ณต๊ฒฉ(XSS: Cross-Site Scripting Attacks)์— ์ทจ์•ฝํ•˜๋‹ค. ๋”ฐ๋ผ์„œ untrusted data์˜ ๊ฒฝ์šฐ, ์ฃผ์˜ํ•˜์—ฌ์•ผ ํ•œ๋‹ค. ํ…์ŠคํŠธ๋ฅผ ์ถ”๊ฐ€ ๋˜๋Š” ๋ณ€๊ฒฝ์‹œ์—๋Š” textContent, ์ƒˆ๋กœ์šด ์š”์†Œ์˜ ์ถ”๊ฐ€ ๋˜๋Š” ์‚ญ์ œ์‹œ์—๋Š” DOM ์กฐ์ž‘ ๋ฐฉ์‹์„ ์‚ฌ์šฉํ•˜๋„๋ก ํ•œ๋‹ค.

style#

style ์†์„ฑ์„ ์‚ฌ์šฉํ•˜๋ฉด inline ์Šคํƒ€์ผ ์„ ์–ธ์„ ์ƒ์„ฑํ•œ๋‹ค. ํŠน์ • ์š”์†Œ์— inline ์Šคํƒ€์ผ์„์ง€์ •ํ•˜๋Š” ๊ฒฝ์šฐ ์‚ฌ์šฉํ•œ๋‹ค.

const dogList = document.querySelector('ul');dogList.insertAdjacentHTML('afterbegin', '<li id="york" class="dog">์š”ํฌ</li>');dogList.insertAdjacentHTML(    'beforeend',    '<li id="dober" class="dog">๋„๋ฒ ๋ฅด๋งŒ</li>',);
const york = document.getElementById('york');const dober = document.getElementById('dober');
york.style.color = 'red';dober.style.color = 'red';

2020-05-15-dom-image-17

style ํ”„๋กœํผํ‹ฐ ๊ฐ’์„ ์ทจ๋“ํ•˜๋ ค๋ฉด window.getComputedStyle์„ ์‚ฌ์šฉํ•œ๋‹ค. ์ด ๋ฉ”์†Œ๋“œ๋Š”์ธ์ž๋กœ ์ฃผ์–ด์ง„ ์š”์†Œ์˜ ๋ชจ๋“  CSS ํ”„๋กœํผํ‹ฐ ๊ฐ’์„ ๋ฐ˜ํ™˜ํ•œ๋‹ค.

const box = document.querySelector('.box');
const width = getStyle(box, 'width');const height = getStyle(box, 'height');const backgroundColor = getStyle(box, 'background-color');const border = getStyle(box, 'border');
console.log('width: ' + width);console.log('height: ' + height);console.log('backgroundColor: ' + backgroundColor);console.log('border: ' + border);
/** * ์š”์†Œ์— ์ ์šฉ๋œ CSS ํ”„๋กœํผํ‹ฐ๋ฅผ ๋ฐ˜ํ™˜ํ•œ๋‹ค. * @param {HTTPElement} elem - ๋Œ€์ƒ ์š”์†Œ ๋…ธ๋“œ. * @param {string} prop - ๋Œ€์ƒ CSS ํ”„๋กœํผํ‹ฐ. * @returns {string} CSS ํ”„๋กœํผํ‹ฐ์˜ ๊ฐ’. */function getStyle(elem, prop) {    return window.getComputedStyle(elem, null).getPropertyValue(prop);}

์ฐธ๊ณ ์ž๋ฃŒ#

๐Ÿ”— ๋ฌธ์„œ ๊ฐ์ฒด ๋ชจ๋ธ(Document Object Model)