DOM 노드의 생성, 수정, 삭제 기초

자바스크립트를 사용하면 DOM 의 모든 노드들을 생성, 수정, 삭제, 복사, 이동 할 수 있습니다.

DOM 노드를 제어하는데 필요한 모든 속성과 메서드를 제공하기 때문에 메서드와 속성의 갯수가 많기 때문에, DOM 을 제어할 때 적절한 메서드를 사용해야 원하는 결과를 얻을 수 있습니다.

자바스크립트의 노드 제어를 위한 속성과 메서드들을 먼저 알아보겠습니다.

특별히 속성이나 메서드에 Element 가 붙은 것은 HTML 태그 엘리먼트를 대상으로 동작하는 속성/메서드입니다.

메서드는 DOM 메서드와 자바스크립트 범용 메서드 2가지가 있습니다.

DOM 메서드는 파라메터로 노드 객체만 사용할 수 있으며, 자바스크립트 메서드는 노드 객체와 DOM 문자열(태그 문자열)을 모두 사용할 수 있습니다.

같은 기능을 하는 경우 DOM 메서드 보다는 자바스크립트 메서드 사용을 추천합니다.

메서드, 속성

타입

설명

appendChild()

DOM 메서드

선택한 엘리먼트의 자식 엘리먼트 중 마지막 엘리먼트 뒤에 추가함.

DOM 메서드로 엘리먼트(노드) 객체만 사용 가능

붙인 노드 오브젝트가 반환됨.

노드 1개만 추가 수 있음.

remove()

DOM 메서드

현재 엘리먼트를 삭제.

삭제할 엘리먼트의 참조만 있으면 됨.

인터넷 익스플로러 미지원

removeChild()

DOM 메서드

현재 엘리먼트의 자식 엘리먼트 1개를 삭제.

부모 엘리먼트와 삭제할 엘리먼트 2개의 참조가 필요함.

replaceChild()

 

현재 엘리먼트르 다른 엘리먼트로 대체합니다.

대체된 노드는 반환 값으로 얻을 수 있습니다.

insertBefore()

DOM 메서드

부모노드.insertBefore(추가할새노드, 기준참조노드);

기준 참조 노드 앞에 새노드를 추가합니다.실행 후 추가된 새 노드 참조를 반환합니다.(추가한 노드가 문서 프래그먼트인 경우 빈 프레그먼트를 반환)

insertAfter() 는 제공되지 않습니다.

hasChildNodes()

DOM 메서드

자식 노드가 있으면 true, 없으면 false 반환

cloneNode()

DOM 메서드

현재 노드를 복사해 반환합니다.

파라메터로 true/false 를 인자로 보낼 수 있습니다.

true 면 노드가 담고 있는 텍스트 등 내용까지 복사됩니다. false 면 노드 외형만 복사합니다.

previousSibling

nextSibling

DOM 속성

previousSibling: 이전 이웃 노드 반환

nextSibling: 다음 이웃 노드 반환

반환할 이웃 노드가 없으면 null 반환

insertAdjacentElement()

DOM 메서드

대상 엘리먼트의 태그 안과 밖 위치에 엘리먼트를 추가합니다.

대상엘리먼트.insertAdjacentElement(위치, 추가할요소);

위치값은 beforebegin, afterbegin, beforeend, afterend 4개를 지원합니다.

대상 엘리먼트 바깥앞(beforebegin), 바깥뒤(afterend), 안쪽내용앞(afterbegin), 안쪽내용뒤(beforeend) 에 엘리먼트를 추가합니다.

엘리먼트 노드에만 사용할 수 있으며, 태그쌍을 기준으로 시작태그와 끝나는 태그의 앞뒤에 삽입하는 방식입니다.

엘리먼트 추가에 성공하면 추가된 엘리먼트가 반환되며, 실패하면 null을 반환합니다.

firstChild

lastChild

DOM 속성

firstChild: 첫번째 자식 노드를 반환

lastChild: 마지막 자식 노드를 반환

firstElementChild

lastElementChild

DOM 속성

firstElementChild: 첫번째 자식 엘리먼트를 반환

lastElementChild: 마지막 자식 엘리먼트를 반환

자식 엘리먼트가 없을 경우 null 반환

children

DOM 속성

현재 노드의 모든 자식 엘리먼트 노드 컬렉션을 반환함.

배열 순환하는 방식으로 반환된 컬렉션을 순환할 수 있음.

엘리먼트 노드만 반환함.

createElement()

createTextNode()

DOM 메서드

createElement(): 엘리먼트를 생성함. 파라메터에는 태그 이름만 사용 가능. 생성된 엘리먼트 노드 객체를 반환함.

createTextNode(): 텍스트 노드를 생성해 텍스트 노드를 반환함.

before()

after()

자바스크립트 메서드

after(): 선택한 노드의 뒤에 추가함.

