본문 바로가기

Language/Javascript

[Javascript] DOM (Document Object Model)의 개념

DOM (Document Object Model)
  • HTML 문서를 Javascript로 조작하기 위한 모델
  • HTML, XML 문서의 프로그래밍 인터페이스이며, 문서의 구조를 계층적인 노드로 나타냄
  • W3C(World Wide Web Consortium) 표준

 

DOM의 구성 요소

 

  • 문서 노드 (Document) : 최상위 노드로 HTML 문서 전체를 대표
  • 요소 노드 (Element) : HTML 태그를 나타냄
  • 속성 노드 (Attribute) : 요소의 속성을 나타냄
  • 텍스트 노드 (Text) : 요소 안의 텍스트를 나타냄
  • 주석 노드 (Comment) : HTML 주석을 나타냄

 

 

DOM의 특징
  • 트리 구조
    • 부모-자식 관계로 구성된 계층적 구조이며, 이를 DOM 트리라고 함
    • 부모, 자식, 형제 노드 간의 관계를 통해 문서를 탐색하거나 조작 가능
  • 라이브 (Live)
    • DOM 객체는 라이브 객체로 변경이 발생하면 즉시 웹 페이지에 반영
  • 조작 가능
    • 자바스크립트를 사용하여 DOM 요소를 선택, 수정, 추가 또는 제거 가능

DOM 요소 선택
  • document.getElementById(id) : 주어진 ID를 가진 요소를 반환
    • , <p> 태그 위에 <script>를 작성하게 되면 DOM 렌더링 시점 문제 때문에 console에는 null이 찍히게 됨
    • 웹 페이지는 HTML, CSS, JavaScript 파일을 순차적으로 처리하고 렌더링하는데, 스크립트가 DOM 요소에 접근하려면 해당 요소들이 이미 로드되어 있어야 하기 때문
      순서를 </body> 이전에 작성하거나 DOMContentLoaded 이벤트 사용
<body>  
    <script>
        let pTag = document.getElementById("testId");
        console.log(pTag);
    </script>
    <p id="testId">p 태그</p>
</body>


</body> 태그 바로 위에 <script> 작성

<body>  
    <p id="testId">p 태그</p>
    <script>
        let pTag = document.getElementById("testId");
        console.log(pTag);
    </script>
</body>

 

  • document.getElementsByTagName(name) : 주어진 태그 이름을 가진 요소들의 목록을 반환
  • document.getElementsByClassName(name) : 주어진 클래스 이름을 가진 요소들의 목록을 반환
  • document.querySelector(selector) : 주어진 CSS 선택자와 일치하는 첫 번째 요소를 반환
  • document.querySelectorAll(selector) : 주어진 CSS 선택자와 일치하는 모든 요소의 목록을 반환

DOM 조작
  • 웹 페이지의 요소를 동적으로 변경하거나 조작하는 방법
  • 이를 통해 HTML 구조와 콘텐츠를 실시간으로 업데이트 가능
텍스트 변경
  • textContent 또는 innerText를 사용하여 요소의 텍스트 내용을 변경 가능
<body>
    <p id="textElement">Hello, world!</p>
    <button onclick="changeText()">Change Text</button>

    <script>
        function changeText() {
            // 텍스트 변경
            document.getElementById("textElement").textContent = "Hello, DOM!";
            document.getElementById("textElement").style.color = "red";
        }
    </script>
</body>

속성 변경
  • setAttribute() 메서드를 사용하여 HTML 요소의 속성을 변경 또는 특정 속성에 대해 직접 접근하여 값을 변경 가능
    setAttribute('속성', '값')
<body>
    <img id="myImage" src="image1.jpg" alt="Old Image">
    <button onclick="changeAttribute()">Change Image</button>

    <script>
        function changeAttribute() {
            // 속성 변경 (src, alt)
            document.getElementById("myImage").setAttribute("src", "image2.jpg");
            document.getElementById("myImage").setAttribute("alt", "New Image");
        }
    </script>
</body>

클래스 추가/삭제
  • classList DOM 요소의 클래스를 조작하는데 사용되는 속성
  • add(), remove(), toggle() 등의 메서드를 사용하여 클래스를 추가하거나 삭제 가능
    • toggle() : 클래스가 존재하면 삭제하고, 존재하지 않으면 추가
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Class Manipulation Example</title>
    <style>
        .highlight {
            color: red;
            font-weight: bold;
        }
    </style>
</head>
<body>
    <p id="myParagraph">This is a paragraph.</p>
    <button onclick="toggleClass()">Toggle Highlight</button>

    <script>
        function toggleClass() {
            // 'highlight' 클래스를 추가하거나 제거
            document.getElementById("myParagraph").classList.toggle("highlight");
        }
    </script>
</body>
</html>

 

요소 생성
  • createElement()를 사용하여 새로운 HTML 요소를 동적으로 생성 가능
<body>
    <div id="container"></div>
    <button onclick="createElementFunction()">Create Paragraph</button>

    <script>
        function createElementFunction() {
            // 새 <p> 요소 생성
            let newParagraph = document.createElement("p");
            newParagraph.textContent = "This is a new paragraph.";
            
            // 새로운 요소를 <div id="container"> 안에 추가
            document.getElementById("container").appendChild(newParagraph);
        }
    </script>
</body>

  • 예제 설명
    1. createElement("elementName")로 새로운 요소를 생성하고, textContent로 텍스트를 설정합니다.
    2. appendChild()를 사용하여 생성된 요소를 특정 부모 요소에 추가
    3. 버튼 클릭 시 새로운 <p> 요소가 생성되어 id가 container인 요소에 추가
