Notice
Recent Posts
Recent Comments
Link
«   2025/01   »
1 2 3 4
5 6 7 8 9 10 11
12 13 14 15 16 17 18
19 20 21 22 23 24 25
26 27 28 29 30 31
Tags
more
Archives
Today
Total
관리 메뉴

개발자공부일기

DOM의 개념과 메서드들 본문

TIL(Today I Learned)

DOM의 개념과 메서드들

JavaCPP 2024. 11. 29. 19:47

 

예전에 DOM의 개념에 대해서는 글을 썼던거 같은데 자세히 메서드까진 다룬적이 없는거 같아서 복습겸 알아봤다.

 

DOM(Document Object Model)은 HTML과 XML 문서의 구조를 나타내는 객체 모델입니다. DOM을 통해 JavaScript는 HTML 문서와 상호작용하고, 문서의 요소를 변경하거나 조작할 수 있습니다. DOM은 웹 페이지를 동적으로 수정할 수 있도록 만들어져 있으며, 페이지 로드 후에도 JavaScript로 실시간으로 페이지를 업데이트할 수 있게 해줍니다.


1. DOM의 기본 개념

DOM은 문서의 구조를 트리 형태로 표현하며, 각 HTML 태그나 요소는 DOM 트리의 노드로 나타냅니다. DOM 트리에서 루트는 <html> 태그이고, 그 아래에 여러 자식 노드가 있습니다. 예를 들어:

<!DOCTYPE html>
<html>
  <head>
    <title>Sample Page</title>
  </head>
  <body>
    <h1>Welcome!</h1>
    <p>This is a sample page.</p>
  </body>
</html>
이 HTML 문서는 아래와 같은 DOM 트리 구조를 가집니다:
 
html
 ├── head
 │    └── title
 └── body
      ├── h1
      └── p

2. DOM의 주요 구성 요소

DOM 트리에서 각 요소는 노드(Node)로 표현되며, 다음과 같은 주요 노드 유형이 있습니다:

  1. Element Node (요소 노드): HTML 요소들, 예를 들어 <h1>, <p>, <div> 등.
  2. Text Node (텍스트 노드): HTML 요소 안의 텍스트 내용.
  3. Attribute Node (속성 노드): HTML 요소의 속성들, 예를 들어 <a href="url">의 href 속성.
  4. Document Node (문서 노드): 전체 HTML 문서의 최상위 노드.

3. DOM을 사용하여 HTML 요소 조작하기

JavaScript를 사용하여 DOM을 조작할 수 있는 다양한 메서드와 속성들이 있습니다. 주로 사용하는 메서드와 속성은 다음과 같습니다:

1) 요소 선택 (Selection)

  • getElementById(id): 특정 id 값을 가진 요소를 선택합니다.
  • getElementsByClassName(class): 특정 클래스명을 가진 모든 요소를 선택합니다.
  • getElementsByTagName(tag): 특정 태그명을 가진 모든 요소를 선택합니다.
  • querySelector(selector): CSS 선택자를 사용하여 첫 번째 요소를 선택합니다.
  • querySelectorAll(selector): CSS 선택자를 사용하여 모든 요소를 선택합니다.
// 예시: id가 'myElement'인 요소 선택
let element = document.getElementById('myElement');

// 예시: 클래스가 'myClass'인 모든 요소 선택
let elements = document.getElementsByClassName('myClass');

2) 요소 수정 (Modification)

  • innerHTML: 요소의 HTML 콘텐츠를 변경합니다.
  • innerText: 요소의 텍스트 콘텐츠를 변경합니다.
  • setAttribute(attribute, value): 요소의 속성을 설정합니다.
  • style: 요소의 CSS 스타일을 직접 변경합니다.
// 예시: 텍스트 콘텐츠 변경
document.getElementById('myElement').innerText = 'Hello, World!';

// 예시: 속성 값 변경
document.getElementById('myElement').setAttribute('class', 'newClass');

// 예시: 스타일 변경
document.getElementById('myElement').style.color = 'blue';​

3) 요소 추가 및 삭제 (Adding and Removing Elements)

  • appendChild(node): 새로운 자식 요소를 추가합니다.
  • removeChild(node): 자식 요소를 제거합니다.
  • createElement(tagName): 새로운 요소를 생성합니다.

appendChild(node)

 

