웹 애플리케이션의 성능을 개선하는 일이 그 어느 때보다 중요해졌습니다. 온라인에서 이루어지는 경제 활동의 비중이 증가하면서, 현재 선진국 경제의 5% 이상이 인터넷에서 이루어지고 있습니다(아래의 인터넷 통계 자료 참조). 또한 상시 접속되고 고도로 연결된 현대 사회에서는 사용자의 기대치도 그 어느 때보다 높습니다. 사이트가 즉시 응답하지 않거나 앱이 지연 없이 작동하지 않으면 사용자는 빠르게 경쟁사로 이동합니다.
예를 들어, 약 10년 전 Amazon이 실시한 연구에서는 당시에도 페이지 로딩 시간이 100밀리초 단축되면 매출이 1% 증가한다는 사실이 입증되었습니다. 또 다른 최근 연구에서는 설문에 참여한 사이트 소유자의 절반 이상이 애플리케이션 성능 저하로 인해 매출이나 고객을 잃었다고 답한 사실이 강조되었습니다.
웹사이트는 얼마나 빨라야 할까요? 페이지 로딩 시간이 1초 늘어날 때마다 약 4%의 사용자가 이탈합니다. 주요 전자상거래 사이트의 최초 상호작용 가능 시간은 1~3초이며, 이 범위에서 전환율이 가장 높습니다. 웹 애플리케이션 성능의 중요성은 매우 크며 앞으로 더욱 커질 것이 분명합니다.
성능을 개선하고 싶다는 생각은 쉽게 할 수 있지만, 실제로 성과를 내기는 어렵습니다. 이 여정에 도움이 되도록 이 블로그 게시물에서는 웹사이트 성능을 최대 10배까지 향상하는 데 유용한 10가지 팁을 소개합니다. 이 글은 충분히 검증된 최적화 기법과 NGINX의 지원을 활용해 애플리케이션 성능을 높이는 방법을 자세히 설명하는 시리즈의 첫 번째 글입니다. 또한 이 시리즈에서는 그 과정에서 얻을 수 있는 잠재적인 보안 개선 효과도 살펴봅니다.
팁 1 – 리버스 프록시 서버로 애플리케이션 속도 향상 및 보안 강화
웹 애플리케이션이 단일 머신에서 실행되는 경우, 성능 문제의 해결책은 명확해 보일 수 있습니다. 더 많은 프로세서와 RAM, 고속 디스크 어레이 등을 갖춘 더 빠른 머신으로 교체하면 됩니다. 그러면 새 머신에서 WordPress 서버, Node.js 애플리케이션, Java 애플리케이션 등을 이전보다 더 빠르게 실행할 수 있습니다. (애플리케이션이 데이터베이스 서버에 액세스하는 경우에도 해결책은 간단해 보일 수 있습니다. 더 빠른 머신 두 대를 마련하고 두 머신 간 연결 속도를 높이면 됩니다.)
문제는 시스템 속도가 원인이 아닐 수도 있다는 점입니다. 웹 애플리케이션은 컴퓨터가 수천 개의 연결을 통해 사용자와 상호 작용하고, 디스크의 파일에 액세스하고, 애플리케이션 코드를 실행하는 등 서로 다른 종류의 작업을 전환하느라 느리게 실행되는 경우가 많습니다. 애플리케이션 서버는 메모리가 부족해 메모리의 일부를 디스크로 스왑하고, 수많은 요청이 디스크 I/O와 같은 단일 작업이 끝나기를 기다리게 되는 스래싱 상태에 빠질 수 있습니다.
하드웨어를 업그레이드하는 대신, 이러한 작업 중 일부를 분담하도록 리버스 프록시 서버를 추가하는 완전히 다른 접근 방식을 취할 수 있습니다. 리버스 프록시 서버는 애플리케이션이 실행되는 시스템 앞에 위치하여 인터넷 트래픽을 처리합니다. 인터넷에 직접 연결되는 것은 리버스 프록시 서버뿐이며, 애플리케이션 서버와의 통신은 빠른 내부 네트워크를 통해 이루어집니다.
리버스 프록시 서버를 사용하면 애플리케이션 서버가 사용자의 웹 앱 상호 작용을 기다릴 필요가 없어지고, 리버스 프록시 서버가 인터넷을 통해 전송할 페이지를 생성하는 데 집중할 수 있습니다. 더 이상 클라이언트의 응답을 기다릴 필요가 없는 애플리케이션 서버는 최적화된 벤치마크에서 달성한 수준에 가까운 속도로 실행될 수 있습니다.
리버스 프록시 서버를 추가하면 웹 서버 구성의 유연성도 높아집니다. 예를 들어 특정 유형의 서버에 과부하가 걸리면 동일한 유형의 서버를 손쉽게 추가할 수 있고, 서버가 다운되면 간편하게 교체할 수 있습니다.
리버스 프록시 서버는 유연성을 제공하므로 다음과 같은 다양한 성능 향상 기능을 구현하기 위한 필수 요소이기도 합니다:
- 부하 분산 (팁 2 참조) – 부하 분산기는 리버스 프록시 서버에서 실행되며 여러 애플리케이션 서버에 트래픽을 고르게 분산합니다. 부하 분산기를 사용하면 애플리케이션을 전혀 변경하지 않고도 애플리케이션 서버를 추가할 수 있습니다.
- 정적 파일 캐싱 (참조: 팁 3) – 이미지 파일이나 코드 파일처럼 직접 요청되는 파일은 리버스 프록시 서버에 저장한 후 클라이언트로 바로 전송할 수 있습니다. 이를 통해 자산을 더 빠르게 제공하고 애플리케이션 서버의 부하를 줄여 애플리케이션을 더 빠르게 실행할 수 있습니다.
- 사이트 보안 강화 – 역방향 프록시 서버에 강력한 보안을 적용하고 공격을 신속하게 감지하여 대응하도록 모니터링함으로써 애플리케이션 서버를 보호할 수 있습니다.
NGINX 소프트웨어는 위에서 설명한 추가 기능과 함께 리버스 프록시 서버로 사용하도록 특별히 설계되었습니다. NGINX는 기존 서버보다 효율적인 이벤트 기반 처리 방식을 사용합니다. NGINX Plus는 애플리케이션 상태 검사, 특수 요청 라우팅, 고급 캐싱 및 지원과 같은 더욱 향상된 리버스 프록시 기능을 제공합니다.

