Notice
Recent Posts
Recent Comments
Link
«   2024/12   »
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
Archives
Today
Total
관리 메뉴

heyday2024 님의 블로그

[JS 문법 5주차] DOM, DOM_API 본문

프론트엔드 부트캠프

[JS 문법 5주차] DOM, DOM_API

heyday2024 2024. 10. 24. 22:28

DOM (Document Object Model)

JS가 생긴 이유: 브라우저에서 동작하게하기 위한 언어로, HTML를 해석해서 웹  페이지를 동적으로 만들기 위해

(Netscape에서 당시 인기많던 자바의 이름을 따서 만들었음)

 

<웹 페이지가 뜨는 과정>

1. 사용자(클라이언트, 브라우저)가 서버에게 요청(request) 함

(ex) 크롬을 통해 클라이언트의 역할함

 

2. 서버로부터 오는 응답 형태가 HTML 문서(document)임. 

 

3. 브라우저가 HTML 파일을 해석함(parsing 파싱)

=====> 브라우저에는 기본적으로 렌더링 엔진이 있음. 서버가 클라이언트에게 준 HTML문서를 렌더링(html를 해석/번역해서 화면에 그려주는 것)함.

  • 렌더링 엔진이 HTML문서에 코드를 한줄, 한줄 보면서 해석함. 
    • 서버로부터 받아 온 그 문서를 javascript는 이해할 수 없기 때문에 javascript가 알아들을 수 있는 방법으로 ‘해석’하는 과정이 필요

4. JS가 알아들을 수 있는 방식으로 해석한 내용을 토대로 DOM TREE 를 구성함. 

출처 : 짐코딩의 CODING GYM

5. DOM Tree랑 CSSOM Tree를 묶어서 Render Tree를 구성함

  • 렌더 트리(Render Tree)는 HTML, CSS 및 JavaScript 문서를 파싱하여 브라우저에서 실제로 렌더링되는 최종 문서 모델을 나타내는 객체의 계층 구조임. 결국은, 브라우저 화면에 그리기 위한 최종 버전을 만들어낸다는 것. 그리고 나서 브라우저에 그림을 그리기 위한 레이아웃을 계산한 후 페인팅 과정이 시작됨.

DOM 트리 (DOM Tree)

  • DOM(Document Object Model) 트리는 HTML 문서를 브라우저가 파싱하면서 생성한 트리 구조. HTML의 각 태그가 DOM 트리의 하나의 노드(node)로 표현되며, 이 트리는 웹 페이지의 구조와 콘텐츠를 나타냄.
  • HTML 문서의 요소들(예: <div>, <p>, <h1>)을 노드로 변환하여 구조적으로 표현하며, 스크립트(Javascript)에서 이 요소들을 제어할 수 있게 해줌.
  • DOM 트리에는 HTML 요소들뿐만 아니라 텍스트, 속성 등도 포함됩니다. 예를 들어, <div class="box">Hello</div>에서 div는 하나의 요소 노드, class="box"는 속성 노드, Hello는 텍스트 노드.

CSSOM 트리 (CSSOM Tree)

  •  CSSOM(CSS Object Model) 트리는 브라우저가 CSS 스타일시트를 파싱한 결과로 생성된 트리 구조. CSS 규칙들이 어떻게 각 HTML 요소에 적용되는지를 나타내며, 이 규칙들을 브라우저가 이해할 수 있는 형태로 변환한 것입니다.
  • CSS 스타일 정보(예: 색상, 크기, 여백 등)를 DOM 트리의 각 노드에 적용하기 위해 사용됨. CSSOM 트리는 DOM 트리와 결합되어 렌더 트리를 생성하며, 최종적으로 화면에 표시할 요소들을 결정.
  •  CSSOM 트리의 각 노드는 CSS 선택자와 그 선택자에 적용된 스타일을 나타냄. 예를 들어, div.box { color: red; }는 .box라는 클래스에 적용된 스타일을 CSSOM 트리에 반영.

<브라우저 렌더링 동작 과정>

1. HTML 파일과 CSS 파일을 파싱해서 각각 Tree를 만든다. (Parsing)

  • DOM, CSSOM(CSS Object Model)

출처: https://tecoble.techcourse.co.kr/post/2021-10-24-browser-rendering/

 

2. 두 Tree를 결합하여 Rendering Tree를 만든다. (Style)

  • DOM Tree와 CSSOM Tree를 매칭시켜서 Render Tree를 구성
  • 예를 들면 Render Tree를 구성할때 visibility: hidden은 요소가 공간을 차지하고, 보이지만 않기 때문에 Render Tree에 포함이 되지만, display: none 의 경우 Render Tree에서 제외됨.
  • 출처: https://tecoble.techcourse.co.kr/static/812332bcab15fdc8d05543579dad9f5c/919e0/2021-10-24-browser-rendering-2.png

