본문 바로가기

JavaScript

요소 생성과 요소 삽입

 

요소 생성과 요소 삽입을 하는 방법에는 두 가지 방법이 있습니다.

 

JavaScript에서 HTML 코드를 작성해 브라우저가 HTML 코드를 분석하고 문서의 특정 위치에 렌더링 하도록 하거나 

 

문서 객체의 createElement() 메서드로 새로운 노드를 생성해 문서 어딘가에 수동으로 삽입하는 방법이 있습니다.

 

JavaScript에서 HTML 코드를 작성해 브라우저가 HTML 코드를 분석하고 문서의 특정 위치에 렌더링 하는 방법에는 

 

요소 노드의 innerHTML 프로퍼티로 HTML 문자열을 추가할 수 있는데 HTML 문자열을 추가하고 렌더링 하면 추가한 위치에 HTML 코드가 있게 됩니다. 

 

대안으로는 insertAdjacentHTML()이 있으며 콘텐츠를 대체하는 대신 렌더링 된 HTML 콘텐츠를 기존의 콘텐츠 옆에 추가하고자 할 때 사용할 수 있는 메서드입니다.

 

createElement() 메서드로 새로운 노드를 생성해 문서 어딘가에 수동으로 삽입하는 방법에는 한 번에 여러 HTML 대신 단일 DOM 요소 노드를 생성할 수 있습니다. 

 

생성된 요소나 요소 노드는 appendChild() 또는 append()에 추가될 수 있으며 새로운 DOM 요소나 노드를 다른 요소의 내부에 추가할 수 있고 새로운 부모 요소나 부모 노드를 추가할 수도 있습니다.

 

prepend(), before() after(), insertBefore() 등을 사용하여 기존 자식 노드 리스트 끝에 추가하는 대신 원하는 특정 위치에 추가할 수 있습니다.

 

replaceChild()replaceWith()를 사용하면 기존의 노드를 교체할 수 있습니다.

 

예시 코드와 함께 하나씩 정리해보겠습니다.

 

 

 

 


innerHTML

 

새로운 요소를 설정하고 싶다면 innerHTML을 사용합니다.

 

사용방법은 아래와 같습니다.

 

 

사용 전 브라우저
  <body>
    <header><h1 id="main-title">Dive into the DOM!</h1></header>
    <section class="red-bg">
      <ul>
        <li class="list-item">Item1</li>
        <li class="list-item">Item2</li>
        <li class="list-item">Item3</li>
      </ul>
    </section>
    <button>Toggle Visibility</button>
    <input id="input-1" class="input-default" value="Enter text..." />
  </body>

 

사용 후 브라우저
const section = document.querySelector("section");
section.innerHTML = "<h2>NEW TITLE</h2>";

문자열로 재설정하고 <h2> 태그와 같은 HTML 코드를 포함하여 사용할 수 있습니다. 

 

<section> 태그 안에 있던 이전 노드들이 모두 사라지고 새로운 HTML 코드로 대체됩니다.

 

innerHTML의 동작 방식은 전체 중첩 HTML 구조를 바꿔버립니다. 기존에 있던 노드는 새로운 입력값으로 바뀌게 되는 것입니다.

 

 

하지만 기존의 있던 노드를 유지한 상태에서 새로운 HTML 코드를 추가하고 싶을 때는 아래와 같은 방법이 있습니다.

 

const list = document.querySelector("ul");
list.innerHTML = list.innerHTML + "<li>Item 4</li>";



기존의 innerHTMl 콘텐츠를 유지하고 새로운 <li>를 마지막에 추가하여 렌더링 한 것입니다.

 

이 접근 방식의 단점은 전체 HTML의 <ul>의 콘텐츠를 새로운 콘텐츠로 교체를 한다는 것입니다.

 

즉 Item4를 추가를 한 것이지만 기존에 있던 Item1, Item 2, Item 3도 다시 렌더링 된 것이기 때문에 성능이 좋지 않은 방법이었습니다.

 

브라우저가 다시 분석하도록 했으며 실제로 바뀌지 않은 HTML 코드를 다시 렌더링 했기 때문입니다. 

 

 

정리

innerHTML은 선택한 요소 노드 안에 있는 모든 HTML 콘텐츠를 변경할 때 유용하지만 기존 콘텐츠를 유지하며 추가할 때는 성능이 좋지 않습니다.

 

 

 


insertAdjacentHTML

 

  <body>
    <header><h1 id="main-title">Dive into the DOM!</h1></header>
    <section class="red-bg">
      <ul>
        <li class="list-item">Item1</li>
        <li class="list-item">Item2</li>
        <li class="list-item">Item3</li>
      </ul>
    </section>
    <button>Toggle Visibility</button>
    <div>
      <input id="input-1" class="input-default" value="Enter text..." />
    </div>
  </body>

input에 사용자 입력값을 받았을 때 문장을 아래 삽입하고 싶은 상황을 가정해보겠습니다.

 

 

const div = document.querySelector("div");
div.innerHTML = div.innerHTML + "<p>WRONG!</p>";

이때 위의 코드처럼 innerHTML을 사용하여 문장을 추가한다면 위의 정리 내용처럼 선택한 요소 노드 안에 있는 모든 콘텐츠가 초기화가 됩니다.

 

innerHTML로 초기화된 모든 콘텐츠는 다시 렌더링이 되기 때문에 사용자의 입력값을 잃게 되는 것입니다.

 

 

 

이때 insertAdjacentHTML을 사용하면 사용자의 입력값을 유지하면서 콘텐츠를 추가할 수 있습니다.

const div = document.querySelector("div");
div.insertAdjacentHTML("beforeend", "<p>WRONG</p>");

