Skip to content

Commit

Permalink
docs: DOM (39.6.3 ~ 39.6.9)
Browse files Browse the repository at this point in the history
  • Loading branch information
ccconac committed Jan 22, 2024
1 parent 4f389a4 commit 366555a
Showing 1 changed file with 237 additions and 0 deletions.
237 changes: 237 additions & 0 deletions docs/39_DOM/λ¬Έμ†Œν¬.md
Original file line number Diff line number Diff line change
Expand Up @@ -647,6 +647,243 @@ DOMPurify.sanitize('<img src="x" onerror="alert(document.cookie)">');
</html>
```

### πŸ’¬ 3. λ…Έλ“œ 생성과 μΆ”κ°€

#### ✨ μš”μ†Œ λ…Έλ“œ 생성

> `Document.prototype.createElement(tagName)` λ©”μ„œλ“œλŠ” μš”μ†Œ λ…Έλ“œλ₯Ό 생성해 λ°˜ν™˜ν•œλ‹€. 이떄 μƒμ„±λœ μš”μ†Œ λ…Έλ“œλŠ” μ•„λ¬΄λŸ° μžμ‹ λ…Έλ“œλ₯Ό 가지고 μžˆμ§€ μ•ŠκΈ° λ•Œλ¬Έμ— μš”μ†Œ λ…Έλ“œμ˜ μžμ‹ λ…Έλ“œμΈ ν…μŠ€νŠΈ λ…Έλ“œλ„ μ—†λŠ” μƒνƒœλ‹€.
```javascript
const $li = document.createElement('li');
console.log($li.childNodes); // NodeList []
```

![](https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbhbrH6%2FbtrAYtFCU9e%2FCmbKmC81nM6ojw8s3IhXVK%2Fimg.png)

#### ✨ ν…μŠ€νŠΈ λ…Έλ“œ 생성

> `Document.prototype.createTextNode(text)` λ©”μ„œλ“œλŠ” ν…μŠ€νŠΈ λ…Έλ“œλ₯Ό 생성해 λ°˜ν™˜ν•œλ‹€. ν…μŠ€νŠΈ λ…Έλ“œλ₯Ό 생성할 뿐 μš”μ†Œ λ…Έλ“œμ— μΆ”κ°€ν•˜μ§€λŠ” μ•ŠκΈ° λ•Œλ¬Έμ— 이후에 μš”μ†Œ λ…Έλ“œμ— ν…μŠ€νŠΈ λ…Έλ“œλ₯Ό μΆ”κ°€ν•˜λŠ” 별도 μ²˜λ¦¬κ°€ ν•„μš”ν•˜λ‹€.
```javascript
const textNode = document.createTextNode('Banana');
```

![](https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcgtlKq%2FbtrAVsOGiDz%2FTom3PpiPkPksdt2rUTzwa1%2Fimg.png)

#### ✨ ν…μŠ€νŠΈ λ…Έλ“œλ₯Ό μš”μ†Œ λ…Έλ“œμ˜ μžμ‹ λ…Έλ“œλ‘œ μΆ”κ°€

> `Node.prototype.appendChild(childNode)` λ©”μ„œλ“œλŠ” λ§€κ°œλ³€μˆ˜ `childNode`μ—κ²Œ 인수둜 μ „λ‹¬ν•œ λ…Έλ“œλ₯Ό `appendChild` λ©”μ„œλ“œλ₯Ό ν˜ΈμΆœν•œ λ…Έλ“œμ˜ λ§ˆμ§€λ§‰ μžμ‹ λ…Έλ“œλ‘œ μΆ”κ°€ν•œλ‹€. μ΄λ•Œ κΈ°μ‘΄ DOMμ—λŠ” μΆ”κ°€λ˜μ§€ μ•ŠλŠ”λ‹€.
μš”μ†Œ λ…Έλ“œμ— μžμ‹ λ…Έλ“œκ°€ ν•˜λ‚˜λ„ μ—†λŠ” κ²½μš°μ—λŠ” `textContext` ν”„λ‘œνΌν‹°λ₯Ό μ‚¬μš©ν•˜λŠ” 것이 더 κ°„νŽΈν•˜λ‹€. 단, μš”μ†Œ λ…Έλ“œμ— μžμ‹ λ…Έλ“œκ°€ μžˆλŠ” 경우 μš”μ†Œ λ…Έλ“œμ˜ `textContent` ν”„λ‘œνΌν‹°μ— λ¬Έμžμ—΄μ„ ν• λ‹Ήν•˜λ©΄ μš”μ†Œ λ…Έλ“œμ˜ λͺ¨λ“  μžμ‹ λ…Έλ“œκ°€ 제거되고 ν• λ‹Ήν•œ λ¬Έμžμ—΄μ΄ ν…μŠ€νŠΈλ‘œ μΆ”κ°€λ˜λ―€λ‘œ μ£Όμ˜ν•΄μ•Ό ν•œλ‹€. 🚨

```javascript
$li.appendChild(document.createTextNode('Banana'));