팁 2 – 로드 밸런서 추가
Adding a 로드 밸런서를 추가하는 것은 비교적 간단한 변경만으로도 사이트의 성능과 보안을 크게 향상할 수 있는 방법입니다. 핵심 웹 서버의 규모와 성능을 키우는 대신, 로드 밸런서를 사용해 여러 서버에 트래픽을 분산합니다. 애플리케이션의 코드 품질이 좋지 않거나 확장성에 문제가 있더라도, 로드 밸런서를 도입하면 다른 변경 없이도 사용자 경험을 개선할 수 있습니다.
로드 밸런서는 우선 리버스 프록시 서버입니다(참조: 팁 1). 즉, 인터넷 트래픽을 수신하여 다른 서버로 요청을 전달합니다. 핵심은 로드 밸런서가 둘 이상의 애플리케이션 서버를 지원하며, 다양한 알고리즘을 사용해 서버 간에 요청을 분산한다는 점입니다. 가장 간단한 로드 밸런싱 방식은 라운드 로빈으로, 새 요청이 들어올 때마다 목록의 다음 서버로 전송합니다. 그 밖에도 활성 연결 수가 가장 적은 서버로 요청을 보내는 방식 등이 있습니다. NGINX Plus는 특정 사용자 세션을 동일한 서버에서 계속 처리할 수 있는 기능을 제공하며, 이를 세션 지속성이라고 합니다.
로드 밸런서는 다른 서버들이 트래픽을 기다리는 동안 특정 서버 하나에 부하가 집중되는 것을 방지하므로 성능을 크게 향상할 수 있습니다. 또한 비교적 저렴한 서버를 추가해도 충분히 활용되도록 할 수 있어 웹 서버 용량을 손쉽게 확장할 수 있습니다.
부하 분산이 가능한 프로토콜에는 HTTP, HTTPS, SPDY, HTTP/2, WebSocket, FastCGI, SCGI, uwsgi, memcached뿐 아니라 TCP 기반 애플리케이션과 기타 계층 4 프로토콜을 포함한 여러 애플리케이션 유형이 있습니다. 웹 애플리케이션을 분석하여 어떤 프로토콜을 사용하고 있으며 어느 부분에서 성능이 저하되는지 파악하세요.
로드 밸런싱에 사용되는 동일한 서버 또는 서버들은 SSL 종료, 클라이언트의 HTTP/1.x 및 HTTP/2 사용 지원, 정적 파일 캐싱과 같은 여러 다른 작업도 처리할 수 있습니다.
NGINX는 부하 분산에 자주 사용됩니다. 자세히 알아보려면 다음 전자책을 다운로드하세요. 소프트웨어 부하 분산기를 선택해야 하는 5가지 이유. 기본 구성 방법은 NGINX 및 NGINX Plus를 사용한 부하 분산, 1부에서 확인할 수 있으며, 전체 설명서는 NGINX Plus 관리자 가이드에서 확인할 수 있습니다. NGINX Plus는 당사의 상용 제품으로, 서버 응답 시간을 기반으로 한 부하 라우팅과 Microsoft의 NTLM 프로토콜을 통한 부하 분산 기능 등 더욱 전문적인 부하 분산 기능을 지원합니다.
팁 3 – 정적 및 동적 콘텐츠 캐싱
캐싱은 콘텐츠를 클라이언트에 더 빠르게 제공하여 웹 애플리케이션의 성능을 향상합니다. 캐싱에는 필요할 때 빠르게 제공할 수 있도록 콘텐츠를 미리 처리하거나, 더 빠른 장치에 콘텐츠를 저장하거나, 클라이언트와 더 가까운 위치에 콘텐츠를 저장하거나, 이러한 방법을 조합하는 등 여러 전략을 사용할 수 있습니다.
고려해야 할 캐싱 유형은 두 가지입니다:
- 정적 콘텐츠 캐싱 – 이미지 파일(JPEG, PNG) 및 코드 파일(CSS, JavaScript)처럼 자주 변경되지 않는 파일은 메모리나 디스크에서 빠르게 가져올 수 있도록 엣지 서버에 저장할 수 있습니다.
- 동적 콘텐츠 캐싱 – 많은 웹 애플리케이션은 페이지 요청이 있을 때마다 새로운 HTML을 생성합니다. 생성된 HTML 사본 하나를 짧은 시간 동안 캐싱하면 요구 사항을 충족할 만큼 최신 콘텐츠를 계속 제공하면서도 생성해야 하는 전체 페이지 수를 크게 줄일 수 있습니다.
예를 들어 페이지 조회 수가 초당 10회이고 해당 페이지를 1초 동안 캐시하면 페이지 요청의 90%가 캐시에서 처리됩니다. 정적 콘텐츠를 별도로 캐시하면 새로 생성된 페이지조차 대부분 캐시된 콘텐츠로 구성될 수 있습니다.
웹 애플리케이션에서 생성된 콘텐츠를 캐싱하는 주요 기법은 세 가지입니다:
- 콘텐츠를 사용자에게 더 가까이 배치 – 콘텐츠 사본을 사용자와 가까운 곳에 보관하면 전송 시간이 단축됩니다.
- 콘텐츠를 더 빠른 시스템으로 이동 – 콘텐츠를 더 빠른 시스템에 저장하면 더욱 신속하게 가져올 수 있습니다.
- 과도하게 사용 중인 머신에서 콘텐츠 이동 – 머신은 다른 작업을 처리하느라 바쁠 때 특정 작업에서 벤치마크 성능보다 훨씬 느리게 작동하기도 합니다. 다른 머신에 캐싱하면 호스트 머신의 부하가 줄어들기 때문에 캐시된 리소스뿐만 아니라 캐시되지 않은 리소스의 성능도 향상됩니다.
웹 애플리케이션의 캐싱은 내부, 즉 웹 애플리케이션 서버에서 시작해 외부로 확장하는 방식으로 구현할 수 있습니다. 먼저 동적 콘텐츠에 캐싱을 적용하여 애플리케이션 서버의 부하를 줄입니다. 그런 다음 정적 콘텐츠(캐싱하지 않으면 동적 콘텐츠가 될 항목의 임시 사본 포함)에 캐싱을 적용하여 애플리케이션 서버의 부하를 더욱 줄입니다. 이후 캐싱을 애플리케이션 서버에서 분리해 더 빠르거나 사용자와 더 가까운 시스템으로 옮기면 애플리케이션 서버의 부담을 덜고 콘텐츠 검색 및 전송 시간을 단축할 수 있습니다.
캐싱을 개선하면 애플리케이션의 속도를 크게 높일 수 있습니다. 많은 웹 페이지에서 대용량 이미지 파일과 같은 정적 데이터가 콘텐츠의 절반 이상을 차지합니다. 캐싱하지 않으면 이러한 데이터를 가져와 전송하는 데 몇 초가 걸릴 수 있지만, 로컬에 캐시하면 몇 분의 1초밖에 걸리지 않습니다.
실제로 캐싱이 어떻게 사용되는지 예를 들면, NGINX와 NGINX Plus에서는 다음 두 지시어를 사용하여 캐싱을 설정합니다: proxy_cache_path 및 proxy_cache. 캐시 위치와 크기, 파일을 캐시에 보관하는 최대 시간 및 기타 매개변수를 지정합니다. 세 번째 지시어이자 널리 사용되는 proxy_cache_use_stale을 사용하면 최신 콘텐츠를 제공하는 서버가 사용 중이거나 다운되었을 때 캐시가 오래된 콘텐츠라도 제공하도록 설정할 수 있으므로, 클라이언트에 아무것도 제공하지 않는 상황을 피할 수 있습니다. 사용자 관점에서 이는 사이트나 애플리케이션의 가동 시간을 크게 향상할 수 있습니다.
NGINX Plus에는 고급 캐싱 기능이 있으며, 여기에는 캐시 제거 지원과 실시간 활동 모니터링을 위한 대시보드의 캐시 상태 시각화 기능이 포함됩니다.
NGINX를 사용한 캐싱에 대한 자세한 내용은 참조 문서 및 NGINX Plus 관리자 가이드를 참조하세요.
참고: 캐싱은 애플리케이션 개발자, 자본 투자 의사 결정자, 실시간 네트워크 운영자 등 조직 내 여러 부문의 사람들과 관련됩니다. 여기에서 언급한 것과 같은 정교한 캐싱 전략은 DevOps 관점의 가치를 잘 보여 줍니다. DevOps 관점에서는 애플리케이션 개발, 아키텍처 및 운영 관점을 통합하여 사이트 기능, 응답 시간, 보안 및 거래 완료나 매출과 같은 비즈니스 성과 목표를 달성하는 데 도움을 줍니다.
팁 4 – 데이터 압축
압축은 성능을 크게 향상할 수 있는 강력한 수단입니다. 사진(JPEG 및 PNG), 동영상(MPEG‑4), 음악(MP3) 등에는 정교하게 설계된 매우 효과적인 압축 표준이 있습니다. 이러한 표준은 각각 파일 크기를 10분의 1 이하로 줄여 줍니다.
HTML(일반 텍스트와 HTML 태그 포함), CSS, JavaScript와 같은 코드 등의 텍스트 데이터는 압축되지 않은 상태로 전송되는 경우가 많습니다. 이러한 데이터를 압축하면 사용자가 체감하는 웹 애플리케이션 성능을 크게 향상할 수 있으며, 특히 속도가 느리거나 제약이 있는 모바일 연결을 사용하는 클라이언트에서 그 효과가 두드러집니다.
이는 사용자가 페이지와 상호 작용하는 데 텍스트 데이터만으로도 충분한 경우가 많고, 멀티미디어 데이터는 보조적이거나 장식적인 역할을 할 수 있기 때문입니다. 지능형 콘텐츠 압축을 사용하면 HTML, Javascript, CSS 및 기타 텍스트 기반 콘텐츠에 필요한 대역폭을 일반적으로 30% 이상 줄일 수 있으며, 그에 따라 로드 시간도 단축됩니다.
SSL을 사용하는 경우 압축을 통해 SSL로 인코딩해야 하는 데이터의 양이 줄어들어, 데이터를 압축하는 데 소요되는 CPU 시간의 일부를 상쇄할 수 있습니다.
텍스트 데이터를 압축하는 방법은 다양합니다. 예를 들어, 헤더 데이터에 맞게 특별히 조정된 SPDY 및 HTTP/2의 새로운 텍스트 압축 방식을 알아보려면 팁 6을 참조하세요. 텍스트 압축의 또 다른 예로 NGINX에서 GZIP 압축을 활성화할 수 있습니다. 서비스에서 텍스트 데이터를 미리 압축한 후에는 .gz 압축 파일을 gzip_static 지시어를 사용하여 직접 제공할 수 있습니다.
팁 5 – SSL/TLS 최적화
보안 소켓 계층(SSL) 프로토콜과 그 후속 프로토콜인 전송 계층 보안(TLS) 프로토콜은 점점 더 많은 웹사이트에서 사용되고 있습니다. SSL/TLS는 원본 서버에서 사용자에게 전송되는 데이터를 암호화하여 사이트 보안을 강화합니다. 이러한 추세에 영향을 미치는 요인 중 하나는 Google이 이제 SSL/TLS 적용 여부를 검색 엔진 순위에 긍정적인 요소로 반영한다는 점입니다.
인기가 높아지고 있음에도 불구하고, SSL/TLS로 인한 성능 저하는 많은 웹사이트에서 여전히 걸림돌이 되고 있습니다. SSL/TLS가 웹사이트 성능을 저하시키는 이유는 두 가지입니다:
- 새 연결이 열릴 때마다 암호화 키를 설정하기 위해 초기 핸드셰이크가 필요합니다. HTTP/1.x를 사용하는 브라우저는 서버당 여러 연결을 설정하므로 이러한 성능 저하가 더욱 커집니다.
- 서버에서 데이터를 암호화하고 클라이언트에서 복호화하는 데 지속적으로 발생하는 오버헤드.
SSL/TLS 사용을 장려하기 위해 HTTP/2와 SPDY(다음 팁에서 설명)의 개발자들은 브라우저 세션당 하나의 연결만 필요하도록 이러한 프로토콜을 설계했습니다. 이를 통해 SSL 오버헤드의 두 가지 주요 원인 중 하나가 크게 줄어듭니다. 하지만 오늘날에도 SSL/TLS를 통해 제공되는 애플리케이션의 성능을 더욱 개선할 수 있습니다.
SSL/TLS 최적화 메커니즘은 웹 서버마다 다릅니다. 예를 들어 NGINX는 일반적인 범용 하드웨어에서 실행되는 OpenSSL을 사용하여 전용 하드웨어 솔루션과 유사한 성능을 제공합니다. NGINX의 SSL 성능은 관련 자료가 잘 갖춰져 있으며, SSL/TLS 암호화 및 복호화에 소요되는 시간과 CPU 부하를 최소화합니다.
또한 SSL/TLS 성능을 향상하는 방법에 대한 자세한 내용은 이 블로그 게시물을 참조하세요. 간단히 요약하면 다음과 같은 기법이 있습니다:
- 세션 캐싱 –
ssl_session_cache지시어를 사용하여 SSL/TLS로 각각의 새 연결을 보호할 때 사용되는 매개변수를 캐시합니다. - 세션 티켓 또는 ID – 특정 SSL/TLS 세션에 대한 정보를 티켓이나 ID에 저장하여 새로 핸드셰이크하지 않고도 연결을 원활하게 재사용할 수 있도록 합니다.
- OCSP 스테이플링 – SSL/TLS 인증서 정보를 캐싱하여 핸드셰이크 시간을 단축합니다.
NGINX 및 NGINX Plus는 SSL/TLS 종료에 사용할 수 있습니다. 즉, 클라이언트 트래픽의 암호화 및 복호화를 처리하면서 다른 서버와는 평문으로 통신합니다. NGINX 또는 NGINX Plus에서 SSL/TLS 종료를 처리하도록 설정하려면 HTTPS 연결 및 암호화된 TCP 연결에 대한 지침을 참조하세요.
팁 6 – HTTP/2 또는 SPDY 구현
이미 SSL/TLS를 사용하는 사이트의 경우, 단일 연결에는 핸드셰이크가 한 번만 필요하므로 HTTP/2와 SPDY를 사용하면 성능이 향상될 가능성이 매우 높습니다. 아직 SSL/TLS를 사용하지 않는 사이트의 경우에는 HTTP/2와 SPDY 덕분에 일반적으로 성능을 저하시키는 SSL/TLS로 전환하더라도 응답성 측면에서는 손해가 없습니다.
Google은 2012년에 HTTP/1.x보다 더 빠른 성능을 구현하기 위한 방법으로 SPDY를 도입했습니다. HTTP/2는 SPDY를 기반으로 최근 승인된 IETF 표준입니다. SPDY는 폭넓게 지원되고 있지만 곧 지원이 중단되고 HTTP/2로 대체될 예정입니다.
SPDY와 HTTP/2의 핵심 기능은 여러 연결 대신 단일 연결을 사용하는 것입니다. 이 단일 연결은 다중화되어 여러 요청과 응답의 일부를 동시에 전송할 수 있습니다.
이러한 프로토콜은 하나의 연결을 최대한 활용함으로써 브라우저의 HTTP/1.x 구현 방식에서 요구되는 여러 연결의 설정 및 관리에 따른 오버헤드를 방지합니다. 단일 연결을 사용하면 SSL/TLS가 보안 연결을 설정하는 데 필요한 시간 소모적인 핸드셰이크를 최소화할 수 있으므로 SSL에서 특히 유용합니다.
SPDY 프로토콜에서는 SSL/TLS를 사용해야 했습니다. HTTP/2에서는 공식적으로 이를 요구하지 않지만, 지금까지 HTTP/2를 지원하는 모든 브라우저는 SSL/TLS가 활성화된 경우에만 HTTP/2를 사용합니다. 즉, HTTP/2를 지원하는 브라우저는 웹사이트가 SSL을 사용하고 해당 서버가 HTTP/2 트래픽을 허용하는 경우에만 HTTP/2를 사용합니다. 그렇지 않으면 브라우저는 HTTP/1.x.
SPDY 또는 HTTP/2를 구현하면 도메인 샤딩, 리소스 병합, 이미지 스프라이트와 같은 일반적인 HTTP 성능 최적화가 더 이상 필요하지 않습니다. 이러한 변화로 코드와 배포가 간소화되고 관리도 쉬워집니다. HTTP/2가 가져오는 변화에 대해 자세히 알아보려면 백서 웹 애플리케이션 개발자를 위한 HTTP/2를 참조하십시오.
이러한 프로토콜 지원의 한 예로, NGINX는 초기부터 SPDY를 지원해 왔으며, 현재 SPDY를 사용하는 대부분의 사이트가 NGINX에서 실행되고 있습니다. 또한 NGINX는 HTTP/2 지원을 선도하고 있으며, 2015년 9월부터 NGINX 오픈 소스와 NGINX Plus에서 HTTP/2를 지원하고 있습니다.
시간이 지나면서 대부분의 사이트가 SSL을 완전히 활성화하고 HTTP/2로 전환할 것으로 NGINX는 예상합니다. 이를 통해 보안이 강화되고, 새로운 최적화 방법이 발견되어 구현됨에 따라 코드는 더 단순해지면서 성능은 향상될 것입니다.
팁 7 – 소프트웨어 버전 업데이트
애플리케이션 성능을 높이는 간단한 방법 중 하나는 안정성과 성능에 대한 평판을 기준으로 소프트웨어 스택의 구성 요소를 선택하는 것입니다. 또한 고품질 구성 요소의 개발자는 시간이 지남에 따라 성능을 개선하고 버그를 수정할 가능성이 높으므로 최신 안정 버전의 소프트웨어를 사용하는 것이 좋습니다. 새 릴리스는 개발자와 사용자 커뮤니티로부터 더 많은 관심을 받습니다. 최신 빌드는 새로운 하드웨어에 맞춘 튜닝을 비롯한 최신 컴파일러 최적화도 활용합니다.
안정적인 최신 릴리스는 일반적으로 이전 릴리스보다 호환성과 성능이 뛰어납니다. 또한 소프트웨어를 최신 상태로 유지하면 성능 튜닝 및 최적화, 버그 수정, 보안 경고를 더 쉽게 파악할 수 있습니다.
구형 소프트웨어를 계속 사용하면 새로운 기능을 활용하지 못할 수도 있습니다. 예를 들어 위에서 설명한 HTTP/2는 현재 OpenSSL 1.0.1을 필요로 합니다. 2016년 중반부터는 HTTP/2에 2015년 1월에 출시된 OpenSSL 1.0.2가 필요합니다.
NGINX 사용자는 먼저 최신 버전의 NGINX 또는 NGINX Plus로 업그레이드할 수 있습니다. 최신 버전에는 소켓 샤딩 및 스레드 풀과 같은 새로운 기능이 포함되어 있으며(팁 9 참조), 두 제품 모두 성능 향상을 위해 지속적으로 조정되고 있습니다. 그런 다음 스택의 하위 계층에 있는 소프트웨어를 살펴보고 가능한 경우 최신 버전으로 업그레이드하세요.
팁 8 – 성능 향상을 위한 Linux 튜닝
오늘날 대부분의 웹 서버 구현에서 기반 운영 체제로 사용되는 Linux는 인프라의 토대인 만큼 성능을 크게 향상할 수 있는 중요한 기회를 제공합니다. 기본적으로 많은 Linux 시스템은 적은 리소스를 사용하고 일반적인 데스크톱 워크로드에 맞도록 보수적으로 조정되어 있습니다. 따라서 웹 애플리케이션에서 최대 성능을 얻으려면 어느 정도의 튜닝이 필요합니다.
Linux 최적화는 웹 서버마다 다릅니다. NGINX를 예로 들어 Linux의 속도를 높이기 위해 고려할 수 있는 주요 변경 사항 몇 가지를 소개합니다:
- 백로그 큐 – 연결이 지연되는 것처럼 보인다면
net.core.somaxconn값을 늘려 보세요. 이 값은 NGINX가 처리할 때까지 대기열에 넣을 수 있는 최대 연결 수를 나타냅니다. 기존 연결 한도가 너무 작으면 오류 메시지가 표시되며, 오류 메시지가 더 이상 나타나지 않을 때까지 이 매개변수를 점진적으로 늘릴 수 있습니다. - 파일 디스크립터 – NGINX는 연결당 최대 2개의 파일 디스크립터를 사용합니다. 시스템에서 많은 연결을 처리하는 경우 증가한 부하를 지원하려면
sys.fs.file_max, 시스템 전체의 파일 디스크립터 한도와nofile, 사용자 파일 디스크립터 한도를 늘려야 할 수 있습니다. - 임시 포트 – NGINX를 프록시로 사용하면 각 업스트림 서버에 대해 임시(“ephemeral”) 포트를 생성합니다. 사용 가능한 포트 수를 늘리려면
net.ipv4.ip_local_port_range로 설정되는 포트 값의 범위를 확장할 수 있습니다. 또한net.ipv4.tcp_fin_timeout설정을 사용하여 비활성 포트가 재사용되기까지의 제한 시간을 줄이면 포트를 더 빠르게 순환시킬 수 있습니다.
NGINX의 경우 NGINX 성능 튜닝 가이드를 참조하여 Linux 시스템이 대량의 네트워크 트래픽도 거뜬히 처리할 수 있도록 최적화하는 방법을 알아보세요!
팁 9 – 웹 서버의 성능을 최적화하세요
어떤 웹 서버를 사용하든 웹 애플리케이션 성능에 맞게 튜닝해야 합니다. 다음 권장 사항은 일반적으로 모든 웹 서버에 적용되지만, 구체적인 설정은 NGINX를 기준으로 설명합니다. 주요 최적화 항목은 다음과 같습니다.
- 액세스 로깅 – 모든 요청의 로그 항목을 디스크에 즉시 기록하는 대신, 항목을 메모리에 버퍼링한 후 한꺼번에 디스크에 기록할 수 있습니다. NGINX에서는 메모리 버퍼가 가득 찼을 때 로그 항목을 디스크에 기록하도록
buffer=size매개변수를access_log지시문에 추가합니다.flush=time매개변수를 추가하면 지정된 시간이 지난 후에도 버퍼의 내용이 디스크에 기록됩니다. - 버퍼링 – 버퍼링은 버퍼가 가득 찰 때까지 응답의 일부를 메모리에 보관하여 클라이언트와의 통신 효율을 높일 수 있습니다. 메모리에 담을 수 없는 응답은 디스크에 기록되므로 성능이 저하될 수 있습니다. NGINX 버퍼링이 활성화되어 있으면,
proxy_buffer_size및proxy_buffers지시어를 사용하여 버퍼링을 관리합니다. - 클라이언트 연결 유지 – 연결 유지를 사용하면 특히 SSL/TLS를 사용할 때 오버헤드가 줄어듭니다. NGINX에서는 클라이언트가 특정 연결을 통해 수행할 수 있는 최대
keepalive_requests횟수를 기본값인 100회보다 늘릴 수 있으며,keepalive_timeout값을 늘려 연결 유지 연결을 더 오래 열어 둘 수 있으므로 이후 요청을 더 빠르게 처리할 수 있습니다. - 업스트림 연결 유지 – 애플리케이션 서버, 데이터베이스 서버 등에 대한 연결인 업스트림 연결에도 연결 유지 기능을 사용하면 유용합니다. 업스트림 연결의 경우
keepalive값을 늘릴 수 있습니다. 이 값은 각 워커 프로세스에서 열린 상태로 유지되는 유휴 연결 유지 연결의 수를 나타냅니다. 이렇게 하면 연결 재사용이 늘어나 새로운 연결을 생성해야 하는 횟수가 줄어듭니다. 자세한 내용은 블로그 게시물 HTTP 연결 유지와 웹 성능을 참조하세요. - 제한 – 클라이언트가 사용하는 리소스를 제한하면 성능과 보안을 향상할 수 있습니다. NGINX에서는
limit_conn및limit_conn_zone지시문을 사용하여 특정 소스의 연결 수를 제한하고,limit_rate지시문을 사용하여 대역폭을 제한합니다. 이러한 설정을 통해 정상적인 사용자가 리소스를 독점하지 못하게 하고 공격을 방지할 수도 있습니다.limit_req및limit_req_zone지시문은 클라이언트 요청을 제한합니다. 업스트림 서버에 대한 연결에는upstream구성 블록에 있는server지시문의max_conns매개변수를 사용합니다. 이렇게 하면 업스트림 서버에 대한 연결 수가 제한되어 과부하를 방지할 수 있습니다. 관련queue지시문은max_conns제한에 도달한 후 지정된 수의 요청을 지정된 시간 동안 보관하는 대기열을 생성합니다. - 워커 프로세스 – 워커 프로세스는 요청 처리를 담당합니다. NGINX는 이벤트 기반 모델과 운영 체제별 메커니즘을 사용하여 요청을 워커 프로세스에 효율적으로 분산합니다. 권장 설정은
worker_processes값을 CPU당 하나로 지정하는 것입니다. 필요한 경우 대부분의 시스템에서worker_connections의 최댓값(기본값 512)을 안전하게 늘릴 수 있습니다. 여러 값을 시험하여 시스템에 가장 적합한 값을 찾으십시오. - 소켓 샤딩 – 일반적으로 단일 소켓 리스너가 새 연결을 모든 워커 프로세스에 분배합니다. 소켓 샤딩은 각 워커 프로세스에 대한 소켓 리스너를 생성하며, 커널은 소켓 리스너가 사용 가능해지는 대로 연결을 할당합니다. 이를 통해 잠금 경합을 줄이고 멀티코어 시스템의 성능을 향상할 수 있습니다. 소켓 샤딩을 사용하려면
reuseport매개변수를listen지시문에 포함하세요. - 스레드 풀 – 모든 컴퓨터 프로세스는 하나의 느린 작업으로 인해 지연될 수 있습니다. 웹 서버 소프트웨어의 경우 디스크 액세스로 인해 메모리에서 정보를 계산하거나 복사하는 것과 같은 훨씬 빠른 여러 작업이 지연될 수 있습니다. 스레드 풀을 사용하면 느린 작업은 별도의 작업 집합에 할당되고, 기본 처리 루프에서는 더 빠른 작업이 계속 실행됩니다. 디스크 작업이 완료되면 결과가 기본 처리 루프로 반환됩니다. NGINX에서는 두 가지 작업, 즉
read()시스템 호출과sendfile()가 스레드 풀로 오프로드됩니다.

