본문 바로가기
자바스크립트(JavaScript)/자바스크립트

[Java Script] 문서 객체 모델(DOM)과 DOM TREE, 노드 추가방법

by yerica 2024. 7. 30.
문서 객체 모델
Document Object Model (DOM)


자바스크립트를 사용하는 이유는 특정 조건이 충족될 때 웹 문서 전체 또는 일부분을 제어하기 위해서이다.
동적으로 반응하게 하려면 웹 문서의 모든 요소를 따로 제어할 수 있어야한다.
이러한 경우 문서객체모델을 사용하면 요소를 제어할 수있다.

텍스트와 이미지가 들어있는 웹문서를 예로 들어보겠다.
웹 브라우저는 마크업 정보를 보면서 단락의 개수나 내용을 확인하며 텍스트 내용을 분석하고 저장한다.
또한 이미지 파일의 개수와 경로, 대체 텍스트등을 파악하여 이미지별로 정리 후 인식한다.
이러한 텍스트나 이미지 요소를 브라우저가 제어하려면 두 요소를 따로 구별하여 인식하여야한다.
이러한 모든 정보 요소를 자바스크립트로 가져와서 프로그래밍할 때 DOM을 이용한다.

DOM은 웹 문서를 하나의 객체로 정의한다.
웹 문서를 이루는 이미지나 텍스트, 표 등의 모든 요소도 각각 객체로 정의된다.
웹 문서 전체는 document 객체이고 이미지는 image 객체이다. 웹 문서 안의 모든 태그는 객체로 인식하고 처리한다.

한마디로 문서 객체 모델을 정의하면 '자바스크립트를 이용하여 웹 문서에 접근하고 제어할 수 있도록 객체를 사용해 웹 문서를 체계적으로 관리하는 방법' 라고 할 수 있다.
HTML 문서로 작성한 웹 문서의 DOM은 HTML DOM이라고 부르고, XML문서에서 사용하는 XML DOM이라고 부른다.

DOM TREE


자바스크립트로 DOM을 조작하려면 실제 웹 문서가 DOM으로 표현되는 방법을 알아야한다.

DOM은 웹 요소를 부모요소와 자식요소로 구분한다.
예를들어 최상위 객체인 HTML 안에 head 와 body 라는 자식요소를 포함한다.
그리고 자식요소 head는 다시 부모요소가 되어 title, meta, link와 같은 자식요소를 품고있다.
이 모습을 도표로 그려보면 마치 나무 뿌리와 닮았다고 하여 DOM TREE라고 부른다.

DOM트리 최상위 객체는 자바스크립트에서 document라고 표현한다.
또한 태그 요소는 여러 속성들이 들어간다.
태그요소 안에 들어있는 속성이나 내용들도 자식으로 나타낸다.

트리 노드 / Tree Node


DOM 객체에서 부모와 자식 구조로 나눠지는 모든 것을 '노드'라고 표현한다.
부모자식 구조를 도표로 표시하면 나무 뿌리의 형태가 되므로 DOM트리라고 부른다.
DOM 트리에서 가지가 갈라져 나온 항목을 노드(node)라고 하고, DOM트리의 시작부분인 html 노드를 나무 뿌리에 해당한다고 해서 루트 노드(root node) 라고 부른다.
루트노드를 시작으로 웹 문서에서 사용한 요소는 계층 구조를 이룬다.
따라서 각 노드 사이의 관계를 부모와 자식, 형제간으로 표현할 수 있다.
부모 노드(parent node)에는 자식 노드(child node)가 있고, 부모 노드가 같은 형제 노드(sibling node)가 있다.

★★★ DOM 을 구성하는 기본 원칙 

  • 모든 HTML 태그는 요소 노드(element node)이다.
  • HTML에서 사용하는 텍스트 내용은 자식 노드인 텍스트 노드(text node)이다.
  • HTML 태그에 있는 속성은 자식 노드인 속성 노드(attribute node)이다.
  • 주석은 주석 노드(comment node)이다.

DOM에서 노드 추가, 삭제하기


