애플리케이션과 웹사이트의 성능이 성공의 중요한 요소라는 것은 누구나 알고 있습니다.
하지만 애플리케이션이나 웹 사이트의 성능을 향상시키는 과정이 항상 명확하지는 않습니다.
코드 품질과 인프라는 물론 중요하지만, 많은 경우 아주 기본적인 애플리케이션 전송 기술에 집중함으로써
애플리케이션의 최종 사용자 경험을 크게 개선할 수 있습니다.
애플리케이션 스택에서 캐싱을 구현하고 최적화하는 것이 그러한 예 중 하나입니다.
이 블로그 게시물에서는 초보자와 고급 사용자 모두 NGINX 및 NGINX Plus에 포함된
콘텐츠 캐시 기능을 활용하여 성능을 개선하는 데 도움이 되는 기술을 다룹니다.
개요
콘텐츠 캐시는 클라이언트와 '원본 서버' 사이에 위치하며 클라이언트가 보는 모든 콘텐츠의 사본을 저장합니다.
클라이언트가 캐시에 저장된 콘텐츠를 요청하면 캐시는 원본 서버에 연결하지 않고 직접 콘텐츠를 반환합니다.
이렇게 하면 콘텐츠 캐시가 클라이언트와 더 가까워져 성능이 향상되고
매번 페이지를 처음부터 생성하는 작업을 하지 않아도 되므로 애플리케이션 서버를 더 효율적으로 사용할 수 있습니다.
웹 브라우저와 애플리케이션 서버 사이에는 클라이언트의 브라우저 캐시, 중개 캐시, CDN(콘텐츠 전송 네트워크),
애플리케이션 서버 앞에 위치한 로드 밸런서 또는 리버스 프록시 등 여러 캐시가 존재할 수 있습니다.
캐싱은 역방향 프록시/로드 밸런서 수준에서도 성능을 크게 향상시킬 수 있습니다.
예를 들어, 작년에 저는 느리게 로드되는 웹사이트의 성능을 튜닝하는 작업을 맡았습니다.
가장 먼저 알아차린 것 중 하나는 메인 홈페이지를 생성하는 데 1초 이상이 걸린다는 것이었습니다.
디버깅을 해본 결과 페이지가 캐시할 수 없는 것으로 표시되어 있어서
각 요청에 따라 동적으로 생성되고 있다는 사실을 발견했습니다.
페이지 자체는 자주 변경되지 않았고 개인화되지 않았기 때문에 이 작업은 필요하지 않았습니다.
실험 삼아 로드 밸런서가 홈페이지를 5초 동안 캐시하도록 표시했는데,
이렇게 하는 것만으로도 눈에 띄게 개선되었습니다.
첫 바이트까지 걸리는 시간이 몇 밀리초로 줄어들었고
페이지가 눈에 띄게 빠르게 로드되었습니다.
NGINX는 일반적으로 애플리케이션 스택에서
리버스 프록시 또는 로드 밸런서로 배포되며 전체 캐싱 기능을 갖추고 있습니다.
다음 섹션에서는 NGINX로 기본 캐싱을 구성하는 방법에 대해 설명합니다.
기본 캐싱 설정 및 구성 방법
기본 캐싱을 사용하려면 proxy_cache_path와 proxy_cache 두 지시어만 필요합니다.
proxy_cache_path 지시어는 캐시의 경로와 구성을 설정하고 proxy_cache 지시어는 이를 활성화합니다.
proxy_cache_path /path/to/cache levels=1:2 keys_zone=my_cache:10m max_size=10g inactive=60m use_temp_path=off; server { # ... location / { proxy_cache my_cache; proxy_pass http://my_upstream; } }proxy_cache_path 지시어에 대한 매개변수는 다음 설정을 정의합니다:
캐시의 로컬 디스크 디렉토리는 /path/to/cache/라고 합니다.
levels는 /path/to/cache/ 아래에 2단계 디렉터리 계층 구조를 설정합니다.
단일 디렉터리에 많은 수의 파일이 있으면 파일 액세스 속도가 느려질 수 있으므로
대부분의 배포에는 2단계 디렉터리 계층 구조를 사용하는 것이 좋습니다.
levels 파라미터를 포함하지 않으면 NGINX는 모든 파일을 동일한 디렉터리에 배치합니다.
keys_zone는 캐시 키와 사용 타이머와 같은 메타데이터를 저장하기 위한 공유 메모리 영역을 설정합니다.
메모리에 키 사본이 있으면 NGINX가 디스크로 이동하지 않고도 요청이 HITMISS
max_size는 캐시 크기의 상한을 설정합니다(이 예에서는 10기가바이트).
값을 지정하지 않으면 캐시가 사용 가능한 모든 디스크 공간을 사용할 수 있도록 커집니다.
캐시 크기가 제한에 도달하면 캐시 관리자라는 프로세스가 가장 최근에 사용된 파일을 제거하여 캐시 크기를 제한 이하로 되돌립니다.
inactive는 항목이 액세스되지 않고 캐시에 남아 있을 수 있는 기간을 지정합니다.
이 예에서는 60분 동안 요청되지 않은 파일은 만료 여부에 관계없이 캐시 관리자 프로세스에 의해 캐시에서 자동으로 삭제됩니다.
기본값은 10분입니다(10m). 비활성 콘텐츠는 만료된 콘텐츠와 다릅니다.
NGINX는 캐시 제어 헤더 (예: Cache-Control:max-age=120)에 정의된 대로 만료된 콘텐츠를 자동으로 삭제하지 않습니다.
만료된(오래된) 콘텐츠는 inactive에 지정된 시간 동안 액세스하지 않은 경우에만 삭제됩니다.
만료된 콘텐츠에 액세스하면 NGINX는 원본 서버에서 콘텐츠를 새로 고치고 inactive 타이머를 재설정합니다.
NGINX는 먼저 캐시 대상 파일을 임시 저장 영역에 쓰고, use_temp_path=off 지시문은
캐시할 동일한 디렉터리에 파일을 쓰도록 NGINX에 지시합니다.
파일 시스템 간에 불필요한 데이터 복사를 방지하려면 이 파라미터를 off로 설정하는 것이 좋습니다.
use_temp_path는 NGINX 버전 1.7.10 및 NGINX Plus R6에서 도입되었습니다.
마지막으로 proxy_cache 지시어는 상위 location 블록(예제에서는 /)의 URL과 일치하는 모든 콘텐츠의 캐싱을 활성화합니다.
또한 proxy_cache 지시문을 서버 블록에 포함할 수 있으며,
자체 location 지시문이 없는 서버의 모든 proxy_cache 블록에 적용합니다.
오리진이 다운되었을 때 캐시된 콘텐츠 전송
NGINX 콘텐츠 캐싱의 강력한 기능은 원본 서버에서 새로운 콘텐츠를 가져올 수 없을 때
캐시에서 오래된 콘텐츠를 제공하도록 구성할 수 있다는 것입니다.
캐시된 리소스에 대한 모든 원본 서버가 다운되었거나
일시적으로 사용 중인 경우 이러한 문제가 발생할 수 있습니다.
NGINX는 오류를 클라이언트에 전달하는 대신 캐시에서 오래된 버전의 파일을 전달합니다.
이렇게 하면 NGINX가 프록시하는 서버에 추가적인 수준의 내결함성을 제공하고
서버 장애 또는 트래픽 급증 시에도 가동 시간을 보장할 수 있습니다.
이 기능을 사용하려면 proxy_cache_use_stale 지시어를 포함하세요:
location / { # ...
proxy_cache_use_stale error timeout http_500 http_502 http_503 http_504;
}이 샘플 구성을 사용하면 NGINX가 원본 서버로부터 error, timeout 또는 지정된 5xx 오류를 수신하고
캐시에 요청된 파일의 오래된 버전이 있으면 오류를 클라이언트로 전달하는 대신 오래된 파일을 전달합니다.
캐시 미세 조정 및 성능 개선
NGINX에는 캐시 성능을 미세 조정할 수 있는 다양한 옵션 설정이 있습니다. 다음은 그 중 몇 가지를 활성화하는 예제입니다:
proxy_cache_path /path/to/cache levels=1:2 keys_zone=my_cache:10m max_size=10g inactive=60m use_temp_path=off;
server {
# ...
location / {
proxy_cache my_cache;
proxy_cache_revalidate on;
proxy_cache_min_uses 3;
proxy_cache_use_stale error timeout updating http_500 http_502
http_503 http_504;
proxy_cache_background_update on;
proxy_cache_lock on;
proxy_pass http://my_upstream;
}
}
이 지시어는 다음과 같은 동작을 구성합니다:
proxy_cache_revalidate는 원본 서버에서 콘텐츠를 새로 고칠 때
조건부 GET 요청을 사용하도록 NGINX에 지시합니다.
클라이언트가 캐시 제어 헤더에 정의된 대로 캐시되었지만 만료된 항목을 요청하는 경우,
NGINX는 원본 서버로 보내는 If-Modified-Since 요청 헤더에 GET 필드를 포함시킵니다.
이렇게 하면 서버가 NGINX가 원래 파일을 캐시할 때 파일에 첨부된 마지막 수정된 이후 수정된 경우에만
전체 항목을 전송하므로 대역폭을 절약할 수 있습니다.
proxy_cache_min_uses는 NGINX가 항목을 캐시하기 전에 클라이언트에서 요청해야 하는 항목의 횟수를 설정합니다.
이 설정은 가장 자주 액세스하는 항목만 캐시에 추가되도록 하므로
캐시가 계속 채워지는 경우에 유용합니다.
기본적으로 proxy_cache_min_uses는 1로 설정되어 있습니다.
proxy_cache_use_stale 지시문에 updating 파라미터를 추가할 수 있습니다, 를
proxy_cache_background_update 지시문과 함께 사용하면 클라이언트가 원본 서버에서 만료되었거나
업데이트가 진행 중인 항목을 요청할 때 NGINX가 오래된 콘텐츠를 제공하도록 지시합니다.
모든 업데이트는 백그라운드에서 수행됩니다.
업데이트된 파일이 완전히 다운로드될 때까지 모든 요청에 대해 오래된 파일이 반환됩니다.
proxy_cache_lock를 활성화하면 여러 클라이언트가 캐시에 최신이 아닌 파일(MISSproxy_cache_lock를 활성화하지 않으면
캐시 누락을 초래하는 모든 요청이 원본 서버로 바로 이동합니다.
캐시를 여러 하드 드라이브에 분할하기
하드 드라이브가 여러 개 있는 경우 NGINX를 사용하여 캐시를 여러 하드 드라이브에 분할할 수 있습니다.
다음은 요청 URI에 따라 클라이언트를 두 개의 하드 드라이브에 균등하게 분할하는 예제입니다:
proxy_cache_path /path/to/hdd1 levels=1:2 keys_zone=my_cache_hdd1:10m max_size=10g inactive=60m use_temp_path=off;
proxy_cache_path /path/to/hdd2 levels=1:2 keys_zone=my_cache_hdd2:10m
max_size=10g inactive=60m use_temp_path=off;
split_clients $request_uri $my_cache {
50% “my_cache_hdd1”;
50% “my_cache_hdd2”;
}
server {
# ...
location / {
proxy_cache $my_cache;
proxy_pass http://my_upstream;
}
}두 개의 proxy_cache_path 지시어는 두 개의 다른 하드 드라이브에
두 개의 캐시(my_cache_hdd1 및 my_cache_hdd2)를 정의합니다.
split_clients 구성 블록은 절반의 요청 결과(50%)의 결과는 my_cache_hdd1에, 나머지 절반은 my_cache_hdd2에 캐싱됩니다.
$request_uri 변수(요청 URI)에 기반한 해시에 따라 각 요청에 사용되는 캐시가 결정되며,
결과적으로 특정 URI에 대한 요청은 항상 동일한 캐시에 캐시됩니다.
이 접근 방식은 RAID 하드 드라이브 설정을 대체할 수 없다는 점에 유의하세요.
하드 드라이브에 장애가 발생하면 장애가 발생한 하드 드라이브로 전송된 요청에 대해
사용자에게 500개의 응답 코드가 표시되는 등 시스템에서 예기치 않은 동작이 발생할 수 있습니다.
적절한 RAID 하드 드라이브 설정은 하드 드라이브 장애를 처리할 수 있습니다.
자주 묻는 질문(FAQ)
이 섹션에서는 NGINX 콘텐츠 캐싱에 대해 자주 묻는 질문에 대한 답변을 제공합니다.
NGINX 캐시를 계측할 수 있나요?
예, add_header 지시어를 사용하면 됩니다:
add_header X-Cache-Status $upstream_cache_status;
이 예는 클라이언트에 대한 응답에 X-Cache-Status HTTP 헤더를 추가합니다.
다음은 $upstream_cache_status에 사용할 수 있는 값입니다:
- MISS - 캐시에서 응답을 찾을 수 없어 원본 서버에서 가져온 것입니다. 응답이 캐시되었을 수 있습니다.
- BYPASS - 응답이 캐시에서 제공되지 않고 원본 서버에서 가져온 이유는 요청이 proxy_cache_bypass 지시어와 일치하기 때문입니다(아래의
- EXPIRED - 캐시에 있는 항목이 만료되었습니다. 응답에 원본 서버의 새 콘텐츠가 포함되어 있습니다.
- STALE - 원본 서버가 올바르게 응답하지 않아서 콘텐츠가 부실하고 proxy_cache_use_stale가 구성되었기 때문에 콘텐츠가 부실합니다.
- 업데이트 중 - 이전 요청에 대한 응답으로 항목이 현재 업데이트 중이므로 콘텐츠가 부실하며
- proxy_cache_use_stale updating가 구성되었습니다.
- REVALIDATED - proxy_cache_revalidate 지시어가 활성화되었고
- NGINX가 현재 캐시된 콘텐츠가 여전히 유효한지 확인했습니다(If-Modified-Since 또는 If-None-Match).
- HIT - 응답에 캐시에서 직접 가져온 유효하고 새로운 콘텐츠가 포함되어 있습니다.
NGINX는 캐시할지 여부를 어떻게 결정하나요?
원본 서버에 미래의 날짜와 시간이 포함된 Expires 헤더가 포함된 경우에만 NGINX가 응답을 캐시합니다,
또는 Cache-Control 헤더와 0이 아닌 값으로 설정된 max-age 지시어가 있는 경우에만 응답을 반환합니다.
기본적으로 NGINX는 Cache-Control 헤더에 있는 다른 지시어를 존중합니다:
헤더에 비공개, No-Cache 또는 No-Store 지시어가 포함된 경우 응답을 캐싱하지 않습니다.
또한 Set-Cookie 헤더가 있는 응답은 캐시하지 않습니다. 또한 GET 및 HEAD 요청에 대한 응답만 캐시합니다.
아래 답변에 설명된 대로 이러한 기본값을 재정의할 수 있습니다.
proxy_buffering가 off로 설정된 경우 NGINX는 응답을 캐시하지 않습니다.
기본값은 on입니다.
Cache-Control 헤더를 무시할 수 있나요?
예, proxy_ignore_headers 지시어를 사용하면 됩니다. 예를 들어, 다음과 같이 구성합니다:
location /이미지/ { proxy_cache my_cache; proxy_ignore_headers Cache-Control; proxy_cache_valid any 30m; # ... }.NGINX는 Cache-Control 헤더를 /images/ 아래의 모든 항목에 대해 무시합니다.
proxy_cache_valid 지시어는 캐시된 데이터의 만료를 강제하며 Cache-Control 헤더를 무시한 경우 필요합니다.
NGINX는 만료가 없는 파일을 캐시하지 않습니다.
헤더에 설정-쿠키가 있는 콘텐츠를 NGINX가 캐시할 수 있나요?
예, 이전 답변에서 설명한 대로 proxy_ignore_headers 지시문을 사용합니다.
NGINX가 POST 요청을 캐시할 수 있나요?
예, proxy_cache_methods 지시어를 사용하면 됩니다:
proxy_cache_methods GET HEAD POST;
이 예제는 POST 요청의 캐싱을 활성화합니다.
NGINX가 동적 콘텐츠를 캐시할 수 있나요?
예. Cache-Control 헤더에서 허용하는 경우 가능합니다. 단기간이라도 동적 콘텐츠를 캐싱하면 요청이 있을 때마다
페이지를 다시 생성할 필요가 없으므로 원본 서버와 데이터베이스의 부하를 줄여 첫 바이트에 도달하는 시간을 개선할 수 있습니다.
캐시에 구멍을 뚫을 수 있나요?
예, proxy_cache_bypass 지시어를 사용하면 됩니다:
location / { proxy_cache_bypass $cookie_nocache $arg_nocache; # ... }이 지시어는 NGINX가 캐시에서 콘텐츠를 먼저 찾지 않고 원본 서버에서 즉시 요청하는 요청 유형을 정의합니다.
이를 캐시에 "구멍 뚫기"라고도 합니다. 이 예제에서는 nocache 쿠키 또는
인수가 있는 요청(예: http://www.example.com/?nocache=true)에 대해 NGINX가 이를 수행합니다.
NGINX는 우회되지 않은 향후 요청을 위해 결과 응답을 계속 캐시할 수 있습니다.
NGINX는 어떤 캐시 키를 사용하나요?
NGINX가 생성하는 키의 기본 형식은 다음 NGINX 변수의 MD5 해시와 유사합니다:
$scheme$proxy_host$request_uri; 실제 사용되는 알고리즘은 약간 더 복잡합니다.
proxy_cache_path /path/to/cache levels=1:2 keys_zone=my_cache:10m max_size=10g inactive=60m use_temp_path=off; server { # ... location / { proxy_cache my_cache; proxy_pass http://my_upstream; } }이 샘플 구성의 경우 http://www.example.org/my_image.jpg에 대한 캐시 키는 md5("http://my_upstream:80/my_image.jpg")로 계산됩니다.
실제 호스트 이름 대신 해시값에 $proxy_host 변수가 사용됩니다(www.example.com).
$proxy_host는 proxy_pass 지시어에 지정된 대로 프록시 서버의 이름과 포트로 정의됩니다.
키의 기초로 사용되는 변수(또는 다른 용어)를 변경하려면 proxy_cache_key 지시어를 사용합니다(다음 질문 참조).
쿠키를 캐시 키의 일부로 사용할 수 있나요?
예. 캐시 키는 예를 들어 임의의 값으로 구성할 수 있습니다:
proxy_cache_key $proxy_host$request_uri$cookie_jessionid;
이 예제에서는 JSESSIONID 쿠키의 값을 캐시 키에 통합합니다.
URI는 같지만 JSESSIONID 값이 다른 항목은 고유 항목으로 별도로 캐시됩니다.
NGINX는 ETag 헤더를 사용하나요?
예. NGINX 1.7.3 및 NGINX Plus R5 이상에서는 ETag 헤더가 If-None-Match와 함께 완전히 지원됩니다.
NGINX는 바이트 범위 요청을 어떻게 처리하나요?
파일이 캐시에 최신 상태인 경우 NGINX는 바이트 범위 요청을 처리하고 해당 항목의 지정된 바이트만 클라이언트에 제공합니다.
파일이 캐시되지 않았거나 오래된 파일인 경우 NGINX는 원본 서버에서 전체 파일을 다운로드합니다.
요청이 단일 바이트 범위에 대한 요청인 경우,
다운로드 스트림에서 해당 범위가 발견되는 즉시 해당 범위를 클라이언트로 전송합니다.
요청이 동일한 파일 내에서 여러 바이트 범위를 지정하는 경우, 다운로드가 완료되면 NGINX는 전체 파일을 클라이언트에 전달합니다.
다운로드가 완료되면 NGINX는 전체 리소스를 캐시로 이동하여 단일 범위 또는 여러 범위에 대한
향후 모든 바이트 범위 요청이 캐시에서 즉시 충족되도록 합니다.
업스트림 서버가 바이트 범위 요청을 지원해야 NGINX가 해당 업스트림 서버에 대한
바이트 범위 요청을 처리할 수 있다는 점에 유의하시기 바랍니다.
NGINX는 캐시 퍼지를 지원하나요?
엔진엑스 플러스는 캐시된 파일의 선택적 퍼지를 지원합니다.
이 기능은 파일이 원본 서버에서 업데이트되었지만 NGINX Plus 캐시에서 여전히 유효한 경우 유용합니다
(Cache-Control:max-age가 여전히 유효하고 inactive 매개 변수에 의해 설정된 시간 초과가 만료되지 않았습니다
(proxy_cache_path 지시문에 대한).
NGINX의 캐시 퍼지 기능을 사용하면 이 파일을 쉽게 삭제할 수 있습니다.
자세한 내용은 캐시에서 콘텐츠 제거를 참조하세요.
NGINX는 Pragma 헤더를 어떻게 처리하나요?
클라이언트는 모든 중간 캐시를 우회하고 요청된 콘텐츠의 원본 서버로 바로 이동하기 위해 Pragma:no-cache 헤더를 추가합니다.
NGINX는 기본적으로 Pragma 헤더를 지원하지 않지만 다음 proxy_cache_bypass 지시어를 사용하여 이 기능을 구성할 수 있습니다:
location /이미지/ { proxy_cache my_cache; proxy_cache_bypass $http_pragma; # ... }NGINX는 stale-while-revalidate 및 stale-if-error 확장을 Cache-Control 헤더에 대해 지원하나요?
예, NGINX Plus R12 및 NGINX 1.11.10 이상에서 사용할 수 있습니다.
stale-while-revalidate 확장은 현재 업데이트 중인 캐시된 응답을 사용할 수 있도록 허용하는 Cache-Control HTTP 헤더의 확장입니다.
- stale-if-error 확장자는 오류 발생 시 부실 캐시된 응답을 사용할 수 있도록 허용하는 Cache-Control HTTP 헤더를 사용합니다.
이 헤더는 위에서 설명한 proxy_cache_use_stale 지시어보다 우선 순위가 낮습니다.
NGINX는 Vary 헤더를 지원하나요?
예, NGINX Plus R5 및 NGINX 1.7.7 이상에서 지원합니다. 다음은 Vary 헤더에 대한 좋은 개요입니다.
위 내용과 같이 NGINX Plus를 활용하여 Demo 가 필요하시면 하단의 전문가에게 상담받기 버튼을 클릭해주세요
애플리케이션과 웹사이트의 성능이 성공의 중요한 요소라는 것은 누구나 알고 있습니다.
하지만 애플리케이션이나 웹 사이트의 성능을 향상시키는 과정이 항상 명확하지는 않습니다.
코드 품질과 인프라는 물론 중요하지만, 많은 경우 아주 기본적인 애플리케이션 전송 기술에 집중함으로써
애플리케이션의 최종 사용자 경험을 크게 개선할 수 있습니다.
애플리케이션 스택에서 캐싱을 구현하고 최적화하는 것이 그러한 예 중 하나입니다.
이 블로그 게시물에서는 초보자와 고급 사용자 모두 NGINX 및 NGINX Plus에 포함된
콘텐츠 캐시 기능을 활용하여 성능을 개선하는 데 도움이 되는 기술을 다룹니다.
개요
콘텐츠 캐시는 클라이언트와 '원본 서버' 사이에 위치하며 클라이언트가 보는 모든 콘텐츠의 사본을 저장합니다.
클라이언트가 캐시에 저장된 콘텐츠를 요청하면 캐시는 원본 서버에 연결하지 않고 직접 콘텐츠를 반환합니다.
이렇게 하면 콘텐츠 캐시가 클라이언트와 더 가까워져 성능이 향상되고
매번 페이지를 처음부터 생성하는 작업을 하지 않아도 되므로 애플리케이션 서버를 더 효율적으로 사용할 수 있습니다.
웹 브라우저와 애플리케이션 서버 사이에는 클라이언트의 브라우저 캐시, 중개 캐시, CDN(콘텐츠 전송 네트워크),
애플리케이션 서버 앞에 위치한 로드 밸런서 또는 리버스 프록시 등 여러 캐시가 존재할 수 있습니다.
캐싱은 역방향 프록시/로드 밸런서 수준에서도 성능을 크게 향상시킬 수 있습니다.
예를 들어, 작년에 저는 느리게 로드되는 웹사이트의 성능을 튜닝하는 작업을 맡았습니다.
가장 먼저 알아차린 것 중 하나는 메인 홈페이지를 생성하는 데 1초 이상이 걸린다는 것이었습니다.
디버깅을 해본 결과 페이지가 캐시할 수 없는 것으로 표시되어 있어서
각 요청에 따라 동적으로 생성되고 있다는 사실을 발견했습니다.
페이지 자체는 자주 변경되지 않았고 개인화되지 않았기 때문에 이 작업은 필요하지 않았습니다.
실험 삼아 로드 밸런서가 홈페이지를 5초 동안 캐시하도록 표시했는데,
이렇게 하는 것만으로도 눈에 띄게 개선되었습니다.
첫 바이트까지 걸리는 시간이 몇 밀리초로 줄어들었고
페이지가 눈에 띄게 빠르게 로드되었습니다.
NGINX는 일반적으로 애플리케이션 스택에서
리버스 프록시 또는 로드 밸런서로 배포되며 전체 캐싱 기능을 갖추고 있습니다.
다음 섹션에서는 NGINX로 기본 캐싱을 구성하는 방법에 대해 설명합니다.
기본 캐싱 설정 및 구성 방법
기본 캐싱을 사용하려면 proxy_cache_path와 proxy_cache 두 지시어만 필요합니다.
proxy_cache_path 지시어는 캐시의 경로와 구성을 설정하고 proxy_cache 지시어는 이를 활성화합니다.
proxy_cache_path /path/to/cache levels=1:2 keys_zone=my_cache:10m max_size=10g inactive=60m use_temp_path=off; server { # ... location / { proxy_cache my_cache; proxy_pass http://my_upstream; } }proxy_cache_path 지시어에 대한 매개변수는 다음 설정을 정의합니다:
levels는 /path/to/cache/ 아래에 2단계 디렉터리 계층 구조를 설정합니다.
단일 디렉터리에 많은 수의 파일이 있으면 파일 액세스 속도가 느려질 수 있으므로
대부분의 배포에는 2단계 디렉터리 계층 구조를 사용하는 것이 좋습니다.
keys_zone는 캐시 키와 사용 타이머와 같은 메타데이터를 저장하기 위한 공유 메모리 영역을 설정합니다.
메모리에 키 사본이 있으면 NGINX가 디스크로 이동하지 않고도 요청이 HITMISS
max_size는 캐시 크기의 상한을 설정합니다(이 예에서는 10기가바이트).
inactive는 항목이 액세스되지 않고 캐시에 남아 있을 수 있는 기간을 지정합니다.
이 예에서는 60분 동안 요청되지 않은 파일은 만료 여부에 관계없이 캐시 관리자 프로세스에 의해 캐시에서 자동으로 삭제됩니다.
기본값은 10분입니다(10m). 비활성 콘텐츠는 만료된 콘텐츠와 다릅니다.
만료된(오래된) 콘텐츠는 inactive에 지정된 시간 동안 액세스하지 않은 경우에만 삭제됩니다.
만료된 콘텐츠에 액세스하면 NGINX는 원본 서버에서 콘텐츠를 새로 고치고 inactive 타이머를 재설정합니다.
NGINX는 먼저 캐시 대상 파일을 임시 저장 영역에 쓰고, use_temp_path=off 지시문은
캐시할 동일한 디렉터리에 파일을 쓰도록 NGINX에 지시합니다.
마지막으로 proxy_cache 지시어는 상위 location 블록(예제에서는 /)의 URL과 일치하는 모든 콘텐츠의 캐싱을 활성화합니다.
또한 proxy_cache 지시문을 서버 블록에 포함할 수 있으며,
자체 location 지시문이 없는 서버의 모든 proxy_cache 블록에 적용합니다.
오리진이 다운되었을 때 캐시된 콘텐츠 전송
캐시에서 오래된 콘텐츠를 제공하도록 구성할 수 있다는 것입니다.
캐시된 리소스에 대한 모든 원본 서버가 다운되었거나
일시적으로 사용 중인 경우 이러한 문제가 발생할 수 있습니다.
NGINX는 오류를 클라이언트에 전달하는 대신 캐시에서 오래된 버전의 파일을 전달합니다.
이렇게 하면 NGINX가 프록시하는 서버에 추가적인 수준의 내결함성을 제공하고
서버 장애 또는 트래픽 급증 시에도 가동 시간을 보장할 수 있습니다.
이 기능을 사용하려면 proxy_cache_use_stale 지시어를 포함하세요:
location / { # ... proxy_cache_use_stale error timeout http_500 http_502 http_503 http_504; }이 샘플 구성을 사용하면 NGINX가 원본 서버로부터 error, timeout 또는 지정된 5xx 오류를 수신하고캐시에 요청된 파일의 오래된 버전이 있으면 오류를 클라이언트로 전달하는 대신 오래된 파일을 전달합니다.
캐시 미세 조정 및 성능 개선
NGINX에는 캐시 성능을 미세 조정할 수 있는 다양한 옵션 설정이 있습니다. 다음은 그 중 몇 가지를 활성화하는 예제입니다:proxy_cache_path /path/to/cache levels=1:2 keys_zone=my_cache:10m max_size=10g inactive=60m use_temp_path=off; server { # ... location / { proxy_cache my_cache; proxy_cache_revalidate on; proxy_cache_min_uses 3; proxy_cache_use_stale error timeout updating http_500 http_502 http_503 http_504; proxy_cache_background_update on; proxy_cache_lock on; proxy_pass http://my_upstream; } }proxy_cache_revalidate는 원본 서버에서 콘텐츠를 새로 고칠 때
캐시를 여러 하드 드라이브에 분할하기
하드 드라이브가 여러 개 있는 경우 NGINX를 사용하여 캐시를 여러 하드 드라이브에 분할할 수 있습니다.
다음은 요청 URI에 따라 클라이언트를 두 개의 하드 드라이브에 균등하게 분할하는 예제입니다:
proxy_cache_path /path/to/hdd1 levels=1:2 keys_zone=my_cache_hdd1:10m max_size=10g inactive=60m use_temp_path=off; proxy_cache_path /path/to/hdd2 levels=1:2 keys_zone=my_cache_hdd2:10m max_size=10g inactive=60m use_temp_path=off; split_clients $request_uri $my_cache { 50% “my_cache_hdd1”; 50% “my_cache_hdd2”; } server { # ... location / { proxy_cache $my_cache; proxy_pass http://my_upstream; } }두 개의 proxy_cache_path 지시어는 두 개의 다른 하드 드라이브에
두 개의 캐시(my_cache_hdd1 및 my_cache_hdd2)를 정의합니다.
split_clients 구성 블록은 절반의 요청 결과(50%)의 결과는 my_cache_hdd1에, 나머지 절반은 my_cache_hdd2에 캐싱됩니다.
$request_uri 변수(요청 URI)에 기반한 해시에 따라 각 요청에 사용되는 캐시가 결정되며,
결과적으로 특정 URI에 대한 요청은 항상 동일한 캐시에 캐시됩니다.
이 접근 방식은 RAID 하드 드라이브 설정을 대체할 수 없다는 점에 유의하세요.
하드 드라이브에 장애가 발생하면 장애가 발생한 하드 드라이브로 전송된 요청에 대해
사용자에게 500개의 응답 코드가 표시되는 등 시스템에서 예기치 않은 동작이 발생할 수 있습니다.
적절한 RAID 하드 드라이브 설정은 하드 드라이브 장애를 처리할 수 있습니다.
자주 묻는 질문(FAQ)
이 섹션에서는 NGINX 콘텐츠 캐싱에 대해 자주 묻는 질문에 대한 답변을 제공합니다.
NGINX 캐시를 계측할 수 있나요?
예, add_header 지시어를 사용하면 됩니다:
add_header X-Cache-Status $upstream_cache_status;이 예는 클라이언트에 대한 응답에 X-Cache-Status HTTP 헤더를 추가합니다.
다음은 $upstream_cache_status에 사용할 수 있는 값입니다:
NGINX는 캐시할지 여부를 어떻게 결정하나요?
원본 서버에 미래의 날짜와 시간이 포함된 Expires 헤더가 포함된 경우에만 NGINX가 응답을 캐시합니다,
또는 Cache-Control 헤더와 0이 아닌 값으로 설정된 max-age 지시어가 있는 경우에만 응답을 반환합니다.
기본적으로 NGINX는 Cache-Control 헤더에 있는 다른 지시어를 존중합니다:
헤더에 비공개, No-Cache 또는 No-Store 지시어가 포함된 경우 응답을 캐싱하지 않습니다.
또한 Set-Cookie 헤더가 있는 응답은 캐시하지 않습니다. 또한 GET 및 HEAD 요청에 대한 응답만 캐시합니다.
아래 답변에 설명된 대로 이러한 기본값을 재정의할 수 있습니다.
proxy_buffering가 off로 설정된 경우 NGINX는 응답을 캐시하지 않습니다.
기본값은 on입니다.
Cache-Control 헤더를 무시할 수 있나요?
예, proxy_ignore_headers 지시어를 사용하면 됩니다. 예를 들어, 다음과 같이 구성합니다:
location /이미지/ { proxy_cache my_cache; proxy_ignore_headers Cache-Control; proxy_cache_valid any 30m; # ... }.NGINX는 Cache-Control 헤더를 /images/ 아래의 모든 항목에 대해 무시합니다.
proxy_cache_valid 지시어는 캐시된 데이터의 만료를 강제하며 Cache-Control 헤더를 무시한 경우 필요합니다.
NGINX는 만료가 없는 파일을 캐시하지 않습니다.
헤더에 설정-쿠키가 있는 콘텐츠를 NGINX가 캐시할 수 있나요?
예, 이전 답변에서 설명한 대로 proxy_ignore_headers 지시문을 사용합니다.
NGINX가 POST 요청을 캐시할 수 있나요?
예, proxy_cache_methods 지시어를 사용하면 됩니다:
proxy_cache_methods GET HEAD POST;이 예제는 POST 요청의 캐싱을 활성화합니다.
NGINX가 동적 콘텐츠를 캐시할 수 있나요?
예. Cache-Control 헤더에서 허용하는 경우 가능합니다. 단기간이라도 동적 콘텐츠를 캐싱하면 요청이 있을 때마다
페이지를 다시 생성할 필요가 없으므로 원본 서버와 데이터베이스의 부하를 줄여 첫 바이트에 도달하는 시간을 개선할 수 있습니다.
캐시에 구멍을 뚫을 수 있나요?
예, proxy_cache_bypass 지시어를 사용하면 됩니다:
location / { proxy_cache_bypass $cookie_nocache $arg_nocache; # ... }이 지시어는 NGINX가 캐시에서 콘텐츠를 먼저 찾지 않고 원본 서버에서 즉시 요청하는 요청 유형을 정의합니다.
이를 캐시에 "구멍 뚫기"라고도 합니다. 이 예제에서는 nocache 쿠키 또는
인수가 있는 요청(예: http://www.example.com/?nocache=true)에 대해 NGINX가 이를 수행합니다.
NGINX는 우회되지 않은 향후 요청을 위해 결과 응답을 계속 캐시할 수 있습니다.
NGINX는 어떤 캐시 키를 사용하나요?
NGINX가 생성하는 키의 기본 형식은 다음 NGINX 변수의 MD5 해시와 유사합니다:
$scheme$proxy_host$request_uri; 실제 사용되는 알고리즘은 약간 더 복잡합니다.
proxy_cache_path /path/to/cache levels=1:2 keys_zone=my_cache:10m max_size=10g inactive=60m use_temp_path=off; server { # ... location / { proxy_cache my_cache; proxy_pass http://my_upstream; } }이 샘플 구성의 경우 http://www.example.org/my_image.jpg에 대한 캐시 키는 md5("http://my_upstream:80/my_image.jpg")로 계산됩니다.
실제 호스트 이름 대신 해시값에 $proxy_host 변수가 사용됩니다(www.example.com).
$proxy_host는 proxy_pass 지시어에 지정된 대로 프록시 서버의 이름과 포트로 정의됩니다.
키의 기초로 사용되는 변수(또는 다른 용어)를 변경하려면 proxy_cache_key 지시어를 사용합니다(다음 질문 참조).
쿠키를 캐시 키의 일부로 사용할 수 있나요?
예. 캐시 키는 예를 들어 임의의 값으로 구성할 수 있습니다:
proxy_cache_key $proxy_host$request_uri$cookie_jessionid;이 예제에서는 JSESSIONID 쿠키의 값을 캐시 키에 통합합니다.
URI는 같지만 JSESSIONID 값이 다른 항목은 고유 항목으로 별도로 캐시됩니다.
NGINX는 ETag 헤더를 사용하나요?
예. NGINX 1.7.3 및 NGINX Plus R5 이상에서는 ETag 헤더가 If-None-Match와 함께 완전히 지원됩니다.
NGINX는 바이트 범위 요청을 어떻게 처리하나요?
파일이 캐시에 최신 상태인 경우 NGINX는 바이트 범위 요청을 처리하고 해당 항목의 지정된 바이트만 클라이언트에 제공합니다.
파일이 캐시되지 않았거나 오래된 파일인 경우 NGINX는 원본 서버에서 전체 파일을 다운로드합니다.
요청이 단일 바이트 범위에 대한 요청인 경우,
다운로드 스트림에서 해당 범위가 발견되는 즉시 해당 범위를 클라이언트로 전송합니다.
요청이 동일한 파일 내에서 여러 바이트 범위를 지정하는 경우, 다운로드가 완료되면 NGINX는 전체 파일을 클라이언트에 전달합니다.
다운로드가 완료되면 NGINX는 전체 리소스를 캐시로 이동하여 단일 범위 또는 여러 범위에 대한
향후 모든 바이트 범위 요청이 캐시에서 즉시 충족되도록 합니다.
업스트림 서버가 바이트 범위 요청을 지원해야 NGINX가 해당 업스트림 서버에 대한
바이트 범위 요청을 처리할 수 있다는 점에 유의하시기 바랍니다.
NGINX는 캐시 퍼지를 지원하나요?
엔진엑스 플러스는 캐시된 파일의 선택적 퍼지를 지원합니다.
이 기능은 파일이 원본 서버에서 업데이트되었지만 NGINX Plus 캐시에서 여전히 유효한 경우 유용합니다
(Cache-Control:max-age가 여전히 유효하고 inactive 매개 변수에 의해 설정된 시간 초과가 만료되지 않았습니다
(proxy_cache_path 지시문에 대한).
NGINX의 캐시 퍼지 기능을 사용하면 이 파일을 쉽게 삭제할 수 있습니다.
자세한 내용은 캐시에서 콘텐츠 제거를 참조하세요.
NGINX는 Pragma 헤더를 어떻게 처리하나요?
클라이언트는 모든 중간 캐시를 우회하고 요청된 콘텐츠의 원본 서버로 바로 이동하기 위해 Pragma:no-cache 헤더를 추가합니다.
NGINX는 기본적으로 Pragma 헤더를 지원하지 않지만 다음 proxy_cache_bypass 지시어를 사용하여 이 기능을 구성할 수 있습니다:
location /이미지/ { proxy_cache my_cache; proxy_cache_bypass $http_pragma; # ... }NGINX는 stale-while-revalidate 및 stale-if-error 확장을 Cache-Control 헤더에 대해 지원하나요?
예, NGINX Plus R12 및 NGINX 1.11.10 이상에서 사용할 수 있습니다.
stale-while-revalidate 확장은 현재 업데이트 중인 캐시된 응답을 사용할 수 있도록 허용하는 Cache-Control HTTP 헤더의 확장입니다.
이 헤더는 위에서 설명한 proxy_cache_use_stale 지시어보다 우선 순위가 낮습니다.
NGINX는 Vary 헤더를 지원하나요?
예, NGINX Plus R5 및 NGINX 1.7.7 이상에서 지원합니다. 다음은 Vary 헤더에 대한 좋은 개요입니다.
위 내용과 같이 NGINX Plus를 활용하여 Demo 가 필요하시면 하단의 전문가에게 상담받기 버튼을 클릭해주세요
전문가에게 상담받기