[JavaScript] textContent 와 innerText

hyowon·2021년 10월 12일
0

특정 요소를 숨기기 위해 display: none 을 사용하면 리플로우가 일어난다. 리플로우 없는 다른 방법이 없을까 생각하다가 textContent는 리플로우가 발생하지 않는다는 생각이 났다. 찾아보다가 textContent 와 innerText 차이를 알게되어서 정리하게되었다.

우선 textContent로 텍스트를 조작하는 일은 리플로우가 발생한다.

리플로우(reflow)란?
브라우저 렌더링 과정에서 생성된 DOM이나 CSSOM를 변경 하게 되면 변경된 DOM과 CSSOM이 다시 렌더 트리로 결합되고 변경된 렌더 트리를 기반으로 레이아웃과 페인트 과정을 거쳐 다시 렌더링 하는것을 리플로우, 리페인트라고 한다.

HTML 요소와 노드 객체

HTML 요소는 렌더링 엔진에 의해 파싱되어 DOM을 구성하는 요소 노드 객체로 변환된다. 이때 HTML 요소의 어트리뷰트는 어트리뷰트 노드로, HTML 요소의 텍스트 콘텐츠는 텍스트 노드로 변환된다.

이렇게 만들어진 노드 객체들은 HTML 요소의 중첩 관계에 의해 계층구조가 생긴다. 노드 객체들로 구성된 트리 자료구조를 DOM 이라 한다.

노드 객체도 자바스크립트의 객체이므로 프로토타입에 의한 상속을 받는다. 프로토타입 체인에 있는 모든 프로퍼티나 메서드를 사용 가능하다는 것이다. DOM이 제공하는 프로퍼티와 메서드를 DOM API라고 하고 DOM API를 사용하면 HTML의 구조나 내용, 스타일 등을 동적으로 변경할 수 있다.

textContent 와 innerText

textContent 와 innerText는 프로퍼티이다.
setter와 getter 모두 존재하는 접근자 프로퍼티로서 요소 노드의 텍스트와 모든 자손 노드의 텍스트를 모두 취득하거나 변경한다.

접근자 프로퍼티란?
자체적으로 값을 갖지 않고 다른 데이터프로퍼티의 값을 읽거나 저장할 때 호출되는 접근자 함수로 구성된 프로퍼티

<!DOCTYPE html>
<html>
  <body>
    <div id="foo">
      Hello <span style="text-transform: uppercase">world!</span>
    </div>
    <div id="bar">
      Hello <span style="text-transform: uppercase">world!</span>
    </div>
  </body>
  <script>
    const $foo = document.getElementById('foo');
    const $bar = document.getElementById('bar');

    console.log($foo.textContent); // Hello world!
    console.log($bar.innerText); // Hello WORLD!

    // HTML 마크업이 포함되어 있으면 문자열 그대로 텍스트로 취급된다.
    $foo.textContent = 'Hi <span>foo</span>';
    $bar.innerText = 'Hi <span>bar</span>';
  </script>
</html>

textContent 와 innerText 로 각각 id만 다르고 내용은 같은 foo와 bar의 텍스트를 가져오면 textContent는 css 는 고려되지않고 텍스트만 가져온다. innerText 는 css가 반영된 결과가 나오게 된다. 그 과정에서 리플로우가 발생하게 된다.

따라서 textContent로 단순히 텍스트를 가져올 때는 리플로우가 발생하지 않는다.

하지만 textContent로 텍스트를 변경할 때는 모든 자식 노드가 제거되고 할당한 문자열이 텍스트로 추가된다. 이것은 DOM을 조작하는 것이므로 리플로우가 발생하게 된다. innerText도 동일하다.

개념을 확실히 알고 구현하는 것이 중요하다고 생각했다.

참고
모던 자바스크립트 Deep Dive
https://developer.mozilla.org/ko/docs/Web/API/Node/textContent

0개의 댓글