JavaScript

[JavaScript] #18 - DOM (Document Object Model)

yoonddo 2023. 1. 25. 14:35

문서 객체 모델 (DOM)

문서 객체 모델 (Document Object Model, DOM)은 말그대로 웹 페이지 내의 모든 콘텐츠를 객체로

나타내 주는 것이다. 그래서 간단하게 생각하면 웹 페이지를 document라고 부르고 document를

자유롭게 다루기 위해서 객체화하고자 구현된 개념이 DOM이라고 생각할 수 있다.

그리고 HTML 태그와 글자, 속성 등 document의 담겨있는 모든 요소들을 하나하나를 객체화 한 단위를 가리켜

노드(Node)라고 부른다.

 

결국 DOM은 웹 페이지를 객체화 한 개념이고, 이 웹페이지의 가장 상단 진입점이 바로 document 객체이다.

document 객체는 전역 객체인 window 객체의 바로 아래에 있는데 window 객체는 앞에  window를 생략해도

되기 때문에 일반적으로는 document에 바로 접근해서 메서드나 프로퍼티들을 활용한다.

window.document
document // window는 생략 가능

Document 객체

window 객체가 브라우저 창을 대변하는 것이라면 document 객체는 브라우저 내에서 컨텐츠를 보여주는웹 페이지 자체를 대변한다고 할 수 있다. 간단하게 웹페이지가 document, 이를 객체화 한 것을 document객체라고 생각할 수도 있다.


Document 객체의 프로퍼티

document 객체를 활용하면 웹페이지의 상태와 모든 HTML 태그들에 접근할 수 있는데, 가장 간단하게프로퍼티 네임에 태그 이름을 입력하ㅏ면 해당 태그에 접근이 가능하다.

document.documentElement // <html> 태그 반환
document.head // <head> 태그 반환
document.title // <title> 태그 반환
document.body // <body> 태그 반환
document.links // href 속성이 있는 <a> 태그 반환
document.images // <img> 태그 반환
document.forms // <form> 태그 반환
document.scripts // <script> 태그 반환

 

웹페이지의 정보를 담은 프로퍼티들도 있다.

document.doctype // 웹 페이지의 문서 형식을 반환
document.readyState // 웹 페이지의 로딩 상태를 반환
document.documentURI //  웹 페이지의 URI를 반환
document.baseURI // 웹 페이지의 절대 URI를 반환
document.URL // 웹 페이지의 완전한 URL 주소를 반환
document.referrer // 링크(linking)되어 있는 문서의 URI를 반환
document.domain // 웹 페이지가 위치한 서버의 도메인을 반환
document.cookie // 웹 페이지의 쿠키를 반환
document.lastModified // 웹 페이지의 마지막 갱신 날짜 및 시간을 반환
document.inputEncoding // 웹 페이지의 문서 인코딩 형식을 반환

