소개 – NGINX를 PHP와 함께 사용하는 방법
PHP는 서버 측 웹 애플리케이션을 만드는 데 가장 널리 사용되는 방식으로, 시장 점유율은 약 80%입니다. (ASP.net은 큰 격차로 2위이며, Java는 그보다도 훨씬 뒤처진 3위입니다.)
PHP 생태계에는 수많은 PHP 프레임워크가 있으며, 그중 가장 인기 있는 것으로는 Laravel, Phalcon, Symfony 2가 있습니다. 또한 PHP는 WordPress 및 Drupal과 같은 인기 콘텐츠 관리 시스템(CMS)의 기반이기도 합니다. (최신 Drupal 릴리스인 Drupal 8에는 Symfony 2가 상당 부분 통합되어 있습니다.
이제 PHP 팀은 PHP 5가 출시된 지 10여 년 만에 새로운 버전인 PHP 7을 출시합니다. 그동안 웹 사용량과 웹사이트에 대한 요구 사항은 모두 기하급수적으로 증가했습니다. PHP는 이러한 급속한 성장에 기여했지만, PHP가 가능하게 한 바로 그 성장으로 인해 PHP의 한계 또한 두드러지게 되었습니다.
PHP는 일반적으로 강력하고 유연하지만 성능 문제가 있는 것으로 여겨집니다. PHP 기반 사이트는 트래픽이 불과 몇 배만 증가해도 쉽게 한계에 부딪힐 수 있습니다. 사이트가 비즈니스 또는 운영 목표를 달성하기 시작할 무렵이면 트래픽이 증가할 때마다 장애가 발생하기 시작합니다.
수많은 PHP 기반 애플리케이션은 비교적 간단한 몇 가지 변경만으로도 성능을 개선할 수 있었습니다. 여기에는 memcached와 같은 도구를 사용한 캐싱, 데이터베이스 튜닝, 그리고 NGINX Open Source 및 NGINX Plus를 활용한 리버스 프록시와 부하 분산이 포함됩니다. NGINX는 애플리케이션의 응답성을 크게 개선하여 사용자 수와 트래픽이 10배 단위로 증가해도 처리할 수 있도록 지원했습니다.
이 블로그 게시물은 PHP 7을 사용하는 웹사이트의 성능을 극대화하는 방법을 다루는 2부작 시리즈의 첫 번째 글입니다. 여기서는 PHP 7로 업그레이드하고, 웹 서버 소프트웨어로 NGINX Open Source 또는 NGINX Plus를 도입하며, URL을 재작성하고(요청을 올바르게 처리하는 데 필요), 정적 파일과 동적 파일을 캐싱하는 방법(애플리케이션 캐싱 또는 마이크로캐싱이라고도 함)에 중점을 둡니다.
다음 블로그 게시물에서는 서버를 추가하여 수행할 수 있는 단계에 중점을 둡니다. 여기에는 리버스 프록시 서버 추가, 여러 애플리케이션 서버로의 전환, 여러 서버 간 부하 분산, 부하 분산 시 세션 지속성 지원, SSL/TLS 및 관련 HTTP/2 프로토콜과 같은 보안 프로토콜 종료가 포함됩니다.
PHP가 한계에 부딪히는 이유
PHP 애플리케이션은 왜 한계에 부딪힐까요? 다른 모든 애플리케이션 서버 소프트웨어가 한계에 부딪히는 것과 같은 이유입니다. 사용자 요청이 들어오면 PHP와 PHP가 구동되는 웹 서버 소프트웨어는 다음과 같은 여러 작업을 수행해야 합니다:
- 요청 해석. 먼저 웹 서버 소프트웨어가, 그다음 PHP가 요청을 수신하고 해석하여 처리하기 위한 프로세스를 실행해야 합니다. 예를 들어 Apache HTTP Server는 JPEG 파일을 가져오는 것처럼 단순한 요청이든 중첩된 CSS 요청을 처리하는 것처럼 복잡한 요청이든, 각각의 데이터 요청을 처리할 리소스를 할당합니다. 이 모든 작업에는 시간과 시스템 리소스, 메모리 할당이 필요합니다. 요청 처리를 시작하기도 전에 OS나 PHP 또는 둘 다 여러 라이브러리를 로드해야 한다면 필요한 메모리가 상당히 커질 수 있습니다.
- 지원 프로토콜 처리SSL/TLS 및/또는 HTTP/2를 사용하는 경우 웹 서버 소프트웨어가 요청을 디코딩해야 하며, 이 과정에는 상당한 시간이 걸릴 수 있습니다.
- 요청을 처리합니다. PHP는 요청을 처리하는 데 필요한 리소스를 한데 모아야 합니다. 이 과정에는 여러 차례의 데이터베이스 호출, 인터넷을 통한 외부 서비스 호출, 복잡한 내부 처리가 필요할 수 있습니다.
- 요청에 응답하기. PHP는 결과를 웹 서버 소프트웨어에 반환해야 하며, 웹 서버 소프트웨어는 이를 HTTP 응답으로 요청자에게 다시 전송합니다. 웹 서버 소프트웨어와 PHP 모두 요청을 처음 수신한 시점부터 최종 확인 응답을 받을 때까지 각 요청마다 활성 상태의 전용 스레드를 실행한다는 점을 기억하세요.
물리 서버, 가상 머신 또는 클라우드 서버 인스턴스가 모든 요청마다 처리하기에는 상당히 많은 작업입니다. 물리 서버든 가상 서버든 서버 머신의 물리 메모리가 소진되면 성능이 저하되는 경향이 있습니다. 그러면 새 요청이 들어올 때 서버는 현재 세션을 디스크로 페이징하기 시작합니다. 파일 요청이 처리되기를 기다리는 동안에도 대기 상태가 발생하여 페이징이 늘어납니다. 어느 한계점(그 범위는 매우 제한적임)을 넘어서면 페이징 작업과 데이터 요청이 처리 작업을 압도하고, 성능은 급격한 악순환에 빠져 사용자가 오랫동안 기다리거나 세션이 완전히 종료되는 상황이 발생합니다.
성능 문제 해결
PHP의 성능 한계를 극복하는 것은 충분히 가능하며, 이를 위해서는 서로 보완하는 여러 단계가 필요합니다. 각 단계는 다른 단계와 함께 적용할 수 있습니다. 대략 다음과 같습니다:
- 하드웨어를 추가해 문제 해결하기. 메모리를 더 늘리고, 디스크 속도를 높이고, 데이터베이스 서버를 분리하고, 콘텐츠 전송 네트워크를 도입하고, 처리 용량을 늘리는 등의 물리적 해결책은 성능 문제를 빠르고 간단하게 해결하는 방법입니다. 이러한 해결책은 가동 시간을 유지하거나 성능을 선형적으로 확장하는 데 도움이 될 수 있습니다.
- PHP 및 애플리케이션 코드 개선. 새로운 버전의 PHP와 새로운 프레임워크, 개선된 애플리케이션 코드는 성능 향상에 큰 도움이 될 수 있습니다. 또한 새 하드웨어에 추가 비용을 들이지 않고도 성능을 두 배, 심지어 네 배까지 높일 수 있습니다.
- 개선된 서버 소프트웨어. 대부분의 웹 서버와 PHP는 처리 중인 각각의 열린 요청에 전용 리소스를 할당합니다. NGINX 서버 소프트웨어는 리소스를 점유하지 않고 요청이 들어오는 대로 처리하여 서버의 리소스 사용량을 최소화합니다.
- 다중 서버 구현. 역방향 프록시 서버를 구현하면 인터넷 요청을 처리하고 하나 이상의 애플리케이션 서버에 요청을 분산(부하 분산)할 수 있습니다. 역방향 프록시 서버는 파일 캐싱, SSL/TLS 및 HTTP/2와 같은 프로토콜의 종단 처리, 여러 애플리케이션 서버의 관리도 담당할 수 있습니다. 애플리케이션 서버가 하나뿐인 경우에도 워크로드의 상당 부분을 덜어 줍니다. 서버가 추가될 때 부하 분산을 사용하면 특정 서버에 감당해야 할 몫보다 많은 부하가 몰리는 것을 방지할 수 있습니다.
이러한 단계를 반드시 특정 순서대로 구현할 필요는 없습니다. 예를 들어 Apache를 웹 서버로 계속 사용하고 애플리케이션 서버를 PHP 7로 업그레이드하지 않더라도, 기존 서버의 “앞단에” NGINX를 역방향 프록시로 구현하기만 하면 성능이 향상되고 여러 애플리케이션 서버를 병렬로 구축할 수 있습니다.
<p>어떤 방식으로 진행하든 기억해야 할 핵심은 현재 애플리케이션 코드를 거의 또는 전혀 변경하지 않고도 성능을 몇 배로 높이고, 처리 용량은 무려 10배까지 늘릴 수 있다는 점입니다. 사람들이 이러한 놀라운 성능 향상을 이미 어떻게 달성했는지, 또는 현재 어떻게 달성해 나가고 있는지 계속 읽어보세요.</p>
참고: 이 블로그 게시물에서는 다중 서버 최적화에 대해서는 자세히 다루지 않습니다. 별도의 데이터베이스 서버와 콘텐츠 전송 네트워크(CDN)를 사용하면 애플리케이션 서버의 부하를 줄이고 성능을 크게 향상할 수 있습니다. 이러한 변경 사항은 여기에서 설명하는 애플리케이션 및 구현 개선과는 별개로 병행할 수 있습니다.
팁 1 – PHP 7로 업그레이드
가능한 한 빨리 PHP 7로 업그레이드해야 하는 주된 이유는 간단합니다. 바로 애플리케이션 속도입니다(메모리 절감 덕분에 속도가 크게 향상됩니다). PHP 7은 이전 PHP 버전보다 두 배 빠르고 메모리 사용량도 훨씬 적다고 합니다. (물론 속도와 메모리 사용량 모두 실제 환경에 따라 달라질 수 있습니다.)
간단히 말해, 응답 시간은 웹 애플리케이션에서 매우 중요합니다. 더 빠르면서도 메모리를 적게 사용해 페이지 스와핑 및 그로 인한 성능 문제의 가능성을 줄이는 웹 앱은 다음 세 가지 효과를 가져옵니다:
- 사용자의 만족도를 높여 사이트를 방문하고 기사 읽기, 제품 정보 확인, 합승 택시 호출, 남는 방 대여, 상품 구매 등의 작업을 완료할 가능성을 높입니다. 애초에 사이트나 앱을 만든 이유가 바로 이것입니다.
- 특정 서버가 사용자 증가로 인해 속도가 느려지거나 심지어 완전히 다운될 위험 없이 더 많은 사용자를 지원할 수 있게 해 줍니다. 파국을 늦추는 것은 언제나 좋은 일이죠.
- 서버에 과부하를 일으켜 운영을 중단시키는 해커 공격에 서버가 덜 취약해집니다. 오늘날에는 누구나 공격을 받지만, 취약한 대상일수록 더 자주, 더 거센 공격을 받습니다. 따라서 취약성을 줄이면 기하급수적으로 더 나은 결과를 얻을 수 있습니다.
이 모든 것은 업그레이드해야 할 훌륭한 이유이며, 종합해 보면 업그레이드의 필요성은 거의 압도적으로 보입니다. 또한 이처럼 뚜렷한 성능상의 이점이 없을 때조차도, 많은 문제를 해결하기 위한 첫 번째 권장 사항은 언제나 “최신 버전으로 업그레이드하세요”입니다. 그렇다면 왜 모두가 곧바로 업그레이드하지 않는 걸까요?
xkcd가 말하는 업데이트
이유는 간단합니다. 사람들은 오래된 코드를 건드리기 싫어하며, 그럴 만한 이유도 있습니다. 오래된 앱이 충분히 잘 작동하고 개발자들이 기존 앱을 업그레이드하는 것보다 새 앱을 만드는 데서 더 좋은 성과를 얻는다면, 그 오래된 앱은 변경되지 않은 채 아주 오랫동안 유지될 수 있습니다. (현재 웹 서버와 앱을 전혀 변경하지 않고 NGINX를 사용해 앱의 성능을 개선하는 방법은 이 시리즈의 두 번째 블로그 게시물을 참조하세요.)
하지만 가능하다면 성능을 더욱 향상하기 위한 첫 단계로 PHP 7로 업그레이드하는 것이 더 효율적입니다. 다만 충분한 테스트를 거쳐 작업을 완료할 수 있는 시간이 확보되기 전에는 시작하지 마세요.
PHP 7로 업그레이드하려면 무엇이 필요한지 살펴보겠습니다:
- 표현식 평가 방식의 변경 사항. 일부 표현식이 PHP 7에서 올바르게 평가되도록 작성 방식을 변경해야 할 수도 있습니다. (또는 매우 신중하게 진행하여 모든 PHP 서버를 한꺼번에 업그레이드하지 않는 경우에는 PHP 5.6과 PHP 7 모두에서 올바르게 평가되도록 해야 합니다.) 가변 변수나 가변 속성을 사용하고 있다면 두 PHP 버전에서 동일한 방식으로 평가되도록 코드를 수정해야 합니다.
- 구문 변경 사항. PHP 7은 ASP 태그나 script 태그를 지원하지 않습니다. switch 문에는 default 절을 여러 개 사용할 수 없습니다. (switch와
if-then-else중 어느 쪽을 사용할지에 관한논쟁은 여기서 다루지 않겠습니다.) - 더 이상 사용되지 않는 기능 제거. PHP 5.x의 여러 버전에서 더 이상 사용되지 않는 것으로 지정된 온갖 기능은 이제 죽은 앵무새보다도 더 확실히 사라졌습니다. 이러한 기능은 PHP 7에서 전혀 작동하지 않습니다. 코드에 이런 기능이 포함되어 있어 모두 제거하려다 하나라도 놓치면, 사이버 먼데이 전날 밤 11시 59분에 장바구니 기능이 틀림없이 사라질 것입니다.
- 새로운 기능. PHP 7에는 기존 코드를 업그레이드하려는 사람이라면 누구나 솔깃할 만한 새로운 기능이 다수 추가되었지만, 코드를 정리할 때 새로운 기능을 추가하는 것은 신중해야 합니다. 새로운 기능은 대개 훌륭하기 때문에 추가된 것이지만, 동시에 버그(자신의 버그와 다른 사람의 버그 모두)를 끌어들이기 쉽고 PHP가 추가로 업그레이드됨에 따라 향후 수정이 필요할 수도 있습니다.
- 일반 코드 검토. 코드를 건드릴 때마다, 아니, 코드 파일을 열고 변경했는지 확실하지 않을 때조차도 파일의 모든 내용을 검토해야 하며, 특히 변경한 부분은 반드시 확인해야 합니다.
- 테스트. 모든 것은 항상 테스트해야 합니다. 변경 사항이 있다면 모든 것을 다시 테스트해야 하며, 그렇다고 해서 모든 버그를 찾아낼 수 있는 것도 아닙니다. 잘 구축된 DevOps 환경에서는 이러한 테스트가 비교적 쉬울 수 있지만, 현재로서는 그런 이상적인 환경을 누리는 사람이 극소수에 불과합니다.
Engine Yard의 이 블로그에는 이러한 문제 대부분에 대한 좋은 예시가 나와 있습니다.
PHP 7로 업그레이드하기로 결정했다면 PHP 7의 새로운 기능을 활용해 코드 전체의 성능을 검토하고 개선하거나, 최소한 핵심 기능만이라도 점검해 보세요. 이는 여러분과 팀이 역량을 키우는 데 가장 좋은 방법이며, 오늘 적용하고 검토하고 테스트한 변경 사항은 앞으로도 오랫동안 도움이 될 가능성이 큽니다. 또한 최적화된 코드는 최적화된 환경에서 실행될 때 큰 효과를 발휘하므로, 이 블로그 게시물에서 소개하는 다른 성능 개선 방법도 최대한 활용할 수 있습니다.
따라서 사이트에서 애플리케이션 코드를 건드리지 않고도 성능을 개선하기 위해 NGINX를 배포하는 경우가 많지만, 과감하게 결단을 내리고 추진해 나가시기를 권합니다. 전환하는 데 도움이 되는 다양한 자료가 있으며, 직접 팔을 걷어붙이고 해결할 수도 있습니다. 공식 PHP 사이트에는 PHP 7 마이그레이션 가이드가 있고, O’Reilly에서 출간한 PHP 7 업그레이드 실전 가이드도 있습니다.
팁 2 – NGINX Open Source 또는 NGINX Plus 선택
NGINX는 1억 4천만 개 이상의 웹사이트에서 실행되는 소프트웨어로, 여기에는 트래픽이 가장 많은 웹사이트 10,000개 중 절반이 포함됩니다. (이 측정에서는 단일 서버 사이트의 웹 서버와 다중 서버 사이트의 리버스 프록시 서버를 감지합니다.) 웹 서버로 사용할 경우 두 제품 모두 즉각적인 성능 향상을 제공하며, 다른 소프트웨어를 실행하는 서버가 과부하로 인해 스래싱이 발생한 경우에는 성능이 최대 10배까지 향상되기도 합니다. 리버스 프록시 서버로 사용할 경우 두 제품 모두 여러 전용 서버를 활용하여 필요에 따라 배포를 원하는 규모까지 확장할 수 있도록 지원합니다.
PHP와 Apache는 모두 열려 있는 각 요청에 리소스를 할당합니다. 둘 중 하나 또는 둘 다 여러 라이브러리를 로드해야 하는 경우 요청당 시작 시간과 메모리 사용량이 상당히 커질 수 있습니다. 웹 서버 소프트웨어를 NGINX로 전환하면 서버 수준에서 이 문제가 해결됩니다. NGINX의 기능을 활용해 웹 서버(예: 정적 파일 제공)나 리버스 프록시 서버(각종 캐싱, 프로토콜 종료, 부하 분산 등)로 작업을 분산하면 PHP가 처리해야 할 작업이 최소화되어 애플리케이션 처리가 간소화되고 빨라집니다.
사이트에 사용자 지정 또는 독점 Apache 모듈이 있는 경우 해당 모듈을 교체하기 전까지 Apache를 NGINX로 대체하지 못할 수 있습니다. 간단한 해결 방법이 있는지 NGINX에 문의해 보세요. 없다면 변경에 필요한 시간과 작업량을 산정하세요.
NGINX를 사용하기로 결정했다면 NGINX Open Source와 NGINX Plus 중에서 선택할 수 있습니다. NGINX Open Source와 비교했을 때 NGINX Plus가 제공하는 가장 두드러진 기능은 다음과 같습니다:
- Precompiled code. NGINX Plus is distributed in compiled form, including popular libraries and dynamic modules that you can add and remove on the fly. (NGINX Open Source is available as both compiled and uncompiled code.) You can make a wide range of configuration changes without restarting the server.
- 지원. NGINX Plus에는 지원 패키지가 포함되어 있어 NGINX 엔지니어에게 직접 문의할 수 있습니다.
- 모니터링 및 관리. DevOps 친화적인 도구를 사용하면 서비스 수준 계약(SLA)을 충족하도록 서버를 지속적으로 운영할 수 있습니다.
리버스 프록시 서버로서 NGINX Plus는 다음과 같은 추가적인 이점을 제공합니다:
- 부하 분산. 두 NGINX 버전 모두 기본적인 HTTP 부하 분산을 지원하지만, NGINX Plus는 더 정교한 알고리즘과 TCP 부하 분산을 추가로 지원합니다.
- 세션 지속성. NGINX Plus는 부하 분산과 함께 더욱 정교한 세션 지속성 기능을 제공하며, 이는 PHP 애플리케이션 서버에서 특히 중요한 경우가 많습니다.
- 모니터링 및 관리. NGINX Plus 모니터링 및 관리의 모든 기능은 다중 서버 배포 환경에서 진가를 발휘하며, 사전 컴파일된 코드와 지원의 가치 또한 더 복잡한 구현 환경에서 극대화됩니다.
NGINX Open Source와 NGINX Plus는 모두 콘텐츠 캐싱과 마이크로캐싱(일명 애플리케이션 캐싱)을 지원합니다. 웹 서버 환경에서 캐싱은 애플리케이션 서버의 부하를 줄이는 데 유용하지만, 두 기능은 여전히 하나의 물리적 머신 또는 가상 머신 인스턴스를 공유합니다. 역방향 프록시 서버에서 캐싱을 사용하면 애플리케이션 서버 장치의 작업 부하를 크게 줄여 성능을 더욱 향상할 수 있습니다.
NGINX Open Source 소프트웨어는 nginx.org에서 직접 다운로드할 수 있으며, 여기에서 커뮤니티 지원도 받을 수 있습니다. 단일 NGINX Plus 구독을 시작하려면 30일 무료 평가판을 신청하거나 온라인으로 구매하세요. 다중 인스턴스 번들에 대해서는 NGINX 영업팀에 문의하세요.
팁 3 – Apache 구성을 NGINX 구문으로 변환
웹 서버 소프트웨어를 Apache에서 NGINX로 전환할 때는 몇 가지 사항을 변경해야 합니다. 자세한 내용은 문서에서 확인할 수 있습니다. sitepoint.com:
- 구성 파일 생성 또는 변환. 구성 코드를 변경하여 NGINX(Apache가 아님)가 구성에 사용할 파일을 지정합니다.
- 읽기/쓰기 권한 변경. 웹사이트의 루트 디렉터리에 있는 파일에 대해 CRUD 작업(생성, 읽기, 업데이트, 삭제)을 수행할 수 있도록 계정에 권한을 추가합니다.
- 유효한 검색 패턴 지정. 요청을 처리할 때 NGINX가 시도할 수 있는 패턴과 시도할 수 없는 패턴을 지정하도록 location 블록을 추가합니다.
- .htaccess 구성 코드 교체. Apache의 구성 세부 정보는 일반적으로 .htaccess 파일이나 정적 구성 파일(예:
mod_rewrite지시문)에 있습니다. 이를 NGINX 구성 파일의 적절한 구성 사양으로 교체하세요. 몇 가지 예는 블로그에서 확인할 수 있습니다.
이러한 변경 작업을 수행하면 NGINX에 익숙해지고, 이 블로그 게시물의 2부에서 설명하는 것처럼 더 복잡한 사이트를 최적화할 수 있는 역량을 갖추게 됩니다. 하지만 이러한 구성 변경에 지나치게 많은 작업이 필요하거나 사이트 운영에 감수하기 어려운 수준의 위험이 따른다면 걱정하지 마세요. 핵심 웹 서버 소프트웨어를 Apache에서 업그레이드하지 않고도, 즉 웹 서버 구성 파일을 변경하지 않고도 2부에서 설명하는 다중 서버 아키텍처를 구현할 수 있습니다.
팁 4 – 정적 파일 캐싱 구현
정적 파일은 적어도 웹 서버 관점에서 자주 변경되지 않는 파일을 말합니다. 일반적으로 JPEG 및 PNG와 같은 그래픽 파일과 CSS 및 JavaScript 같은 코드 파일이 정적 파일에 포함됩니다. 이러한 파일을 애플리케이션 서버나 별도의 데이터베이스 서버에 두면, 파일에 대한 요청을 생성하고 처리하는 데 필요한 모든 오버헤드와 함께 애플리케이션 코드가 해당 요청을 처리해야 합니다. 이로 인해 애플리케이션 서버가 더 중요한 작업에 집중하지 못하게 되며, 물리적 메모리가 과부하되어 새로운 요청이 들어올 때 현재 처리 중인 요청이 디스크로 페이징되는 상황에 가까워질 수 있습니다.
정적 파일 캐싱은 NGINX의 핵심 기능입니다. 웹 서버 또는 리버스 프록시 서버에서 구현할 수 있습니다:
- NGINX 웹 서버에서 정적 파일 캐싱을 사용하면 애플리케이션 서버의 부하를 줄일 수 있으며, 훨씬 적은 메모리 오버헤드로 파일을 더 빠르게 가져올 수 있습니다. 하지만 파일은 여전히 동일한 물리적 서버 또는 가상 서버 인스턴스에서 가져오므로, 서버의 프로세서는 애플리케이션 실행 외의 작업도 계속 처리해야 합니다.
- NGINX 리버스 프록시 서버는 웹 서버와 다른 머신 또는 인스턴스에서 실행되므로, 정적 파일을 캐싱해도 애플리케이션 서버의 리소스를 전혀 사용하지 않습니다. 따라서 애플리케이션 서버는 애플리케이션 실행에만 집중할 수 있습니다.
NGINX에서 정적 파일 캐싱을 구현하는 전체 과정은 세 단계로 이루어집니다:
- 검색에 사용할 루트 디렉터리를 지정합니다.
- 요청 처리.
- 응답 속도 최적화.
리버스 프록시 서버를 사용하지 않는 NGINX 웹 서버에서는 일반적인 의미의 캐싱을 하지 않습니다. 대신 X-Accel-Redirect 헤더를 사용하여 정적 파일 요청을 웹 서버로 바로 전달합니다. 애플리케이션 서버에는 해당 요청이 전달되지 않으므로 모든 리소스를 애플리케이션 요청 처리에 집중할 수 있습니다. 리버스 프록시 서버를 사용하는 경우에는 정적 파일 캐싱을 사용하며, 애플리케이션이 실행되는 물리적 서버나 가상 서버 인스턴스는 정적 파일 요청 처리에 전혀 관여하지 않습니다.
응답 속도를 최적화하는 예로, 다음 구성 스니펫을 사용하면 NGINX가 운영 체제의 sendfile 시스템 호출을 사용하도록 설정할 수 있습니다. 이 호출은 파일을 중간 버퍼에 복사하지 않으므로 파일 전송 단계를 하나 줄여 줍니다:
location /mp3 { sendfile on;
sendfile_max_chunk 1m;
# ...
}정적 파일 캐싱을 위한 NGINX 구성에 대한 자세한 내용은 NGINX Plus 관리자 가이드를 참조하세요.
팁 5 – 마이크로캐싱 구현
혼동스럽게도 마이크로캐싱은 여러 이름으로 불리며, 여기에는 애플리케이션 캐싱과 단순히 캐싱도 포함됩니다. NGINX에서는 이러한 파일의 유효 기간이 짧다는 점을 강조하기 위해 마이크로캐싱이라는 용어를 사용합니다.
사용자가 댓글을 남길 수 있는 블로그 게시물 페이지가 있다고 가정해 보겠습니다. 새로운 방문자가 페이지에 접속할 때마다, 또는 기존 사용자가 자신이나 다른 사람이 새로 남긴 댓글을 확인하기 위해 페이지를 새로 고칠 때마다 최신 댓글을 표시하고 싶을 것입니다. 이 경우에는 누군가 페이지를 방문할 때마다 페이지를 새로 생성하는 것이 좋은 방법처럼 보입니다.
하지만 ‘매번’ 새로 생성하는 작업은 부담이 될 수 있습니다. 페이지 방문이 초당 한 번이라면 방문할 때마다 페이지를 새로 생성하는 것이 합리적입니다. 그러나 사이트의 다른 모든 페이지와 더불어 해당 페이지에 초당 10명, 100명, 1,000명이 방문한다면 애플리케이션 서버에 과부하가 걸릴 수 있습니다. 사용자에게 최신 콘텐츠를 제공하려다 보면 결국 아무도 콘텐츠를 빠르게 받아보지 못하게 됩니다.
마이크로캐싱은 페이지를 한 번 생성한 후 캐시된 버전을 짧은 시간(예: 1초 또는 몇 초) 동안 유효한 것으로 설정하는 방식입니다. 캐시된 버전이 만료되면 다음 요청 시 새로운 페이지가 생성되고, 그 직후의 요청에는 해당 페이지의 캐시된 버전이 제공됩니다. 이는 정적 파일과 동일한 방식으로 작동하지만, 훨씬 짧은 시간 단위로 이루어집니다.
이 이미지는 사이트에서 마이크로캐싱할 수 있는 콘텐츠를 어디에서 찾아야 하는지 보여줍니다. 이 이미지는 당사의 Owen Garrett이 작성한 마이크로캐싱 블로그 게시물에서 가져온 것입니다.
많은 동적 콘텐츠가 마이크로캐싱에 적합합니다
마이크로캐싱은 애플리케이션 서버의 부하를 줄이는 것이 가장 필요한 순간에 바로 그 역할을 하면서도 사용자에게 미치는 악영향은 거의 또는 전혀 없다는 점에서 매우 훌륭합니다. 워낙 유용해서 일부 시스템에는 기본 기능으로 내장되어 있습니다. Drupal은 강력한 내장 마이크로캐싱 기능을 매우 중요하게 여기기 때문에 Drupal 생태계에서는 마이크로캐싱을 단순히 ‘캐싱’이라고 부릅니다.
하지만 Drupal의 솔루션은 다소 미흡하며, 이와 유사한 솔루션도 마찬가지입니다. 애플리케이션 서버의 작업량은 줄어들지만, 구성과 구현, 파일 제공을 관리하는 주체는 여전히 Drupal(더 일반적으로는 PHP)입니다. NGINX를 마이크로캐싱에 사용하면 애플리케이션 서버는 마이크로캐시에 지정된 주기에 따라 새 페이지를 생성하는 작업 외에는 완전히 부담을 덜 수 있습니다. 다른 요청은 아예 전달받지도 않으며, 캐시 적중 시 데이터를 저장하거나 가져올 필요도 없습니다.
NGINX Plus 또는 기타 도구를 사용하면 사이트를 모니터링하여 어떤 페이지에 마이크로캐싱을 적용하면 효과적인지 확인할 수 있습니다. 다음 구성 코드 조각은 200 OK 상태 코드가 포함된 응답에 1초의 캐싱 기간을 적용합니다.
proxy_cache_path /tmp/cache keys_zone=cache:10m levels=1:2 inactive=600s max_size=100m;server {
proxy_cache cache;
proxy_cache_valid 200 1s;
# ...
}1부 결론
PHP 블로그 게시물의 첫 번째 파트에서는 단일 서버 솔루션과 캐싱을 중점적으로 다룹니다. 캐싱은 단일 서버 구현에서도 효과적이지만, 리버스 프록시 서버를 함께 사용하면 더욱 효과적입니다. 파트 2에서는 리버스 프록시 서버의 이점과 PHP 애플리케이션을 위한 다중 서버 구현을 설명합니다.
NGINX Plus를 사용해 보려면 지금 30일 무료 체험을 시작하거나, 사용 사례에 대해 논의하려면 문의해 주세요.
작성자 소개

관련 블로그 게시물
시청하기: 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에게서 알아보세요.