โ๏ธ ์ด๋ฒ ์ ๋ ์ ํตํด ์๊ฒ ๋ ๊ฒ
DOM์ด๋ ๋ฌด์์ธ๊ฐ์?
innerHTML์ ๋จ์ ์ ๋ฌด์์ธ๊ฐ์?
<๋ต ๋ฏธ๋ฆฌ๋ณด๊ธฐ>
๐ค DOM์ด๋ ๋ฌด์์ธ๊ฐ์?
๐ค HTML ๋ฌธ์์ ๊ณ์ธต์ ๊ตฌ์กฐ์ ์ ๋ณด๋ฅผ ํํํ๋ฉฐ ์ด๋ฅผ ์ ์ดํ ์ ์๋ API, ์ฆ ํ๋กํผํฐ์ ๋ฉ์๋๋ฅผ ์ ๊ณตํ๋ ํธ๋ฆฌ ์๋ฃ๊ตฌ์กฐ์ด๋ค.
๐ค innerHTML์ ๋จ์ ์ ๋ฌด์์ธ๊ฐ์?
๐ค ์ฌ์ฉ์๋ก๋ถํฐ ์ ๋ ฅ๋ฐ์ ๋ฐ์ดํฐ๋ฅผ ๊ทธ๋๋ก innerHTML ํ๋กํผํฐ์ ํ ๋นํ๋ ๊ฒ์ XSS(ํฌ๋ก์ค ์ฌ์ดํธ ์คํฌ๋ฆฝํ ๊ณต๊ฒฉ)์ ์ทจ์ฝํฉ๋๋ค. ๋ํ ์์ ๋ ธ๋์ ๊ธฐ์กด ์์ ๋ ธ๋๋ฅผ ์ ๊ฑฐํ๊ณ ํ ๋นํ HTML ๋งํฌ์ ๋ฌธ์์ด์ ํ์ฑํ์ฌ DOM์ ๋ณ๊ฒฝํ๊ฒ ๋ฉ๋๋ค.
โ๏ธ DOM์ด๋?
Document Object Model์ HTML ๋ฌธ์์ ๊ณ์ธต์ ๊ตฌ์กฐ์ ์ ๋ณด๋ฅผ ํํํ๋ฉฐ ์ด๋ฅผ ์ ์ดํ ์ ์๋ API, ์ฆ ํ๋กํผํฐ์ ๋ฉ์๋๋ฅผ ์ ๊ณตํ๋ ํธ๋ฆฌ ์๋ฃ๊ตฌ์กฐ์ด๋ค.
HTML ์์๋ ๋ ๋๋ง ์์ง์ ์ํด ํ์ฑ๋์ด DOM์ ๊ตฌ์ฑํ๋ ์์ ๋ ธ๋ ๊ฐ์ฒด๋ก ๋ณํ๋๋ค.
ํธ๋ฆฌ ์๋ฃ๊ตฌ์กฐ๋ ๋ถ๋ชจ ๋ ธ๋์ ์์ ๋ ธ๋๋ก ๊ตฌ์ฑ๋์ด ๋ ธ๋ ๊ฐ์ ๊ณ์ธต์ ๊ตฌ์กฐ๋ฅผ ํํํ๋ ์๋ฃ๊ตฌ์กฐ์ด๋ค.
์ต์์ ๋ ธ๋๋ ๋ฃจํธ ๋ ธ๋๋ผ๊ณ ํ๋ฉฐ ๋ถ๋ชจ ๋ ธ๋๊ฐ ์๋ค. ๋ฃจํธ ๋ ธ๋๋ 0๊ฐ ์ด์์ ์์ ๋ ธ๋๋ฅผ ๊ฐ๋๋ค. ์์ ๋ ธ๋๊ฐ ์๋ ๋ ธ๋๋ฅผ ๋ฆฌํ ๋ ธ๋๋ผ๊ณ ํ๋ค.
๋ ธ๋ ๊ฐ์ฒด๋ค๋ก ๊ตฌ์ฑ๋ ํธ๋ฆฌ ์๋ฃ๊ตฌ์กฐ๋ฅผ DOM์ด๋ผ๊ณ ํ๋ค.
โ๏ธ ๋ ธ๋ ํ์
โ ๋ฌธ์ ๋ ธ๋ :
DOM ํธ๋ฆฌ์ ์ต์์์ ์กด์ฌํ๋ ๋ฃจํธ ๋ ธ๋๋ก์ document ๊ฐ์ฒด๋ฅผ ๊ฐ๋ฆฌํจ๋ค. HTML ๋ฌธ์๋น document ๊ฐ์ฒด๋ ์ ์ผํ๋ค.
์์ ๋ ธ๋, ์ดํธ๋ฆฌ๋ทฐํธ ๋ ธ๋, ํ ์คํธ ๋ ธ๋)
โ ์์ ๋ ธ๋ :
HTML ์์๋ฅผ ๊ฐ๋ฆฌํค๋ ๊ฐ์ฒด๋ค. ๋ถ๋ชจ ๋ ธ๋์ ์ฐ๊ฒฐ๋์ด ์๋ค.
โ ์ดํธ๋ฆฌ๋ทฐํธ ๋ ธ๋ :
HTML ์์์ ์ดํธ๋ฆฌ๋ทฐํธ๋ฅผ ๊ฐ๋ฆฌํค๋ ๊ฐ์ฒด๋ค. ์์ ๋ ธ๋์๋ง ์ฐ๊ฒฐ๋์ด ์๋ค.
โ ํ ์คํธ ๋ ธ๋ :
HTML ์์์ ํ ์คํธ๋ฅผ ๊ฐ๋ฆฌํค๋ ๊ฐ์ฒด๋ค. ์์ ๋ ธ๋์ ์์ ๋ ธ๋์ด๋ฉฐ, ์์ ๋ ธ๋๋ฅผ ๊ฐ์ง ์ ์๋ ๋ฆฌํ ๋ ธ๋์ด๋ค.
DOM์ ๊ตฌ์ฑํ๋ ๋ ธ๋ ๊ฐ์ฒด๋ DOM API๋ฅผ ์ฌ์ฉํ ์ ์๋ค. ์ด๋ฅผ ํตํด ๋ ธ๋ ๊ฐ์ฒด๋ ์์ ์ ๋ถ๋ชจ, ํ์ , ์์์ ํ์ํ๊ณ ์์ ์ ์ดํธ๋ฆฌ๋ทฐํธ์ ํ ์คํธ๋ฅผ ์กฐ์ํ ์ ์๋ค.
ํ๋ก ํธ์๋ ๊ฐ๋ฐ์๋ HTML์ DOM๊ณผ ์ฐ๊ด์ง์ด ๋ฐ๋ผ๋ด์ผํ๋ค.
โ๏ธ ์์ ๋ ธ๋ ์ทจ๋
์์ ๋ ธ๋๋ฅผ ์ทจ๋ํ๋ ๊ฑด HTML ์์๋ฅผ ์กฐ์ํ๋ ์์์ ์ด๋ค!
- id๋ก ์์ ๋ ธ๋ ์ทจ๋ํ๊ธฐ (getElementById)
document.getElementById('apple');
id ๊ฐ์ HTML ๋ฌธ์ ๋ด์์ ์ ์ผํ ๊ฐ์ด์ด์ผ ํ๋ค.
- ํ๊ทธ ์ด๋ฆ์ผ๋ก ์์ ๋ ธ๋ ์ทจ๋ํ๊ธฐ (getElementsByTagName)
document.getElementsByTagName('li');
- class๋ก ์์ ๋ ธ๋ ์ทจ๋ํ๊ธฐ (getElementsByClassName)
document.getElementsByClassName('fruit');
- css ์ ํ์๋ก ์์ ๋ ธ๋ ์ทจ๋ํ๊ธฐ (querySelector / querySelectorAll)
/* ์ ์ฒด ์ ํ์: ๋ชจ๋ ์์๋ฅผ ์ ํ */
* { ... }
/* ํ๊ทธ ์ ํ์: ๋ชจ๋ p ํ๊ทธ ์์๋ฅผ ๋ชจ๋ ์ ํ */
p { ... }
/* id ์ ํ์: id ๊ฐ์ด 'foo'์ธ ์์๋ฅผ ๋ชจ๋ ์ ํ */
#foo { ... }
/* class ์ ํ์: class ๊ฐ์ด 'foo'์ธ ์์๋ฅผ ๋ชจ๋ ์ ํ */
.foo { ... }
/* ์ดํธ๋ฆฌ๋ทฐํธ ์ ํ์: input ์์ ์ค์ type ์ดํธ๋ฆฌ๋ทฐํธ ๊ฐ์ด 'text'์ธ ์์๋ฅผ ๋ชจ๋ ์ ํ */
input[type=text] { ... }
/* ํ์ ์ ํ์: div ์์์ ํ์ ์์ ์ค p ์์๋ฅผ ๋ชจ๋ ์ ํ */
div p { ... }
/* ์์ ์ ํ์: div ์์์ ์์ ์์ ์ค p ์์๋ฅผ ๋ชจ๋ ์ ํ */
div > p { ... }
/* ์ธ์ ํ์ ์ ํ์: p ์์์ ํ์ ์์ ์ค์ p ์์ ๋ฐ๋ก ๋ค์ ์์นํ๋ ul ์์๋ฅผ ์ ํ */
p + ul { ... }
/* ์ผ๋ฐ ํ์ ์ ํ์: p ์์์ ํ์ ์์ ์ค์ p ์์ ๋ค์ ์์นํ๋ ul ์์๋ฅผ ๋ชจ๋ ์ ํ */
p ~ ul { ... }
/* ๊ฐ์ ํด๋์ค ์ ํ์: hover ์ํ์ธ a ์์๋ฅผ ๋ชจ๋ ์ ํ */
a:hover { ... }
/* ๊ฐ์ ์์ ์ ํ์: p ์์์ ์ฝํ
์ธ ์ ์์ ์์นํ๋ ๊ณต๊ฐ์ ์ ํ
์ผ๋ฐ์ ์ผ๋ก content ํ๋กํผํฐ์ ํจ๊ป ์ฌ์ฉ๋๋ค. */
p::before { ... }
โ๏ธ ์์ ๋ ธ๋์ ํ ์คํธ ์กฐ์
nodeValue & textContent
<!DOCTYPE html>
<html>
<body>
<!-- ์์ ๋
ธ๋์ ์ฝํ
์ธ ์์ญ์ ๋ค๋ฅธ ์์ ๋
ธ๋๊ฐ ์๊ณ ํ
์คํธ๋ง ์กด์ฌ -->
<div id="foo">Hello</div>
</body>
<script>
const $foo = document.getElementById('foo');
// ์์ ๋
ธ๋์ ์ฝํ
์ธ ์์ญ์ ์์ ์์ ๋
ธ๋๊ฐ ์๊ณ ํ
์คํธ๋ง ์กด์ฌํ๋ค๋ฉด
// firstChild.nodeValue์ textContent๋ ๊ฐ์ ๊ฒฐ๊ณผ๋ฅผ ๋ฐํํ๋ค.
console.log($foo.textContent === $foo.firstChild.nodeValue); // true
</script>
</html>
textContent ํ๋กํผํฐ์ ์ ์ฌํ ๋์์ ํ๋ innerText ํ๋กํผํฐ!
ํ์ง๋ง innerText ํ๋กํผํฐ๋ CSS์ ์์ข ์ ์ด๋ผ textContent ํ๋กํผํฐ๋ณด๋ค ๋๋ฆฌ๊ณ , CSS์ ์ํด ๋นํ์๋๋ ์์ ๋ ธ๋์ ํ ์คํธ๋ฅผ ๋ฐํํ์ง ์๋๋ค.
โ๏ธ DOM ์กฐ์
DOM ์กฐ์์ ์๋ก์ด ๋ ธ๋๋ฅผ ์์ฑํ์ฌ DOM์ ์ถ๊ฐํ๊ฑฐ๋ ๊ธฐ์กด ๋ ธ๋๋ฅผ ์ญ์ ๋๋ ๊ต์ฒดํ๋ ๊ฒ์ ๋งํ๋ค.
DOM ์กฐ์์ ์ํด ๋ฆฌํ๋ก์ฐ์ ๋ฆฌํ์ธํธ๊ฐ ๋ฐ์ํด์ ์ฑ๋ฅ์ ์ํฅ์ ์ฃผ๊ฒ ๋๋ค.
innerHTML
์์ ๋ ธ๋์ innerHTML ํ๋กํผํฐ๋ฅผ ์ฐธ์กฐํ๋ฉด ์์ ๋ ธ๋์ ์ฝํ ์ธ ์์ญ ๋ด์ ํฌํจ๋ ๋ชจ๋ HTML ๋งํฌ์ ์ ๋ฌธ์์ด๋ก ๋ฐํํ๋ค.
<!DOCTYPE html>
<html>
<body>
<div id="foo">Hello <span>world!</span></div>
</body>
<script>
// #foo ์์์ ์ฝํ
์ธ ์์ญ ๋ด์ HTML ๋งํฌ์
์ ๋ฌธ์์ด๋ก ์ทจ๋ํ๋ค.
console.log(document.getElementById('foo').innerHTML);
// "Hello <span>world!</span>"
</script>
</html>
โป textContent๋ HTML ๋งํฌ์ ์ ๋ฌด์ํ๊ณ ํ ์คํธ๋ง ๋ฐํํ์ง๋ง, innerHTML์ HTML ๋งํฌ์ ์ด ํฌํจ๋ ๋ฌธ์์ด ๊ทธ๋๋ก ๋ฐํํ๋ค.
โ๏ธ innerHTML์ ๋จ์ โ๏ธ
1. ์ฌ์ฉ์๋ก๋ถํฐ ์ ๋ ฅ๋ฐ์ ๋ฐ์ดํฐ๋ฅผ ๊ทธ๋๋ก innerHTML ํ๋กํผํฐ์ ํ ๋นํ๋ ๊ฒ์ XSS(ํฌ๋ก์ค ์ฌ์ดํธ ์คํฌ๋ฆฝํ ๊ณต๊ฒฉ)์ ์ทจ์ฝํ๋ค!!
2. ์์ ๋ ธ๋์ innerHTML ํ๋กํผํฐ์ HTML ๋งํฌ์ ๋ฌธ์์ด์ ํ ๋นํ๋ ๊ฒฝ์ฐ ์์ ๋ ธ๋์ ๋ชจ๋ ์์ ๋ ธ๋๋ฅผ ์ ๊ฑฐํ๊ณ ํ ๋นํ HTML ๋งํฌ์ ๋ฌธ์์ด์ ํ์ฑํ์ฌ DOM์ ๋ณ๊ฒฝํ๋ค. => insertAdjacentHTML์ ๊ธฐ์กด ๋ ธ๋ ์ญ์ ์ํจ(XSS ๊ณต๊ฒฉ์ ์ทจ์ฝํ๊ฑด ๋ง์ฐฌ๊ฐ์ง!!)
์์ ๋ ธ๋ ์์ฑ๊ณผ ์ถ๊ฐ
<!DOCTYPE html>
<html>
<body>
<ul id="fruits">
<li>Apple</li>
</ul>
</body>
<script>
const $fruits = document.getElementById('fruits');
// 1. ์์ ๋
ธ๋ ์์ฑ
const $li = document.createElement('li');
// 2. ํ
์คํธ ๋
ธ๋ ์์ฑ
const textNode = document.createTextNode('Banana');
// 3. ํ
์คํธ ๋
ธ๋๋ฅผ $li ์์ ๋
ธ๋์ ์์ ๋
ธ๋๋ก ์ถ๊ฐ
$li.appendChild(textNode);
// 4. $li ์์ ๋
ธ๋๋ฅผ #fruits ์์ ๋
ธ๋์ ๋ง์ง๋ง ์์ ๋
ธ๋๋ก ์ถ๊ฐ
$fruits.appendChild($li);
</script>
</html>
๐ ์์๋ฅผ ์ถ๊ฐํ ๋๋ง๋ค DOM์ ๊ฑด๋๋ฆฌ๊ธฐ ๋๋ฌธ์ ์ฑ๋ฅ์ ์ข์ง ์๋ค.
<!DOCTYPE html>
<html>
<body>
<ul id="fruits"></ul>
</body>
<script>
const $fruits = document.getElementById('fruits');
// DocumentFragment ๋
ธ๋ ์์ฑ
const $fragment = document.createDocumentFragment();
['Apple', 'Banana', 'Orange'].forEach(text => {
// 1. ์์ ๋
ธ๋ ์์ฑ
const $li = document.createElement('li');
// 2. ํ
์คํธ ๋
ธ๋ ์์ฑ
const textNode = document.createTextNode(text);
// 3. ํ
์คํธ ๋
ธ๋๋ฅผ $li ์์ ๋
ธ๋์ ์์ ๋
ธ๋๋ก ์ถ๊ฐ
$li.appendChild(textNode);
// 4. $li ์์ ๋
ธ๋๋ฅผ DocumentFragment ๋
ธ๋์ ๋ง์ง๋ง ์์ ๋
ธ๋๋ก ์ถ๊ฐ
$fragment.appendChild($li);
});
// 5. DocumentFragment ๋
ธ๋๋ฅผ #fruits ์์ ๋
ธ๋์ ๋ง์ง๋ง ์์ ๋
ธ๋๋ก ์ถ๊ฐ
$fruits.appendChild($fragment);
</script>
</html>
๐ DOM์ ํ๋ฒ๋ง ํ๋ฒ๋ง ๋ณ๊ฒฝํด์ ๋ฆฌํ๋ก์ฐ์ ๋ฆฌํ์ธํธ๋ ํ๋ฒ๋ง ์คํ๋๋ค.
์ฌ๋ฌ๊ฐ์ ์์ ๋ ธ๋๋ฅผ DOM์ ์ถ๊ฐํ๋ ๊ฒฝ์ฐ DocumentFragment ๋ ธ๋๋ฅผ ์ฌ์ฉํ์!!
๐ฉ๐ป ๋ชจ๋ ์๋ฐ์คํฌ๋ฆฝํธ Deep Dive๋ฅผ ์ ๋ ํ๊ณ ์ ๊ฐ ์ดํดํ ๋ด์ฉ์ ์ ๋ฆฌํ ๊ธ์ ๋๋ค ๐ฉ๐ป
'๐Language > JavaScript' ์นดํ ๊ณ ๋ฆฌ์ ๋ค๋ฅธ ๊ธ
[Deep Dive] ๋๊ธฐ์ ๋น๋๊ธฐ, ๋น๋๊ธฐ๊ฐ ์ฒ๋ฆฌ๋ ์ ์๋ ์ด์ (0) | 2022.12.19 |
---|---|
[Deep Dive] REST API๊ฐ ๋ฌด์์ธ๊ฐ์? (0) | 2022.12.16 |
[Deep Dive] ๋ธ๋ผ์ฐ์ ์ ๋ ๋๋ง ๊ณผ์ (0) | 2022.12.14 |
[Deep Dive] ํด๋ก์ ์ ๋ ์์ปฌ์ค์ฝํ (0) | 2022.12.12 |
[Deep Dive] this (0) | 2022.12.07 |