본문으로 건너뛰기

글자와 클래스 바꾸기

자바스크립트 목차웹 페이지 움직이기레슨 67 / 76

목차

document.querySelector⁠로 요소를 찾았다면, 이제 그 요소의 **글자(textContent)**와 **클래스(classList)**를 바꿔 화면을 움직일 차례입니다. 여기서 가장 중요한 원리는 자바스크립트 변수를 바꿨다고 해서 화면이 저절로 바뀌지는 않는다는 점입니다.

5단계 중 1단계. let n = 2; 뒤 count.textContent에 대입하면 그때 계산한 문자열 "남음 2개"가 화면 요소에 들어갑니다.

1글자 읽기와 바꾸기: textContent

요소 안에 들어 있는 글자를 읽거나 새 글자로 바꿀 때는 el.textContent 속성을 씁니다.

<p id="count" class="count">
  전체 3개 중 2개 남음
</p>
결과 화면

여러 줄로 들여쓴 HTML 요소의 textContent를 읽으면 줄바꿈과 앞뒤 공백이 함께 따라옵니다. 그래서 글자를 읽어 비교할 때는 **.trim()**으로 앞뒤 공백을 깎아 냅니다(HTML·CSS 과목의 브라우저 규칙 2).

'use strict';

const countEl = document
  .querySelector('#count');
console.log(
  countEl.textContent.trim(),
);

countEl.textContent =
  '전체 3개 중 1개 남음';