웹 문서에서 처음 화면에는 보이지 않다가 클릭이나 이벤트가 발생하면 내용이 나타나는 경우가 있다.
이런 동작은 css의 display 속성을 사용해서 만들 수도 있지만, DOM 트리에 새로운 노드를 추가하는 방법도 있다.
이때 주의할 점은 노드를 추가하면 단순히 요소 노드 뿐 아니라 텍스트와 속성 노드도 함께 추가해주어야 한다는 것이다.

노드 리스트란?


노드를 여러개 저장한 형태를 말한다.
배열와 같이 저장되어있지만 진짜 배열은 아니다.
DOM 에서 새로운 노드를 만들어 추가하거나 삭제하려면 '노드 리스트(node list)'를 사용해야한다.
DOM에 접근할 때 querySelectorAll()메서드를 사용하면 노드를 한꺼번에 여러 개 가져올 수 있다.
이때 노드 정보를 여러 개 저장한 것이 노드 리스트이다.
배열과 비슷하게 동작한다는 특징이 있다.
여러 개 노드 중 특정한 노드를 불러오고 싶다면 아래와 같은 기본형을 사용한다.
// 기본형
document.querySelectorAll('li')[인덱스번호]

 새로운 노드 추가 과정 


새로운 노드를 추가할 때에는 DOM 트리를 구성하는 기본 원칙에 따라 추가하여 생성할 수 있다.
단순히 태그에 해당하는 요소 노드 뿐만 아니라 텍스트 노드와 속성노드도 추가해야한다.
예를 들어 img 태그 요소를 자바스크립트를 이용해 동적으로 생성하고 싶다면 <img> 태그의 요소노드 뿐만 아니라 속성에 해당하는 src, alt 같은 속성 노드도 추가해야 한다.
어떠한 웹 문서의 DOM 트리에 새로운 노드를 추가하려면 그 문서에 새로운 소스 코드를 작성해야한다.
그래서 새 노드를 추가할 때는 웹 문서에 어떤 소스를 추가할지 먼저 생각하고 그에 따라 요소노드나 텍스트 노드, 속성 노드도 만들어야한다. 

텍스트 노드를 사용하는 새로운 요소 추가하기


더보기

1. 요소 노드 만들기 - createElement()메서드

DOM에 새로운 요소를 추가할 때 가장 먼저 해야 할 일은 요소 노드를 만드는 것이다.

이 때 사용하는 메서드는 createElement()메서드인데 괄호 안에 해당하는 요소 노드를 만들면 된다.

 // 기본형
 document.createElement('노드명');

2. 텍스트 노드 만들기 - createTextNode()메서드 

새로운 요소 노드를 만들었다면 다음은 내용을 담는 텍스트 노드를 자식 노드로 만들어 연결해야한다.

텍스트 노드를 만드는 메서드는 createTextNode()메서드로 아래의 기본형을 사용한다. 

// 기본형
document.createTextNode('텍스트');

3. 자식 노드 연결하기 - appendChlid()메서드

위는 새로운 노드들을 만들어 놓기만 한 상태로 아직까지 부모노드와 자식노드가 연결되지 않은 상태이다.

appendChlid()메서드는 텍스트 노드나 속성 노드를 만든 후 요소 노드에 연결할 때 사용한다.

이때 appendChlid()메서드를 사용해서 연결하는 노드는 자식 노드 중 맨 끝에 추가된다.

// 기본형
부모노드.appendChlid(자식노드)
예시

See the Pen Untitled by 26%익산의 (@moroiolt-the-typescripter) on CodePen.


속성값이 있는 노드 추가하기 


더보기

1. 요소 노드 만들기 - createElement()

// 기본형
document.createElement('노드명')

 2. 속성 노드 만들기 - createAttribute()

속성 노드를 추가할 때 createAttribute()메서드를 사용한다.

// 기본형
document.createAttribute('속성명')

3. 속성 노드에 속성값을 추가하기 - .value 프로퍼티

생성한 속성 노드에 값을 추가할 때에는 value 프로퍼티를 사용한다.

// 기본형
요소노드.value = "속성값"

 4. 속성노드를 부모노드에 추가하기 - setAttributeNode()  

