
[Javascript] HTML 태그 동적 추가하는 다양한 방법들
Javascript를 통해 상황에 따라 동적으로 태그를 추가하고 싶은 경우가 있습니다. 단순한 작업이지만 이를 위한 함수들이 꽤 많이 있습니다. 한번 알아볼까요?
태그 동적인 추가를 위한 방법들
태그를 추가할 때에는 크게 두 가지 방법이 있습니다. 문자열을 만들어서 넣거나 노드로 만들어서 넣는 방법입니다.
innerHTML
insertAdjacentHTML
insertBefore
appendChild
append
prepend
before
after
innerHTML
innerHTML은 태그 안의 HTML 값을 가지고 있습니다. 예를 들어 다음과 같은 HTML 태그들이 있다면
<p>
<span>햄이네 박사라네!</span>
</p>
이 p 태그의 innerHTML 값은 span 태그가 나오게 됩니다.
let pTag = document.querySelector("p");
// "<span>햄이네 박사라네!</span>"
console.log(pTag.innerHTML);
이렇게 가져온 값에 다른 것을 넣어준다면
pTag = "<span>아이네라네!</span>";
그에 맞게 HTML 내용도 바뀌게 됩니다.
<p>
<span>아이네라네!</span>
</p>
innerHTML 내용을 바꾸다보니 기존 내용이 사라지는 문제가 있습니다.
innerHTML로 동적으로 추가하는 방법
innerHTML로 기존 것을 그대로 두면서 추가하려면, 기존의 문자열 또한 유지해줘야합니다.
pTag.innerHTML = pTag.innerHTML + "<span>아이네라네!</span>";
// 위와 동일한 방법
pTag.innerHTML += "<span>아이네라네!</span>";
insertAdjacentHTML
innerHTML은 해당 내용 자체를 바꾸기 때문에 전체를 지웠다가 다시 씁니다. 추가를 계속 할수록 지웠다가 써야하는 양이 많아지기 때문에 시간이 많이 걸립니다. 그래서 DOM tree에 안에 원하는 위치에 맞게 추가하는 목적으로는 insertAdjcentHTML
을 사용하는게 더 좋습니다.
태그.insertAdjacentHTML(위치, 텍스트);
태그는 querySelector 등으로 가져온 태그 값이고, 텍스트는 HTML 형식으로 넣을 값입니다. 중요한 것은 위치입니다. 4가지 종류의 값이 들어있습니다.

예를 들어 다음 태그에 1부터 5까지 숫자가 적인 태그를 넣고 싶다면
<div>
<!-- 1부터 5까지 숫자를 넣고싶은 상황 -->
</div>
beforeend로 계속 맨 뒤에 추가합니다.
const tag = document.querySelector("div");
for (let i = 1; i <= 5; i++) {
tag.insertAdjacentHTML("beforeend", `<span>${i}</span>`);
}
그러면 다음과 같은 결과가 됩니다.
<div>
<span>1</span>
<span>2</span>
<span>3</span>
<span>4</span>
<span>5</span>
</div>
만약 순서를 거꾸로 하고 싶다면 앞에서부터 넣을 수 있게 위치 값을 afterbegin으로 하면 됩니다.
const tag = document.querySelector("div");
for (let i = 1; i <= 5; i++) {
tag.insertAdjacentHTML("afterbegin", `<span>${i}</span>`);
}
<div>
<span>5</span>
<span>4</span>
<span>3</span>
<span>2</span>
<span>1</span>
</div>
insertBefore
insertBefore
는 특정 태그 앞에 삽입합니다.
태그.insertBefore(추가할 노드, 기준 노드);
기준 노드에 값을 어떻게 넣냐에 따라 위치가 달라집니다.

