15
2017-Sep
[jQuery] 성능 최적화
작성자: Blonix
IP ADRESS: *.64.228.3 조회 수: 1857
출처 : http://yubylab.tistory.com/entry/jQuery-jQuery-%EC%84%B1%EB%8A%A5-%EC%B5%9C%EC%A0%81%ED%99%94
여전히 DOM을 다루는데 있어서는 jQuery는 최고의 라이브러리중 하나라고 생각을 합니다. 이전에 jQuery 제대로 사용하기라는 글을 썻습니다. 그때는 jQeruy의 Bad Practice 에 초점을 맞췄다면 이번에는 Performance 측면에서의 jQuery 코드작성법에 대해서 알아보겠습니다.
1.Append Outside of Loops
jQuery가 DOM을 다루는데 개발자 입장에서는 매우 편합니다. 그런데 편한만큼 그 내부에서는 많은 작업들이 이뤄지고 있고 그 작업은 우리가 생각하는것 이상으로 비용이 꽤나 들어가는 작업입니다. 예를들면 이런 작업입니다.
로 빈 리스트를 마크업해둔상태에서 Ajax 를 통해 DOM을 붙이는 작업이 있습니다. 코드를 한번 보겠습니다.
전달받은 myArray를 each문을 돌면서 하나하나 ul#list에 붙이는 작업이니 일단 원하는 결과를 얻었습니다. 그런데 위의 경우에는 매번 ul#list에 하나하나 엘리먼트를 붙이는 작업입니다. 배열의 엘리먼트의 갯수가 많아는 경우에는 그 갯수만큼 DOM을 조작해야하는 비용적인 측면에서 매우 과한 소비가 일어나게 됩니다.
DOM조작은 될수있으면 최소화 하는 것을 지향해야합니다. 위의 코드는 다음과 같이 작성가능합니다.
2.Cache Length During Loops
정말 아무렇지 않게 다음과 같은 for 문을 작성합니다.
뭐 일단 동작에는 아무런 문제가 없습니다. 그런데 위코드의 문제는 loop를 반복할때마다 엘리먼트의 lenght 프로퍼티에 계속 접근을 한다는 것입니다. 이뿐만아닙니다.
위와같은 코드에서 매번 초를 바꿔주는 코드를 업데이트 할때마다 timmer 엘리먼트를 찾게 됩니다.
자주 반복해서 사용되는 엘리먼트는 브라우저상에 캐시를 시켜두고 그 캐시된 상태의 엘리먼트만를 통해 무언가 작업을 해야합니다. 위의 코드는 다음과 같이 작성하는 것을 권장합니다.
3.Detach Elements to Work with Them
동적으로 테이블을 생성하는 작업을 한다고 가정하겠습니다. 기존에 테이블에 수많은 데이터가 존재하고 이제 Ajax 요청으로 새롭게 테이블을 구성해야 하는 상황입니다.
아마 대부분 이런식으로 작성을 할것같습니다.
remove() 메서드를 사용해 내부의 자식 요소들을 모두 제거하고 거기에 새로운 데이터를 append 하는 방식입니다. 위에서도 말했다시피 우리는 최대한 느린 DOM을 조작하는 일을 최대한 피하려고 합니다. 그래서 위와 같이 DOM의 하위요소들을 지우고 나중에 다시 추가하려는 작업을 진행할때 사용하라고 jQuery1.4버전 이후부터 제공하는 Detach() 라는 메서드를 제공하고 있습니다.
훨씬 좋은 성능으로 DOM을 다룰수가 있습니다.
4.Don't Act on Absent Elements
존재하지 않는 엘리먼트를 상대로 무언가를 시도하지 말라는 이야기입니다. 예를들면 이런거 입니다.
팝업을 띄우기 전에 일단 popup이라는 엘리먼트가 있다면 숨기고 새롭게 띄우려고 합니다. 그래서 띄우기 전에 일단 한번 hide()를 시키고 작업을 시작합니다.
hide() 메서드가 만약popup엘리먼트가 있다면 별로 문제될것이 없습니다. 그런데 popup이라는 엘리먼트가 동적으로 생성되기 때문에 DOM 상에 존재하지 않는다면 꽤많은 오버해드가 발생하게 됩니다. 실제 jQuery UI의 위젯들을 사용할때도 강력하게 권장하는 가이드이기도 합니다.
그럼 어떤식으로 작성을 하는지 보겠습니다.
위코드 보다 조금 더 좋은 방법입니다.
일단 엘리먼트 존재 유무를 판단하고 동작을 시킵니다.
그러나 최상의 방법은 다음과 같습니다. 해당 동작을 통합해서 다루는 플러그인을 추가하는 것입니다.
5.Optimize Selectors
jQuery의 가장 큰 장점은 DOM을 다룰때 엘리먼트 접근이 매우 편하다는 것입니다. 그냥 생각하는 그대로 접근을 해도 어지간하면 다 접근이 가능합니다.
대신 jQuery 가 제공하는 셀렉터들의 특성을 제대로 이해하지 못하고 사용하다 보면 성능상의 보틀넥을 발생시키는 요인이 될수있습니다.
1) jQuery Extensions
가능하다면 jQuery가 제공하는 jQuery extensions가 포한함 셀렉터의 사용을 피하는것이 좋습니다. 해당 메서드는 https://api.jquery.com/category/selectors/jquery-selector-extensions/ 여기에서 확인 가능합니다. extensions가 제공하는 메서드는 브라우저가 기본으로 제공하는 querySelectorAll() DOM 메서드의 성능상의 이점을 전혀 사용하지 못합니다. jQuery는 1.8버전을 시작으로 Sizzle 이라는 셀렉터 엔진을 사용하여 jQuery를 새롭게 제공하고 있습니다. 관련된 내용은 https://blog.jquery.com/2012/07/04/the-new-sizzle/ 이곳에서 확인하시면 됩니다.
위에서 사용되는 :even 의 경우에는 CSS 가 제공하는 selectore요소가 아닙니다. 모든 경우는 아니지만 몇몇의 경우에는 성능상의 이슈를 만들기도 합니다.
2) Avoid Excessive Specificity
지나치게 구체적으로 DOM을 선택하는 것도 생각과는 다르게 성능상에 좋지 않은 이슈를 만들어 냅니다. 내가 자세하게 해당 엘리먼트를 지정해주면 jQuery가 DOM을 선택할때 더빠르게 찾겠지라는 생각으로 아래와 같이 지나치게 디테일한 selector를 작성하면 정반대로 좋지않은 성능을 보이게 됩니다.
결국 각 레이어를 모두 돌면서 엘리먼트를 선택하는 것이기 때문에 최대한 심플하게 selector를 작성하는 것이 selector의 성능을 향상시키는 방법입니다.
3) ID-Based Selctors
일단 검색의 시작은 ID기반으로 하는 것이 가장 좋습니다.
여기서 보면 $(...) 구문안에 여러 엘리먼트의 정보를 넣는데... 이거 좋지 않습니다.
위의 코드의 경우에는 document.querySelectorAll()을 통해서 DOM을 선택하지만 두번째의 경우에는 document.getElementById() 를 통해 DOM을 선택하기에 훨씬 빠릅니다. 물론 추가적으로 find() 메서드가 붙어 성능상이 감소가 조금있지만 그래도 첫번째 보다는 빠릅니다.
6.Use Stylesheets for Changing CSS on Many Elements
20개입니다. 20개 이상의 엘리먼트의 스타일을 jQuery를 통해서 설정해야 한다면 head 태그에 style을 정의 하는 것이 좋습니다.
일단 여기까지가 jQuery 가 공식적으로 가이드하는 성능관련 코딩 방법입니다. 위의 방법을 인지하고 코드를 작성해 나가면 훨씬 좋은 성능의 어플리케이션을 만들수가 있으실겁니다.
마지막으로 jQuery 소스코드는 아시다시피 오픈소스입니다. 그리고 javascipt로 매우 잘짜여진 유서깊은? 코드입니다. 한번 코드를 분석해보는 것도 javascipt를 이해하는 좋은 방법이라고 생각합니다. 그리고 내가 사용하는 jQuery 를 잘 이해하고 사용하는 방법이기도 하고요..