속성 노드는 요소 노의 자식으로 연결해야한다.

새로 만든 속성 노드를 요소 노드에 연결하려면 .setAttributeNode()메서드를 사용한다.

만약 추가할 속성이 요소 노드에 이미 들어있다면 기존 속성노드를 새 속성 노드로 대체한다.

// 기본형
요소노드.setAttributeNode('속성 노드')
예시

See the Pen Untitled by 26%익산의 (@moroiolt-the-typescripter) on CodePen.


텍스트 필드로 리스트 만들기
input 에 값을 입력하면 그 내용을 리스트로 입력하도록 하는 기능을 만들어보겠다.
위의 기능을 만들기 위해선 텍스트 노드를 만드는 방법과 input에 입력되는 값이 value 프로퍼티의 값과 같다는 것을 알아야한다.
input 태그에 사용자가 입력한 내용 받아오기
: 텍스트 필드와 같이 사용자가 입력한 내용을 자바스크립트로 받아올 때는 .value 프로퍼티를 이용한다.
먼저 입력값을 받아올 input태그를 먼저 선택해서 변수에 담아둔 다음 변수명.value를 해주면,
현재 입력되어있는 내용을 자바스크립트로 가져올 수 있다.     
// 기본형 1 : 현재 요소에 입력된 값을 가져온다.
요소선택.value 

// 기본형 2 : 현재 요소에 입력된 값을 바꾼다.
요소선택.value = '값';​

 

See the Pen Untitled by 26%익산의 (@moroiolt-the-typescripter) on CodePen.


노드 삭제하기


DOM 트리에서 특정 노드를 삭제할 때 특정 노드를 삭제할 때 기억해야하는 것은 부모노드에서 자식 노드를 삭제해야 한다는 것이다. 삭제해야할 노드가 있다면 반드시 부모노드를 먼저 찾아야한다.
그렇기 때문에 노드를 삭제하는 메서드 외에도 부모 노드를 찾는 프로퍼티가 필요하다.
parentNode 프로퍼티
: parentNode 프로퍼티는 현재 노드의 접근하여 부모노드의 요소 노드를 반환한다.
// 기본형
노드.parentNode​
텍스트 필드로 리스트를 만들때 사용했던 예시를 활용해 보겠다.
li들을 클릭하면 사라지게 만들기 위해서는 li의 부모를 먼저 찾아야한다.
콘솔창에 document.querySelectorAll에 .parentNode를 찾아보니 아래와 같이 ul이 뜨는 것을 확인 할 수 있다.

부모 노드를 선택했다면 이제 자식 노드를 삭제하는 메서드를 활용하여 삭제하면 된다.
이때는 removeChild() 메서드를 사용한다.
removeChild()메서드
: 부모노드를 찾은 후 부모 노드 안에 있는 자식 노드를 삭제하고 싶다면 removeChild메서드를 사용하면 된다.
이름에서도 알 수 있듯이 자식노드를 삭제하는 메서드이다.
// 기본형
부모노드.removeChild(자식노드)​

See the Pen Untitled by 26%익산의 (@moroiolt-the-typescripter) on CodePen.

변수에 li들를 담은 뒤 → let items = document.querySelectorAll("li")
반복문으로 부모노드가 있을 경우 부모노드 안의 li를 클릭했을 때 li를 삭제하는 기능을 넣는다.
addEventListener를 사용하여 기능을 넣었다.

추가하려는 자식노드를 가장 앞으로 가져오기


appendChild()메서드를 이용하면 새로운 노드를 부모노드의 맨 끝에 추가한다.
추가되는 노드의 순서를 바꿔 표시하려면 부모노드와 자식노드의 관계를 파악한 후에 마지막 자식노드를 맨 앞에 추가해야한다.
부모노드의 자식노드 중 가장 앞의 자식노드는 부모노드의 인데스0번에 위치한다.
이를 표현하기위해 부모노드.childNodes[0]라는 문법을 사용하고, 이 노드 앞에 새로운 노드를 추가하려면 .insertBefore()메서드를 사용한다.
// 기본형
부모노드.insertBefore(추가할 노드, 노드 위치)