티스토리 뷰

자바스크립트

createElement vs innerHTML

devhanyoung 2024. 4. 9. 21:20

 

우아한테크코스 레벨 1 미션을 하며 바닐라 JS로 SPA 앱을 만들게 되었다.

동적 렌더를 하기 위해서는 JS를 통해 DOM Element를 추가해야 했다.

리액트만 사용했던 터라 JS로 DOM Element를 추가하는 방법에 대해 진지하게 고민해본 적은 없었다.

 

이번 기회에 학습해보니 DOM Element를 추가할 수 있는 방법에는 크게 두 가지가 있었다.

바로 createElement와 innerHTML이다.

둘은 결과물만 놓고 보았을 때는 유사하지만, 사용 방법이나 동작 방식, 그리고 그에 따른 장단점에 차이가 존재했다.

 

이번 포스팅을 통해 두 방식의 사용법에 대해 간단히 알아보고, 둘을 비교해보겠다.

 

목차는 다음과 같다.

1. 소개
  1-1. createElement
  1-2. innerHTML
2. 비교
  2-1. createElement가 더 좋은 점
  2-2. innerHTML이 더 좋은 점
3. 참고) insertAdjacentHTML

 

(엄밀히 따지자면 createElement는 요소를 생성하는 함수이고, innerHTML은 DOM Element의 프로퍼티이므로 비교 대상으로 보기 애매하다. 본문에서는 createElement(append하는 절차까지 포함해서 생각)와 innerHTML을 요소를 추가하는 방식으로 바라보고 서술하겠다.)


1. 소개

먼저 createElement와 innerHTML에 대해 간단히 알아보자.

1-1. createElement

createElement(tagName)
createElement(tagName, options)

사용법은 매우 간단하다.

태그 이름을 넘기면 해당 태그의 요소가 만들어져 반환된다.

두번째 인자인 option 객체에는 is 프로퍼티를 포함할 수 있는데, 이는 custom element의 tag 이름이 된다. (거의 사용하지 않을 것 같다.)

// createElement를 이용하여 customElement를 생성하는 로직
const someList = document.createElement("ul", { is: "some-list" });

// 동일한 형태의 customElement 요소 선언 로직 (생성 x) / 지금 맥락에서 꼭 이해해야 하는 코드는 아님
class SomeList extends HTMLUListElement {}
customElements.define("some-list", SomeList);

 

참고로, createElement는 요소를 생성하는 역할만 수행한다.

따라서 요소의 속성을 설정하거나 텍스트를 집어넣는 등의 처리를 위해서는 별도의 로직이 필요하다.

사용 방식은 아래와 같다.

// 요소 생성
const newElement = document.createElement("div");

// 요소 설정
newElement.textContent = "새로운 요소";
newElement.className = "myClass";
newElement.id = "myId";

// 요소를 DOM에 추가
document.body.append(newElement);

1-2. innerHTML

innerHTML의 사용법은 createElement보다 더 간단하다.

// innerHTML을 통해 문자열 형태의 요소를 받아옴
const content = element.innerHTML;

// 마크업 문자열을 파싱해 요소를 생성하고, 그 요소로 기존 자식 요소를 대체함
element.innerHTML = "<div id='myId' class='myClass'>New Element 입니다</div>"

단지 마크업 문자열만 할당하면 요소가 추가된다(기존 자식 요소를 대체).

 

2. 비교

얼핏만 봐서는 간단하게 사용할 수 있는 innerHTML이 더 좋아보인다.

그런데 둘을 비교해보면 꼭 그렇지만은 않다.

각각의 장단점에는 무엇이 있는지 살펴보자.

2-1. createElement가 더 좋은 점

  • 성능 상 이점이 있다: createElement는 요소를 새롭게 만든다. 그리고 Element.append는 해당 요소의 원래 자식 요소들은 그대로 두고 새로운 요소를 추가하기만 한다. 그에 반해 innerHTML은 해당 요소 내부 모든 자식 요소를 대체한다. 이때 내부 모든 요소에 대해  reparse와 recreate가 이뤄진다. 따라서 일부 요소만 추가하는 경우에도 기존의 자식 요소도 전부 다시 파싱하고 생성하는 비용이 불필요하게 발생한다. 이런 점으로 인해, 기존의 자식 요소를 유지한 채 새로운 요소를 추가만 하는 경우에는 createElement가 성능 상 유리하다.
  • 보안 상 더 안전하다: innerHTML은 문자열 그대로를 파싱하기 때문에 해당 문자열에 script 태그가 포함된다면 보안에 위협이 될 수 있다. XSS 공격에 노출되는 것이다. 따라서 사용자의 입력 값에 기반해서 요소를 만들 때 주의를 기울여야 한다. 태그 형태의 문자열도 단순 문자열로만 파싱하는 textContent 속성을 이용하거나, 태그가 포함된 사용자 입력값을 sanitize해야 한다. 반면 createElement을 이용하면 문자열 전체를 그대로 파싱하는 일이 없기 때문에 이런 고민을 할 필요가 없다. 

2-2. innerHTML이 더 좋은 점

  • 사용법이 직관적이며 가독성이 좋다: createElement는 사용하기가 굉장히 번거롭다. 요소를 생성하고, 해당 요소에 담긴 내용이나 속성 설정을 별도의 로직으로 처리해 주어야 하기 때문이다. 그래서 createElement로 작성된 코드는 상당히 절차적이다. 이에 반해 innerHTML은 그저 마크업 문자열만 입력해주면 된다. 적은 그대로 요소가 채워지기 때문에 상당히 직관적이다.

 

참고) insertAdjacentHTML

innerHTML의 가독성 측면의 장점과 createElement의 성능 상 이점을 모두 누릴 수 있는 api가 있다.

바로 insertAdjacentHTML이다.

insertAdjacentHTML은 아래와 같이 사용할 수 있다.

Element.insertAdjacentHTML(position, "<div id='myId' class='myClass'>new element 입니다</div>")

 

innerHTML과 마찬가지로 간편하게 마크업 문자열을 이용해 요소를 추가할 수 있다.

position을 통해 삽입할 요소의 위치를 지정할 수 있다(beforebegin, afterbegin, beforeend, afterend).

insertAdjacentHTML은 문자열을 이용해 간편하게 요소를 추가하면서도, 기존의 요소를 대체하지 않으므로 과도한 reparse, recreate이 발생하지 않는다.

 

한편, innerHTML과 마찬가지로 XSS 공격에는 취약하다는 단점이 있다.


짧은 소감

js를 공부하다보면 비슷한 동작을 수행하는 api가 정말 많다.

이때 각각의 특징을 모른다면, 그저 익숙하다는 이유로 더 비효율적이거나 부적절한 도구를 사용하게 될 수도 있다.

선택지가 많아 보일 때 무작정 익숙한 것을 채택하기보다는, 어떤 옵션이 있는지 충분히 고민해서 좋은 선택을 하자.

물론 모든 선택지에는 trade off가 있으니 완벽한 선택지란 없다.

하지만 적어도 그것을 선택한 나만의 이유는 존재해야 할 것이다.


참고 자료 🙇🏻‍♂️

[javascripttutorial.net] JavaScript innerHTML vs createElement

 

'자바스크립트' 카테고리의 다른 글

실행 컨텍스트와 JS 코드 실행 과정 탐구  (0) 2024.03.27