예를 들어 다음과 같이 HTML의 내용이 있다고 해보겠습니다.
<p>
<span>1</span>
<span>2</span>
<span>3</span>
<span>4</span>
</p>
만약 insertBefore를 사용해서 기준 태그를 넣지 않는다면
let tag = document.querySelector("p");
// <span>아이네라네!</span> 생성
const newTag = document.createElement("span");
newTag.innerText = "아이네라네!";
// p 태그 마지막에 추가
tag.insertBefore(newTag, null);
마지막에 추가됩니다.
<p>
<span>1</span>
<span>2</span>
<span>3</span>
<span>4</span>
<span>아이네라네!</span>
</p>
만약 기준 노드를 3번 째 span으로 잡는다면
// 세 번째 노드를 찾습니다.
const span = tag.querySelector("span:nth-child(3)");
// 세 번째 노드 앞에 넣습니다.
tag.insertBefore(newTag, span);
<p>
<span>1</span>
<span>2</span>
<span>아이네라네!</span>
<span>3</span>
<span>4</span>
</p>
동일한 노드를 여러 번 넣기
그런데 만약에 만들어놨던 노드를 재활용하기 위해 여러번 만든다면 주의를 해야합니다.
tag.insertBefore(newTag, null);
tag.insertBefore(newTag, null);
tag.insertBefore(newTag, null);
기대하는 결과는 다음과 같지만
<p>
<span>1</span>
<span>2</span>
<span>3</span>
<span>4</span>
<span>아이네라네!</span>
<span>아이네라네!</span>
<span>아이네라네!</span>
</p>
실제로는 하나만 나타납니다.
<p>
<span>1</span>
<span>2</span>
<span>3</span>
<span>4</span>
<span>아이네라네!</span>
</p>
그래서 cloneNode로 복사해서 넣거나 새로 만들어서 넣어야합니다.
tag.insertBefore(newTag.cloneNode(true), null)
tag.insertBefore(newTag.cloneNode(true), null)
tag.insertBefore(newTag.cloneNode(true), null)
// or
for (let i = 0; i < 3; i++) {
const newTag = ...
tag.insertBefore(newTag, null);
}
이는 뒤에 나오는 appendChild
도 동일합니다. Node로 넣는 함수들에서는 이런 것들을 주의해야합니다.
appendChild
insertBefore에서 null을 넣은 것과 같습니다. HTML이 다음과 같이 동일하게 있다면 4 뒤에 넣을 수 있습니다.
<p>
<span>1</span>
<span>2</span>
<span>3</span>
<span>4</span>
</p>
해당 태그의 맨 마지막에 추가합니다.
let tag = document.querySelector("p");
// <span>아이네라네!</span> 생성
const newTag = document.createElement("span");
newTag.innerText = "아이네라네!";
// p 태그 마지막인 4 뒤에 추가
tag.appendChild(newTag);
결과는 insertBefore에 기준 태그가 null인 경우와 동일합니다.
<p>
<span>1</span>
<span>2</span>
<span>3</span>
<span>4</span>
<span>아이네라네!</span>
</p>
append, prepend, before, after
이 4개 함수를 하나로 묶은 이유는 모두 동일한 입력과 동작을 수행하기 때문입니다.
append(node1)
append(node1, node2)
append(node1, node2, /* ... */, nodeN)
prepend(node1)
prepend(node1, node2)
prepend(node1, node2, /* ... */, nodeN)
before(node1)
before(node1, node2)
before(node1, node2, /* ... */, nodeN)
after(node1)
after(node1, node2)
after(node1, node2, /* ... */, nodeN)
위 함수들과 다른 점은 여러 개의 노드를 넣을 수 있다는 점입니다. 서로 다른 점은 들어가는 위치입니다. insertAdjacentHTML
와 유사합니다.

예를 들어 다음 태그에 여러 개 태그를 추가해본다고 해보겠습니다.
<div></div>
Node하나랑 텍스트를 두 개를 해당 태그 뒤에 넣는다고 하면 다음과 같이하면 됩니다.
const tag = document.querySelector("div");
const newNode = document.createElement("span");
newNode.innerText = "아이네!";
tag.after(newNode, "<span>안녕!!</span>");
<div><span>아이네!</span>"<span>안녕!!</span>"</div>
텍스트로 넣은 것은 파싱되지 않고 있는 그대로 들어갑니다. 이 점 주의해주세요.

마무리하며
이렇게 javascript로 태그를 동적으로 추가하는 다양한 방법에 대해 알아보았습니다. 개인적으로는 노드로 추가해서 만든다면 append
같은 함수들을 많이 사용하고, 문자열을 넣는다면 insertAdjacentHTML
을 많이 사용합니다. 여러분들은 어떤가요?!