Logo

jQuery 없이 자바스크립트만으로 HTML 요소 조작하기

2006년에 출시되었던 jQuery는 한 때는 자바스크립트 개발이 곧 jQuery 개발이라고 여겨질 정도로 정도로 상당히 오랫동안 자바스크립트 생태계를 주름잡던 라이브러리입니다. 하지만 최근에는 React, Angular, Vue.js, Svelte와 같은 모던 자바스크립트 라이브러리에 밀려 주로 레거시(legacy) 코드에서나 미처 못해 쓰는 라이브러리로 전략하고 말았는데요. 아무래도 컴포넌트 기반의 웹 프로그래밍의 대세가 되고 브라우저의 표준화가 전반적으로 개선되고 있어서 앞으로 jQuery의 입지는 점점 더 좁아질 것 같습니다.

사실 예전에 jQuery로 많이 하던 대부분의 작업들은 이제 자바스크립트의 DOM API만으로도 충분히 대체할 수 있는데요. 이번 포스팅에서는 jQuery 없이 순수하게 자바스크립트만을 이용하여 HTML 문서에 특정 요소를 선택하고 조작하는 방법에 대해서 알아보겠습니다.

jQuery: jQuery(), $()

먼저 과거에 jQuery를 이용해서 HTML 문서에서 요소(element)를 어떻게 선택했었는지 간단히 상기해보겠습니다.

jQuery는 CSS 선택자를 넘기면 해당 선택자에 부합하는 모든 요소를 반환하는 jQuery() 또는 줄여서 $() 함수를 제공했습니다.

예를 들어, HTML 문서 상에서 <p> 태그를 사용하고 있는 모든 요소는 다음과 같이 얻을 수 있었습니다.

const $p = jQuery("p");
// 또는 줄여서 ...
const $p = $("p");

참고로 이 함수는 jQuery에서 제공하는 다른 메서드를 계속 연결하여 연쇄적으로 호출을 할 수 있도록 특수한 타입의 객체를 반환합니다. (이러한 프로그래밍 기법을 보통 메서드 체이닝(method chaining)이라고도 합니다.)

따라서 jQuery()$() 함수로 선택한 요소를 대상으로는 JavaScript의 DOM API를 사용할 수 없으며, 이것이 한 번 jQuery로 작성된 코드는 순수 자바스크립트 코드로 변환하기 어려운 이유이고도 합니다.

JavaScript: querySelector(), querySelectorAll()

자바스크립트에서는 jQuery와 동일한 방식으로 CSS 선택자를 넘겨서 원하는 HTML 요소를 찾을 수 있도록 querySelector(), querySelectorAll() 함수를 제공하고 있습니다. 함수 명이 암시하듯이 querySelector() 함수는 선택자에 부합하는 요소 중에서 첫 번째 요소만을 반환하고, querySelectorAll() 함수는 선택자에 부합하는 모든 요소를 반환합니다.

위에서 jQuery로 작성한 코드를 avaScript의 DOM API를 사용해서 재작성 해보겠습니다.

// 첫번째 요소
const pEl = document.querySelector("p");
// 여러 요소
const pEls = document.querySelectorAll("p");

위와 같이 querySelector()querySelectorAll() 함수를 사용하면 반환된 HTML 요소를 상대로 자연스럽게 DOM API에서 제공하는 다른 메서드를 사용할 수 있게 됩니다.

흔히 이렇게 외부 라이브러리를 사용하지 않거나 최소한으로 사용하여 작성한 자바스크립트 코드를 Vanilla JavaScript라고 하는데요. 어떤 라이브러리나 프레임워크를 사용하더라도 작동이 잘 되는 큰 장점이 있습니다.

텍스트 변경하기

지금부터 실제 프로젝트에서 접해볼만한 jQuery 사용 사례를 살펴보도록 하겠습니다.

다음 <h1> 요소의 텍스트를 안녕하세요!로 어떻게 바꿀 수 있을까요?

<h1 id="title">제목 미정</h1>

먼저 jQuery의 $() 함수를 이용해서 작성해보겠습니다.

const $heading = $("h1#title");
$heading.text("안녕하세요!");

이제 자바스크립트의 querySelector() 함수를 작성해보겠습니다.

const headingEl = document.querySelector("h1#title");
headingEl.textContent = "안녕하세요!";

jQuery의 text() 함수는 DOM API의 textContent 속성으로 간단하게 대체가 가능함을 알 수 있습니다.

스타일 변경하기

예전에는 jQuery로 HTML 요소의 스타일을 변경하곤 했었는데요.

다음 3개의 <div> 요소에 파란색 테두리를 적용하고 공백을 24px, 너비를 48px로 설정해볼까요?

<div class="fruit">딸기</div>
<div class="fruit">바나나</div>
<div class="fruit">수박</div>

먼저 jQuery의 $() 함수를 이용해서 작성해보겠습니다.

const $fruits = $("div.fruit");
$fruits.css("border", "1px solid blue");
$fruits.css("padding", "24px");
$fruits.css("width", "48px");

이제 자바스크립트의 querySelectorAll() 함수를 작성해보겠습니다.

