DOM

DOM (Document Object Model)

DOM[1]은 HTML을 프로그래머의 관점으로 바라본 것이다. 웹 페이지는 일종의 문서이고, 이 문서는 웹 브라우저를 통해 문서가 해석되어 웹 브라우저 화면에 나타나거나, HTML 소스 자체로 나타난다.

동일한 문서를 사용하여 다양한 형태로 표현할 수 있다는 점에서 DOM은 동일한 문서를 표현, 저장, 그리고 조작하는 방법을 제공한다. DOM은 웹 페이지의 객체 지향 표현이며, 자바스크립트를 통해 DOM을 수정할 수 있다.

DOM은 프로그래밍 언어는 아니다. 하지만, DOM이 없다면 자바스크립트는 웹 페이지의 여러 요소들(html 문서, header, table, text)과 관련된 정보를 갖지 못한다.

위 요소들은 웹 문서를 위한 Document Object Model의 한 부분이며, 즉 이러한 요소들을 DOM과 자바스크립트와 같은 언어를 통해 접근하고 조작할 수 있다.

dom
Fig 1. 2017년 독일로 놀러갔을 때 찍었던 베를린 돔(Berliner Dom)

거대한 구조물인 돔이 있고, 그 돔을 겨울엔 따뜻하게, 여름엔 시원하게, 낡은 창문은 수리하고, 청소를 해가며 단순한 건물이 마치 살아 움직이는 것(?) 처럼 유지하기 위하여…

베를린 돔을 구성하는 요소들(대문, 동상, 창문, 큰방, 작은방…) 등이 DOM 구조가 되고, 망치, 빗자루, CCTV, 에어컨 등 도구들이 자바스크립트가 될 수 있을 것 같다…

HTML에 자바스크립트를 적용하기 위해 <script> 태그를 이용한다.

<script> 태그를 추가하는 두가지 방법이 있다.

  1. head 안쪽에 삽입
  2. body 태그가 끝나기 전에 삽입

<head> 안쪽에 삽입하는 경우

<!DOCTYPE html>
<html>
  <head>
    <meta charset="UTF-8" />
    <title>Document</title>
    <!-- script 요소 삽입 위치 -->
    <script src="script.js"></script>
  </head>
  <body>
    <div>Hello JavaScript!</div>
  </body>
</html>

<body> 태그가 끝나기 전에 삽입하는 경우

<!DOCTYPE html>
<html>
  <head>
    <meta charset="UTF-8" />
    <title>Document</title>
  </head>
  <body>
    <div>Hello JavaScript!</div>
    <!-- script 요소 삽입 위치 -->
    <script src="script.js"></script>
  </body>
</html>

브라우저는 HTML의 구조와 CSS를 렌더링하는 중 <script> 태그를 만나면 이에 대한 해석과 구현이 완료될 때 까지 렌더링을 멈춘다.

<head>에 무거운 스크립트가 삽입되어 실행될 경우, 렌더링에 방해가 되어 오랫동안 완성되지 못한 화면을 노출하게 된다. 즉, 로딩 시간이 길어진다.

집이 아직 지어지지도 않았는데, 침대, 책상, 컴퓨터, 에어컨, 청소 도구 등을 먼저 가져간 느낌이다…

그래서 <head>에 삽입되는 스크립트는 HTML을 재설정하는 가벼운 스크립트들이 자주 사용된다.

<body>에 삽입될 경우, 브라우저의 렌더링이 완료된 상태에서 스크립트가 실행된다. 웹 페이지의 콘텐츠를 변경하는 스크립트의 경우, 화면에 노출된 채로 변화된다.

대부분의 스크립트 태그의 위치로 추천되는 위치이며, 문서의 DOM 구성이 완료된 시점에 실행되므로 별다른 추가 설정이 필요하지 않다.

CRUD

Document 객체에는 여러가지 속성과 다양한 메소드가 존재한다. 이 기술들을 내 손발처럼 자유자재로 사용하기 위해, CRUD(Create, Read, Update and Delete)를 알아야 한다.

  • Create : document 객체를 이용해 HTML 요소를 만든다.
  • Read : document 객체를 이용해 HTML 요소를 조회한다.
  • Update : document 객체를 이용해 HTML 요소를 갱신한다.
  • Delete : document 객체를 이용해 HTML 요소를 삭제한다.

Create

document 객체의 createElement 메소드를 이용하면 HTML 요소를 생성할 수 있다.

const myDiv = document.createElement('div');
myDiv.textContent = 'Hello Velog!';
// <div></div> 빈 div에 텍스트를 추가하는 textContent 메소드

div태그를 만들고 그 안에 내용을 추가했는데, 아무것도 보이지 않는다.
myDiv라는 div요소는 브라우저 렌더링 영역에 포함되어있지 않기 때문이다.