// μœ„ μ½”λ“œμ™€ λ™μΌν•˜κ²Œ λ™μž‘
$li.textContent = 'Banana';
```

![](https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fee7Vxs%2FbtrASCch6fG%2FpwOuWO0289sDzigfOtxVaK%2Fimg.png)

#### ✨ μš”μ†Œ λ…Έλ“œλ₯Ό DOM에 μΆ”κ°€

> `Node.prototype.appendChild` λ©”μ„œλ“œλ₯Ό μ‚¬μš©ν•΄ ν…μŠ€νŠΈ λ…Έλ“œμ™€ λΆ€μž κ΄€κ³„λ‘œ μ—°κ²°ν•œ μš”μ†Œ λ…Έλ“œλ₯Ό #fruits μš”μ†Œ λ…Έλ“œμ˜ λ§ˆμ§€λ§‰ μžμ‹ μš”μ†Œλ‘œ μΆ”κ°€ν•œλ‹€. 이 κ³Όμ •μ—μ„œ μƒˆλ‘­κ²Œ μƒμ„±ν•œ μš”μ†Œ λ…Έλ“œκ°€ DOM에 μΆ”κ°€λœλ‹€.
기쑴의 DOM에 μš”μ†Œ λ…Έλ“œλ₯Ό μΆ”κ°€ν•˜λŠ” μ²˜λ¦¬λŠ” 이 과정뿐이며 μœ„ μ˜ˆμ œλŠ” 단 ν•˜λ‚˜μ˜ μš”μ†Œ λ…Έλ“œλ₯Ό 생성해 DOM에 ν•œ 번 μΆ”κ°€ν•˜λ―€λ‘œ DOM은 ν•œ 번 λ³€κ²½λœλ‹€. μ΄λ•Œ λ¦¬ν”Œλ‘œμš°μ™€ λ¦¬νŽ˜μΈνŠΈκ°€ μ‹€ν–‰λœλ‹€.

```javascript
$fruits.appendChild($li);
```

![](https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbUsuIa%2FbtrARFHlsRe%2FrxAS601yGvQqk9pVZkotxk%2Fimg.png)

### πŸ’¬ 4. 볡수의 λ…Έλ“œ 생성과 μΆ”κ°€

> `DocumentFragment` λ…Έλ“œλŠ” λ…Έλ“œ 객체의 μΌμ’…μœΌλ‘œ, λΆ€λͺ¨ λ…Έλ“œκ°€ μ—†μ–΄ κΈ°μ‘΄ DOMκ³ΌλŠ” λ³„λ„λ‘œ μ‘΄μž¬ν•œλ‹€λŠ” νŠΉμ§•μ΄ μžˆλ‹€. μžμ‹ λ…Έλ“œλ“€μ˜ λΆ€λͺ¨ λ…Έλ“œλ‘œμ„œ λ³„λ„μ˜ μ„œλΈŒ DOM을 κ΅¬μ„±ν•˜μ—¬ κΈ°μ‘΄ DOM에 μΆ”κ°€ν•˜κΈ° μœ„ν•œ μš©λ„λ‘œ μ‚¬μš©ν•œλ‹€.
`DocumentFragment` λ…Έλ“œλŠ” κΈ°μ‘΄ DOMκ³ΌλŠ” λ³„λ„λ‘œ μ‘΄μž¬ν•˜λ―€λ‘œ μžμ‹ λ…Έλ“œλ₯Ό 좔가해도 κΈ°μ‘΄ DOMμ—λŠ” μ–΄λ– ν•œ 변경도 λ°œμƒν•˜μ§€ μ•ŠμœΌλ©°, DOM에 μΆ”κ°€ν•˜λ©΄ μžμ‹ μ€ 제거되고 μžμ‹ μ˜ μžμ‹ λ…Έλ“œλ§Œ DOM에 μΆ”κ°€λœλ‹€. λ¦¬ν”Œλ‘œμš°μ™€ 리페인트 λ˜ν•œ ν•œ 번만 μ‹€ν–‰λœλ‹€.

![](https://blog.kakaocdn.net/dn/cduCw4/btrABLuYwLy/rFA4dBOA0DWAVJmj2DXceK/img.png)

```html
<!doctype html>
<html>
<body>
<ul id="fruits"></ul>
<script>
const $fruits = document.getElementById('fruits');
const $fragment = document.createDocumentFragment();
['Apple', 'Banana', 'Orange'].forEach((text) => {
const $li = document.createElement('li'); // 1. μš”μ†Œ λ…Έλ“œ 생성
const textNode = document.createTextNode(text); // 2. ν…μŠ€νŠΈ λ…Έλ“œ 생성
$li.appendChild(textNode); // 3. ν…μŠ€νŠΈ λ…Έλ“œλ₯Ό $li μš”μ†Œμ˜ μžμ‹ λ…Έλ“œλ‘œ μΆ”κ°€
$fragment.appendChild($li); // 4. $li μš”μ†Œ λ…Έλ“œλ₯Ό DocumentFragment λ…Έλ“œμ˜ λ§ˆμ§€λ§‰ μžμ‹ λ…Έλ“œλ‘œ μΆ”κ°€
});
// 5. DocumentFragment λ…Έλ“œλ₯Ό #fruits μš”μ†Œ λ…Έλ“œμ˜ λ§ˆμ§€λ§‰ μžμ‹ λ…Έλ“œλ‘œ μΆ”κ°€
$fruits.appendChild($fragment);
</script>
</body>
</html>
```

### πŸ’¬ 5. λ…Έλ“œ μ‚½μž…

#### ✨ λ§ˆμ§€λ§‰ λ…Έλ“œλ‘œ μΆ”κ°€

> `Node.prototype.appendChild` λ©”μ„œλ“œλŠ” 인수둜 전달받은 λ…Έλ“œλ₯Ό μžμ‹ μ„ ν˜ΈμΆœν•œ λ…Έλ“œμ˜ λ§ˆμ§€λ§‰ μžμ‹ λ…Έλ“œλ‘œ DOM에 μΆ”κ°€ν•œλ‹€. λ…Έλ“œλ₯Ό μΆ”κ°€ν•  μœ„μΉ˜λŠ” μ •ν•  수 μ—†κ³  μ–Έμ œλ‚˜ λ§ˆμ§€λ§‰ μžμ‹ λ…Έλ“œλ‘œ μΆ”κ°€ν•œλ‹€.
```html
<!doctype html>
<html>
<body>
<ul id="fruits">
<li>Apple</li>
<li>Banana</li>
</ul>
<script>
const $li = document.createElement('li');
$li.appendChild(document.createTextNode('Orange'));
document.getElementById('fruits').appendChild($li);
</script>
</body>
</html>
```

#### ✨ μ§€μ •ν•œ μœ„μΉ˜μ— λ…Έλ“œ μ‚½μž…

> `Node.prototype.insertBefore(newNode, childNode)` λ©”μ„œλ“œλŠ” 첫 번째 인수둜 전달받은 λ…Έλ“œλ₯Ό 두 번째 인수둜 전달받은 λ…Έλ“œ μ•žμ— μ‚½μž…ν•œλ‹€.
μ΄λ•Œ 두 번째 인수둜 전달받은 λ…Έλ“œλŠ” λ°˜λ“œμ‹œ `insertBefore` λ©”μ„œλ“œλ₯Ό ν˜ΈμΆœν•œ λ…Έλ“œμ˜ μžμ‹ λ…Έλ“œμ—¬μ•Ό ν•˜λ©°, μ•„λ‹Œ 경우 `DOMException` μ—λŸ¬κ°€ λ°œμƒν•œλ‹€. 전달받은 두 번째 μΈμˆ˜κ°€ null인 κ²½μš°μ—λŠ” `appendChild` λ©”μ„œλ“œμ²˜λŸΌ λ™μž‘ν•œλ‹€.

```html
<!doctype html>
<html>
<body>
<ul id="fruits">
<li>Apple</li>
<li>Banana</li>
</ul>
<script>
const $fruits = document.getElementById('fruits');
const $li = document.createElement('li');
$li.appendChild(document.createTextNode('Orange'));
$fruits.insertBefore($li, $fruits.lastElementChild); // Apple - Orange - Banana
// 두 번째 인수둜 전달받은 λ…Έλ“œλŠ” λ°˜λ“œμ‹œ #fruits μš”μ†Œ λ…Έλ“œμ˜ μžμ‹ λ…Έλ“œμ—¬μ•Ό 함
$fruits.insertBefore($li, document.querySelector('div')); // DOMException
// $fruits.insertBefore($li, null);
// Apple - Banana - Orange
</script>
</body>
</html>
```

### πŸ’¬ 6. λ…Έλ“œ 이동

> DOM에 이미 μ‘΄μž¬ν•˜λŠ” λ…Έλ“œλ₯Ό `appendChild` λ˜λŠ” `insertBefore` λ©”μ„œλ“œλ₯Ό μ‚¬μš©ν•΄ DOM에 λ‹€μ‹œ μΆ”κ°€ν•˜λ©΄ ν˜„μž¬ μœ„μΉ˜μ—μ„œ λ…Έλ“œλ₯Ό μ œκ±°ν•˜κ³  μƒˆλ‘œμš΄ μœ„μΉ˜μ— λ…Έλ“œλ₯Ό μΆ”κ°€ν•˜λ©° μ΄λ™ν•œλ‹€.
```html
<!doctype html>
<html>
<body>
<ul id="fruits">
<li>Apple</li>
<li>Banana</li>
<li>Orange</li>
</ul>
<script>
const $fruits = document.getElementById('fruits');
const [$apple, $banana] = $fruits.children; // 이미 μ‘΄μž¬ν•˜λŠ” μš”μ†Œ 취득
// 이미 μ‘΄μž¬ν•˜λŠ” $apple μš”μ†Œ λ…Έλ“œ #fruits μš”μ†Œ λ…Έλ“œμ˜ λ§ˆμ§€λ§‰ λ…Έλ“œλ‘œ 이동
$fruits.appendChild($apple); // Banana - Orange - Apple
// 이미 μ‘΄μž¬ν•˜λŠ” $banana μš”μ†Œ λ…Έλ“œ #fruits μš”μ†Œμ˜ λ§ˆμ§€λ§‰ μžμ‹ λ…Έλ“œ μ•žμœΌλ‘œ 이동
$fruits.insertBefore($banana, $fruits.lastElementChild); // Orange - Banana - Apple
</script>
</body>
</html>
```

### πŸ’¬ 7. λ…Έλ“œ 볡사

> `Node.prototype.cloneNode([deep: true | false])` λ©”μ„œλ“œλŠ” λ…Έλ“œμ˜ 사본을 생성해 λ°˜ν™˜ν•œλ‹€. falseλ₯Ό 인수둜 μ „λ‹¬ν•˜κ±°λ‚˜ μƒλž΅ν•˜λ©΄ λ…Έλ“œλ₯Ό 얕은 볡사<sup>shallow copy</sup>ν•˜μ—¬ λ…Έλ“œ μžμ‹ λ§Œμ˜ 사본을 μƒμ„±ν•œλ‹€. 얕은 λ³΅μ‚¬λ‘œ μƒμ„±λœ μš”μ†Œ λ…Έλ“œλŠ” μžμ† λ…Έλ“œλ₯Ό λ³΅μ‚¬ν•˜μ§€ μ•ŠμœΌλ―€λ‘œ ν…μŠ€νŠΈ λ…Έλ“œλ„ μ—†λ‹€.
```html
<!doctype html>
<html>
<body>
<ul id="fruits">
<li>Apple</li>
</ul>
<script>
const $fruits = document.getElementById('fruits');
const $apple = $fruits.firstElementChild;
const $shallowClone = $apple.cloneNode();
$shallowClone.textContent = 'Banana'; // ν…μŠ€νŠΈκ°€ μ—†λŠ” 사본 λ…Έλ“œμ— ν…μŠ€νŠΈ μΆ”κ°€
$fruits.appendChild($shallowClone);
// #fruits μš”μ†Œλ₯Ό κΉŠμ€ 볡사해 λͺ¨λ“  μžμ† λ…Έλ“œκ°€ ν¬ν•¨λœ 사본 생성
const $deepClone = $fruits.cloneNode(true);
$fruits.appendChild($deepClone);
</script>
</body>
</html>
```

### πŸ’¬ 8. λ…Έλ“œ ꡐ체

> `Node.prototype.replaceChild(newChild, oldChild)` λ©”μ„œλ“œλŠ” μžμ‹ μ„ ν˜ΈμΆœν•œ λ…Έλ“œμ˜ μžμ‹ λ…Έλ“œλ₯Ό λ‹€λ₯Έ λ…Έλ“œλ‘œ κ΅μ²΄ν•œλ‹€. 즉, μžμ‹ μ„ ν˜ΈμΆœν•œ λ…Έλ“œμ˜ μžμ‹ λ…Έλ“œμΈ `oldChild` λ…Έλ“œλ₯Ό `newChild` λ…Έλ“œλ‘œ κ΅μ²΄ν•œλ‹€. μ΄λ•Œ `oldChild` λ…Έλ“œλŠ” DOMμ—μ„œ μ œκ±°λœλ‹€.
```html
<!doctype html>
<html>
<body>
<ul id="fruits">
<li>Apple</li>
</ul>
<script>
const $fruits = document.getElementById('fruits');
// κΈ°μ‘΄ λ…Έλ“œμ™€ ꡐ체할 μš”μ†Œ λ…Έλ“œ 생성
const $newChild = document.createElement('li');
$newChild.textContent = 'Banana';
// $fruits μš”μ†Œ λ…Έλ“œμ˜ 첫 번째 μžμ‹ μš”μ†Œ λ…Έλ“œ $newChild μš”μ†Œ λ…Έλ“œλ‘œ ꡐ체
$fruits.replaceChild($newChild, $fruits.firstElementChild);
</script>
</body>
</html>
```

### πŸ’¬ 9. λ…Έλ“œ μ‚­μ œ

> `Node.prototype.removeChild(child)` λ©”μ„œλ“œλŠ” child λ§€κ°œλ³€μˆ˜μ— 인수둜 μ „λ‹¬ν•œ λ…Έλ“œλ₯Ό DOMμ—μ„œ μ‚­μ œν•œλ‹€.
```html
<!doctype html>
<html>
<body>
<ul id="fruits">
<li>Apple</li>
<li>Banana</li>
</ul>
<script>
const $fruits = document.getElementById('fruits');
// #fruits μš”μ†Œ λ…Έλ“œμ˜ λ§ˆμ§€λ§‰ μš”μ†Œ DOMμ—μ„œ μ‚­μ œ
$fruits.removeChild($fruits.lastElementChild);
</script>
</body>
</html>
```

## πŸ‘€ REFERENCE

λͺ¨λ˜ μžλ°”μŠ€ν¬λ¦½νŠΈ Deep Dive 39μž₯ DOM

0 comments on commit 366555a

Please sign in to comment.