새로운 자식 요소를 부모 요소의 마지막 자식으로 추가합니다.

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>appendChild Example</title>
</head>
<body>
  <div id="container">
    <p>기존 내용</p>
  </div>

  <script>
    // 새로운 요소를 생성하고 appendChild로 추가
    const newParagraph = document.createElement('p');  // <p> 요소 생성
    newParagraph.textContent = '새로운 문단입니다.';   // 내용 추가

    const container = document.getElementById('container');  // 부모 요소
    container.appendChild(newParagraph);  // 부모 요소에 새로운 <p> 요소 추가
  </script>
</body>
</html>
<div id="container">
  <p>기존 내용</p>
  <p>새로운 문단입니다.</p> <!-- 새로 추가된 내용 -->
</div>

appendChild()는 container 안에 새로운 <p> 요소를 추가하여 화면에 나타납니다.  

 

remonveChild(node)

 

부모 요소에서 특정 자식 요소를 제거합니다.

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>removeChild Example</title>
</head>
<body>
  <div id="container">
    <p>기존 내용</p>
    <p>삭제할 문단입니다.</p>
  </div>

  <script>
    const container = document.getElementById('container');
    const paragraphToRemove = container.getElementsByTagName('p')[1];  // 두 번째 <p> 요소

    container.removeChild(paragraphToRemove);  // 해당 <p> 요소 제거
  </script>
</body>
</html>
<div id="container">
  <p>기존 내용</p> <!-- 첫 번째 <p>는 남음 -->
</div>

removeChild()는 container 안에서 두 번째 <p> 요소를 제거합니다.

 

createElement(tagName)

 

새로운 HTML 요소를 생성합니다. 이 메서드는 요소를 생성하지만, 아직 DOM에 추가되지 않으므로 추가적인 메서드(appendChild(), insertBefore() 등)로 삽입해야 합니다.

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>createElement Example</title>
</head>
<body>
  <div id="container">
    <p>기존 내용</p>
  </div>

  <script>
    const newDiv = document.createElement('div');  // <div> 요소 생성
    newDiv.textContent = '새로운 div 요소입니다.';  // 내용 추가

    const container = document.getElementById('container');
    container.appendChild(newDiv);  // 새로운 <div> 요소를 부모 요소에 추가
  </script>
</body>
</html>
<div id="container">
  <p>기존 내용</p>
  <div>새로운 div 요소입니다.</div> <!-- 새로 생성된 <div> -->
</div>

createElement()는 새로운 <div> 요소를 생성하고 appendChild()로 container에 추가하여 화면에 나타납니다.

4) 이벤트 처리 (Event Handling)

DOM은 사용자의 상호작용을 처리할 수 있게 해주는 이벤트를 지원합니다. 예를 들어, 클릭, 키보드 입력, 마우스 이동 등의 이벤트를 처리할 수 있습니다.

  • addEventListener(event, function): 이벤트 리스너를 추가합니다.
  • removeEventListener(event, function): 이벤트 리스너를 제거합니다.
// 클릭 이벤트 처리
document.getElementById('myButton').addEventListener('click', function() {
    alert('Button clicked!');
});

 

removeEventListener(event, function)는 이미 등록된 이벤트 리스너를 제거하는 메서드입니다. 이 메서드는 특정 이벤트에 대해 등록된 이벤트 핸들러(함수)를 더 이상 실행하지 않게 만듭니다. 이를 통해 메모리 누수를 방지하거나, 특정 조건에서 이벤트 리스너를 제거할 수 있습니다.

사용법

element.removeEventListener(event, function, [options]);
  • event: 이벤트 유형 (예: 'click', 'keydown', 'mouseover' 등).
  • function: 제거하려는 이벤트 리스너로 사용된 함수.
  • options (선택적): addEventListener()에서 사용한 options 객체와 동일하게 사용될 수 있습니다. 예: { once: true } 등.

주의점

  • removeEventListener는 같은 함수만 제거합니다. 즉, 이벤트 리스너를 추가할 때 사용한 함수와 완전히 동일한 함수 객체를 removeEventListener에 전달해야 합니다.
  • 익명 함수나 화살표 함수는 제거할 수 없습니다. 그 이유는 익명 함수는 객체가 아니라, 매번 다른 인스턴스로 생성되기 때문입니다.