3. Rendering Tree에서 각 노드의 위치와 크기를 계산한다. (Layout)

  • Render Tree를 화면에 어떻게 배치해야 할 것인지 노드의 정확한 위치와 크기를 계산
  • 루트부터 노드를 순회하면서 노드의 정확한 크기와 위치를 계산하고 Render Tree에 반영
  • 만약 크기 값을 %로 지정하였다면, Layout 단계에서 % 값을 계산해서 픽셀 단위로 변환

4. 계산된 값을 이용해 각 노드를 화면상의 실제 픽셀로 변환하고, 레이어를 만든다. (Paint)

  • Layout 단계에서 계산된 값을 이용해 Render Tree의 각 노드를 화면상의 실제 픽셀로 변환
  • . 이때 픽셀로 변환된 결과는 하나의 레이어가 아니라 여러 개의 레이어로 관리됨
  •  스타일이 복잡할수록 Paint 시간도 늘어난다

5. 레이어를 합성하여 실제 화면에 나타낸다. (Composite)

  • Paint 단계에서 생성된 레이어를 합성하여 실제 화면에 나타낸다.

 

DOM

- Document(HTML 파일)를 Javascript가 알아먹을 수 있는 Object 형태로 Modeling한 것

- 그리고 브라우저에 기본적으로 내장되어 있는 API 중 하나이기도 함.

 

💡 API란? 

어떤 시스템에서 데이터나 서비스를 요청할 때, 해당 시스템과 사용자간의 인터페이스 역할을 하는 것. 

(카페에서 고객이 음료를 시키고자할 때 사용하는 메뉴판 같은 것: 고객과 카페 사이의 인터페이스)

예를 들어 날씨 앱에서 사용지가 현재 위치의 날씨를 확인하려고하면, 앱은 해당 기능을 제공하는 날씨 서비스의 API를 호출하여 날씨 정보를 받아옴.

 

---> 즉,  API는 다른 시스템에서 제공하는 기능을 사용할 수 있도록 도와주는 중간자 역할을 함.

----> 브라우저의 경우, 기본적으로 DOM과 관련된 API를 제공해서 브라우저의 DOM객체에 접근할 수 있도록 도와줌. 예를 들어, 버튼을 클릭했을 때 이벤트가 일어나거나 마우스 호버와 같은 동작들은 DOM요소를 제어하는 기능들이라고 볼 수 있는데, 이는 DOM이 사용자가 그렇게 DOM을 제어할 수 있도록 허락했기 때문에 할 수 있는 것. 결국 DOM이 자기자신을 컨트롤 할 수 있게 사용자에게 API(메뉴판처럼)을 준 것과 다름없음. 

 


DOM은 그렇다면 브라우저가 아닌 환경에서도 돌아갈 수 있을까?

 

Reference Error가 났다.

 

지금까지 사용한 자바스크립트의 런타임 (프로그래밍 언어가 구동되는 환경)은 두가지가 있음

1. chrome browser 개발자 도구 (브라우저)

2. VSCode (node.js 환경)

 

---> DOM은 항상 브라우저 환경에서만 돌아간다는 것을 꼭 기억해야함!!!

 

결국, DOM은 브라우저에 내장되어 있기 때문에 HTML의 내용을 Javascript로  접근 하고 제어 할 수 있음!!!

 

 


모든 DOM의 node들은 속성과 메서드 를 가지고 있음

💡 DOM의 node?

DOM에서 Node란 웹 페이지를 구성하는 모든 HTML 태그와 텍스트, 그리고 속성 등을 하나의 블록으로 취급하는 것!

이러한 블록들은 서로 계층 구조로 연결되어 있으며, 각 블록은 자식 노드, 부모 노드, 형제 노드와 관계를 가짐.

이러한 관계를 이용하여 DOM 트리를 탐색하고 조작할 수 있음.

 

DOM 요소 하나 하나가(네모, 동그라미) 노드. 그리고 각 노드는 속성(특성)과 메서드(요소를 제어할 수 있는 것) 가짐.

 

 

💡 DOM 요소의 속성과 메서드 구분:

DOM의 Node 객체에서 속성과 메서드를 구분하는 가장 쉬운 방법은 Node 객체의 속성은 값을 가지고 있는 반면, 메서드는 동작을 수행한다는 것.

즉, Node 객체의 속성은 해당 객체의 특성을 나타내는 값을 가져오거나 설정하는 데 사용되며, 메서드는 해당 객체가 수행하는 작업을 나타내는 함수.

예를 들어, Node 객체의 nodeName 속성은 해당 노드의 이름을 나타내는 문자열 값을 반환. 반면에 appendChild() 메서드는 해당 노드의 자식 노드를 추가하는 메서드이며, DOM 트리에서 해당 노드의 위치를 변경하는 동작을 수행

 

* 속성 VS 메서드

document.getElementById("demo").innerHTML = "Hello World!";
//동사로 시작하는 건 주로 메서드임 
//getElementById(): 아이디를 가져와라 ----> 메서드
//innerHTML : 값을 갖음 ----> 속성

 

* 메서드 VS 함수

// example1(메서드의 예)
person.getName();