insertAdjacentHTML은 첫 번째 인자로 추가시킬 위치를, 두 번째 인자로 추가할 콘텐츠를 받습니다.

 

 

 

Element.insertAdjacentHTML() - Web API | MDN

insertAdjacentHTML() 메서드는 HTML or XML 같은 특정 텍스트를 파싱하고, 특정 위치에 DOM tree 안에 원하는 node들을 추가 한다. 이미 사용중인 element 는 다시 파싱하지 않는다. 그러므로 element 안에 존재하

developer.mozilla.org

 

insertAdjacentHTML은 선택 요소 노드의 모든 것을 다시 렌더링 하지 않고 추가할 콘텐츠만 렌더링 하여 추가하기 때문에 효율적으로 추가할 수 있습니다. 

 

 해당 접근법의 단점은 추가된 콘텐츠에 직접 접근이 불가능하다는 점입니다.( innerHTML도 마찬가지입니다. )

 

 


createElement

 

createElement()는 문서에서만 사용이 가능합니다. 다른 DOM 노드나 DOM 객체에서는 사용이 되지 않습니다.

 

즉 사용은 언제나 document.createElement()가 되어야 하는 것입니다.

 

기본 사용법
document.createElement( '생성하고자 하는 요소의 태그 이름' )

createElement()는 최소 1개의 인자가 필요하며 해당 인자는 생성하고자하는 요소의 태그 이름입니다.

 

 

appendChild()와 append()
.appendChild(추가하고자하는 노드)

.append(추가하고자하는 노드)

기본 사용법은 위와 같습니다.

 

appendChild()는 모든 노드를 추가할 수 있습니다.(텍스트 노드도 추가할 수 있습니다.)

 

list.append("test");

appendChild()와 append()의 사용법은 거의 비슷하지만 append()의 경우 인자로 문자열을 바로 받아 텍스트 노드로 만들어 간편하게 추가할 수 도 있습니다. 

 

list.append(추가할 노드1, 추가할 노드2);

또 다른 차이점은 append()는 여러 개의 노드를 한 번에 추가할 수 있다는 점입니다. 

 

 

 

 

 

아래 예시 코드와 함께 정리해보겠습니다.

 

  <body>
    <header><h1 id="main-title">Dive into the DOM!</h1></header>
    <section class="red-bg">
      <ul>
        <li class="list-item">Item1</li>
        <li class="list-item">Item2</li>
        <li class="list-item">Item3</li>
      </ul>
    </section>
    <button>Toggle Visibility</button>
    <div>
      <input id="input-1" class="input-default" value="Enter text..." />
    </div>
  </body>

<ul> 요소 노드 안에 <li> 요소 노드를 추가하고 싶은 상황입니다. insertAdjacentHTML를 사용해도 되지만 직접 접근이 불가능한 단점 때문에 createElement()를 사용하여  <li> 요소 노드를 추가해보겠습니다.

// <ul> 요소 노드를 선택합니다.
const list = document.querySelector("ul");

// <li> 요소 노드를 생성합니다.
const newList = document.createElement("li");

// <li> 요소 노드 안에 텍스트 노드를 생성합니다.
newList.textContent = "Item4";

// 텍스트 노드가 포함된 <li> 요소 노드를 <ul> 요소 노드에 추가합니다.
list.appendChild(newList);

createElement를 사용하면 안에 콘텐츠는 요소 노드만 생성이 되기 때문에 원하는 구성을 설정해주셔야 합니다.

 

append()나 appendChild()를 사용하여 추가하고 싶은 곳에 추가해주시면 됩니다.

 

createElement를 사용해 생성한 요소 노드는 이미 JavaScript 메모리에 있기 때문에 DOM에 항목을 추가하지 않아도 텍스트 노드나 스타일 프로퍼티를 설정할 수 있습니다.

 

createElement의 가장 큰 장점은 이벤트 리스너 추가나 스타일을 변경하는 등의 모든 작업을 할 수 있는 객체라는 점입니다. 

 

 

prepend()

만약 생성한 노드를 끝 쪽이 아닌 제일 앞쪽에 삽입하고 싶다면 append() 대신 prepend()를 사용하시면 됩니다.

 

before()
const list = document.querySelector("ul");

const newList = document.createElement("li");

newList.textContent = "Item4";

// <ul> 요소 노드 안의 마지막 자식 요소노드에 접근하여 앞에 삽입
list.lastElementChild.before(newList);

before()를 사용하면 지정된 요소 노드 앞으로 삽입이 가능합니다.

 

after()
const list = document.querySelector("ul");

const newList = document.createElement("li");

newList.textContent = "Item4";

list.lastElementChild.after(newList);

before()와 사용 방식이 같으며 지정된 요소 노드 뒤에 삽입이 가능합니다.

 

replaceWith()
const list = document.querySelector("ul");

const newList = document.createElement("li");

newList.textContent = "Item4";

list.firstElementChild.replaceWith(newList);

replaceWith()를 사용하면 지정된 요소 노드의 교체가 가능합니다. 

 

 

 

before()와 after()의 경우 Safari 지원이 되지 않고 append()와 prepend()는 Safari 지원이 됩니다. 

 

때문에 before()와 after()의 사용은 더 신중하게 결정하셔야 합니다. 

 

 

'JavaScript' 카테고리의 다른 글

배열(Array) 생성  (0) 2022.09.04
요소 제거하기  (0) 2022.08.28
classList  (0) 2022.08.28
DOM 트래버싱(Traversing the DOM)  (0) 2022.08.25
속성(Attribute)과 프로퍼티(Propertie)  (0) 2022.08.24