HTML에서는 innerHTML, innerText, textContent가 DOM(Document Object Model)의 속성으로, HTML 요소의 내용을 읽고 업데이트할 수 있게 해줍니다.

하지만 이들은 포함하는 내용과 HTML 마크업을 다루는 방법에 있어 차이가 있습니다.

이 글을 끝까지 읽고 나면, 이 세 속성의 차이점과 각각을 언제 사용해야 하는지 알게 될 것입니다.

목차

  • innerHTML 속성이란 무엇인가요?
  • innerText 속성이란 무엇인가요?
  • textContent 속성이란 무엇인가요?
  • innerHTML, innerText, textContent로 내용을 읽는 방법
  • innerHTML, innerText, textContent로 내용을 업데이트하는 방법
  • innerHTML을 사용할 때의 보안 문제
  • 결론

먼저 이 세 속성이 어떻게 작동하는지 설명하겠습니다. 그리고 나면 몇 가지 사용 예제를 통해 그 차이를 경험해볼 수 있을 것입니다.

innerHTML 속성이란 무엇인가요?

innerHTML 속성을 사용하면 요소의 HTML 마크업과 텍스트 내용을 모두 읽을 수 있습니다. 이 말은 요소의 내용을 설정할 때 HTML 태그를 포함할 수 있으며, 브라우저가 이를 올바르게 렌더링한다는 뜻입니다.

하지만, 사용자 입력이나 신뢰할 수 없는 출처로부터 내용을 innerHTML을 통해 삽입하는 경우에는 조심해야 합니다. 공격자들은 HTML 에 script 태그를 이용해 악의적인 코드를 삽입하고 앱에서 실행할 수 있습니다. 이에 대해선 글 뒷부분에서 자세히 다루겠습니다.

innerText 속성이란 무엇인가요?

이 속성은 렌더링된 텍스트 내용에 초점을 맞춥니다. innerText를 사용해 요소의 내용을 읽을 때, 화면에 나타나는 그대로의 텍스트를 반환합니다. HTML 태그는 무시됩니다. 또한 CSS 스타일로 숨겨진 텍스트도 포함하지 않습니다.

스타일을 반영해야 할 때는 innerText를 사용하는 것을 고려해야 합니다. 요소의 innerText를 수정하면 브라우저가 텍스트 크기 변경에 맞춰 레이아웃을 조정해야 할 수 있기 때문에 성능에 영향을 줄 수 있습니다.

textContent 속성이란 무엇인가요?

textContent 속성도 모든 HTML 태그를 무시하고 텍스트만 반환합니다. innerText가 화면에 렌더링된 텍스트를 읽는 반면, textContent는 마크업 그대로의 텍스트를 읽습니다. 화면에 표시되는 것과 상관없이 모든 텍스트를 반환합니다.

또한, textContent는 스타일을 고려하지 않고 순수한 텍스트만 다룹니다. 그러므로 성능이 중요한 상황에서 스타일을 반영할 필요가 없다면 textContent가 innerText에 비해 효율적인 선택이 될 수 있습니다.

innerHTML, innerText, textContent로 내용 읽기
이제 몇 가지 실용적인 예제를 통해 세 속성을 더 잘 이해해봅시다.

다음은 네 개의 항목이 있는 간단한 내비게이션 바를 위한 마크업입니다. “Pricing”이라는 텍스트를 가진 마지막 요소는 숨겨져 있습니다(디스플레이 설정이 none). 모든 세 속성을 사용해서 nav 요소의 콘텐츠를 확인해보겠습니다.

<nav>
  <a>Home</a>
  <a>About</a>
  <a>Contact</a>
  <a style="display: none">Pricing</a>
</nav>

innerHTML로 내용 가져오기

// Reading content with innerHTML
const navElement = document.querySelector('nav')
console.log(navElement.innerHTML)

nav 요소 안의 모든 HTML 태그와 그 텍스트 내용을 포함한 전체 콘텐츠를 innerHTML 속성이 반환합니다.

innerText로 내용 가져오기

// Reading content with innerText
const navElement = document.querySelector('nav')
console.log(navElement.innerText)

innerText 속성은 화면에 렌더링된 내용을 반환합니다. 모든 HTML 태그를 무시합니다. 그리고 숨겨진 요소(디스플레이가 none으로 설정된)도 무시합니다.

textContent로 내용 가져오기

// Reading content with textContent
const navElement = document.querySelector('nav')
console.log(navElement.textContent)

textContent 속성은 HTML 마크업 그대로의 콘텐츠를 반환합니다. innerText처럼 HTML 태그를 무시하지만 스타일은 고려되지 않아 숨겨진 “Pricing” 텍스트도 반환합니다.

innerHTML, innerText, textContent로 내용 업데이트하기

이 세 속성은 DOM 요소의 내용을 업데이트할 때도, 내용을 읽거나 가져올 때처럼 비슷하게 동작합니다.