예제 : 이벤트 리스너 추가 및 제거

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>removeEventListener Example</title>
</head>
<body>
  <button id="myButton">Click Me!</button>

  <script>
    // 클릭 이벤트 리스너를 추가
    function handleClick() {
      alert('Button clicked!');
    }

    const button = document.getElementById('myButton');
    button.addEventListener('click', handleClick);

    // 5초 후에 이벤트 리스너 제거
    setTimeout(() => {
      button.removeEventListener('click', handleClick);
      console.log('Event listener removed!');
    }, 5000);  // 5초 뒤에 클릭 이벤트 리스너 제거
  </script>
</body>
</html>

실행 결과:

  1. 버튼을 클릭하면 handleClick 함수가 실행되어 alert('Button clicked!')가 나타납니다.
  2. 5초 후, removeEventListener가 호출되어 버튼 클릭 시 더 이상 알림이 나타나지 않습니다.

익명 함수로 이벤트 리스너 추가 및 제거 (불가능)

 

익명 함수는 removeEventListener에서 제거할 수 없으므로, 5초 후에도 버튼 클릭 시 알림이 계속 나타납니다. removeEventListener는 동일한 함수를 제거해야 하기 때문에, 익명 함수는 비교가 불가능하여 제거되지 않습니다.


예제 3: 화살표 함수로 이벤트 리스너 추가 및 제거 (불가능)

 

화살표 함수는 실제로 메모리 상에서 다른 참조를 가질 수 있기 때문에, removeEventListener는 addEventListener에 사용된 정확한 동일한 함수 객체를 요구합니다. 그러나 화살표 함수는 익명 함수와 마찬가지로 메모리 상에서 다르게 처리되기 때문에 동일한 함수를 제거할 수 없습니다. removeEventListener가 정상적으로 작동하기 위해서는 화살표 함수나 익명 함수 대신 명명된 함수를 사용해야 합니다.

 

5) DOM 탐색 (Traversing)

DOM 트리 내에서 요소를 탐색하는 메서드도 있습니다:

  • parentNode: 부모 노드를 참조합니다.
  • childNodes: 자식 노드를 모두 반환합니다. (텍스트, 주석도 포함)
  • firstChild: 첫 번째 자식 노드를 반환합니다.
  • lastChild: 마지막 자식 노드를 반환합니다.
  • nextSibling: 현재 노드의 다음 형제 노드를 반환합니다.
  • previousSibling: 현재 노드의 이전 형제 노드를 반환합니다.

1. parentNode

parentNode는 현재 노드의 부모 노드를 참조합니다. 만약 노드가 <html>, <body>와 같은 루트 노드라면 parentNode는 null을 반환합니다.

예제:

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>parentNode Example</title>
</head>
<body>
  <div id="parent">
    <p id="child">Hello, world!</p>
  </div>

  <script>
    const child = document.getElementById('child');
    console.log(child.parentNode);  // <div id="parent">...</div> 출력
  </script>
</body>
</html>
  • 출력: child 요소의 parentNode는 <div id="parent"> 요소입니다.

2. childNodes

childNodes는 현재 노드의 모든 자식 노드를 포함하는 NodeList 객체를 반환합니다. 이 속성은 텍스트 노드나 주석 노드도 포함하므로, HTML 요소 노드만 필요하면 children 속성을 사용해야 합니다.

예제:

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>childNodes Example</title>
</head>
<body>
  <div id="parent">
    <p>Hello, world!</p>
    <p>Another paragraph.</p>
  </div>

  <script>
    const parent = document.getElementById('parent');
    console.log(parent.childNodes);  // <NodeList>에 텍스트 노드와 p 요소가 포함됨
  </script>
</body>
</html>
  • 출력: childNodes는 텍스트 노드를 포함하여 3개의 항목을 반환합니다. (<p> 태그 2개와 텍스트 노드 1개)

3. firstChild

firstChild는 현재 노드의 첫 번째 자식 노드를 반환합니다. 만약 자식이 없으면 null을 반환합니다.

예제:

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>firstChild Example</title>
</head>
<body>
  <div id="parent">
    <p>First child element</p>
    <p>Second child element</p>
  </div>

  <script>
    const parent = document.getElementById('parent');
    console.log(parent.firstChild);  // 텍스트 노드를 반환 (공백 텍스트)
    console.log(parent.firstElementChild);  // <p>First child element</p> 출력
  </script>
