DOM

도현수·2022년 7월 20일
0

javascript

목록 보기
12/20
post-thumbnail

DOM(Document Object Model)은 HTML의 요소들의 계층적 구조와 정보를 표현하며 요소들을 객체(Objcet)처럼 조작할 수 있는 모델이다. 웹 개발자들이 HTML을 아주 작은 단위까지 접근할 수 있도록 구조를 만들었고, 이렇게 만들어진 구조가 바로 DOM이다. DOM을 이용하면 한 번 작성되면 수정할 때 까지 고정되는, 다시 말해 HTML의 한계인 '정적'이라는 특징을 뛰어넘어 웹 페이지를 동적으로 움직일 수 있게 만든다.

노드란 무엇인가?

사실 DOM을 공부하면서 가장 어려움을 겪었던 부분이었다.

HTML요소는 렌더링 엔진에 의해 파싱되어 DOM을 구성하는 노드 객체로 변환된다.

이 뭔...노드가 뭔데?
노드란 HTML에 대한 모든 것을 담고있는 계층적 정보 단위를 의미한다. HTML DOM은 노드라고 불리는 계층적 단위에 정보를 저장하고 있다. HTML DOM은 이러한 노드들을 정의하고, 그들 사이의 관계를 설명해준다. HTML의 정보는 노드 트리라고 불리는 계층적 구조에 저장되며 각각의 노드들의 관계를 보여준다. 그리고 자바스크립트에서는 DOM을 이용해 이 노드에 접근할 수 있다.

노드 트리

노드 트리는 노드들의 계층 구조로 이뤄진다. 이 트리구조는 단 하나의 최상위 노드에서 시작하는데 이를 루트 노드라 한다. 루트 노드는 부모 노드가 없으며 0개 이상의 자식 노드를 가진다. 반대로 자식이 없는 노드는 리프 노드라 한다.

다시한번 강조하자면, 이렇게 노드 객체들로 구성된 트리 자료구조를 DOM이라고 한다. 노드 트리로 구조화 되어서 DOM을 DOM 트리라고 부르기도 한다.

노드에서 중요한 4가지 타입은 다음과 같다.

1.문서 노드

 트리의 가장 취에 존재하는 루트 노드로서 문서 전체, 즉, document를 가리킨다. 문서 노드는 HTML문서 전체를 가리키는 객체이기 때문에 전역 객체의 document프로퍼티에 바인딩 되어 있다. 따라서 문서 노드는 document나 window.document로 참조할 수 있다.
 또한, 문서당 document 객체는 유일하기 때문에, 자바 스크립트 코드들이 script태그 여러개로 분리되어 있더라도 단 하나의 document 객체를 바라본다.
문서노드는 DOM의 루트 노드 이므로 다른 노드들(텍스트, 요소, 어트리뷰트)에 접근하려면 문서노드를 무조건 거쳐야 한다.

2.요소 노드

  HTML의 요소들을 가리키는 객체이다. HTML요소의 중첩 관계(div태그의 자식요소로 들어간 div태그 등)에 따라 부자관계를 가지며, 이 관계를 통해 정보를 구조화한다. 따라서 사실상 문서의 구조는 요소 노드를 통해 표현된다고 할 수 있다.

3.어트리뷰트 노드

  요소의 속성을 가리키는 객체이다. 속성이 지정된 요소 노드와 연결되어있는데, 공통인 부모 노드가 없으므로 요소 노드와 형제 노드라고 볼 수 없다. 하지만 어트리뷰트 노드에 접근하려면 반드시 해당 요소 노드에 접근해야 한다.

4.텍스트 노드

  HTML의 텍스트를 가리키는 개체이다. 문서의 정보를 표현하며, 리프 노드이다. 즉, 노드 트리의 최종단이라 할 수 있으며 때문에 텍스트 노드에 접근하려면 부모인 요소 노드에 먼저 접근해야 한다.

