NGINX Slice 모듈을 사용하여 다운로드 최적화

NGINX slice 모듈은 요청을 하위 요청으로 분할하는 필터로, 각 하위 요청은 특정한 응답 범위를 반환합니다. 필터는 큰 응답의 더욱 효과적인 캐싱을 제공합니다.

이 포스트는 slice 모듈을 사용하여 대용량 파일 다운로드 성능을 향상하는 방법에 대한 가이드입니다.

환경 정보

  • Ubuntu 22.04.3 LTS
  • nginx/1.27.2 (nginx-plus-r33-p2)
  • NGINX Plus Server:
    • CPU – 8 vCPUs
    • Memory – 16GB
  • Backend Server:
    • CPU – 8 vCPUs
    • Memory – 8GB

목차

1. NGINX Slice 모듈이란?
2. 다운로드 최적화
3. NGINX Slice 모듈 구성
4. NGINX Slice 모듈 테스트

4-1. 기본 기능 테스트
4-2. 성능 테스트
5. 결론

1. NGINX Slice 모듈이란?

NGINX의 slice 모듈은 요청을 하위 요청으로 분할하는 필터로, 클라이언트의 요청을 여러 개의 하위 요청으로 나누어 처리합니다. 이를 통해 더 작은 조각으로 나누어 전송할 수 있습니다.

Syntax:         slice size;
Default:        slice 0;
Context:        http, server, location

slice 지시문을 사용하여 크기를 설정합니다. 0 값은 응답을 slice로 분할하는 것을 비활성화합니다. 또한 크기가 너무 낮은 값은 과도한 메모리 사용과 많은 수의 파일이 열릴 수 있습니다.

하위 요청이 필요한 범위를 반환하려면 $slice_range 변수를 Range 요청 헤더 필드로 프록시 서버에 전달해야 합니다. 캐싱이 활성화된 경우 $slice_range를 캐시 키에 추가하고 206 status code가 있는 응답의 캐싱을 활성화해야 합니다.

slice 모듈은 아래와 같은 변수를 지원합니다.

$slice_range – HTTP 바이트 범위 형식의 현재 슬라이스 범위, 예를 들어 bytes=0-1048575.

2. 다운로드 최적화

큰 파일을 다운로드할 때 사용자는 여러 가지 문제에 직면할 수 있습니다.

  • 네트워크 불안정성 – 큰 파일 다운로드 중 네트워크 연결이 끊어지거나 불안정해질 경우, 다운로드가 중단될 수 있습니다.
  • 서버 부하 – 대량의 데이터 전송은 서버에 큰 부하를 줄 수 있습니다. 특히, 여러 사용자가 동시에 큰 파일을 다운로드 할 경우 서버 성능이 저하될 수 있습니다.

NGINX의 slice 모듈은 이러한 다운로드 최적화 문제를 해결하는 데 효과적인 도구입니다. Slice 모듈을 사용하면 다음과 같이 성능 개선이 가능합니다.

3. NGINX Slice 모듈 구성

proxy_cache_path /var/cache/nginx/slice levels=1:2 keys_zone=cache:10m max_size=10g inactive=60m use_temp_path=off;

upstream backend {
        server 192.168.201.102:8000;
}

server {
    listen       80;
    server_name  example.com;

    location /large/ {
        slice                   8m;
        proxy_cache             cache;
        proxy_cache_key         $uri$is_args$args$slice_range;
        proxy_set_header        Range $slice_range;
        proxy_cache_valid       200 206 1h;
        proxy_http_version      1.1;

        proxy_pass http://backend;
    }
}

slice 적용 (slice 8m;)

  • 파일을 8MB 단위로 쪼개서 요청
  • 클라이언트가 5GB 파일을 다운로드하면, NGINX는 8MB씩 잘라서 백엔드 서버에 요청

캐시 적용 (proxy_cache cache;)

  • 백엔드에서 가져온 slice를 캐시하여, 같은 요청이 올 때 다시 백엔드에 요청하지 않도록 설정

캐시 키 구성 (proxy_cache_key $uri$is_args$args$slice_range;)

  • 캐시 키를 파일의 URL과 slice 범위를 기반으로 설정
  • 같은 파일이라도 slice 범위가 다르면 별도로 캐싱됨

Range 헤더 설정 (proxy_set_header Range $slice_range;)

  • 클라이언트의 요청을 기반으로 백엔드에 특정 바이트 범위를 요청하도록 Range 헤더를 설정
  • 예를 들어 클라이언트가 10MB~20MB 범위를 요청하면, Range: bytes=10485760-20971520로 백엔드에 전달

캐시 만료 시간 (proxy_cache_valid 200 206 1h;)

  • 200 (OK), 206 (Partial Content) 응답을 1시간 동안 캐싱
  • slice 요청도 206 응답을 받으므로 캐싱 가능

HTTP/1.1 설정 (proxy_http_version 1.1;)

  • HTTP/1.0을 사용하면 Range 요청이 정상적으로 동작하지 않을 수 있기 때문에 HTTP/1.1을 강제

