본문 바로가기

.Net Technology/UI Performance

넥슨 사이트의 성능튜닝 - #3 HTTP 요청 줄이기



안녕하세요~ 암암리에 넥슨의 뒤를 캐고 있는 튜닝요원 HOONS입니다. 이전 포스트(넥슨 사이트의 성능 튜닝 – #2 캐시의 활용)에서는 사용자가 재방문하게 되었을 때 성능을 2배 이상 올릴 수 있는 방법에 대해서 살펴 보았습니다. 사용자의 재방문 비율이 높을 거라 예상되는 넥슨에서는 반드시 적용해야할 부분이라고 생각합니다. 참고로 이 포스트는 연계성이 있기 때문에 앞에서부터(웹사이트 성능을 결정하는 요소들) 차례대로 보아야 쉽게 이해할 수 있을 것입니다.

오늘은 재방문이 아닌 처음 방문할 때의 성능을 올리기 위한 방법을 살펴보고자 합니다. 다시 한번 강조하는 것은 이번 넥슨 사이트 관련 포스트는 UI 단의 성능 올리기 위한 수사를 진행하고 있는 것입니다. 넥슨 사이트의 경우 HTTP 요청이 150번 이상 일어나고 있는 것을 볼 수 있습니다. 이 요청을 최대한 줄이면 줄인 만큼 성능은 향상 됩니다. 그럼 넥슨은 150번인데 다른 게임 사이트들은 어떨까요? 넥슨은 많은 편에 속하는 걸까요? HOONS요원이 다른 게임 사이트들의 요청(Request)수를 한번 조사해 보았습니다. 또한 캐시를 어떻게 활용하고 있는지도 한번 조사해 보았습니다. 

 
사이트 이름
요청 수
비고
한게임(http://www.hangame.com/)
212개
- 캐시 만료기간 사용
- Active-X 설치 2번 물어봄
넷마블 (http://www.netmarble.net/)
153개
- 캐시 만료기간 사용하지 않음
- Active-X 설치 1번 물어봄
피망 (http://pmang.sayclub.com/)
351개
- 캐시 만료기간 사용
- Active-X 설치 없음
[3개 게임 사이트의 요청 수]

다른 게임 사이트를 비교해봤을때 넥슨이 거의 가장 가벼운 사이트로 볼 수 있습니다. 한게임 경우 로딩 중에 즉, 화면이 하얀 상태에서 Active-X 설치 여부를 묻게 됩니다. 이 부분이 좀 아쉬웠지만 대신 여러 파일들이 만료기간을 대부분 지정하고 있었습니다. 넷마블은 요청 수는 비교적 적었으나 캐시 만료기간을 지정하지 않고 있었고 피망 사이트는 만료기간은 사용하고 있지만 요청되는 파일이 상대적으로 많았습니다. 캐시 만료기간을 지정하지 않은 사이트는 넷마블과 넥슨이었고 피망과 한게임은 지정해서 사용하고 있었습니다. 여기서 HOONS의 짐작으로 네오위즈(피망)는 세이클럽, NHN(한게임)은 네이버와 같은 더 큰 규모의 사이트들을 운영해오고 있기 때문에 사이트 성능에 노하우가 반영된 거라 생각됩니다. 하지만 넷마블이나 넥슨은 게임 사이트 요청 수가 비교적 적다는 부분에서 좋은 점수를 주고 싶습니다. 
 
그렇다면 HTTP 요청을 줄이면 왜 성능이 좋아질지 먼저 간단하게 언급해 보겠습니다. 사이트의 성능은 파일이 무겁고 안 무겁고 보다는 얼마나 많은 요청들을 주고 받는가에 따라서 많이 좌우됩니다. 예를 들면 200K 짜리 5개를 다운 받는 것 보다는 1M 짜리 1개가 훨씬 빠르다는 것입니다. 그렇다면 왜 그럴까요? HTML 페이지 안에 있는 하나하나의 파일들은 브라우저에서 TCP 요청에 의해서 전달됩니다. 물론 Keep-Alive라는 헤더 속성을 이용해서 연결을 유지해서 다음 요청으로 전달되지만 그 요청을 동시적으로 보낼 수 없기 때문에 줄줄이 앞의 요청이 끝나기 까지 기다리게 됩니다. 현재 인터넷 익스플로러 그 각각의 연결자체가 시간이 소비되는 것이고 또한 그 파일을 요청하기 위해서 파일마다 생성되어 주고 받는 Header값 또한 무시 못합니다. 때문에 하나로 합치는 작업이 중요한 것입니다. 자, 그렇다면 이제 HTTP 요청을 줄이기 위해서 어떤 작업들을 진행해야 할지 살펴보도록 하겠습니다. 
 


 

이미지맵의 활용
 
언제부터인가 디자이너들 사이에서 “통 이미지는 최대한 잘라라”가 일반적인 공식이 되어 버렸습니다. 그 이유는 뭐 로딩이 느리기 때문에 조금씩 빨리 보여주기 위해서였습니다. 하지만 그렇게 자른 이미지가 전체적으로는 더 느리게 전달됩니다. 왜냐하면 이미지를 자른 만큼 HTTP 요청이 늘어나기 때문입니다. 여기서 우리는 성능을 위해서 이미지맵으로 돌아가야 합니다. 
 
무조건 이미지 맵으로 만들라는 뜻은 아닙니다. 이미지가 연결되어 있고 단순한 링크의 개념으로 사용하고 있다면 이미지 맵을 이용하라는 것입니다. 그럼 넥슨 홈페이지에서는 이미지맵을 적용할 수 있는 부분은 어디일까요? 다음 그림을 살펴봅시다. 

[넥슨 홈페이지]

 
다음과 같은 부분을 이미지 맵으로 처리하면 성능을 더 좋게 만들 수 있을 것입니다. 여기서 HOONS는 아래의 게임을 설명하고 있는 부분을 이미지 맵으로 처리해 보도록 하겠습니다. 먼저 공정한 테스트를 위해서 중간 부분만 때서 새로운 HTML파일에 저장하였습니다. 그리고 속도와 요청 수를 측정해 보았습니다. 
 

[일반적인 요청]
 
약 0.09초 정도 걸리는 것을 볼 수 있습니다. 물론 로컬이기 때문에 무지 빠릅니다. 실제로는 2배정도 걸린다고 생각하면 될 것입니다. 요청은 34번이 일어났습니다. 이제 저 이미지를 통으로 만들도록 하겠습니다. HOONS는 하나의 이미지로 만들 것이지만 실제로 4~5개 정도로 쪼개서 만드는 것이 기능성 면에서 더 유용할 것 같기도 하네요. 그럼 하나의 통 이미지로 만들었을 때의 요청 수는 얼마나 나올까요? 또 시간은 어떻게 나올까요? 혹시나 이미지 사이사이의 공백들이 이미지로 들어갔기 때문에 더 용량이 커져서 느려지지는 않을까요? 그럼 결과를 살펴봅시다. 
 

[이미지맵으로 변환했을 때]
 
요청은 단순하게 2번 일어났고 요청 시간은 0.016초가 걸리게 되었습니다. 즉, 6배정도 빨라지게 되는 것입니다. “여기서 잠깐! HOONS요원, 그런데 고작 0.07초 빠르게 하려고 이미지 맵으로 처리하라는 건가요?” 아닙니다. 앞에서도 말했지만 이 테스트 환경은 저의 로컬이기 때문에 그렇습니다. 별로 신비성이 없다고 생각할 수 있기 때문에 HOONS요원의 개인 서버로 올려서 테스트 해보았습니다. URL은 다음과 같습니다. 
 

일반 이미지: http://blog.hoons.kr/NexonExpires/이미지맵적용전.htm
이미지맵 적용: http://blog.hoons.kr/NexonExpires/이미지맵적용후.htm

 
그럼 속도는 어떻게 나올지 조사해 보도록 하겠습니다. 

[HOONS 서버에서의 테스트]
 

0.5초 정도 절감할 수 있는 것을 볼 수 있습니다. 이번 테스트에서는 일부로 HTML을 무겁게 하였습니다. 이전 포스트에서 조사했을 때 넥슨 메인화면의 속도는 2초였습니다. 이렇게 0.5초를 줄이면 25%나 되는 성능이 향상되는 것입니다. 화면에 보이는 것과 같이 용량은 더 많습니다. 하지만 그 속도는 6배나 빠른 것을 볼 수 있습니다. 예전부터 이미지를 잘게 쪼개는 습관이 사이트의 성능을 더 망가뜨리고 있는 것입니다. 반드시 기능 구분이 필요하고 개체의 개념으로 그 개체가 독립되어야 할 경우에만 이미지를 쪼개서 사용하고 나머지는 이미지맵을 활용하는 것이 성능에 훨씬 좋습니다. 
 

 
자바스크립트 & 스타일시트 합치기
 
넥슨은 총 18개의 자바스크립트와 1개의 스타일시트를 사용하고 있습니다. 스타일시트 1개를 사용하는 것은 굉장히 좋지만 스크립트가 18개라는 점은 조금 아쉽습니다. 그 중에 9개의 스크립트는 페이지 상위에 위치하고 있습니다. 이 스크립트를 하나로 합친다면 성능은 향상됩니다. 스크립트를 기능별로 쪼개서 사용하고 있는 경우가 일반적일 것입니다. 하지만 18개는 상대적으로 좀 많이 사용하고 있는 것입니다. (-_-;)실제로 개발은 그렇게 한다 하더라도 배포 전에 하나로 합쳐서 내보내는 작업을 배포 프로세스로 포함시킬 수 있을 것입니다. “아니~ HOONS요원, 성능이 얼마나 올라간다고 이런 귀찮은 작업을 하자는 것입니까?” 성능은 귀찮음과 비례합니다. 성능이 빠를수록 사용자의 경험은 높아지게 되고, 서버의 부하도 줄일 수 있습니다. 요청 수가 줄기 때문에 당연히 서버의 성능도 올라갈 수 있는 것이고 서버의 부하가 적으면 서버 비용이 절약 되므로 결국 회사와 사용자 둘 다 윈윈 할 수 있는 작업입니다.


 
모든 스크립트를 하나로 합치는 것은 불가능할 것입니다. 스크립트가 모여있지 않고 다른 곳에 위치하고 있다는 것은 document.write와 같은 뭔가 UI와 관련된 작업을 하기 위해서일 가능성이 높습니다. 때문에 여기서 합쳐서 테스트 해 볼 스크립트는 모여있는 스크립트 입니다. 조사해본 결과 9개의 스크립트가 HEAD 영역 안에 모여있었습니다. 그 중에 제일 처음 스크립트는 5개의 스크립트를 다운로드 하는 스크립트였습니다. 즉, 처음 페이지에서 14개나 다운 받게 된다는 것입니다. 그럼 14개의 요청을 하나로 줄였을 때 어떤 성능 향상을 가져올 수 있는지 확인해 보도록 하겠습니다. 
 
HOONS가 Copy&Paste작업으로(T_T) 다음과 같이 테스트 파일을 만들었습니다. 
 
14개의 스크립트: http://blog.hoons.kr/NexonExpires/9개의스크립트.htm
1개로 모은 스크립트: http://blog.hoons.kr/NexonExpires/1개의스크립트.htm
 
“9개의스크립트.htm” 이 파일명은 처음에 스크립트가 9개인 줄 알고 테스트하려고 만들게 되었습니다. 여기서 HOONS는 14개의 스크립트를 모두 1개의 스크립트로 모으는 작업을 하였습니다.(ㅠㅠ) 그럼 결과를 확인해보도록 하겠습니다. 

[14개의 스크립트와 1개의 스크립트 차이]
 

대략 50% 정도 성능 향상이 되는 걸 볼 수 있습니다. HOONS요원의 서버가 그렇게 빠르지 않기 때문에 시간은 좀 많이 나오는군요. 앞에서 언급했듯이 귀찮음과 성능과 비례합니다. 개발 생산성이나 기능성 면에서 효율이 좀 떨어지다 하더라도 스크립트의 수를 줄이면 성능은 향상됩니다. 더욱이나 이 스크립트들은 Head에 위치하고 있습니다. Head에 두면 안 되는 이유에 대해서 다음 포스트에서 설명할 것이지만 그 중에 하나를 언급하면 페이지가 로딩되는 과정이 느려지는 것입니다. 위 화면을 보면 1초가 걸리는걸 볼 수 있는데 사용자는 1초 동안 흰색 화면을 계속 보고 있게 되는 것입니다. 때문에 사용자는 느리다고 느낄 수 있습니다. 넥슨의 스크립트 파일을 하나로 모으는 작업 중에 파일 안에 아무 내용도 없는 파일을 하나 볼 수 있었습니다. 개발자가 실수로 빼지 않은 것 같았습니다. 이 경우 괜히 Request만 하나 잡아 먹게 되는 것이죠 (^_^) 여튼 스타일시트나 자바스크립트나 마찬가지 입니다. 반드시 필요한 경우가 아니면 파일을 분할하는 것은 좋지 않다는 것을 기억해 두도록 합시다.
 
 


CSS Sprite라고 들어봤습니까?
 

마지막으로 소개할 방법은 CSS Sprite라는 기술입니다. 쉽게 이해하기 위해서 구글 사이트를 예를 들어 설명하도록 하겠습니다. 구글의 다운로드 기록을 보면 이미지는 총 3개만 사용하고 있는 것을 볼 수 있습니다. 하지만 구글 페이지를 보면 3개 이상의 이미지를 사용하고 있습니다. 그럼 구글은 이미지 맵을 이용하고 있는 걸까요? 그렇지 않습니다. 구글은 실제로 60개 이상의 이미지가 사용되지만 CSS Sprite라는 기술을 이용해서 2개로 줄여서 사용하고 있는 것입니다. 앞의 예제를 통해서 봤듯이 60개의 Request를 2개로 줄일 수 있다면 성능은 얼마나 좋아질지 상상이 갈 것입니다. 그럼 구글 페이지를 살펴보겠습니다. 
 



[실제로 사용되고 있는 구글의 이미지]
 
이 수수께끼는 다운 받은 3개의 이미지들을 열어보면 풀 수 있습니다. 
 
[이미지의 수수께끼]

 
실제로 구글이 다운 받은 이미지는 이렇게 하나의 통 이미지를 다운받게 됩니다. 이유는 간단합니다. 요청(Request) 수를 줄이기 위해서 입니다. 그럼 어떻게 이 이미지들을 잘라서 보여주는 겁니까? 그것은 바로 CSS Sprite라는 기술을 이용해서 원하는 이미지를 지정하고 잘라서 표현할 수 있는 것입니다. 우리가 CSS Sprite를 많이 사용하지 않는 것은 유지보수뿐만 아니라 개발하는 것 자체가 굉장히 귀찮기 때문입니다. 계속 반복해서 강조하는 내용이 바로 귀찮아져야 성능을 올릴 수 있다는 것입니다. 
 
그럼 CSS Sprite를 어떻게 사용하는지 간단한 예제를 살펴보도록 하겠습니다. HOONS는 다음과 같은 이미지를 준비했습니다. 



[sprite.png파일]

그리고 이 파일을 잘라서 이용하는 문법은 다음과 같습니다.
 
<style>
    .orangeBG
    {
        background: url( 'sprites.png' ) repeat-x 0 0;
        height: 20px;
    }
    .greenBG
    {
        background: url( 'sprites.png' ) repeat-x 0 -20px;
        height: 20px;
    }
    .blueBG
    {
        background: url( 'sprites.png' ) repeat-x 0 -40px;
        height: 20px;
    }
</style>
 
이렇게 스타일을 작성하면 단 한번의 요청으로 여러 개의 이미지를 사용할 수 있는 것입니다. 
 

[CSS Sprite 테스트]


CSS Sprite를 활용하면 이미지맵 그 이상의 성능을 올릴 수 있습니다. 
 


요약

앞에서 캐시의 만료기간을 지정하는 것은 재방문 한 사람을 위한 튜닝 방법이었습니다. 이번 포스트에서 설명한 방법은 사이트에 처음 방문할 경우 Request 수를 최소화 하면서 보다 가볍게 만드는 팁들을 설명했습니다. CSS Sprite, 자바스크립트 파일합치기, 이미지 맵과 같은 기법들을 사용하면 150개의 요청도 절반으로 줄일 수 있을 것이고 또한 그만큼 성능도 빨라지게 될 것입니다. 성능만 빨라집니까? 요청수가 줄면 서버의 부하도 어느 정도 줄게 됩니다. 이미지를 무조건 쪼개서 가볍게 하는 것이 페이지를 가볍게 하는 방법이 아닙니다. 또한 파일의 크기를 작게 하는 것이 페이지를 가볍게 만드는 것이 아닙니다. 페이지를 가볍게 한다는 것은 HTTP 요청을 최소화 해서 빠른 시간 내에 페이지를 로드 하는 것입니다. 
 
지금까지 튜닝요원 HOONS였습니다. 감사합니다. (_ _;)
.
.
.
.
.
.
.
.
.
.
.