HTML태그 (

드들을 사용하면 다양한 방법으로 웹 페이지 내의 태그들에 접근할 수 있다.

// 파라미터로 전달한 태그이름을 가진 모든 태그들을 반환(배열)
document.getElementsByTagName(태그이름)

// 파라미터로 전달한 ID를 가진 태그를 반환
document.getElementById(아이디)

// 파라미터로 전달한 클래스 이름을 가진 모든 태그들을 반환(배열)
document.getElementsByClassName(클래스이름)

// 파라미터로 전달한 name 속성을 가진 태그를 반환
document.getElementByName(name속성값)

// 파라미터로 전달한 선택자에 맞는 첫 번째 태그를 반환
document.querySelector(선택자)

// 파라미터로 전달한 선택자에 맞는 모든 태그들을 반환(배열)
document.querySelectorAll(선택자)

노드 생성하기

 

1. HTMLtag 노드 생성하기 (createElement 메서드)

// document.createElement(tagName);
const divElement = document.createElement('div');

document 문서의 createElement(tagName) 메서드를 활용하면 태그 노드를 생성할 수 있다.

 

2. Text 노드 생성하기 (createTextNode 메서드)

// document.createTextNode(text)
const textNode = document.createTextNode('Hello');

document문서의 createTextNode(text) 메소드를 활용하면, 메서드의 이름과 같이 text 노드를 생성할 수 있다.

text노드라고 하면, 말그대로 문자를 말한다.

 

예를 들어서 아래와 같은 HTML 태그가 있다면, 

<div>
  Hello
</div>

div태그는 태그 노드, Hello는 Text노드에 해당된다.


노드 다루기 (삽입, 삭제)

 

1. 노드 삽입하기 (appendChild 메서드)

[추가할 노드의 부모노드].appendChild([추가할 노드])

위와 같은 모양으로 appendChild메서드를 사용하면 노드 안에 노드를 삽입할 수 있다.

단, 메서드 이름에서도 알 수 있듯, 자식 노드로 삽입이 되기 때문에 추가할 노드의 부모 노드에 먼저 접근해야 한다.

let newH1 = document.createElement('h1');
let newTitle = document.createTextNode('Hi!?');

newH1.appendChild(newTitle);

위의 코드를 살펴보면, 일단 <h1>이라는 태그를 만들었고 그 안에 'Hi!?'라는 문자를 삽입해 준 코드다.

그래서 지금 newH1 변수에는 

<h1>Hi!?</h1>

위와 같은 노드가 담겨 있는 것이라고 볼 수 있다.

 

자, 그런데 아직 이 노드는 바로 웹페이지에 반영되는 것이 아니라, 가상의 공간에 생성되기만 한 것이다.

그래서 이미 존재하는 노드에 접근해서 생성한 노드를 한 번 더 삽입해 주어야 웹페이지에 반영되는 것이다.

 

만약 아래와 같은 HTML 코드가 있다고 가정해보자.

<div id="container">
  <h1 id="title">Hello</h1>
</div>

이렇게 작성되어있는 상황에서

let container = document.getElementById('container');

let newH1 = document.createElement('h1');
let newTitle = document.createTextNode('Hi!?');

newH1.appendChild(newTitle);
container.appendChild(newH1);

위와 같이 코드를 작성하면,

<div id="container">
  <h1 id="title">Hello</h1>
  <h1>Hi!?</h1>
</div>

이런 결과로 이어진다.

이렇게 appendChild를 이용해 노드를 삽입하면, 접근한 노드의 가장 마지막에 새로운 노드가 추가되는 방식이다.


2. 노드 삭제하기 (removeChild 메서드)

위 코드에 이어서 노드를 삭제하려면, removeChild 메서드를 사용하면 된다.

[삭제할 노드의 부모노드].removeChild(삭제할 노드)

이 메서드도 마찬가지로 먼저 부모 노드에 접근해서 자식 노드를 삭제해야 한다.

앞선 코드에서 title이라는 id를 가진 h1태그를 삭제하려면 다음과 같이 작성하면 된다.

let container = document.getElementById('container');

let newH1 = document.createElement('h1');
let newTitle = document.createTextNode('Hi!?');

newH1.appendChild(newTitle);
container.appendChild(newH1);

let oldTitle = document.getElementById('title');
container.removeChild(oldTitle);

이렇게 하면, 아래와 같이 title이라는 id를 가진 h1 태그는 사라지게 된다.

<div id="container">
  <h1>Hi!?</h1>
</div>

이렇게 삭제와 삽입을 잘 활용하면 태그의 내용을 자유롭게 수정할 수가 있다.


하지만, 초 간단 마법 innerHTML!

하지만, 뭔가 createElement, createTextNode, appendChild, removeChild.. 뭔가 간단한 DOM을 수정하려고 해도 너무 많은 코드가 필요하고 심지어 복잡하기도 하다.

사실 노드에는 innerHTML이라는 파라미터가 존재하는데 말 그대로 해당 노드의 내부 HTML을 그대로 보여주는 것이다.

그래서 이 파라미터를 할당 연산자를 통해 새로운 HTML 태그 값을 문자열로 할당하면 앞에서 열심히 태그를 수정한 것

보다 훨씬 더 간단하게 노드를 수정할 수가 있다.

한 가지 주의해야 될 부분은 당연히 파라미터 값을 재할당하는 것이기 때문에 HTML 코드를 추가하는 개념이 아니라, 

대체해버린다는 점이다. 앞에서 열심히 작성한 코드를 innerHTML로 바꿔보면

<div id="container">
  <h1 id="title">Hello</h1>
</div>

이런 HTML 코드가 있을 때,

let container = document.getElementById('container');

container.innerHTML = '<h1>Hi!?</h1>';

이렇게만 해주면

<div id="container">
  <h1>Hi!?</h1>
</div>

바로 이렇게 수정이 된다.

정말 간단하고 간편하게 노드를 수정할 수 있지만 실제 서비스에 이런 로직을 구현하게 되면 보안 이슈가 생길 수 있는

치명적인 단점이 있다.

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

자료 출처 : https://bigtop.tistory.com/49https://bigtop.tistory.com/50