script 태그

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

<script src="script.js"></script>

위의 경우에는 script.js를 불러온다.
주의해야 할 점은, script 태그는 등장과 함께 실행된다는 점이다. 브라우저가 html을 파싱하다 script를 만나면 잠시 html의 파싱을 멈추고 script를 실행한다. 때문에 사용자가 빈 화면을 보게 되는 시간이 길어질 위험이 있고, 자바스크립트 파일은 아직 존재하지도 않는 요소를 참조하는 오류 또한 발생할 수 있다. 따라서 script태그는 body가 끝나기 전, 혹은 head에 작성할 경우 defer와 같이 사용하는 편이 좋다.

DOM 다루기 - CRUD에 집중하자

CREATE

document.createElement('div')

document.createElement는 새로운 요소를 만드는 메서드이며 위의 코드는 새로운 'div'요소를 만드는 코드이다. 자바스크립트에서 어떤 작업의 결과를 담으려면 변수를 선언하고 어떤 작업의 결과를 변수에 할당해야한다. 그렇다면 다시한번 div를 할당해보면

const test = document.createElement('div')

하지만 여기까지 했을 때, 브라우저 화면 상으로는 아무런 변화가 존재하지 않는다. 왜일까?
DOM트리를 생각해 보았을 때, 위의 코드는 단지 요소 노드가 어디에도 연결되어 있지 않고 떠있을 뿐이다. 따라서 이 코드를 트리 구조에 연결을 시켜줘야 한다.

APPEND

위에서 노드가 연결되지 않고 둥둥 떠다니는 문제는 append 혹은 prepend로 해결할 수 있다.

document.body.append(test)

이렇게 하면 body요소 내부의 끝 부분에 선언된 tweetDiv(div)를 추가할 수 있으며, 이는 곧 노드가 자식 요소로 연결되었음을 의미한다.

READ

DOM으로 HTML 엘리먼트의 정보를 조회하기 위해서는 querySelector의 첫 번째 인자로 셀렉터(selector)를 전달하여 확인할 수 있다.

const oneTest = document.querySelector('.test')

위의 코드는 class가 test인 첫번째 요소를 조회한다. 단, 여러 요소를 전부 가져오기 위해서는 querySelectorAll 을 사용한다. 이렇게 조회한 HTML 요소들은 배열처럼 for문을 사용하실 수 있지만, 배열이 아닌 유사 배열임에 주의한다.
이를 이용해 container에 위의 div를 넣는 코드는 다음과 같다.

const container = document.querySelector('#container')
const test = document.createElement('div')
container.append(test)

UPDATE

우선 요소에 text를 추가하는 textcontent

test.textContent = 'dev';

요소의 클래스를 추가 혹은 삭제하는 claaList

test.classList.add('tweet')

요소에 새로운 속성을 추가하는 setAttribute 등이 있다.(만약 해당 속성이 이미 존재한다면 지우고 새롭게 다시 적용한다.)

element.setAttribute( 'attributename', 'attributevalue' )

DELETE

삭제에는 여러 방법이 있다.
우선 remove를 통한 삭제가 있다.

const container = document.querySelector('#container')
const test = document.createElement('div')
container.append(test)
test.remove() // 이렇게 append 했던 요소를 삭제할 수 있다.

innerHTML을 통해 여러개의 자식요소들을 한꺼번에 지울 수 있다. 다만 innerHTML은 보안에서 문제가 있기 때문에 다른 메서드를 이용한다.

document.querySelector('#container').innerHTML = '';

innerHTML의 문제때문에 removeChild를 통해 자식 요소를 제거할 수 있다. removeChild는 자식을 지정하고 삭제하는데, 다음과 같이 자식 요소가 남지 않을때까지 삭제할 수 있다.

const container = document.querySelector('#container');
while (container.firstChild) {
  container.removeChild(container.firstChild);
}

0개의 댓글