before(): 선택한 노드의 앞에 추가함.

문자열, 엘리먼트(노드) 객체 모두 추가 요소로 사용 가능하며, 문자열을 인자로 넣을 경우 텍스트 노드가 추가됨.

반환값이 없음(undefined 반환)

나머지 파라메터로 여러 개의 노드와 문자열을 추가하는 것이 가능.

인터넷 익스플로러 미지원.

createTextNode(), createElement() 이용한 노드 생성 및 추가 과정을 before()/after() 1개의 메서드로 줄여서 사용할 수 있기 때문에 코드 최적화 및 가독성 향상에 유리합니다.

가급적 before(), after() 메서드를 사용해 DOM 을 제어하는 것을 추천합니다.

prepend()

append()

자바스크립트 메서드

prepend(): 현재 엘리먼트의 첫번째 자식 엘리먼트 앞에 추가함.

append(): 현재 엘리먼트의 자식 엘리먼트 중 마지막 엘리먼트 뒤에 추가함.

문자열, 엘리먼트(노드) 객체 모두 추가 요소로 사용 가능하며, 문자열을 인자로 넣을 경우 텍스트 노드가 추가됨.

반환값이 없음(undefined 반환)

나머지 파라메터로 여러 개의 노드와 문자열을 추가하는 것이 가능.

인터넷 익스플로러 미지원.

createTextNode(), createElement() 이용한 노드 생성 및 추가 과정을 prepend()/append() 1개의 메서드로 줄여서 사용할 수 있기 때문에 코드 최적화 및 가독성 향상에 유리합니다.

가급적 prepend(), append() 메서드를 사용해 DOM 을 제어하는 것을 추천합니다.

이 메서드와 속성들은 DOM을 제어할 때 각각의 용도가 다르므로 DOM 제어시 어떤 메서드를 써야하는지 아는 것이 중요합니다.

HTML 도큐먼트 생성

자바스크립트 메서드를 사용해 DOM 트리 전체를 생성할 수 있습니다.

HTML 페이지에 아이프레임(newframe) 이 하나 있다고 치고, 여기에 자바스크립트로 HTML 도큐먼트를 만들어서 아이프레임에 HTML DOM을 붙여넣어서 페이지가 표시되도록 해보겠습니다.

// HTML 도큐먼트 생성let newdoc = document.implementation.createHTMLDocument("HTML Document");
// div 태그 안에 내용을 만들어 넣음.let div = newdoc.createElement("div");div.innerHTML = "<span>HTML 문서 샘플</span>";// 도큐먼트 바디(body)에 자식으로 붙임newdoc.body.appendChild(div);
targetdoc = document.getElementById('newframe').contentDocument;//HTML 도큐먼트를 붙여넣을 아이프레임 참조 얻기
let newnode = targetdoc.importNode(newdoc.documentElement, true);// 붙여넣을 새 노드를 복사해옴
targetdoc.replaceChild(newnode, targetdoc.documentElement);// 아이프레임 도큐먼트를 새 노드로 대체

엘리먼트 선택

엘리먼트 선택은 querySelector(), querySelectorAll() 두개의 메서드를 사용합니다.

메서드 이름에서 알 수 있듯이 querySelector()는 엘리먼트 1개를 반환합니다. 반환할 엘리먼트가 없으면 null을 반환합니다.

querySelectorAll() 는 엘리먼트(노드) 리스트를 반환합니다. 반환할 엘리먼트가 없을 경우 길이가 0인 엘리먼트 리스트를 반환합니다.

반환할 엘리먼트가 없을 경우 반환하는 결과가 다른 점을 주의해야 합니다.

반환값을 조건문으로 체크할 때 null 과 비교해야할지, length 속성이 0인지를 비교해야할지를 구분해야 하기 때문입니다.

두 메서드는 인자로 엘리먼트 선택을 위한 CSS 선택자 문자열을 입력 받습니다.

CSS 선택자는 태그의 ID, 또는 CSS 클래스를 사용할 수 있습니다.

element.querySelector('id');

element.querySelectorAll('.class');

CSS 선택자는 id나 클래스 1개를 사용하는 간단한 선택부터, CSS와 ID를 조합한 복잡한 선택까지 지원합니다.

예를 들어

element.querySelectorAll('div.section > p#comment span.bold');

같은 복잡한 CSS 선택자를 사용할 수도 있습니다.

엘리먼트 생성

노드 생성은 HTML 엘리먼트를 생성하는 createElement() 와 텍스트 노드를 만드는 createTextNode() 메서드 2개를 사용할 수 있습니다.

태그 생성을 하는 createElement() 메서드로 태그를 만들어 HTML 도큐먼트에 붙여보겠습니다.

먼저 createElement() 로 구조를 만드는 방법입니다.

let div = document.createElement('div');let span = document.createElement('span');span.innerText = 'HTML 문서 샘플';div.appendChild(span);document.body.appendChild(div);