실행 결과
전체 3개 중 2개 남음
(#count 글자 → 1개 남음)

반대로 countEl.textContent에 '전체 3개 중 1개 남음'처럼 새 문자열을 대입하면 화면의 글자가 그 자리에서 바뀝니다.

2변수를 바꿔도 화면은 저절로 바뀌지 않는다

2단원의 규칙 2(식은 그 줄을 실행할 때 한 번 계산되어 값으로 바뀐다)는 브라우저 화면에서도 그대로 적용됩니다.

아래 코드에서 n을 2에서 1로 바꿨을 때, countEl.textContent를 다시 대입하지 않으면 어떻게 되는지 보세요.

let n = 2;
const el = { textContent: '' };
el.textContent = `남음 ${n}개`;
n = 1;
console.log(el.textContent);

el.textContent = `남음 ${n}개`;
console.log(el.textContent);
실행 결과
남음 2개
남음 1개
  1. 3번 줄에서 `남음 ${n}개`는 그 순간의 값인 '남음 2개'로 계산되어 el.textContent에 들어갑니다.
  2. 4번 줄에서 n = 1로 변수를 바꿔도, 이미 들어가 있는 el.textContent는 저절로 바뀌지 않고 '남음 2개' 그대로입니다.
  3. 7번 줄처럼 바뀐 변수로 el.textContent에 다시 대입해야 화면 글자가 '남음 1개'로 바뀝니다.

3클래스 붙였다 떼기: classList

할 일 줄에 취소선을 긋거나 회색으로 바꿀 때 자바스크립트에서 글자 색과 줄 스타일을 일일이 적지 않습니다. CSS 파일(style.css)에 이미 .done .text 취소선(text-decoration: line-through) 규칙이 준비되어 있으므로, 자바스크립트는 **classList**로 'done' 클래스만 붙였다 똅니다.

'use strict';

const item = document
  .querySelector(
    '#todo-list li',
  );

item.classList.add('done');
item.classList.remove('done');
item.classList.toggle('done');
console.log(
  item.classList
    .contains('done'),
);
실행 결과
true
(첫째 줄에 취소선이 그어짐)
  • classList.add('done'): 'done' 클래스를 붙입니다(이미 있으면 그대로 둡니다).
  • classList.remove('done'): 'done' 클래스를 똅니다.
  • classList.toggle('done'): 'done'이 없으면 붙이고, 있으면 똅니다. 두 번째 인자로 불리언을 넘겨 toggle('done', t.done)⁠처럼 쓰면 둘째 인자가 참일 때 붙이고 거짓일 때 똅니다.
  • classList.contains('done'): 'done' 클래스가 붙어 있으면 true, 없으면 false를 돌려줍니다.

예제

결과를 먼저 생각한 뒤 펼쳐 보세요. 맞혀 보기는 점수에 들지 않습니다.

초기 상태가 <li class="todo">우유 사기</li>⁠인 요소를 li로 찾았습니다. 아래 네 줄을 차례로 실행한 뒤 li.classList.contains('done')⁠과 화면 글자는 무엇일까요?

'use strict';

let label = '우유 사기';
li.textContent = label;
label = '치즈 사기';
li.classList.toggle('done');
li.classList.toggle('done');
결과 보기
실행 결과
contains('done'): false
화면 글자: 우유 사기
  • toggle('done')을 두 번 불렀으므로 붙었다가 다시 떨어져 false입니다.
  • label = '치즈 사기'로 변수만 바꾸고 li.textContent = label⁠을 다시 대입하지 않았으므로 화면 글자는 '우유 사기' 그대로입니다.

자주 틀리는 곳

  1. 변수를 바꾸면 화면도 저절로 바뀐다고 생각한다: let count = 2;를 count = 1;로 바꿨다고 해서 이전에 넣은 countEl.textContent가 따라 바뀌지 않습니다. 상태를 바꾼 뒤에는 늘 화면 요소의 textContent나 classList를 다시 갱신해야 합니다.
  2. 사용자가 입력한 글자를 innerHTML에 넣는다: el.innerHTML = text는 문자열 속의 <script>나 HTML 태그를 실제 태그로 해석해 실행하므로 악성 스크립트가 실행되는 보안 문제(XSS)가 생깁니다. 글자를 넣을 때는 태그를 글자 그대로 안전하게 표시하는 **textContent**를 씁니다.
  3. classList 대신 el.style로 모양을 직접 고친다: 자바스크립트에서 el.style.color = 'gray'⁠처럼 직접 스타일을 박아 넣으면 다크 모드나 CSS 규칙과 충돌합니다. 모양은 CSS 클래스(.done, .active)에 맡기고 자바스크립트는 classList만 바꿉니다.
  4. 자식 요소가 있는 부모에 textContent = '글자'를 대입한다: 체크박스와 <span class="text">, 삭제 단추가 들어 있는 li에 바로 li.textContent = '치즈'⁠를 대입하면 안쪽의 체크박스와 삭제 단추가 통째로 지워집니다. 글자만 바꿀 때는 안쪽 span.text를 찾아 바꿔야 합니다.

확인 문제

  1. el.classList.toggle('active')⁠를 실행할 때, el에 이미 'active' 클래스가 붙어 있었다면 어떻게 되나요?
정답

'active' 클래스가 제거됩니다(toggle은 있으면 떼고, 없으면 붙입니다).

  1. 사용자가 입력 칸에 친 할 일 글자 text를 span 요소에 넣으려고 합니다. span.innerHTML = text 대신 span.textContent = text⁠를 써야 하는 까닭을 쓰세요.
정답

innerHTML은 입력 글자 안의 태그 기호를 HTML 태그로 해석해 의도하지 않은 스크립트가 실행될 위험(XSS)이 있지만, textContent는 어떤 글자든 안전한 일반 텍스트로만 넣기 때문입니다.

  1. 다음 코드가 끝난 뒤 화면의 #count 문단에 보이는 글자는 '1개'인가요, '2개'인가요? '1개'가 보이게 하려면 마지막에 어떤 한 줄을 더해야 하나요?
'use strict';
let left = 2;
const c = document
  .querySelector('#count');
c.textContent = `${left}개`;
left = left - 1;
정답

화면에는 여전히 '2개'가 보입니다. 변수 left를 바꾼 뒤 마지막 줄에 c.textContent = ... 대입을 한 번 더 실행해야 '1개'로 바뀝니다.

끝까지 내려오면 저절로 표시됩니다. 이 기기에만 저장합니다.

자바스크립트 목차로