요소 삽입
  • appendChild(), insertBefore() 등을 사용하여 새로 생성한 요소를 다른 요소에 삽입
<body>
    <div id="container">
        <p>First Paragraph</p>
    </div>
    <button onclick="insertElement()">Insert Paragraph Before</button>

    <script>
        function insertElement() {
            // 새 <p> 요소 생성
            let newParagraph = document.createElement("p");
            newParagraph.textContent = "This paragraph is inserted before the first one.";
            
            // 새 요소를 첫 번째 <p> 요소 앞에 삽입
            let container = document.getElementById("container");
            container.insertBefore(newParagraph, container.firstChild);
        }
    </script>
</body>

 

  • 예제 설명
    1. insertBefore(newNode, referenceNode)는 newNode를 referenceNode 앞에 삽입
    2. 버튼을 클릭하면 새 <p> 요소가 첫 번째 <p> 요소 앞에 삽입
요소 삭제
  • removeChild()를 사용하여 부모 요소에서 자식 요소를 삭제 가능
<body>
    <div id="container">
        <p id="paragraph">This paragraph will be removed.</p>
    </div>
    <button onclick="removeElement()">Remove Paragraph</button>

    <script>
        function removeElement() {
            // <p> 요소 삭제
            let paragraph = document.getElementById("paragraph");
            paragraph.parentNode.removeChild(paragraph);
        }
    </script>
</body>


이벤트 처리
  • 사용자가 웹 페이지와 상호작용하는 방식을 정의하는 중요한 개념
이벤트 리스너 등록 (addEventListener)
  • HTML 요소에 이벤트를 연결하는 가장 일반적인 방법
  • 이벤트가 발생하면, 지정된 함수(이벤트 핸들러)가 호출
<body>
    <button id="myButton">Click Me</button>
    <script>
        // 버튼 요소 선택
        const button = document.getElementById("myButton");

        // 이벤트 리스너 등록
        button.addEventListener("click", () => {
            alert("Button clicked!");
        });
    </script>
</body>

이벤트 객체 (event)
  • 이벤트가 발생하면 브라우저는 이벤트와 관련된 정보가 담긴 event 객체를 핸들러 함수에 전달
  • 이 객체를 사용하여 이벤트의 세부 정보를 확인하거나 제어 가능
<body>
    <button id="myButton">Click Me</button>
    <script>
        const button = document.getElementById("myButton");

        button.addEventListener("click", (event) => {
            console.log("Event Type:", event.type); // 클릭 이벤트 타입
            console.log("Target Element:", event.target); // 이벤트 발생한 요소
            console.log(event)
        });
    </script>
</body>


이벤트 버블링과 캡처링
  • 이벤트는 DOM 트리 구조를 따라 위로 전파(버블링)되거나 아래로 전파(캡처링)
  • 이벤트 버블링
    • 이벤트가 가장 안쪽 요소에서 발생한 후, DOM 트리를 따라 상위 요소로 전파
    • 기본 동작 방식버블링
  • 이벤트 캡처링
    • 이벤트가 최상위 요소에서 시작하여, DOM 트리를 따라 안쪽 요소로 전파
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Event Bubbling & Capturing</title>
    <style>
        div {
            padding: 20px;
            margin: 10px;
            border: 1px solid black;
        }
    </style>
</head>
<body>
    <div id="outerDiv">
        Outer Div
        <div id="innerDiv">
            Inner Div
        </div>
    </div>

    <script>
        const outerDiv = document.getElementById("outerDiv");
        const innerDiv = document.getElementById("innerDiv");

        // 버블링 방식 (기본)
        outerDiv.addEventListener("click", () => {
            alert("Outer Div clicked (Bubbling)");
        });

        innerDiv.addEventListener("click", () => {
            alert("Inner Div clicked (Bubbling)");
        });

        // 캡처링 방식
        outerDiv.addEventListener(
            "click",
            () => {
                alert("Outer Div clicked (Capturing)");
            },
            true // 캡처링 모드 활성화
        );
    </script>
</body>
</html>

 

  • 기본 동작 : 버블링
    • Inner Div를 클릭하면 Inner Div 핸들러가 먼저 실행되고, 이후 Outer Div 핸들러가 실행
  • 캡처링 활성화
    • true로 설정된 핸들러는 캡처링 단계에서 실행
    • 클릭 시 Outer Div 캡처링 핸들러가 가장 먼저 실행

 

  • Inner Div 클릭 : Outer Div(Capturing) - Inner Div (Bubbling) - Outer Div (Bubbling)
  • Outer Div 클릭 : Outer Div(Capturing) - Outer Div(Bubbling
이벤트 전파 중지
  • 이벤트가 상위 요소로 전파되는 것을 막고 싶을 때 event.stopPropagation()을 사용
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Stop Propagation</title>
    <style>
        div {
            padding: 20px;
            margin: 10px;
            border: 1px solid black;
        }
    </style>
</head>
<body>
    <div id="outerDiv">
        Outer Div
        <div id="innerDiv">
            Inner Div
        </div>
    </div>

    <script>
        const outerDiv = document.getElementById("outerDiv");
        const innerDiv = document.getElementById("innerDiv");

        outerDiv.addEventListener("click", () => {
            alert("Outer Div clicked");
        });

        innerDiv.addEventListener("click", (event) => {
            alert("Inner Div clicked");
            event.stopPropagation(); // 이벤트 전파 중지
        });
    </script>
</body>
</html>
  • Inner Div clicked 실행 후 종료(Outer Div clicked 실행 X)