innerHTML 프로퍼티에는 HTMLstring만 사용할 수 있다.
el.innerHTML='<div title="Some title">Some text</div>';
name = "<script>alert('I am John in an annoying alert!')</script>";
el.innerHTML = name; // harmless in this case
위와 같이 텍스트로 자바스크립트 코드를 실행시킬수 있기 때문에 위험할수도 있다. HTML5에서는 Script를 감지하여 방지할 수 있다.
하지만 Script를 사용하지 않고도 자바스크립트 코드를 실행시킬수 있는 방법이 있어 보안위험성이 여전히 존재하기 때문에 일반 텍스트를 삽입 할 때 Node.textContent
를 사용하는 것을 추천한다.
(분명 HTML을 파싱해야 할일이 있을텐데 그러면 내가 작성한 코드는 아래 내용을 주의해서 사용하고 외부 코드를 사용할 때는 innerHTML 사용하는 것을 지양하면 되지 않을까라는 생각이 든다.)
const name = "<img src='x' onerror='alert(1)'>";
el.innerHTML = name; // shows the alert
반면에 appendChild는 innerHTML과 다르게 의도치 않은 코드 실행을 예방할 수 있다. 예를 들면 텍스트에는 일부 자바스크립트 코드가 포함되어있을수도 있는데 innerHTML은 이 자바스크립트 코드가 실행될수도 있지만 appendChild는 텍스트를 text node로 변환하기 때문에 안전하다.
appendChild 메서드에는 Node object만 사용할 수 있다.
const parent = document.createElement('ul');
const child = document.createElement('li');
parent.appendChild(child);
// <ul><li></li></ul>
Node는 DOM에 있는 모든 타입의 객체에 부여되는 일반적인 이름이다. 예를 들면 Document
, <HTML></HTML>
, <a></a>
, Text
들이 Node라고 할 수 있다.
Element는 element라고 불리는 Node type으로 <HTML></HTML>
, <a></a>
들이 해당한다. 즉 Node 아래에는 여러타입이 있고 그 타입 중에 element라고 불리는 Node type이 Element에 해당하는 것이다.
Node Type에는 아래와 같이 여러가지가 존재한다.
The following constants have been deprecated and are not in use anymore: Node.ENTITY_REFERENCE_NODE (5), Node.ENTITY_NODE (6), and Node.NOTATION_NODE (12).
아래와 같이 지정해야할 속성이 많아진다면 innerHTML이 간결하다.
// using innerHTML
el.innerHTML='<div title="Some title">Some text</div>';
// using appendChild
const cell = document.createElement("div");
cell.title = "Some title";
cell.appendChild(document.createTextNode("Some text"));
el.appendChild(cell);
innerHTML을 ++ㅡ +=와 같이 사용하는 경우 전체 태그의 내용을 재분석하고 모든 HTML 요소를 다시 생성하기 때문에 반복적으로 사용하는 경우 appendChild를 사용하는것이 좋다.
전체 태그의 내용을 재분석하기 때문에 이전의 Dom에 부착되어 있는 이벤트 리스너를 제거한다는 사실도 알고 있으면 좋다.