백엔드로 프록시 (proxy_pass http://backend;)

  • 실제 파일은 백엔드 서버에서 가져옴

NGINX를 재시작하여 cache를 활성화합니다.

systemctl restart nginx

4. NGINX Slice 모듈 테스트

Backend 서버에 약 5GB의 파일이 있으며, Slice 모듈을 통해 다운로드합니다.

4-1. 기본 기능 테스트

5GB 파일 다운로드 시 8MB 단위로 청크가 전송되는지 확인합니다.

# time curl -O http://example.com/large/bigfile.iso

  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
100 5005M  100 5005M    0     0   143M      0  0:00:34  0:00:34 --:--:--  129M

real    0m37.228s
user    0m1.333s
sys     0m27.153s

백엔드 서버에서 로그를 확인해보면 NGINX slice 모듈이 8MB로 분할하여 요청하는 것을 확인할 수 있습니다.

# Backend Log

192.168.201.104 - - [06/Feb/2025:07:32:51 +0000] "GET /large/bigfile.iso HTTP/1.1" 206 8388608 "-" "curl/7.81.0" "-" Range: "bytes=0-8388607"
192.168.201.104 - - [06/Feb/2025:07:32:51 +0000] "GET /large/bigfile.iso HTTP/1.1" 206 8388608 "-" "curl/7.81.0" "-" Range: "bytes=8388608-16777215"
192.168.201.104 - - [06/Feb/2025:07:32:51 +0000] "GET /large/bigfile.iso HTTP/1.1" 206 8388608 "-" "curl/7.81.0" "-" Range: "bytes=16777216-25165823"
192.168.201.104 - - [06/Feb/2025:07:32:51 +0000] "GET /large/bigfile.iso HTTP/1.1" 206 8388608 "-" "curl/7.81.0" "-" Range: "bytes=25165824-33554431"
192.168.201.104 - - [06/Feb/2025:07:32:51 +0000] "GET /large/bigfile.iso HTTP/1.1" 206 8388608 "-" "curl/7.81.0" "-" Range: "bytes=33554432-41943039"
192.168.201.104 - - [06/Feb/2025:07:32:51 +0000] "GET /large/bigfile.iso HTTP/1.1" 206 8388608 "-" "curl/7.81.0" "-" Range: "bytes=41943040-50331647"
192.168.201.104 - - [06/Feb/2025:07:32:51 +0000] "GET /large/bigfile.iso HTTP/1.1" 206 8388608 "-" "curl/7.81.0" "-" Range: "bytes=50331648-58720255"
192.168.201.104 - - [06/Feb/2025:07:32:51 +0000] "GET /large/bigfile.iso HTTP/1.1" 206 8388608 "-" "curl/7.81.0" "-" Range: "bytes=58720256-67108863"
192.168.201.104 - - [06/Feb/2025:07:32:51 +0000] "GET /large/bigfile.iso HTTP/1.1" 206 8388608 "-" "curl/7.81.0" "-" Range: "bytes=67108864-75497471"
192.168.201.104 - - [06/Feb/2025:07:32:51 +0000] "GET /large/bigfile.iso HTTP/1.1" 206 8388608 "-" "curl/7.81.0" "-" Range: "bytes=75497472-83886079"
192.168.201.104 - - [06/Feb/2025:07:32:51 +0000] "GET /large/bigfile.iso HTTP/1.1" 206 8388608 "-" "curl/7.81.0" "-" Range: "bytes=83886080-92274687"

/var/cache/nginx/slice 하위를 확인해보면 8MB로 캐싱되는 것을 확인할 수 있습니다.

4-2. 성능 테스트

NGINX Slice 모듈을 사용했을 때와 사용하지 않았을 때, 그리고 캐싱된 파일을 요청할 때의 서버 성능을 확인합니다.

성능을 테스트하기 위해 aria2와 htop을 사용하여 성능을 테스트했습니다.

Slice 모듈 적용 전:

# aria2c -x 1 -s 1 http://example.com/large/bigfile.iso

02/07 02:04:08 [NOTICE] Downloading 1 item(s)
[#bdc369 4.8GiB/4.8GiB(99%) CN:1 DL:251MiB]                                                                                                     
02/07 02:04:31 [NOTICE] Download complete: /root/delete/bigfile.iso

Download Results:
gid   |stat|avg speed  |path/URI
======+====+===========+=======================================================
bdc369|OK  |   294MiB/s|/root/delete/bigfile.iso

Status Legend:
(OK):download completed.

NGINX Slice 모듈 미적용 시의 일반적인 다운로드 방식과 유사한 조건을 만들기 위해 aria2c -x 1 -s 1 example.com/large/bigfile.iso로 요청을 보냈을 때 평균 다운로드 속도는 294MiB/s 가 나온 것을 확인할 수 있습니다.

아래 NGINX Plus 서버의 CPU 사용량을 확인해보면 하나의 커넥션을 통해 한 번에 다운로드를 진행하게 됩니다.

nginx slice

Slice 모듈 적용 후(Cache MISS):

# aria2c -x 8 -s 8 http://example.com/large/bigfile.iso

02/07 04:20:02 [NOTICE] Downloading 1 item(s)
[#93a541 4.7GiB/4.8GiB(97%) CN:7 DL:202MiB]                                                                                                     
02/07 04:20:32 [NOTICE] Download complete: /root/delete/bigfile.iso

Download Results:
gid   |stat|avg speed  |path/URI
======+====+===========+=======================================================
93a541|OK  |   214MiB/s|/root/delete/bigfile.iso

NGINX Slice 모듈과 캐싱을 조합하여 성능을 높이기 위해 aria2c -x 8 -s 8 example.com/large/bigfile.iso로 요청을 보냈을 때 평균 다운로드 속도는 평균 214MiB/s 가 나온 것을 확인할 수 있습니다.

아래 NGINX Plus 서버의 CPU 사용량을 확인해보면 8개의 연결을 동시에 생성하여 파일을 여러 조각으로 나누어 받는 방식입니다.

nginx slice

Slice 모듈 적용 후(Cache HIT):

# aria2c -x 8 -s 8 http://example.com/large/bigfile.iso

02/07 04:48:55 [NOTICE] Downloading 1 item(s)
[#61c973 4.6GiB/4.8GiB(95%) CN:8 DL:330MiB]                                                                                                     
02/07 04:49:16 [NOTICE] Download complete: /root/delete/bigfile.iso

Download Results:
gid   |stat|avg speed  |path/URI
======+====+===========+=======================================================
61c973|OK  |   324MiB/s|/root/delete/bigfile.iso

Status Legend:
(OK):download completed.

NGINX Slice 모듈과 캐싱을 조합하여 성능을 높이기 위해 aria2c -x 8 -s 8 example.com/large/bigfile.iso로 요청을 보냈을 때 평균 다운로드 속도는 평균 324MiB/s 가 나온 것을 확인할 수 있습니다.

아래 NGINX Plus 서버의 CPU 사용량을 확인해보면 기본적으로 2개 정도의 worker process가 사용되었으며, 캐시에서 즉시 응답하여 속도가 가장 빠른 것을 확인할 수 있습니다.

nginx slice

총 3가지의 테스트로 본 결론은 아래와 같습니다.

구분Slice 미적용Slice 적용 (Cache MISS 응답)Slice 적용 (Cache HIT 응답)
백엔드 요청 수1개 요청다수의 작은 요청없음 (캐시에서 응답)
초기 응답 속도빠름상대적으로 느림매우 빠름
네트워크 사용량클라이언트-백엔드 직접 대용량 전송작은 조각들이 개별적으로 전송NGINX 캐시에서 빠르게 전송
NGINX CPU 사용량낮음높음 (많은 작은 요청을 처리)낮음
다운로드 속도빠름상대적으로 느림매우 빠름

5. 결론

NGINX Slice 적용 vs. 미적용 비교 표

구분Slice 미적용Slice 적용 (Cache MISS 응답)Slice 적용 (Cache HIT 응답)
백엔드 요청 방식1개의 큰 파일을 스트리밍다수의 작은 조각 요청NGINX 캐시에서 제공
백엔드 부하높음 (단일 요청으로 대용량 전송)더 높음 (여러 개 작은 요청)없음
초기 응답 속도빠름상대적으로 느림매우 빠름
NGINX 처리 방식단일 요청 전달여러 개의 Slice 요청 처리캐시에서 바로 응답
TCP 연결 수1개다수의 연결없음
다운로드 속도일반적으로 빠름상대적으로 느림매우 빠름
캐싱 활용 가능 여부낮음 (전체 파일 단위 캐싱)높음 (조각별 캐싱 가능)최고 (바로 응답)
네트워크 활용 효율낮음 (긴 세션 유지)높음 (병렬 요청 가능)매우 높음
대규모 트래픽 대응어려움 (백엔드 부하 집중)더 어려움 (백엔드 요청 증가)매우 용이 (NGINX가 응답)

대용량 파일 다운로드를 최적화하는 데 있어 NGINX Slice 모듈은 중요한 역할을 합니다. 기존 방식(미적용)과 비교했을 때, Slice 적용 시 작은 조각 단위로 요청을 처리할 수 있어 캐싱 효율이 증가하고, 멀티 커넥션 다운로드와 함께 사용하면 속도를 극대화할 수 있습니다.

하지만 Slice 적용 후 Cache MISS 시에는 백엔드 요청 수가 증가하여 속도가 일시적으로 느려질 수 있다는 단점이 있습니다. 따라서 최적의 성능을 위해 캐시를 적극 활용하고, Slice 크기(slice 10m 등)를 조정하는 것이 중요합니다.

궁극적으로, Slice + 캐시를 조합하면 백엔드 부하를 최소화하면서도 빠르고 안정적인 다운로드 환경을 구축할 수 있습니다.

NGINX 상업용 버전을 직접 사용해 보시려면 30일 무료 평가판을 신청하거나 NGINX STORE에 연락하여 논의하십시오.

NGINX STORE를 통한 솔루션 도입 및 기술지원 무료 상담 신청

* indicates required