[JS] 요소 노드의 텍스트 조작하기(nodeValue, textContent, innerHTML)

초코침·2023년 2월 24일
0

JavaScript

목록 보기
6/26

Node.prototype.nodeValue

nodeValue

  • setter와 getter가 모두 존재하는 접근자 프로퍼티
  • 참조와 할당이 모두 가능
  • 노드 객체의 nodeValue 프로퍼티를 참조하면 노드 객체의 값(텍스트 노드의 텍스트) 리턴
  • 텍스트가 아닌 노드(문서 노드, 요소 노드 등) 참조 시 null 리턴

텍스트 읽기

요소 노드의 텍스트 노드요소 노드의 자식 노드이므로 firstChild 프로퍼티로 접근할 수 있다(물론 firstChild 프로퍼티가 반환한 노드가 요소 노드일 수 있다.).

텍스트 쓰기

Node.prototype.textContent

textContent

  • setter와 getter가 모두 존재하는 접근자 프로퍼티
  • 참조와 할당이 모두 가능
  • 요소 노드의 텍스트와 모든 자손 노드의 텍스트를 모두 취득하거나 변경
  • 요소 노드의 textContent 프로퍼티를 참조하면 요소 노드의 콘텐츠 영역 내의 텍스트를 모두 반환
  • 콘텐츠 영역의 HTML 마크업은 무시됨

텍스트 읽기

div 내부에 있는 HTML 마크업 span은 무시되고 텍스트만을 가져온다.

텍스트 쓰기

새로 할당한 문자열에 HTML 마크업이 포함되어있다 하더라도 파싱되지 않고 문자열로 인식한다.

textContent와 유사한 innerText 프로퍼티

innerText 프로퍼티는 CSS에 순종적이기 때문에, CSS를 고려해야하므로 textContent 프로퍼티보다 느리다는 단점이 있기 때문에 textContent의 사용이 더 권장된다.

Element.prototype.innerHTML

innerHTML

  • setter와 getter가 모두 존재하는 접근자 프로퍼티
  • 요소 노드의 HTML 마크업을 취득하거나 변경
  • 요소 노드의 innerHTML 프로퍼티를 참조하면 요소 노드의 콘텐츠 영역 내의 모든 HTML 마크업을 문자열로 반환
  • textContent와 다르게 HTML 마크업을 무시하지 않음
  • 요소 노드의 innerHTML 프로퍼티에 문자열을 할당하면 요소 노드의 모든 자식 노드가 제거되고 할당한 문자열에 포함되어 있는 HTML 마크업이 파싱되어 요소 노드의 자식 노드로 DOM에 반영됨

텍스트 읽기

textContent와 다르게 span 태그도 포함하여 문자열로 가져온다.

텍스트 쓰기

textContent와 다르게 새로 할당할 문자열에 들어있는 span 태그를 HTML 마크업으로 인지한다.

+= 를 사용하면 innerHTML에 문자열을 이어 붙일 수 있다.

innerHTML의 단점

XSS 공격

요소 노드의 innerHTML 프로퍼티에 할당한 HTML 마크업 문자열은 파싱되어 요소 노드의 자식으로 DOM에 반영된다. 이때 사용자로부터 받은 입력 데이터를 그대로 innerHTML에 반영하는 것은 XSS 공격(Cross-Site Scripting Attacks)에 취약하므로 위험하다. HTML 마크업 내에 자바스크립트 악성 코드가 포함되어 있다면 파싱 과정에서 그대로 실행될 수 있기 때문이다.

document.getElementId('foo').innerHTML='
	<script>자바스크립트로 작성된 악성코드 ㄷㄷ</script>
';

따라서 HTML5에서는 프로퍼티로 삽입된 자바스크립트 코드를 실행하지 않는다. 다만, 자바스크립트 코드 이외에도 에러 이벤트를 강제로 발생시켜서 자바스크립트 코드가 실행되도록 할 수 있기 때문에 XSS 공격이 가능하다. 이를 대비해 HTML 새니티제이션을 할 수 있다.

요소 추가의 비효율성

변경이 없는 요소도 모두 제거 됐다가 새롭게 생성된다.

$list.innerHTML += '<li>사과</li>';
$list.innerHTML += '<li>배</li>';
$list.innerHTML += '<li>복숭아</li>';

+=를 사용하면 변경이 없는 요소는 내버려두고 문자열을 이어 붙이기만 하는 것처럼 동작하지만, 사실은 변경이 없는 요소도 지워졌다가 새로 만들어진다 즉, 기존 자식 노드를 모두 제거하고 새롭게 자식 노드를 생성해 DOM에 반영하게 되어 비효율적이다.

요소 삽입 시 위치 지정 불가

요소를 삽입할 땐 항상 마지막에 추가만 가능하다.

<body>
    <ol id="list">
      <li>사과</li>
      <li>포도</li>
    </ol>
</body>

사과와 포도 사이에 새로운 요소를 넣고 싶어도 innerHTML을 사용하면 넣을 수 없다. innerHTML은 복잡하지 않은 요소를 새로 추가할 때는 유용하겠으나, 기존 요소를 제거하지 않고 위치를 지정해 새로운 요소를 삽입할 때는 적합하지 않은 프로퍼티다.

profile
블로그 이사중 🚚 (https://sungjihyun.vercel.app)

0개의 댓글