팁. 운영 체제나 지원 서비스의 설정을 변경할 때는 한 번에 하나의 설정만 변경한 다음 성능을 테스트하세요. 변경으로 인해 문제가 발생하거나 사이트 속도가 빨라지지 않으면 원래대로 되돌리세요.
NGINX 웹 서버 튜닝에 대한 자세한 내용은 블로그 게시물인 성능 향상을 위한 NGINX 튜닝을 참조하세요.
팁 10 – 실시간 활동을 모니터링하여 문제와 병목 현상 해결
고성능 애플리케이션 개발 및 제공 방식의 핵심은 실제 환경에서 애플리케이션이 발휘하는 성능을 실시간으로 면밀히 관찰하는 것입니다. 특정 디바이스 내부와 웹 인프라 전반의 활동을 모니터링할 수 있어야 합니다.
사이트 활동 모니터링은 대부분 수동적입니다. 즉, 현재 상황을 알려줄 뿐, 문제를 발견하고 해결하는 일은 사용자의 몫입니다.
모니터링을 통해 여러 유형의 문제를 감지할 수 있습니다. 여기에는 다음이 포함됩니다:
- 서버가 다운되었습니다.
- 서버가 불안정하게 작동하며 연결이 끊어지고 있습니다.
- 서버에서 캐시 미스 비율이 높게 나타나고 있습니다.
- 서버가 올바른 콘텐츠를 전송하지 않고 있습니다.
New Relic이나 Dynatrace와 같은 글로벌 애플리케이션 성능 모니터링 도구를 사용하면 원격 위치에서 페이지 로드 시간을 모니터링할 수 있으며, NGINX를 사용하면 애플리케이션 전송 측면을 모니터링할 수 있습니다. 애플리케이션 성능 데이터를 통해 최적화가 사용자에게 실질적인 효과를 내는 시점과 트래픽을 감당하기 위해 인프라 용량 확장을 고려해야 하는 시점을 파악할 수 있습니다.
문제를 신속하게 식별하고 해결할 수 있도록 NGINX Plus는 애플리케이션 인식 상태 점검 기능을 제공합니다. 이는 정기적으로 반복 실행되어 문제를 알리는 데 사용되는 합성 트랜잭션입니다. NGINX Plus는 기존 작업이 완료되는 동안 새 연결을 차단하는 세션 드레이닝 기능과 복구된 서버가 부하 분산 그룹 내에서 점진적으로 정상 처리 속도에 도달하도록 하는 느린 시작 기능도 제공합니다. 상태 점검을 효과적으로 활용하면 사용자 경험에 심각한 영향을 미치기 전에 문제를 식별할 수 있으며, 세션 드레이닝과 느린 시작 기능을 사용하면 서버를 교체하는 과정에서 체감 성능이나 가동 시간에 부정적인 영향을 주지 않도록 할 수 있습니다. 그림은 서버, TCP 연결 및 캐싱으로 구성된 웹 인프라를 위한 NGINX Plus 내장 실시간 활동 모니터링 대시보드를 보여 줍니다.
결론 – 10배의 성능 향상 확인
웹 애플리케이션마다 달성할 수 있는 성능 개선의 폭은 크게 다르며, 실제 향상 정도는 예산, 투자할 수 있는 시간, 기존 구현의 미비점에 따라 달라집니다. 그렇다면 여러분의 애플리케이션에서 어떻게 10배의 성능 향상을 달성할 수 있을까요?
각 최적화가 미칠 수 있는 잠재적 영향을 가늠하는 데 도움이 되도록, 위에서 자세히 설명한 각 팁을 통해 기대할 수 있는 성능 향상 수준을 정리했습니다. 다만 실제 효과는 환경에 따라 크게 달라질 수 있습니다.
- 리버스 프록시 서버 및 부하 분산 – 부하 분산이 없거나 제대로 이루어지지 않으면 성능이 극도로 저하되는 상황이 발생할 수 있습니다. NGINX와 같은 리버스 프록시 서버를 추가하면 웹 애플리케이션이 메모리와 디스크 사이에서 데이터를 반복적으로 교환하느라 성능이 저하되는 현상을 방지할 수 있습니다. 부하 분산을 사용하면 과부하 상태인 서버의 작업을 여유가 있는 서버로 옮길 수 있으며, 손쉽게 확장할 수 있습니다. 이러한 변경을 통해 성능을 크게 향상할 수 있습니다. 현재 구현에서 성능이 가장 저조한 시점과 비교하면 10배 향상도 쉽게 달성할 수 있으며, 전반적인 성능 역시 그보다는 작지만 상당한 수준으로 개선할 수 있습니다.
- 동적 및 정적 콘텐츠 캐싱 – 과부하된 웹 서버를 애플리케이션 서버로도 사용하고 있다면 동적 콘텐츠를 캐싱하는 것만으로도 사용량이 가장 많은 시간대의 성능을 10배 향상할 수 있습니다. 정적 파일을 캐싱해도 성능을 몇 배 향상할 수 있습니다.
- 데이터 압축 – 사진에는 JPEG, 그래픽에는 PNG, 동영상에는 MPEG‑4, 음악 파일에는 MP3와 같은 미디어 파일 압축 형식을 사용하면 성능을 크게 향상할 수 있습니다. 이러한 형식을 모두 적용한 후 텍스트 데이터(코드 및 HTML)까지 압축하면 초기 페이지 로드 속도를 두 배로 높일 수 있습니다.
- SSL/TLS 최적화 – 보안 핸드셰이크는 성능에 큰 영향을 미칠 수 있으므로 이를 최적화하면 특히 텍스트가 많은 사이트에서 초기 응답성이 최대 2배가량 향상될 수 있습니다. SSL/TLS를 통한 미디어 파일 전송을 최적화해도 성능 향상 폭은 크지 않을 가능성이 높습니다.
- HTTP/2 및 SPDY 구현 – SSL/TLS와 함께 사용하면 이러한 프로토콜을 통해 전반적인 사이트 성능이 점진적으로 향상될 수 있습니다.
- Linux 및 웹 서버 소프트웨어(예: NGINX) 튜닝 – 버퍼링 최적화, 연결 유지(keepalive) 사용, 시간이 많이 소요되는 작업을 별도의 스레드 풀로 오프로드하는 등의 조치를 통해 성능을 크게 향상할 수 있습니다. 예를 들어 스레드 풀을 사용하면 디스크 집약적인 작업의 속도를 거의 10배 높일 수 있습니다.
이러한 기법을 직접 적용해 보시기 바랍니다. 이를 통해 애플리케이션 성능을 얼마나 개선할 수 있었는지 여러분의 이야기를 듣고 싶습니다. 아래 댓글로 결과를 공유하거나 #NGINX 및 #webperf 해시태그를 달아 트윗해 주세요!
인터넷 통계 자료
Statista.com – 2016년 G20 국가의 국내총생산에서 인터넷 경제가 차지하는 비중
Kissmetrics – 로딩 시간이 수익에 미치는 영향(인포그래픽)
Econsultancy – 사이트 속도: 전환율 향상을 위한 사례 연구, 팁 및 도구
작성자 소개