// example2(함수의 예)
testLogging();

 


DOM에 접근 및 제어해보기

1. 항상 돔트리의 최상단 노드 === document

//getRootNode()는 최상위 루트 노드를 반환하는 메서드.
document.getRootNode(); //document

 

2. childNodes, parentNode를 이용해서 트리 구조 내에서 이동가능

- DOM은 모두 노드로 이루어져 있기 때문에 부모노드 - 자식노드 관계 로 이루어짐.

 

3. document 관련 api

(1) Finding

/** 찾아봅시다 */

// 해당 id명을 가진 요소 하나를 반환합니다.
document.getElementById("id명")

// 해당 선택자를 만족하는 요소 하나를 반환합니다.
document.querySelector("선택자")

// 해당 class명을 가진 요소들을 배열에 담아 인덱스에 맞는 요소를 반환합니다.
document.getElementsByClassName("class명")[인덱스]

// 해당 태그명을 가진 요소들을 배열에 담아 인덱스에 맞는 요소를 반환합니다.
document.getElementsByTagName("태그명")[인덱스]

// 해당 선택자를 만족하는 모든 요소들을 배열에 인덱스에 맞는 요소를 반환합니다.
document.querySelectorAll("선택자명")[인덱스]

// 새로운 노드를 생성합니다.
const div = document.createElement('div');
document.body.append(div);
document.body.append(div);

 

(2) changing

/** property(=속성)을 바로 바꿔버려잇! */

// 이 둘은 차이가 있어요!
element.innerHTML = new html content
element.innerText = new text

//innerHTML은 태그와 텍스트 모두 포함하여 콘텐츠를 설정하거나 반환함.
//새 HTML 태그를 추가하거나 기존 HTML 구조를 변경할 때 사용
//예를 들어 element.innerHTML = "<b>Hello</b>"를 사용하면, element의 콘텐츠는 굵은 텍스트로 표시됨
//보안 문제(예: XSS)가 발생가능


//innerText는 순수 텍스트만 설정하며 HTML 태그는 무시
//텍스트 내용을 설정하거나 반환할 때 HTML을 무시하고 태그 없이 일반 텍스트로 처리
//예를 들어 element.innerText = "<b>Hello</b>"를 사용하면 태그 없이 그대로 "<b>Hello</b>"로 표시




// style을 바꿔요.
element.style.property = new style

//method를 통해 클래스를 추가해봐요.
element.setAttribute(attribute, value)

// 어랏? 그럼 이런것도 가능??
element.setAttribute("style", "background-color:red;");

// ....
element.style.backgroundColor = "red";

// input 필드의 변신

 

// createElements
const para = document.createElement("p");
para.innerText = "This is a paragraph";
document.body.appendChild(para);

// createTextNode(elements는 아니구여, 그냥 글자...)
let textNode = document.createTextNode("Hello World");
document.body.appendChild(textNode);

// write. 조심 또 조심!
document.write("Hello World!");

document.write("<h2>Hello World!</h2><p>Have a nice day!</p>");

// 골로 가는 코드
function myFunction() {
  document.write("Hello World!");
}

// version 01
element.addEventListener("click", myFunction);
function myFunction() {
  document.getElementById("demo").innerHTML = "Hello World";
}

// version 02
element.addEventListener("click", function() {
  document.getElementById("demo").innerHTML = "Hello World";
});
  • document.createElement("p"): 새로운 HTML 요소를 생성합니다. 예제에서는 <p> 태그를 생성하고, innerText로 텍스트를 추가한 후, appendChild를 사용하여 이 요소를 body에 추가합니다.
  • document.createTextNode("Hello World"): HTML 요소가 아닌 순수 텍스트 노드를 생성합니다. 생성된 텍스트는 <p>나 <div> 같은 HTML 요소가 아닌 텍스트 자체로 body에 추가됩니다.
  • document.write: 브라우저가 HTML 문서를 렌더링할 때 HTML을 바로 삽입하여 출력하는 방식입니다.
    • HTML 문서가 이미 완전히 로드된 상태에서 document.write를 호출하면 현재 페이지의 모든 내용이 지워지고 새로 작성되므로, 사용 시 매우 주의해야 합니다. 특히, 이벤트 핸들러에서 호출하면 예상치 못한 페이지 소멸 문제가 발생할 수 있습니다.

 

<요소에 접근>

 

이런 html 파일을 브라우저 상에 rendering하면,

 

이렇게 DOM 트리 구조가 만들어지고, 선택자(id, class...)로 요소에 접근 가능하다. childeren과 parentNode를 사용해서 얼마든지 트리구조 안에서 상위, 하위 요소들에 쉽게 접근이 가능하다.
li 태그는 하나가 아니라 여러개이기 때문에 getElementByTagName을 사용하면 error가 생기고, getElementByTagName을 사용해야한다. 이처럼 세심하게 DOM객체는 API를 제공해주고 있다.

 

 

<요소 제어>

이런 식으로 JS를 사용해서 얼마든지 DOM 요소를 제어할 수 있음.