</body>
</html>
  • 출력: firstChild는 공백 텍스트 노드를 반환합니다. firstElementChild를 사용하면 첫 번째 <p> 태그를 반환합니다.

4. lastChild

lastChild는 현재 노드의 마지막 자식 노드를 반환합니다. 자식이 없으면 null을 반환합니다.

예제:

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>lastChild Example</title>
</head>
<body>
  <div id="parent">
    <p>First child element</p>
    <p>Second child element</p>
  </div>

  <script>
    const parent = document.getElementById('parent');
    console.log(parent.lastChild);  // 텍스트 노드를 반환 (공백 텍스트)
    console.log(parent.lastElementChild);  // <p>Second child element</p> 출력
  </script>
</body>
</html>
  • 출력: lastChild는 공백 텍스트 노드를 반환합니다. lastElementChild를 사용하면 마지막 <p> 태그를 반환합니다.

5. nextSibling

nextSibling은 현재 노드의 바로 다음 형제 노드를 참조합니다. 만약 다음 형제 노드가 없다면 null을 반환합니다.

예제:

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>nextSibling Example</title>
</head>
<body>
  <div id="parent">
    <p>First paragraph</p>
    <p>Second paragraph</p>
  </div>

  <script>
    const firstParagraph = document.querySelector('p');
    console.log(firstParagraph.nextSibling);  // 텍스트 노드를 반환 (줄 바꿈 공백)
    console.log(firstParagraph.nextElementSibling);  // <p>Second paragraph</p> 출력
  </script>
</body>
</html>
  • 출력: nextSibling은 텍스트 노드를 반환합니다. 공백 문자나 줄 바꿈을 포함할 수 있습니다. nextElementSibling을 사용하면 실제로 다음 <p> 태그를 반환합니다.

6. previousSibling

previousSibling은 현재 노드의 바로 이전 형제 노드를 참조합니다. 이전 형제 노드가 없다면 null을 반환합니다.

예제:

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>previousSibling Example</title>
</head>
<body>
  <div id="parent">
    <p>First paragraph</p>
    <p>Second paragraph</p>
  </div>

  <script>
    const secondParagraph = document.querySelectorAll('p')[1];
    console.log(secondParagraph.previousSibling);  // 텍스트 노드를 반환 (줄 바꿈 공백)
    console.log(secondParagraph.previousElementSibling);  // <p>First paragraph</p> 출력
  </script>
</body>
</html>
  • 출력: previousSibling은 텍스트 노드를 반환합니다. previousElementSibling을 사용하면 이전 <p> 태그를 반환합니다.

4. DOM 이벤트

웹 페이지에서 사용자의 행동에 반응하려면 DOM 이벤트를 사용해야 합니다. 이벤트는 페이지 로딩, 사용자 입력, 클릭 등 다양한 상호작용을 감지합니다. 일반적인 DOM 이벤트는 다음과 같습니다:

  • click: 마우스 클릭 이벤트
  • mouseover: 마우스를 요소 위로 올렸을 때
  • keydown: 키보드 키를 눌렀을 때
  • submit: 폼 제출 시
 

5. DOM의 중요성

  • 동적 웹 페이지 만들기: DOM을 사용하면 JavaScript로 웹 페이지의 콘텐츠나 구조를 동적으로 변경할 수 있습니다.
  • 상호작용: 버튼 클릭, 폼 제출, 드래그 앤 드롭 등 사용자 인터랙션에 반응하는 웹 애플리케이션을 만들 수 있습니다.
  • 애니메이션 및 효과: DOM을 조작하여 애니메이션을 만들거나, CSS 스타일을 실시간으로 변경할 수 있습니다.

6. 요약

  • DOM은 HTML 문서를 객체로 모델링한 것입니다.
  • JavaScript를 사용해 DOM을 수정하고, 이벤트를 처리하며, 페이지와 상호작용할 수 있습니다.
  • DOM을 통해 HTML, CSS를 동적으로 조작할 수 있어, 웹 페이지의 동적 콘텐츠와 상호작용을 처리하는 핵심입니다.
 

 

'TIL(Today I Learned)' 카테고리의 다른 글

데이터베이스 정규화  (0) 2024.12.03
RESTful API  (0) 2024.12.02
아이탬시뮬레이터 트러블 슈팅  (0) 2024.11.28
Prisma Transaction  (0) 2024.11.27
OSI 7계층  (0) 2024.11.26