jQuery DOM 조작 — 내용과 속성, 클래스를 바꾸는 방법

요소를 골랐다면 이제 바꿀 차례입니다. jQuery의 DOM 조작 메서드에는 공통 규칙이 하나 있는데, 이것만 잡아 두면 외울 양이 절반으로 줄어듭니다. 이 글에서는 그 규칙을 먼저 설명하고 내용·속성·클래스·스타일·구조를 바꾸는 메서드를 차례로 다룹니다.

괄호를 비우면 읽기, 값을 넣으면 쓰기

jQuery의 상당수 메서드는 이름이 하나인데 역할이 둘입니다. 인자를 주지 않으면 현재 값을 읽어 오고, 인자를 주면 그 값으로 바꿉니다. DOM이란 브라우저가 HTML을 읽어 메모리에 만들어 둔 나무 구조를 말하며, 우리가 실제로 손대는 대상이 바로 이것입니다.

var title = $('#noteTitle').text();      // 읽기
$('#noteTitle').text('오늘의 강좌 노트'); // 쓰기

$('#noteBody').html('<strong>중요</strong> 표시');
var keyword = $('#searchInput').val();   // 입력칸의 값 읽기
$('#searchInput').val('');               // 입력칸 비우기

세 메서드의 담당이 다릅니다. text는 태그를 뺀 순수 글자, html은 태그를 포함한 내용, val<input>이나 <select> 같은 폼 요소의 입력값을 다룹니다. 문단에 val()을 쓰면 빈 문자열만 돌아오므로 주의해야 합니다.

차이가 결정적으로 드러나는 때는 사용자가 입력한 글을 화면에 넣는 경우입니다. html()로 넣으면 사용자가 적은 태그가 진짜 태그로 해석됩니다. 댓글이나 검색어를 표시할 때는 반드시 text()를 써야 합니다.

attr과 prop — 적어 둔 값과 지금 상태

이 둘의 구분은 입문자가 가장 자주 틀리는 지점입니다. attr은 HTML 문서에 글자로 적혀 있는 속성을 다루고, prop은 브라우저가 관리하는 현재 상태를 다룹니다.

상황 써야 할 메서드 돌아오는 값
링크 주소 읽기·바꾸기 attr('href') 문자열
이미지 경로 바꾸기 attr('src') 문자열
체크박스가 지금 켜졌는지 prop('checked') true 또는 false
버튼 비활성화 여부 prop('disabled') true 또는 false
$('#noteLink').attr('href', '/jquery-event/');
$('#agreeBox').prop('checked', true);

if ($('#agreeBox').prop('checked')) {
  $('#submitBtn').prop('disabled', false);
}

사용자가 체크박스를 눌러 해제해도 HTML 원문의 checked 글자는 그대로 남아 있습니다. 그래서 attr('checked')로 확인하면 화면과 다른 답을 얻습니다. 켜짐과 꺼짐처럼 true 또는 false로 답할 수 있는 것은 전부 prop이라고 외워 두면 실수가 사라집니다.

클래스는 직접 스타일보다 안전합니다

화면 모양을 바꾸는 방법은 두 가지입니다. 스타일을 코드에서 직접 지정하거나, 미리 만들어 둔 클래스를 붙였다 떼는 것입니다.

$('#note12').addClass('active');
$('#note12').removeClass('draft');
$('#note12').toggleClass('open');   // 있으면 떼고 없으면 붙임

if ($('#note12').hasClass('active')) {
  $('#note12').find('.tag').css('color', '#c0392b');
}

// 여러 속성을 한 번에
$('.note-card').css({
  'border-radius': '8px',
  'padding': '16px'
});

css는 요소에 스타일을 직접 붙이기 때문에 나중에 CSS 파일로 덮어쓰기가 어려워집니다. 색이나 여백처럼 디자인에 속하는 값은 CSS 파일에 클래스로 정의해 두고 jQuery는 toggleClass로 상태만 바꾸는 편이 관리하기 좋습니다. css는 계산으로 얻은 값을 넣을 때처럼 꼭 필요한 경우에만 쓰시기 바랍니다.

구조를 바꾸는 다섯 가지 위치

새 요소를 끼워 넣을 때는 어디에 넣을지가 메서드 이름으로 구분됩니다. 안쪽인지 바깥쪽인지, 앞인지 뒤인지 네 갈래입니다.

var $card = $('#note12');

$card.append('<p>맨 안쪽 끝에 붙습니다</p>');
$card.prepend('<p>맨 안쪽 처음에 붙습니다</p>');
$card.after('<hr>');      // 카드 바깥, 바로 다음
$card.before('<hr>');     // 카드 바깥, 바로 앞

$card.empty();   // 카드 안을 비움 (카드는 남음)
$card.remove();  // 카드 자체를 지움

emptyremove의 차이를 놓치면 목록을 새로 그릴 때 컨테이너까지 사라져 버립니다. 목록 내용만 갈아 끼우는 상황에서는 empty가 맞습니다.

var titles = ['선택자 정리', '이벤트 위임', '애니메이션 큐'];
var $list = $('#noteList').empty();

$.each(titles, function (index, title) {
  $list.append('<li>' + (index + 1) + '. ' + title + '</li>');
});

반복문 안에서 append를 여러 번 부르면 그때마다 화면을 다시 계산합니다. 항목이 많다면 문자열을 먼저 이어 붙인 뒤 한 번만 호출하는 편이 빠릅니다. 순수 자바스크립트로 같은 일을 하려면 innerHTMLcreateElement를 나눠 써야 하는데, 그 내용은 자바스크립트로 HTML 문서 다루기에 정리돼 있습니다.

요소를 고르는 방법이 아직 익숙하지 않다면 jQuery 선택자를 먼저 보시고, 여기서 만든 요소에 동작을 붙이는 방법은 jQuery 이벤트에서 이어집니다.

핵심 정리

  • 하나의 이름, 두 가지 역할 — 인자가 없으면 읽기, 있으면 쓰기입니다.
  • text와 html — 사용자가 입력한 글을 표시할 때는 반드시 text를 씁니다.
  • attr과 prop — 문서에 적힌 값은 attr, 켜짐·꺼짐 같은 현재 상태는 prop입니다.
  • 클래스 우선 — 디자인 값은 CSS에 두고 toggleClass로 상태만 바꾸는 편이 안전합니다.
  • empty와 remove — 안쪽만 비울 것인지 요소째 지울 것인지 구분해야 합니다.