관련 블로그 게시물
시청하기: KubeCon North America 2023에서의 NGINX Gateway Fabric
이 영상에서는 KubeCon의 NGINX 부스를 찾아가, 저희가 공개한 Kubernetes Gateway API 구현을 살펴봅니다.
F5 NGINX로 대규모 WAF 플릿을 확인하고 관리하는 2가지 방법
앱 보안을 강화하는 두 가지 방법을 소개합니다. NGINX Management Suite를 통해 WAF 운영에 대한 가시성을 높이고, NGINX App Protect WAF를 활용해 코드형 보안을 구현하는 것입니다.
Ingress 컨트롤러 선택 가이드, 4부: NGINX Ingress Controller 옵션
개발 주체, 개발 철학, 프로덕션 환경 준비도, 보안 및 지원을 기준으로 어떤 NGINX Ingress 컨트롤러가 가장 적합한지 알아보세요.
진화하는 공격 환경에 NGINX App Protect Denial of Service가 적응하는 방법
NGINX App Protect Denial of Service(DoS)가 계층 7 DoS 공격을 방어하기 위해 완화 방법을 실시간으로 조정하는 방식을 설명합니다. 정상적인 사용자 행동과 서버 상태에 대한 모델을 생성하여 공격을 나타내는 이상 징후를 감지하고 맞춤형 완화 시그니처를 적용할 수 있습니다.
NGINX Instance Manager를 활용한 대규모 구성 업데이트 및 인증서 관리
NGINX Instance Manager 버전 1.0에는 두 가지 새로운 기능이 도입되었습니다. NGINX 인스턴스에 태그와 사용자 역할을 지정하면 전체 그룹에 구성을 한 번에 적용할 수 있습니다. 인증서 검사는 만료 예정인 인증서를 감지하여 서비스 중단을 방지할 수 있도록 인증서를 교체할 수 있게 해줍니다.
Netflix가 자사 CDN의 핵심으로 NGINX를 선택한 이유
Netflix가 글로벌 콘텐츠 전송 네트워크인 Open Connect의 스트리밍 미디어 기술로 NGINX를 선택한 이유를 NGINX 개발자 Gleb Smirnoff에게서 알아보세요.