이 붕 떠있는 myDiv요소를 웹 브라우저에 표현하기 위해선 Append를 사용해야 한다. Append는 지정한 요소의 자식 요소로 붙이는 메소드이다.

const myDiv = document.createElement('div');
myDiv.textContent = 'Hello Velog!';
document.body.appendChild(myDiv);

부모 요소인 <body></body> 안에 방금 만든 myDiv를 자식 요소로 붙이기 위해 appendChild 메소드를 사용하면 웹 브라우저에 표현할 수 있다.

Read

DOM으로 HTML 엘리먼트의 정보를 조회하기 위해 querySelector를 이용할 수 있다.
입력인자에 클래스 이름(".class"), ID("#id"), 또는 태그("div") 등을 전달하는 것으로 HTML 요소의 정보를 읽을 수 있다.

const getEl = document.querySelectorAll('.className');
// class 이름이 classname인 모든 HTML 요소를 유사 배열로 받아옵니다.

querySelectorquerySelectorAll의 차이는 전자는 입력인자에 일치하는 최상단 요소 하나만 받아온다.

후자는 입력인자와 같은 요소들을 전부 받아온다.

독립적인 의미를 가진 ID의 경우, querySelector('#id')를 사용하고, 여러개가 존재할 수 있는 class는 querySelectorAll('.class')를 사용하면 될 것 같다.

Update

기존에 생성하고, 부모 요소에 추가한 DOM 객체를 업데이트하여 다양한 작업을 수행할 수 있다.

textContent를 이용해 DOM 객체의 value를 추가 및 수정할 수 있다.

또한, 생성한 DOM 객체는 현재 id, class가 지정되어있지 않다. 이 경우, CSS 스타일링이 적용되지 않는다. CSS 스타일링을 적용하기 위해 div 엘리먼트에 class를 추가할 수 있다.

const myDiv = document.createElement('div');
myDiv.textContent = 'Hello Velog!';
myDiv.classList.add('myDiv');
document.body.appendChild(myDiv);
console.log(myDiv);
// <div class="myDiv">Hello Velog!</div>

Delete

요소를 삭제하는 방법은 여러가지가 있다. 삭제하고자 하는 요소의 위치를 알 경우, remove를 사용해 요소를 삭제할 수 있다.

myDiv.remove();

여러 개의 요소를 지우기 위해, 반복문을 사용할 수 있다. 어떤 부모 요소의 모든 자식 요소를 지우고자 한다면 다음과 같이 표현할 수 있다.

const myUl = document.createElement('ul');
const myLi = document.createElement('li');
document.body.append(myUl);
myUl.append(myLi);

// document.body의 첫번째 자식요소가 존재할 때, 반복문이 실행됩니다.
// 반복이 실행될 때, document.body의 첫번째 자식요소를 삭제합니다.
while (document.body.firstChild) {
  document.body.removeChild(document.body.firstChild);
}

반복문의 조건을 달리한다면 원하는 요소만 삭제할 수 있다.

Event

모든 웹 사이트는 각각의 기능을 하는 요소들이 있고, 그 요소들을 시각적으로 표현하는 이미지나 버튼이 있다. 이미지나 버튼을 클릭하거나, 드래그 하는 등, 사용자의 입력에 따라 발생하는 이벤트들이 있다.

사용자가 요소에 어떤 이벤트를 발생시켰을 때, 이벤트의 결과를 반환하는 이벤트 핸들러를 요소에 적용해야 한다.

어떤 버튼을 클릭했을 때 발생하는 이벤트 핸들러를 작성할 경우,

onClick 또는 addEventListener를 사용한다.

const btn = document.querySelectorAll('button');
btn.onclick(function)
or
btn.addEventListner('click',function)

( ) 안에는 이벤트 핸들러 함수가 들어간다. 여기서 주의할 점은 함수 자체(function)를 할당해야한다는 것이다. 함수의 결과값(function())을 할당하게 되면 버튼을 클릭했을 때 단 한 번만 이벤트가 실행된다.

우리가 원하는 건 클릭했을 때마다 해당 함수가 실행되어야 하기 때문에, 함수 자체를 할당해야 한다.

위처럼 반복문을 이용해 동일한 className을 가진 button요소를 가져왔고, 여러 개의 class가 존재할 경우 유사 배열로 가져오기 때문에, 반복문을 활용해 .btn 클래스에 각각 이벤트 핸들러를 적용했다.

버튼을 클릭하면 버튼의 textContent을 알림 창에 띄우는 이벤트 함수를 작성하여 이벤트 핸들러에 할당했다.

클릭했을 때의 이벤트 외에도, 이벤트 객체는 다양하다.

Notes

[1]문서 객체 모델(The Document Object Model, 이하 DOM)은 HTML, XML 문서의 프로그래밍 interface 이다.

Reference

YUNSU BAE

YUNSU BAE

주니어 웹 개발자 배윤수 입니다!

예술의 영역을 동경하고 있어요. 🧑‍🎨