행복한 아빠

극단적인 웹 애플리케이션 성능 향상 방법 본문

문제발생시

극단적인 웹 애플리케이션 성능 향상 방법

행복한아빠 2009.12.15 21:22

느린 사이트는 우리를 참 짜증나게 합니다. 더 힘든 건 그 사이트를 내가 만들었을 때입니다. 튜닝을 할 건 다 했고 그래도 성능이 안 나오면 흥분하는 고객을 진정시키는 건 참 어려운 일입니다.
최후의 수단인 캐싱을 이용한 성능향상 방법을 소개합니다.

미리 만들어 놓기
극단적인 성능 향상 방법이라고해서 뭐 대단한 것은 아닙니다. 바로 캐싱하는 방법입니다. 우리는 알게 모르게 캐싱을 많이 사용하고 있습니다. DB도 그렇고 파일 시스템도 그렇고 웹서버도 사실 캐싱을 사용하고 있습니다. 반복적으로 사용하는 정보는 매번 만들지 않고 한번만 만들어 사용하자는 전략입니다.


웹 애플리케이션은 많은 경로를 지나고 그만큼 많은 캐싱 지점이 있습니다. 그림과 같은 단순한 아키텍처에서도 4개정도의 캐싱 가능한 지점이 있네요.
  • 1번 지점에는 HTTP이 제공하는 막강한 캐싱 메커니즘이 있습니다. 바로 304이죠. 이 메커니즘은 한번 수정여부만 확인하고 아예 서버에 요청을 하지 않아 제일 효율이 좋은 방법입니다.
    HTTP 304 Not Modified 구현 방법 을 참조하세요.
  • 2번 지점은 페이지 요청결과(HTML, XML, JSON, ..) 자체를 캐싱하는 기능입니다.
  • 3번 지점은 서버쪽 연산결과를 메모리나 파일등에 넣고 계속 쓰는 것입니다. 대개 프로그래밍을 수반합니다.
  • 4번 지점은 DB 질의 결과를 캐싱하는 것인데 iBatis나 Hibernate 같은 좋은 프레임워크들이 지원합니다.

캐싱지점이 브라우저와 가까울 수록 성능은 매우 뛰어난 반면 뒤로 갈수록 활용성이 좋아지는 장단점이 있습니다.


View 레이어 캐싱
표현계층이라고도 하는데 여기서는 OSCache로 서버 요청후 만들어진 결과(HTML, XML, JSON)를 통째로 캐싱하는 방법을 살펴봅니다. OSCache는 이를 위한 Servlet Filter를 제공합니다. 이를 이용한다면 웹 애플리케이션이 극단적으로 빨라지게 됩니다.

1. oscache 설치
http://www.opensymphony.com/oscache/download.action 에 가서 oscache를 다운로드 받고 oscache-2.x.x.jar를 웹애플리케이션 WEB-INF/lib 에 복사합니다. maven을 사용하는 분들은 아래 dependency를 걸어주면 됩니다.


2. CacheFilter 설치
WEB-INF/web 파일에 다음을 추가하세요.


이제 필터에 걸린 요청(위의 경우 JSP)은 한 번 호출하면 그 후로는 캐싱의 것을 반환해 속도가 극도로 빨라집니다. 너무 쉽네요. 많은 설정이 init-param 에서 이루어집니다.


Flush
이와 같이 하면 한 번 캐싱된 페이지는 데이터가 바뀌어도 이전과 동일한 화면이 나올겁니다. 변경된 데이터를 화면에 반영하기 위해서는 캐시를 새로 적용해야합니다. 가장 간단한 방법은 cache를 삭제(flush)하는 겁니다. 물론 주기적으로 캐싱을 삭제하거나 삭제 정책을 추가하는 방법도 있습니다.

Cache를 flush하는 API를 제공합니다. 여기서는 그것을 이용하겠습니다.

1. CacheGroupsProvider
CacheFilter를 flush하기 위해서는 그룹을 지정해야 합니다. 그런데 아무런 장치가 없으면 그룹이라는게 생기지 않습니다. 다음과 같은 소스를 만들어 web.xml에 추가합니다.


위의 경우는 무조건 mygroup 라는 캐시 그룹만 생성합니다. 즉 모든 요청의 캐시는 위 그룹이 들어가죠.
web.xml 은 다음과 같이 변경합니다.


2. Cache 삭제 서비스 생성
다음과 같은 소스로 cache를 삭제하는 서블릿이나 action을 만듭니다.


정보를 갱신하여 cache를 다시 만들고 싶을때 위 소스가 실행되는 url 요청을 하면 됩니다.

내가 적용한 곳은 하루마다 배치 작업 후 갱신이 필요한 페이지라 배치 작업 후 위의 서비스 URL로 캐시를 날리고 다시 캐싱하기 위해 각 페이지 URL을 호출하는 배치 작업을 만들었습니다.

온라인으로 캐시를 갱신하기 위해서는 하나하나 캐시 갱신을 위한 판단을 할 필요가 있기에 캐시키를 생성하는 ICacheKeyProvider와 캐시 전략을 결정하는 EntryRefreshPolicy 인터페이스를 잘 살펴봐야 합니다.


기본에 충실하자
이 방법은 튜닝 후 맨 마지막에 하시기를 권합니다. 캐싱이 막강한 튜닝방법 중 하나이지만 마구 썼다가는 아키텍처가 무지 복잡해집니다(갱신 문제, 동기화 문제, 분산 캐싱...). 우선 각 기능을 충실하게 튜닝하고 난 후 캐싱이 효과적인 부분을 선택하여 쓰시기 바랍니다. 너무 캐싱에 의지하지 마세요~


32 Comments
댓글쓰기 폼