const fruitEls = document.querySelectorAll("div.fruit");
fruitEls.forEach((el) => {
  el.style.border = "1px solid blue";
  el.style.padding = "24px";
  el.style.width = "48px";
});

여기서 주의깊게 볼 점은 jQuery를 사용할 때는 몇개의 요소가 선택이 되던지 일괄적으로 다음 메서드가 적용된다는 것입니다. 따라서 css() 메서드 한 번 호출할 때 마다 3개의 <div> 요소에 동일할 스타일이 반영됩니다.

반면에 자바스크립트의 querySelectorAll() 함수를 사용할 때는 forEach() 함수를 이용해서 루프를 돌면서 각 요소에 스타일을 적용해줘야 합니다.

클래스 변경하기

HTML 요소의 클래스를 추가하거나 삭제하는 것도 jQuery로 흔히 했던 작업이었습니다.

예를 들어, 첫 번째 <div> 요소로 부터 active 클래스를 삭제하고, 반대로 두 번째와 세 번째 요소에 active 클래스를 추가해보겠습니다.

<div class="fruit active">딸기</div>
<div class="fruit">바나나</div>
<div class="fruit">수박</div>
.active {
  background: yellow;
}

먼저 jQuery로 작성해보겠습니다.

const $fruits = $("div.fruit");
$fruits.eq(0).removeClass("active");
$fruits.eq(1).addClass("active");
$fruits.eq(2).toggleClass("active");

이제 자바스크립트로 작성해보겠습니다.

const fruitEls = document.querySelectorAll("div.fruit");
fruitEls[0].classList.remove("active");
fruitEls[1].classList.add("active");
fruitEls[2].classList.toggle("active");

jQuery로 선택된 여러 개의 요소 중 각각의 요소를 접근할 때는 eq() 메서드를 사용하는 반면에 자바스크립트를 사용할 때는 배열을 다루듯이 인덱스를 사용하면 됩니다.

또한 jQuery 코드는 xxxClass() 형태의 메서드를 호출하는 반면에 자바스크립트 코드는 classList 속성을 통해서 동일한 작업을 수행합니다.

형제/부모 요소 선택하기

이미 선택된 요소를 기준으로 형제나 부모 요소를 선택하려면 어떻게 해야할까요?

<div>
  <div>딸기</div>
  <div class="active">바나나</div>
  <div>수박</div>
</div>

jQuery에서는 prev() 메서드를 사용해서 이전 요소, next() 메서드를 사용해서 다음 요소, parent() 메서드를 사용해서 부모 요소를 선택할 수 있었습니다.

$div = $("div.active");
$div.css("color", "yellow");
$div.prev().css("color", "red");
$div.next().css("color", "green");
$div.parent().css("background", "black");

자바스크립트에서도 동일한 기능할 하는 속성인 nextElementSibling, previousElementSibling, parentElement을 제공하고 있습니다.

const divEl = document.querySelector("div.active");
divEl.style.color = "yellow";
divEl.nextElementSibling.style.color = "green";
divEl.previousElementSibling.style.color = "red";
divEl.parentElement.style.background = "black";

하위 요소 탐색하기

마지막으로 살펴본 사례는 이미 선택된 요소의 하위에 있는 요소를 탐색하는 경우입니다.

다음 HTML 코드에서 <form> 요소를 먼저 선택하고, 그 아래에 있는 <input> 요소의 값을 입력해보겠습니다.

<form>
  <label>이메일<input type="email"/><label>
  <label>비밀번호<input type="password"/><label>
</form>

jQuery에서는 보통 find() 메서드를 사용해서 이미 선택된 요소 하위에 있는 요소를 선택할 수 있었습니다.

const $form = $("form");

const $email = $form.find('input[type="email"]');
$email.val("user@test.com");

const $password = $form.find('input[type="password"]');
$password.val("1234");

자바스크립트에서는 querySelector() 함수나 querySelectorAll() 함수를 문서(document) 뿐만 아니라 요소(element)를 대상으로도 호출할 수 있습니다.

const formEl = document.querySelector("form");

const emailEl = formEl.querySelector('input[type="email"]');
emailEl.value = "user@test.com";

const passwordEl = formEl.querySelector('input[type="password"]');
passwordEl.value = "1234";

<input> 요소의 값을 설정할 때, jQuery 코드는 val() 함수를 자바스크립트 코드는 value 속성을 사용하는 부분 주의하세요.

마치면서

이상으로 jQuery에서 하던 HTML 요소를 선택하고 조작하는 코드를 어떻게 순수하게 자바스크립트 코드로 대체할 수 있는지에 대해서 살펴보았습니다. jQuery의 API가 자바스크립트의 DOM API와 비슷한 것 같으면서도 살짝씩 달라서 좀 햇갈리시죠? 😓 예제 코드를 직접 작성하시다보면 금방 익숙해지시실 거라고 생각합니다.

jQuery의 예처럼 라이브러리 성쇄는 트랜드에 매우 민감합니다. 지금 잘 나가는 React도 언제가는 더 핫한 라이브러리로 인해 인기가 떨어지겠지요? 이럴수록 자바스크립트 본연의 기능을 잘 활용할 줄 아는 게 더욱 중요하지 않을까 생각해보면서 포스팅을 마무리하겠습니다.