jQuery는 JavaScript의 뛰어난 라이브러리 중 하나입니다. 순수 JavaScript에 비해 간단하게 DOM접근을 할 수 있다는 것이 큰 이유입니다.

DOM이 무엇인지, 이 DOM접근을 하는 경우와 이유는 무엇인지 알아보고 DOM접근시 jQuery와 순수 JavaScript의 차이, 성능을 함께 알아보도록 하겠습니다.

1. DOM(Document Object Model)이란?

제가 DOM에 대하여 처음 공부를 시작할 때 가장 어려웠던 것이 바로 그 개념 자체였습니다. 그 이유는 기본적인 용어의 개념이 잘 잡혀있지 못했기 때문이라는 생각이 듭니다. 그래서 이번엔 아주 기본적인 개념도 함께 짚어봅니다.

문서(Document)란 HTML이나 XML문서과 같이 부분적 요소나 내용이 관련된 것들끼리 묶여서 존재하는 구조화 된 문서입니다.  (ex. 같은 내용은 같은 태그 안에 존재)

이렇게 구조화 된 문서에 스크립트를 이용하여 접근할 때에도, 구조적으로 표현하는 방식(Object Model)을 제공하는 것이 바로 DOM이라고 보면 됩니다.

각 element를 트리의 node로 표현하는 DOM트리를 통해 이를 쉽게 알 수 있습니다. (참고: 원래 DOM은 DNM(Document Node Model)로 불렸지만, 부르기 힘들다는 이유로 DOM이라고 불리게 되었습니다.) 다음 그림은 DOM을 통해 구조화된 HTML문서의 트리 구조를 보여줍니다.

[그림 1] DOM Tree 출처: http://www.w3schools.com/js/js_htmldom.asp

위 트리 구조를 보면, Element(태그)뿐만 아니라 Attribute, Text까지 노드로 표현되어 있음을 알 수 있습니다. 즉, DOM을 통해 스크립트가 문서 내의 모든 요소에 동적으로 접근할 수 있다는 것입니다.

그래서 DOM을 사용하면 문서상의 요소에 접근해 생김새나 내용, 속성을 조작할 수 있습니다. 뿐만 아니라 새로운 요소나 내용을 만들어서 사용자가 필요로 할 때 문서상에 적용시킬 수 있습니다. 이러한 점 때문에 DOM접근은 웹 페이지상의 풍부한 상호작용을 위해서 꼭 필요한 작업 중에 하나입니다.

하지만 이를 순수 JavaScript로 하게 되면, 다수의 반복문과 긴 스크립트를 작성해야 하는 경우가 많습니다. 바로 이 문제를 해결하는 것이 jQuery의 장점 중 하나입니다.

2.  jQuery의 DOM접근 & 순수 JavaScript의 DOM 접근

jQuery에서는 CSS의 선택자(Selector) 방식을 사용해서 DOM에 접근합니다. 아래 그림의 오른쪽이 jQuery에서 선택자를 사용하는 방식입니다. 선택자에는 여러 가지 종류가 있는데, 자주 사용하는 선택자로는 id선택자, class선택자, tag선택자 등이 있습니다. CSS선택자에 대한 더 자세한 정보는 제가 지난번에 포스팅 하였던 <CSS: 선택자(Selector) 이해>글을 참고해 주세요. CSS선택자를 이해하는 것이 jQuery를 사용하는 데에 큰 도움이 될 것입니다.

[그림 2] CSS선택자와 jQuery선택자

그럼 이제 jQuery에서의 DOM접근과 JavaScript에서의 DOM접근을 비교해보도록 하겠습니다.

위에서도 언급했듯이, jQuery에서는 위 그림의 내용처럼 jQuery DOM객체 생성함수인 $();을 사용하여 선택자로 간단하게 DOM에 접근합니다. 하지만 JavaScript에서는 브라우저의 여러 가지 내장 메소드(method)를 통해 DOM에 접근합니다.

표에 나오는 것 처럼 jQuery의 간단한 문법에 비해, 순수 JavaScript의 DOM접근은 다양한 종류의 긴 이름을 가진 메소드를 사용합니다. 위 표의 두번째 줄에 있는 태그를 통한 DOM요소 접근의 예를 한가지 보겠습니다.

$(function(){
	var a = document.getElementsByTagName("h2");
	console.log(a);
    
	var b = document.querySelectorAll("h2");
	console.log(b);
    
	var c = $("h2");
	console.log(c);
});

[예제 1] 브라우저 내장메소드와 jQuery선택자

이 코드가 반환하는 객체들을 살펴보았습니다.

[그림 3] 반환 객체

