Skip to content

Commit

Permalink
docs: DOM (39.7)
Browse files Browse the repository at this point in the history
  • Loading branch information
ccconac committed Jan 23, 2024
1 parent 366555a commit 65ce9e5
Showing 1 changed file with 244 additions and 0 deletions.
244 changes: 244 additions & 0 deletions docs/39_DOM/λ¬Έμ†Œν¬.md
Original file line number Diff line number Diff line change
Expand Up @@ -884,6 +884,250 @@ $fruits.appendChild($li);
</html>
```

## πŸ”Ž 7. μ–΄νŠΈλ¦¬λ·°νŠΈ

### πŸ’¬ 1. μ–΄νŠΈλ¦¬λ·°νŠΈ λ…Έλ“œμ™€ attributes ν”„λ‘œνΌν‹°

> HTML λ¬Έμ„œκ°€ νŒŒμ‹±λ  λ•Œ HTML μš”μ†Œμ˜ μ–΄νŠΈλ¦¬λ·°νŠΈλŠ” ν•˜λ‚˜λ‹Ή ν•˜λ‚˜μ˜ μ–΄νŠΈλ¦¬λ·°νŠΈ λ…Έλ“œλ‘œ λ³€ν™˜λ˜μ–΄ μš”μ†Œ λ…Έλ“œμ™€ μ—°κ²°λœλ‹€. μ΄λ•Œ λͺ¨λ“  μ–΄νŠΈλ¦¬λ·°νŠΈ λ…Έλ“œμ˜ μ°Έμ‘°λŠ” μœ μ‚¬ λ°°μ—΄ 객체이자 μ΄ν„°λŸ¬λΈ”μΈ `NamedNodeMap` 객체에 담겨 μš”μ†Œ λ…Έλ“œμ˜ `attributes` ν”„λ‘œνΌν‹°μ— μ €μž₯λœλ‹€.
HTML μš”μ†ŒλŠ” μ—¬λŸ¬ 개의 μ–΄νŠΈλ¦¬λ·°νŠΈ<sup>attribute, 속성</sup>λ₯Ό κ°€μ§ˆ 수 μžˆλ‹€. HTML μš”μ†Œμ˜ λ™μž‘μ„ μ œμ–΄ν•˜κΈ° μœ„ν•œ 좔가적인 정보λ₯Ό μ œκ³΅ν•˜λŠ” HTML μ–΄νŠΈλ¦¬λ·°νŠΈλŠ” HTML μš”μ†Œμ˜ μ‹œμž‘ νƒœκ·Έ<sup>start/opening tag</sup>에 `μ–΄νŠΈλ¦¬λ·°νŠΈ 이름="μ–΄νŠΈλ¦¬λ·°νŠΈ κ°’"` ν˜•μ‹μœΌλ‘œ μ •μ˜ν•œλ‹€.

μš”μ†Œ λ…Έλ“œμ˜ λͺ¨λ“  μ–΄νŠΈλ¦¬λ·°νŠΈ λ…Έλ“œλŠ” μš”μ†Œ λ…Έλ“œμ˜ `Element.prototype.attributes` ν”„λ‘œνΌν‹°λ‘œ 취득 κ°€λŠ₯ν•˜λ©°, 읽기 μ „μš© μ ‘κ·Όμž ν”„λ‘œνΌν‹°λ‹€.

![](https://blog.kakaocdn.net/dn/LF5sZ/btrAVtfRhI3/7oeJekZumTTFkF1iMxZLw0/img.png)

```html
<!doctype html>
<html>
<body>
<input id="user" type="text" value="sohee" />
<script>
// μš”μ†Œ λ…Έλ“œμ˜ λͺ¨λ“  μ–΄νŠΈλ¦¬λ·°νŠΈ λ…Έλ“œμ˜ μ°Έμ‘°κ°€ λ‹΄κΈ΄ NamedNodeMap 객체 λ°˜ν™˜
const { attributes } = document.getElementById('user');
console.log(atrributes); // NamedNodeMap {0: id, 1: type, 2: value, id: id, type: type, value: value, length: 3}
console.log(attributes.id.value); // user
console.log(attributes.type.value); // text
console.log(attributes.value.value); // sohee
</script>
</body>
</html>
```

### πŸ’¬ 2. HTML μ–΄νŠΈλ¦¬λ·°νŠΈ μ‘°μž‘

> `Element.prototype.getAttribute(attributeName)/setAttribute(attributeName, attributeValue)` λ©”μ„œλ“œλ₯Ό μ‚¬μš©ν•˜λ©΄ `attributes` ν”„λ‘œνΌν‹°λ₯Ό ν†΅ν•˜μ§€ μ•Šκ³  μš”μ†Œ λ…Έλ“œμ—μ„œ λ©”μ„œλ“œλ₯Ό 톡해 직접 HTML μ–΄νŠΈλ¦¬λ·°νŠΈ 값을 μ·¨λ“ν•˜κ±°λ‚˜ λ³€κ²½ν•  수 μžˆμ–΄μ„œ νŽΈλ¦¬ν•˜λ‹€.
νŠΉμ • HTML μ–΄νŠΈλ¦¬λ·°νŠΈκ°€ μ‘΄μž¬ν•˜λŠ”μ§€ ν™•μΈν•˜λ €λ©΄ `Element.prototype.hasAttribute(attributeName)` λ©”μ„œλ“œλ₯Ό, νŠΉμ • HTML μ–΄νŠΈλ¦¬λ·°νŠΈλ₯Ό μ‚­μ œν•˜λ €λ©΄ `Element.prototype.removeAttribute(attributeName)` λ©”μ„œλ“œλ₯Ό μ‚¬μš©ν•œλ‹€.

```html
<!doctype html>
<html>
<body>
<input id="user" type="text" value="sohee" />
<script>
const $input = document.getElementById('user');
const inputValue = $input.getAttribute('value');
console.log(inputValue); // sohee
$input.setAttribute('value', 'foo'); // value μ–΄νŠΈλ¦¬λ·°νŠΈ κ°’ λ³€κ²½
console.log($input.getAttribute('value')); // foo
if ($input.hasAttribute('value')) {
$input.removeAttribute('value');
}
console.log($input.hasAttribute('value')); // false
</script>
</body>
</html>
```

### πŸ’¬ 3. HTML μ–΄νŠΈλ¦¬λ·°νŠΈ vs DOM ν”„λ‘œνΌν‹°

> **μš”μ†Œ λ…Έλ“œλŠ” 2개의 μƒνƒœ, 즉 초기 μƒνƒœμ™€ μ΅œμ‹  μƒνƒœλ₯Ό 관리해야 ν•œλ‹€. μš”μ†Œ λ…Έλ“œμ˜ 초기 μƒνƒœλŠ” μ–΄νŠΈλ¦¬λ·°νŠΈ λ…Έλ“œκ°€ κ΄€λ¦¬ν•˜λ©°, μš”μ†Œ λ…Έλ“œμ˜ μ΅œμ‹  μƒνƒœλŠ” DOM ν”„λ‘œνΌν‹°κ°€ κ΄€λ¦¬ν•œλ‹€.**
μš”μ†Œ λ…Έλ“œ κ°μ²΄μ—λŠ” HTML μ–΄νŠΈλ¦¬λ·°νŠΈμ— λŒ€μ‘ν•˜λŠ” DOM ν”„λ‘œνΌν‹°κ°€ μ‘΄μž¬ν•œλ‹€. DOM ν”„λ‘œνΌν‹°λ“€μ€ HTML μ–΄νŠΈλ¦¬λ·°νŠΈ 값을 μ΄ˆκΈ°κ°’μœΌλ‘œ 가지고 있으며, 참쑰와 변경이 κ°€λŠ₯ν•œ μ ‘κ·Όμž ν”„λ‘œνΌν‹°μ΄λ‹€.

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

```html
<!doctype html>
<html>
<body>
<input id="user" type="text" value="sohee" />
<script>
const $input = document.getElementById('user');
$input.value = 'foo';
console.log($input.value); // foo
</script>
</body>
</html>
```

HTML μ–΄νŠΈλ¦¬λ·°νŠΈλŠ” λ‹€μŒκ³Ό 같이 DOMμ—μ„œ 쀑볡 κ΄€λ¦¬λ˜κ³  μžˆλŠ” κ²ƒμ²˜λŸΌ λ³΄μ΄μ§€λ§Œ 그렇지 μ•Šλ‹€.

> 1. μš”μ†Œ λ…Έλ“œμ˜ `attributes` ν”„λ‘œνΌν‹°μ—μ„œ κ΄€λ¦¬ν•˜λŠ” μ–΄νŠΈλ¦¬λ·°νŠΈ λ…Έλ“œ
> 2. HTML μ–΄νŠΈλ¦¬λ·°νŠΈμ— λŒ€μ‘ν•˜λŠ” μš”μ†Œ λ…Έλ“œμ˜ ν”„λ‘œνΌν‹° (DOM ν”„λ‘œνΌν‹°)
**HTML μ–΄νŠΈλ¦¬λ·°νŠΈμ˜ 역할은 HTML μš”μ†Œμ˜ 초기 μƒνƒœλ₯Ό μ§€μ •ν•˜λŠ” κ²ƒμœΌλ‘œ, HTML μ–΄νŠΈλ¦¬λ·°νŠΈ 값은 초기 μƒνƒœλ₯Ό μ˜λ―Έν•˜κ³  μ΄λŠ” λ³€ν•˜μ§€ μ•ŠλŠ”λ‹€.** input μš”μ†Œμ˜ μš”μ†Œ λ…Έλ“œκ°€ μƒμ„±λ˜μ–΄ 첫 λ Œλ”λ§μ΄ λλ‚œ μ‹œμ κΉŒμ§€ μ–΄νŠΈλ¦¬λ·°νŠΈ λ…Έλ“œμ˜ μ–΄νŠΈλ¦¬λ·°νŠΈ κ°’κ³Ό μš”μ†Œ λ…Έλ“œμ˜ value ν”„λ‘œνΌν‹°μ— ν• λ‹Ήλœ 값은 HTML μ–΄νŠΈλ¦¬λ·°νŠΈ κ°’κ³Ό λ™μΌν•˜λ‹€. _ν•˜μ§€λ§Œ 첫 λ Œλ”λ§ 이후 μ‚¬μš©μžκ°€ input μš”μ†Œμ— 무언가λ₯Ό μž…λ ₯ν•˜κΈ° μ‹œμž‘ν•˜λ©΄ 상황이 달라진닀._

```html
<!doctype html>
<html>
<body>
<input id="user" type="text" value="sohee" />
<script>
const $input = document.getElementById('user');
// attributes ν”„λ‘œνΌν‹°μ— μ €μž₯된 value κ°’
console.log($input.getAttribute('value')); // sohee
// μš”μ†Œ λ…Έλ“œμ˜ value ν”„λ‘œνΌν‹°μ— μ €μž₯된 value μ–΄νŠΈλ¦¬λ·°νŠΈ κ°’
console.log($input.value); // sohee
</script>
</body>
</html>
```

μš”μ†Œ λ…Έλ“œλŠ” μƒνƒœλ₯Ό 가지고 μžˆλ‹€. input μš”μ†Œ λ…Έλ“œλŠ” 초기 μƒνƒœ 값을 κ΄€λ¦¬ν•˜μ§€ μ•ŠμœΌλ©΄ μ›ΉνŽ˜μ΄μ§€λ₯Ό 처음 ν‘œμ‹œν•˜κ±°λ‚˜ μƒˆλ‘œκ³ μΉ¨ν•  λ•Œ 초기 μƒνƒœλ₯Ό ν‘œμ‹œν•  수 μ—†κΈ° λ•Œλ¬Έμ— μ‚¬μš©μžμ˜ μž…λ ₯에 μ˜ν•΄ λ³€κ²½λœ **μ΅œμ‹  μƒνƒœ<sup>foo</sup>λ₯Ό** 관리해야 ν•˜λŠ” 것은 λ¬Όλ‘ , HTML μ–΄νŠΈλ¦¬λ·°νŠΈλ‘œ μ§€μ •ν•œ **초기 상<sup>sohee</sup>도** 관리해야 ν•œλ‹€.

#### ✨ μ–΄νŠΈλ¦¬λ·°νŠΈ λ…Έλ“œ

> **HTML μ–΄νŠΈλ¦¬λ·°νŠΈλ‘œ μ§€μ •ν•œ HTML μš”μ†Œμ˜ 초기 μƒνƒœλŠ” μ–΄νŠΈλ¦¬λ·°νŠΈ λ…Έλ“œμ—μ„œ κ΄€λ¦¬ν•œλ‹€.** μ‚¬μš©μžμ˜ μž…λ ₯에 μ˜ν•΄ μƒνƒœκ°€ λ³€κ²½λ˜μ–΄λ„ λ³€ν•˜μ§€ μ•Šκ³  HTML μ–΄νŠΈλ¦¬λ·°νŠΈλ‘œ μ§€μ •ν•œ HTML μš”μ†Œμ˜ 초기 μƒνƒœλ₯Ό κ·ΈλŒ€λ‘œ μœ μ§€ν•œλ‹€. 즉, μ‚¬μš©μžμ˜ μž…λ ₯에 μ˜ν•΄ λ³€ν•˜μ§€ μ•ŠμœΌλ―€λ‘œ κ²°κ³ΌλŠ” μ–Έμ œλ‚˜ λ™μΌν•˜λ‹€.
```html
<!doctype html>
<html>
<body>
<input id="user" type="text" value="sohee" />
<script>
document.getElementById('user').getAttribute('value'); // sohee
document.getElementById('user').setAttribute('value', 'foo'); // 초기 μƒνƒœ κ°’ λ³€κ²½
</script>
</body>
</html>
```

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

#### ✨ DOM ν”„λ‘œνΌν‹°

> **μ‚¬μš©μžκ°€ μž…λ ₯ν•œ μ΅œμ‹  μƒνƒœλŠ” HTML μ–΄νŠΈλ¦¬λ·°νŠΈμ— λŒ€μ‘ν•˜λŠ” μš”μ†Œ λ…Έλ“œμ˜ DOM ν”„λ‘œνΌν‹°κ°€ κ΄€λ¦¬ν•œλ‹€. DOM ν”„λ‘œνΌν‹°λŠ” μ‚¬μš©μžμ˜ μž…λ ₯에 μ˜ν•œ μƒνƒœ 변화에 λ°˜μ‘ν•˜μ—¬ μ–Έμ œλ‚˜ μ΅œμ‹  μƒνƒœλ₯Ό μœ μ§€ν•œλ‹€.**
DOM ν”„λ‘œνΌν‹°μ— 값을 ν• λ‹Ήν•˜λŠ” 것은 HTML μš”μ†Œμ˜ μ΅œμ‹  μƒνƒœ 값을 λ³€κ²½ν•˜λŠ” κ²ƒμœΌλ‘œ, μ‚¬μš©μžκ°€ μƒνƒœλ₯Ό λ³€κ²½ν•˜λŠ” ν–‰μœ„μ™€ κ°™λ‹€. 이떄 HTML μš”μ†Œμ— μ§€μ •ν•œ μ–΄νŠΈλ¦¬λ·°νŠΈ κ°’μ—λŠ” μ–΄λ– ν•œ 영ν–₯도 주지 μ•ŠλŠ”λ‹€. 단, μ‚¬μš©μž μž…λ ₯에 μ˜ν•œ μƒνƒœ 변화와 κ΄€κ²ŒμžˆλŠ” DOM ν”„λ‘œνΌν‹°λ§Œ μ΅œμ‹  μƒνƒœ 값을 κ΄€λ¦¬ν•˜λ©° κ΄€κ³„μ—†λŠ” 경우 항상 λ™μΌν•œ κ°’μœΌλ‘œ μ—°λ™ν•œλ‹€.

```html
<!doctype html>
<html>
<body>
<input id="user" type="text" value="sohee" />
<script>
const $input = document.getElementById('user');
// μ‚¬μš©μžκ°€ input μš”μ†Œμ˜ μž…λ ₯ ν•„λ“œμ— κ°’ μž…λ ₯ν•  λ•Œλ§ˆλ‹€ μ΅œμ‹  μƒνƒœ 값을 취득 (value ν”„λ‘œνΌν‹° 값은 μ‚¬μš©μžμ— μ˜ν•΄ λ™μ μœΌλ‘œ 변경됨)
$input.output = () => {
console.log('value ν”„λ‘œνΌν‹° κ°’', $input.value);
};
// 초기 μƒνƒœ 값은 λ³€ν•˜μ§€ μ•Šκ³  μœ μ§€λ¨
console.log('value μ–΄νŠΈλ¦¬λ·°νŠΈ κ°’', $input.getAttribute('value')); // sohee
$input.value = 'foo';
console.log($input.value); // foo
// 초기 μƒνƒœ 값은 λ³€ν•˜μ§€ μ•Šκ³  μœ μ§€λ¨
console.log($input.getAttribute('value')); // sohee
</script>
</body>
</html>
```

#### ✨ HTML μ–΄νŠΈλ¦¬λ·°νŠΈμ™€ DOM ν”„λ‘œνΌν‹°μ˜ λŒ€μ‘ 관계

> λŒ€λΆ€λΆ„μ˜ HTML μ–΄νŠΈλ¦¬λ·°νŠΈλŠ” HTML μ–΄νŠΈλ¦¬λ·°νŠΈ 이름과 λ™μΌν•œ DOM ν”„λ‘œνΌν‹°μ™€ 1:1둜 λŒ€μ‘ν•˜μ§€λ§Œ, μ–Έμ œλ‚˜ 1:1둜 λŒ€μ‘ν•˜λŠ” 것은 μ•„λ‹ˆλ©° HTML μ–΄νŠΈλ¦¬λ·°νŠΈ 이름과 DOM ν”„λ‘œνΌν‹° ν‚€κ°€ λ°˜λ“œμ‹œ μΌμΉ˜ν•˜λŠ” 것도 μ•„λ‹ˆλ‹€.
- id μ–΄νŠΈλ¦¬λ·°νŠΈμ™€ id ν”„λ‘œνΌν‹°λŠ” 1:1 λŒ€μ‘ν•˜λ©°, λ™μΌν•œ κ°’μœΌλ‘œ μ—°λ™ν•œλ‹€.
- input μš”μ†Œμ˜ value μ–΄νŠΈλ¦¬λ·°νŠΈλŠ” value ν”„λ‘œνΌν‹°μ™€ 1:1 λŒ€μ‘ν•œλ‹€. ν•˜μ§€λ§Œ, value μ–΄νŠΈλ¦¬λ·°νŠΈλŠ” 초기 μƒνƒœλ₯Ό, value ν”„λ‘œνΌν‹°λŠ” μ΅œμ‹  μƒνƒœλ₯Ό κ°–λŠ”λ‹€.
- class μ–΄νŠΈλ¦¬λ·°νŠΈλŠ” className, classList ν”„λ‘œνΌν‹°μ™€ λŒ€μ‘ν•œλ‹€.
- for μ–΄νŠΈλ¦¬λ·°νŠΈλŠ” htmlFor ν”„λ‘œνΌν‹°μ™€ 1:1 λŒ€μ‘ν•œλ‹€.
- td μš”μ†Œμ˜ colspan μ–΄νŠΈλ¦¬λ·°νŠΈλŠ” λŒ€μ‘ν•˜λŠ” ν”„λ‘œνΌν‹°κ°€ μ‘΄μž¬ν•˜μ§€ μ•ŠλŠ”λ‹€.
- textContent ν”„λ‘œνΌν‹°λŠ” λŒ€μ‘ν•˜λŠ” μ–΄νŠΈλ¦¬λ·°νŠΈκ°€ μ‘΄μž¬ν•˜μ§€ μ•ŠλŠ”λ‹€.
- μ–΄νŠΈλ¦¬λ·°νŠΈ 이름은 λŒ€μ†Œλ¬Έμžλ₯Ό κ΅¬λ³„ν•˜μ§€ μ•Šμ§€λ§Œ λŒ€μ‘ν•˜λŠ” ν”„λ‘œνΌν‹° ν‚€λŠ” 카멜 μΌ€μ΄μŠ€λ₯Ό λ”°λ₯Έλ‹€.

#### ✨ DOM ν”„λ‘œνΌν‹° κ°’μ˜ νƒ€μž…

> getAttribute λ©”μ„œλ“œλ‘œ μ·¨λ“ν•œ μ–΄νŠΈλ¦¬λ·°νŠΈ 값은 μ–Έμ œλ‚˜ λ¬Έμžμ—΄μ΄μ§€λ§Œ, DOM ν”„λ‘œνΌν‹°λ‘œ μ·¨λ“ν•œ μ΅œμ‹  μƒνƒœ 값은 λ¬Έμžμ—΄μ΄ 아닐 μˆ˜λ„ μžˆλ‹€.
```html
<!doctype html>
<html>
<body>
<input type="checkbox" checked />
<script>
const $checkbox = document.querySelector('input[type=checkbox]');
console.log($checkbox.getAttribute('checked')); // '' (μ–Έμ œλ‚˜ λ¬Έμžμ—΄)
console.log($checkbox.checked); // true (λ¬Έμžμ—΄ 아닐 μˆ˜λ„ 있음)
</script>
</body>
</html>
```

### πŸ’¬ 4. data μ–΄νŠΈλ¦¬λ·°νŠΈμ™€ dataset ν”„λ‘œνΌν‹°

> data μ–΄νŠΈλ¦¬λ·°νŠΈμ™€ dataset ν”„λ‘œνΌν‹°λ₯Ό μ‚¬μš©ν•˜λ©΄ HTML μš”μ†Œμ— μ •μ˜ν•œ μ‚¬μš©μž μ •μ˜ μ–΄νŠΈλ¦¬λ·°νŠΈμ™€ μžλ°”μŠ€ν¬λ¦½νŠΈ 간에 데이터λ₯Ό κ΅ν™˜ν•  수 μžˆλ‹€.
data μ–΄νŠΈλ¦¬λ·°νŠΈ 값은 `HTMLElement.dataset` ν”„λ‘œνΌν‹°λ‘œ 취득할 수 μžˆλ‹€. `dataset` ν”„λ‘œνΌν‹°λŠ” HTML μš”μ†Œμ˜ λͺ¨λ“  data μ–΄νŠΈλ¦¬λ·°νŠΈμ˜ 정보λ₯Ό μ œκ³΅ν•˜λŠ” `DOMStringMap` 객체λ₯Ό λ°˜ν™˜ν•œλ‹€.

```html
<!doctype html>
<html>
<body>
<ul class="users">
<li id="1" data-user-id="7621" data-role="admin">Lee</li>
<li id="2" data-user-id="9524" data-role="subscriber">Kim</li>
</ul>
<script>
const users = [...document.querySelector('.users').children];
const user = users.find((user) => user.dataset.userId === '7621');
console.log(user.dataset.role); // "admin"
user.dataset.role = 'subscriber';
console.log(user.dataset); // DOMStringMap {userId: "7621", role: "subscriber""
</script>
</body>
</html>
```

data μ–΄νŠΈλ¦¬λ·°νŠΈμ˜ data- 접두사 λ‹€μŒμ— μ‘΄μž¬ν•˜μ§€ μ•ŠλŠ” 이름을 ν‚€λ‘œ μ‚¬μš©ν•΄ dataset ν”„λ‘œνΌν‹°μ— 값을 ν• λ‹Ήν•˜λ©΄ HTML μš”μ†Œμ— data μ–΄νŠΈλ¦¬λ·°νŠΈκ°€ μΆ”κ°€λœλ‹€.

```html
<!doctype html>
<html>
<body>
<ul class="users">
<li id="1" data-user-id="7621">Lee</li>
<li id="2" data-user-id="9524">Kim</li>
</ul>
<script>
const users = [...document.querySelector('.users').children];
const user = users.find((user) => user.dataset.userId === '7621');
user.dataset.role = 'admin';
console.log(user.dataset);
/*
DOMStringMap {userId: "7621", role: "admin"}
β†’ <li id="1" data-user-id="7621" data-role="admin">Lee</li>
*/
</script>
</body>
</html>
```

## πŸ‘€ REFERENCE

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

0 comments on commit 65ce9e5

Please sign in to comment.