엘리먼트의 innerHTML 속성에 태그 문자열을 직접 입력해서 DOM을 생성할 수도 있습니다.

document.body.innerHTML = '<div><span>HTML 문서 샘플</span></div>';

엘리먼트 삭제

remove(), 또는 removeChild() 메서드로 엘리먼트를 삭제할 수 있습니다.

remove()는 엘리먼트 자신을 삭제합니다.

removeChild()는 부모 요소의 자식 요소를 삭제합니다. 부모요소.removeChild(자식요소); 형식으로 부모 요소와 자식 요소 모두를 선택해야 합니다.

document.getElementById('delid').remove();
let parent = document.getElementById('parentdiv');let child = document.getElementById('childspan');parent.removeChild(child);

엘리먼트 삽입, 이동

생성한 엘리먼트, 또는 선택한 엘리먼트를 HTML 도큐먼트의 원하는 위치에 삽입하는 메서드는 여러가지가 있습니다.

노드를 어느 위치에 삽입하냐에 따라 사용하는 메서드가 다르기 때문에 위치에 따른 사용 메서드를 구분할 수 있어야 합니다.

아래는 DOM 트리에서 메서드 별로 어떤 위치에 삽입되는지 위치를 표시한 것입니다.

<!DOCTYPE html><html><head>  <title>Elemetnt Insert</title></head><body>  <ul id="friends">    <li class="animal">라이언</li>    <li class="fruit">어피치</li>    <li class="animal">프로도</li>    <li class="alien">콘      <ul class="keyword">        <li>3세</li>        <li>숏다리</li>        <li>초록괴수</li>      </ul>    </li>  </ul>  <ul class="icons">    <li>      <span>스몰</span>      <span>미디엄</span>      <span>빅</span>    </li>  </ul>  <ul id="newfriends">  </ul></body></html>

이렇게 구성된 HTML 페이지에서 엘리먼트를 삽입, 이동 처리를 해보겠습니다.

// 새 <li> 엘리먼트 새성let li = document.createElement('li');let litext = document.createTextNode('무지');li.appendChild(litext);

// 새 <li> 엘리먼트를 붙일 대상 부모 선택let targetul = document.getElementById('friends');targetul.appendChild(li); // friends ID를 가진 ul 자식들 맨끝에 새로 만든 <li> 태그를 붙임.
//이동할 엘리먼트 선택let sourceli = document.querySelector('ul#friends li:first-child');//삽입할 위치 기준 엘리먼트 선택let targetli =  document.querySelector('ul#friends li:last-child');//붙여넣는 위치에 주의해야 함//1뎁스 ul 마지막 요소가 아니라 중첩된 내부 ul 끝에 붙게됨.targetli.after(sourceli);

//문자열을 가지는 li 엘리먼트를 생성해 자식 엘리먼트로 붙임var appendli = document.createElement("li");appendli.append("왕눈이");document.querySelector('ul li ul').append(appendli);

//마지막 차일드 엘리먼트 선택let selected = document.querySelector('.icons li span:last-child');//추가할 span 노드 생성-let newspan = document.createElement('span');let newspantext = document.createTextNode('빅');newspan.appendChild(newspantext);//마지막 엘리먼트 앞에 추가selected.parentNode.insertBefore(newspan,selected);
//animal 클래스 속성을 가진 li 엘리먼트들을 선택let items = document.querySelectorAll('.animal');// 나머지 파라메터로 newfriend ID 를 가지는 새 ul 에 선택한 엘리먼트들을 추가document.querySelector('#newfriends').prepend(...items);

엘리먼트 교체

선택한 엘리먼트 자체를 새로 생성한 엘리먼트, 또는 선택한 다른 엘리먼트로 바꿀 수 있습니다.

replaceChild() 메서드는 현재 엘리먼트의 하위에 있는 자식 엘리먼트 1개를 새 엘리먼트로 교체합니다.

새 엘리먼트 1개를 만들어서 기존 엘리먼트를 교체해 보겠습니다.

// <p> 엘리먼트 생성let p = document.createElement('p'); // <p> 엘리먼트 생성let ptext = document.createTextNode('문단 텍스트 내용'); // 문단 내용 텍스트 생성p.appendChild(ptext); // 문단 내용을 <p>에 텍스트 채움
let originalp = document.getElementById('paragraphid'); // 교체할 엘리먼트 선택
let oldp = originalp.parentNode.replaceChild(p, originalp); // 교체할 엘리먼트의 부모 태그에서 자식 엘리먼트 교체

엘리먼트를 교체한 후 replaceChild() 메서드는 원래 엘리먼트를 반환합니다.

원래 엘리먼트를 재활용하거나 다른 위치에 다시 붙여야 할 경우, 반환 엘리먼트를 변수에 저장해 사용할 수 있습니다.