이를 좀 더 이해하기 위한 예제를 살펴보겠습니다.

innerHTML로 내용 설정하기

아래 마크업에는 헤더 요소와 빈 ul 태그가 포함되어 있습니다. innerHTML 속성을 사용해 ul태에 몇 가지 내용을 삽입할 수 있습니다.

<h2>Programming languages</h2>
<ul class="languages-list"></ul>
const langListElement = document.querySelector('.languages-list')

// Setting or updating content with innerHTML
langListElement.innerHTML = `
  <li>JavaScript</li>
  <li>Python</li>
  <li>PHP</li>
  <li>Ruby</li>
`

JavaScript 코드는 HTML 리스트의 문자열을 innerHTML의 값으로 전달합니다. innerHTML 속성은 HTML 태그를 인식하고 내용을 그에 맞게 형식화합니다.

innerHTML과 달리 innerText와 textContent는 HTML 태그를 무시하고 모든 것을 문자열로 렌더링합니다.

innerText로 내용 설정하기

같은 예제를 사용해서 innerText 속성으로 프로그래밍 언어 목록의 내용을 업데이트하는 방법을 살펴보겠습니다.

const langListElement = document.querySelector('.languages-list')

langListElement.innerText = `
  <li>JavaScript</li>
  <li>Python</li>
  <li>PHP</li>
  <li>Ruby</li>
`

innerText는 HTML 태그를 무시하고 화면에 그대로의 텍스트로 출력합니다. 하지만 줄바꿈과 공백은 여전히 인식합니다.

textContent로 내용 설정하기

내용을 설정하거나 업데이트할 때, textContent 속성은 HTML 마크업을 무시하고 줄바꿈, 공백과 같은 것들도 무시합니다.

const langListElement = document.querySelector('.languages-list')

langListElement.textContent = `
  <li>JavaScript</li>
  <li>Python</li>
  <li>PHP</li>
  <li>Ruby</li>
`

textContent는 줄바꿈과 공백을 무시하기 때문에 모든 텍스트가 같은 줄에 표시됩니다. 텍스트 형식이 중요하지 않음에도 원본 텍스트를 원할 때는 textContent가 적절한 선택이 됩니다.

innerHTML을 사용할 때의 보안 문제

innerHTML은 HTML 태그를 처리하고 해석하기 때문에, 신뢰할 수 있는 출처에서 내용을 삽입하거나 적절히 검증하고 정화한 내용만 사용하는 것이 좋습니다.

브라우저는 HTML script 태그 안에 넣은 JavaScript 코드를 실행할 것입니다. 이는 Cross-Site Scripting (XSS)에 문을 열 수 있는데, 여기서 공격자들은 당신의 웹 페이지 컨텍스트에서 악의적인 스크립트를 주입하고 실행할 수 있습니다.

예를 들어 보겠습니다:

앱에서 사용자 코멘트를 위한 컨테이너로 div를 사용한다고 가정합시다. 코멘트를 추가하기 위해 검증이나 정화 없이 innerHTML을 사용합니다.

이는 사용자가 악의적인 스크립트를 주입하고 실행할 수 있다는 예를 들어 더 간단한 예시입니다:

const commentSection = document.getElementById('commentSection')

let userComment = `<img src="malicious-script.jpg" onerror="alert('Malicious Script Executed!')"> This is my comment!`;

commentSection.innerHTML = userComment;

사용자는 일부러 이미지의 src 속성값으로 잘못된 값을 줍니다. 이것은 onerror 이벤트를 트리거하고 “Malicious Script Executed!”라는 문자열이 있는 경고를 실행합니다.

공격자가 중요한 사용자 정보를 훔치거나 페이지 내용을 조작하거나 기타 악의적인 행동을 취할 수 있는 유해한 JavaScript 코드를 주입하는 데 이용할 수 있다는 것을 상상해볼 수 있겠습니다.

결론

innerHTML, innerText, textContent 세 속성을 사용하여 DOM 요소의 내용을 조작할 수 있지만 서로 다르게 동작합니다. 이들을 이해하는 것은 각각을 적절히 사용해야 할 순간을 결정하는 데 도움이 될 것입니다.

innerHTML 속성은 HTML 태그를 인식하고 태그에 따라 내용을 렌더링합니다. 반면, innerText와 textContent는 HTML 태그를 무시하고 텍스트의 일부분으로 처리합니다. 이 글에서도 배운 바와 같이 innerHTML은 보안 위험을 초래할 수 있고, 이 점을 유의해야 한다는 것을 알게 되었습니다.

또한, innerText는 화면에 나타나는 내용을 읽고 숨겨진 내용은 무시하며 텍스트 서식을 반영합니다. 그러나 textContent는 마크업에 나타나는 내용을 읽습니다. 이는 숨겨진 내용도 읽는다는 것을 의미하지만 내용을 설정할 때는 공백이나 줄 바꿈과 같은 서식을 무시하게 됩니다.