jQuery 선택자를 통해 반환된 객체는 jQuery객체이고, document.getElementsByTagName을 통해 반환된 객체는 HTMLCollection, document.querySelectorAll을 통해 반환된 객체는 NodeList입니다.

jQuery를 통해 선택하게 되면 jQuery객체, 순수 JavaScript를 통해 선택하면 native JavaScript객체를 반환한다는 것을 알 수 있습니다.

(참고: HTMLCollection과 NodeList의 차이는 http://stackoverflow.com/questions/15627385/what-is-the-difference-between-a-htmlcollection-and-a-nodelist-in-dom 이나 http://alebelcor.github.io/2011/htmlcollections-nodelists/ 를 참고하시면 좋을 것 같습니다.)

3. jQuery선택자의 내부적 처리

한가지 고려해야 할 문제가 있습니다. 바로 속도의 문제인데요. jQuery는 선택자를 사용해서 간단하게 DOM에 접근할 수 있지만, 각 방법별로 내부적 처리가 다르기 때문에 어떤 것은 빠르고 어떤 것은 느리다는 단점이 있습니다.

위에서 jQuery의 DOM접근과 순수 JavaScript의 DOM접근을 비교했지만 사실 jQuery는, 내부적으로 가능하다면 순수 JavaScript의 브라우저 내장 메소드를 사용하게 됩니다. 바로 속도 향상을 위해서인데요. 하지만 브라우저 내장 메소드가 지원되지 않는 경우, 모든 DOM노드를 순회해야 하기 때문에 속도가 느려집니다.

위의 브라우저 내장 메소드 중에서도 getElementsByClassName()은 IE8이하에서는 지원하지 않고, querySelector() / querySelectorAll() 메소드는 아래 그림 미만 버전의 브라우저에서는 지원하지 않기 때문에 브라우저에 따라서도 속도가 달라질 수 있습니다.

[그림 4] querySelector의 browser compatibility 출처: https://developer.mozilla.org/ko/docs/Web/API/Element.querySelector

jQuery선택자는 내부적으로 가능하다면 브라우저 내장 메소드를 사용한다고 말씀드렸습니다. 그러면, getElementsBy-() 의 메소드를 사용할 수 없는 선택자들은 (가능한 브라우저일 경우에) querySelector()나 querySelectorAll() 메소드를 사용하겠지요. 하지만 이조차도 불가능해서 jQuery가 직접 DOM tree를 순회해야만 하는 선택자들이 있습니다.

바로 jQuery만의 확장된 선택자인데요. 예를 들어 :last, :first, :even, :eq() 등이 있습니다. 이는 CSS 선택자 표준에 포함되지 않은 것으로 jQuery에서만 사용가능한 선택자 입니다. 아래는 jQuery API문서에서 jQuery Extension Selector에 대해 기술한 내용입니다.

jQuery has extended the CSS3 selectors with the following selectors. Because these selectors are jQuery extension and not part of the CSS specification, queries using them cannot take advantage of the performance boost provided by the native DOM querySelectorAll() method. To achieve the best performance when using these selectors, first select some elements using a pure CSS selector, then use .filter().
jQuery는 다음의 선택자들로 CSS3 선택자를 확장했습니다. 이 선택자들은 CSS표준에 명세되지 않은 jQuery만의 확장이기 때문에, 이들을 사용하면 네이티브 DOM 메소드인 querySelectorAll()이 제공하는 빠른 속도를 제공받을 수 없습니다. 이들을 사용해서 가장 좋은 성능을 내기 위해서는, 먼저 순수 CSS 선택자만을 사용해서 Element를 선택한 후 filter()함수를 사용해야 합니다.

출처: http://api.jquery.com/category/selectors/jquery-selector-extensions/

맺음말

jQuery를 사용하면, 아무래도 순수 JavaScript에 비해 속도가 느린 것이 사실입니다. 물론 DOM접근 자체를 최소화하는 것이 성능 면에서는 가장 좋은 것이지요. 하지만 단순하면서도 다양한 기능들을 사용할 수 있게 해주는 편리함은, jQuery를 가장 널리 쓰이는 JavaScript라이브러리로 만들어 주었습니다. jQuery의 장점을 최대화하면서도 성능의 측면을 함께 고민하는 개발을 해야겠다는 생각이 듭니다.

읽어주셔서 감사합니다.

참고 도서 및 사이트

namoosori
안녕하세요. 나무소리 입니다. 나무소리는 넥스트리(주)의 교육 브랜드 입니다.넥스트리가 지난 20년 동안 쌓아온 개발 및 교육 경험들을 나무소리를 통해 많은 분들과 공유 하려고 합니다.앞으로 저희 나무소리를 통해 보다 나은 교육을 경험 하실 수 있도록 구성원 모두 최선을 다하겠습니다.