NGINX vs Caddy: HTTPS, 리로드, 캐시 비교
NGINX와 Caddy를 비교해 달라는 요청을 받고 처음 떠올린 답은 단순했습니다. Caddy는 설정이 쉽고 NGINX는 오래되고 강력하다는 구분이었습니다. 공식 문서를 확인하니 이 설명은 방향만 맞고, 2026년의 선택 기준으로 쓰기에는 빠진 내용이 많았습니다.
가장 먼저 고쳐야 했던 것은 HTTPS에 관한 제 전제였습니다. NGINX는 Certbot 같은 외부 도구가 반드시 필요하다고 생각하기 쉽습니다. 지금은 NGINX도 ACME 모듈을 제공합니다. 그렇다고 Caddy와 같아진 것은 아닙니다. NGINX는 모듈을 설치하고 발급자와 인증서 상태를 구성하는 방식이고, Caddy는 도메인을 설정하는 순간 자동 HTTPS가 기본으로 작동합니다.
둘 중 어느 쪽이 더 빠르다는 숫자는 이 글에 넣지 않았습니다. 동일한 하드웨어와 TLS, 캐시, 버퍼, 로그 조건으로 직접 측정하지 않았기 때문입니다. 대신 운영하면서 계속 차이를 만드는 기본값과 구성 방식을 비교했습니다.
가장 짧은 설정에서 차이가 드러납니다
애플리케이션이 127.0.0.1:3000에서 실행 중이고 example.com으로 공개한다고 가정해 보겠습니다. Caddyfile은 다음 두 줄로 시작할 수 있습니다.
example.com {
reverse_proxy 127.0.0.1:3000
}DNS가 서버를 가리키고 80번과 443번 포트가 열려 있으면 Caddy가 공개 인증서를 발급하고 갱신하며 HTTP 요청을 HTTPS로 돌립니다. 이 동작은 별도의 TLS 지시문을 추가해서 생기는 것이 아니라 Automatic HTTPS의 기본 동작입니다.
같은 프록시를 NGINX의 HTTP 설정으로 쓰면 다음과 같습니다.
server {
listen 80;
server_name example.com;
location / {
proxy_pass http://127.0.0.1:3000;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
}
}이 설정은 HTTP 리버스 프록시입니다. HTTPS를 사용하려면 인증서 관리와 listen 443 ssl, 인증서 경로 또는 ACME 모듈 구성을 더해야 합니다. NGINX 설정이 잘못되었다는 뜻은 아닙니다. Caddy가 더 많은 정책을 기본값으로 정해 두었다는 뜻입니다.
저는 이 차이를 “설정 줄 수”보다 “누가 인증서 수명주기를 소유하는가”의 차이로 보았습니다. Caddy는 발급, 갱신, HTTP 리디렉션을 웹 서버의 기본 책임으로 봅니다. NGINX는 관리자가 구성 요소와 정책을 선택할 여지를 더 많이 남깁니다.
NGINX도 ACME를 지원하지만 기본 경험은 다릅니다
NGINX의 ngx_http_acme_module은 ACMEv2 인증서 관리를 구현합니다. 공식 문서에 따르면 사전 빌드된 nginx-module-acme 패키지는 NGINX 1.29.0부터 제공됩니다. HTTP-01과 TLS-ALPN-01 challenge를 지원하고 발급한 인증서와 키를 상태 디렉터리에 보관할 수 있습니다.
제가 예상과 달랐던 부분은 “NGINX에는 자동 인증서 관리가 없다”가 더 이상 맞지 않는다는 점입니다. 다만 모듈 설정에는 ACME 발급자, 상태 경로, 공유 메모리 영역, 인증서 변수와 challenge용 리스너가 등장합니다. Caddy의 도메인 한 줄과는 추상화 수준이 다릅니다.
도메인이 몇 개 안 되는 일반 서비스라면 Caddy의 기본값이 편합니다. 인증서 발급 정책과 저장 경로를 기존 운영 체계에 맞추거나, 이미 NGINX 배포 규칙이 정착된 조직이라면 NGINX ACME 모듈 또는 기존 인증서 자동화가 더 자연스러울 수 있습니다.
Caddy의 On-Demand TLS도 눈에 띄는 차이입니다. 시작할 때 모든 도메인을 알 수 없는 사용자 지정 도메인 SaaS에서 TLS handshake 시점에 인증서를 가져올 수 있습니다. 공개 환경에서는 아무 도메인이나 발급하지 않도록 허용 여부를 확인하는 ask 또는 permission 구성이 필요합니다. Caddy On-Demand TLS 옵션
리로드는 둘 다 안전하지만 내부 방식이 다릅니다
처음에는 Caddy만 무중단 리로드를 강조할 수 있다고 생각했습니다. NGINX도 오래전부터 안전한 설정 리로드를 제공합니다.
nginx -s reload를 실행하면 master process가 새 설정의 문법을 검사합니다. 적용에 성공하면 새 worker를 시작하고, 기존 worker는 새 연결을 받지 않은 채 처리 중인 요청을 마친 뒤 종료합니다. 설정 적용이 실패하면 기존 구성으로 계속 동작합니다. NGINX 리로드 설명
Caddy는 admin API에 새 구성 전체를 전달합니다. 새 구성을 준비하고 검증한 뒤 교체하며, 실패하면 이전 구성을 유지합니다. 공식 API 문서는 이 변경을 원자적이고 무중단인 작업으로 설명합니다. caddy reload도 내부적으로 이 API를 사용합니다. Caddy API
운영 관점에서 차이는 다음과 같습니다.
- 파일과 프로세스 신호가 중심이면 NGINX 방식이 익숙합니다.
- API로 설정을 생성하고 일부 경로만 바꾸는 제어 시스템이라면 Caddy의 JSON 구성과 admin API가 잘 맞습니다.
- Caddy admin API는 기본적으로 loopback에서만 접근하게 두고, 외부에 그대로 노출하지 않는 편이 안전합니다.
둘 다 변경 전에 설정 검증을 CI나 배포 단계에 넣는 것이 좋습니다. 안전한 리로드 기능이 잘못된 라우팅 규칙까지 올바르게 만들어 주지는 않습니다.
HTTP/3와 캐시에서는 선택이 반대로 갈립니다
새 프로토콜의 기본값은 Caddy 쪽이 적극적입니다. Caddy의 HTTP 서버는 기본 프로토콜 목록이 h1 h2 h3입니다. HTTP/3를 사용하면 QUIC을 위한 UDP 소켓도 엽니다. Caddy HTTP 모듈
NGINX의 ngx_http_v3_module은 공식 문서에서 여전히 experimental로 표시됩니다. 기본 빌드에도 포함되지 않으며 --with-http_v3_module과 호환 TLS 라이브러리가 필요합니다. NGINX HTTP/3 모듈
반대로 오리진 응답 캐시는 NGINX가 기본 제품 안에서 더 강합니다. proxy_cache, 캐시 키, stale 응답, background update, lock과 재검증을 세밀하게 설정할 수 있습니다. NGINX proxy cache 문서
Caddy의 표준 reverse_proxy에는 같은 종류의 응답 캐시가 들어 있지 않습니다. Caddy 문서에 표시되는 http.handlers.cache는 기본 배포에 포함되지 않는 비표준 모듈이며, custom build가 필요합니다. Caddy cache 모듈 문서
이 차이 때문에 단순 프록시에서는 Caddy를 골랐던 팀도 오리진에서 복잡한 캐시 정책을 운영하려면 NGINX를 다시 검토할 수 있습니다. 앞단 CDN이 캐시를 전담한다면 Caddy에 캐시 모듈이 없다는 점이 중요하지 않을 수도 있습니다.
리버스 프록시 기능은 둘 다 충분하지만 경계가 다릅니다
NGINX와 Caddy 모두 여러 upstream, 로드 밸런싱, 실패 처리와 헤더 조작을 지원합니다. 기본 기능 이름만 비교하면 차이가 작아 보입니다.
NGINX 오픈소스 버전에는 round robin, least connections, IP hash와 passive health check가 있습니다. 능동 health check와 일부 실시간 upstream 재구성 기능은 NGINX Plus 범위에 들어갑니다. NGINX 로드 밸런싱 문서
Caddy의 표준 reverse_proxy는 active health check와 passive health check, 여러 로드 밸런싱 정책, SRV 및 A/AAAA 기반 dynamic upstream을 제공합니다. Caddy reverse_proxy 문서
확장 방식도 다릅니다. NGINX는 빌드 옵션과 외부 또는 dynamic module을 사용합니다. Caddy 플러그인은 Go module로 작성하고 보통 xcaddy로 플러그인이 포함된 바이너리를 빌드합니다. 어느 쪽이든 비표준 모듈을 쓰기 시작하면 업데이트 때 호환성과 빌드 재현성을 관리해야 합니다.
로그는 Caddy가 구조화된 JSON 흐름을 만들기 편하고 Prometheus 형식의 메트릭도 켤 수 있습니다. NGINX는 log_format으로 필요한 필드를 오래된 운영 도구에 맞추기 쉽습니다. 이미 조직에 로그 수집 규칙과 대시보드가 있다면 새 서버의 기본 형식보다 기존 파이프라인과의 호환성이 더 중요합니다.
제가 고르는 기준
| 상황 | 먼저 고를 후보 | 이유 |
|---|---|---|
| 새 웹앱의 단순 리버스 프록시 | Caddy | 짧은 설정과 자동 HTTPS |
| 소수 인원이 운영하는 여러 작은 서비스 | Caddy | 인증서 갱신과 HTTPS 리디렉션을 기본 처리 |
| 사용자 지정 도메인이 계속 추가되는 SaaS | Caddy | 제한을 건 On-Demand TLS 활용 가능 |
| 오리진에서 세밀한 응답 캐시 운영 | NGINX | 내장 proxy cache와 다양한 제어 지시문 |
| 기존 NGINX 설정과 운영 절차가 많은 조직 | NGINX | 마이그레이션보다 기존 검증 자산을 유지하는 편이 유리 |
| FastCGI, uwsgi, SCGI 등 여러 upstream 방식 | NGINX | 오래 축적된 모듈과 설정 선택지 |
| API가 프록시 설정을 자주 바꾸는 시스템 | Caddy | 원자적 admin API와 JSON 구성 |
| HTTP/3를 기본 경로로 빠르게 사용 | Caddy | 기본 프로토콜에 h3 포함 |
제가 새로 만드는 작은 서비스라면 Caddy부터 시작하겠습니다. 도메인과 upstream을 적고 나면 HTTPS와 갱신이 함께 끝나는 기본값이 운영할 항목을 줄여 줍니다.
이미 NGINX가 안정적으로 동작하고 있다면 설정이 조금 길다는 이유만으로 바꾸지는 않겠습니다. 특히 캐시, 복잡한 location 규칙, 기존 로그 분석, 배포 검증 절차가 쌓여 있다면 그 자산의 가치가 큽니다. NGINX에도 이제 ACME 모듈이 있으므로 인증서 자동화 하나만으로 교체를 결정할 이유도 줄었습니다.
두 후보 사이에서 망설인다면 실제 서비스 하나의 설정을 각각 작성해 보는 것이 가장 빠릅니다. 인증서 발급과 갱신, 리로드, 로그, 캐시까지 적었을 때 별도 구성 요소가 적은 쪽을 고르겠습니다. 기능표보다 그 설정 파일과 배포 절차가 앞으로 관리할 비용을 더 정확히 보여 줍니다.
함께 읽기
- 운영에서만 AI 답변이 한 번에 나온다면, nginx가 스트림을 삼키고 있습니다챗봇 답변을 한 글자씩 흘려보내는 것은 기술적 과시가 아닙니다. 사람이 기다릴 수 있게 만드는 장치입니다. 같은 5초라도 빈 화면을 보는 5초와 글자가 차오르는 5초는 완전히 다른 시간입니다.
- 블로그를 서브도메인에서 하위 경로로 옮긴 이유, 그리고 CSP가 애드센스를 막고 있었습니다회사 사이트와 기술 블로그를 따로 운영하는 구성은 흔합니다. 회사는 duolabs.co.kr, 블로그는 blog.duolabs.co.kr.
- Neon·Supabase 대체 서비스: 2026년 비교와 추천 순위Neon과 Supabase를 대신할 서비스를 정리해 달라는 질문을 받았습니다. 처음에는 후보를 한 표에 놓고 유명한 순서부터 매기려 했습니다. 공식 문서를 다시 읽어 보니 출발점부터 잘못되었습니다.
- Neon vs Supabase: 리전, egress, 리얼타임 비교Vercel 서울 리전에서 도는 Next.js 앱에 붙일 관리형 Postgres 를 고르는 중이었습니다. 처음에는 두 서비스의 가격표를 나란히 놓고 비교하면 끝날 일이라고 생각했습니다. 실제로는 가격이 아니라, 나중에 되돌릴 수 없는 것들에서 갈렸습니다.
- 웹 플랫폼 핵심 개념 지도: URL에서 렌더링과 보안까지웹 개발을 프레임워크 이름으로만 배우면 기술이 바뀔 때마다 지식도 함께 낡아 보입니다. 하지만 브라우저가 주소를 해석하고, 서버와 통신하고, 문서를 파싱하고, 픽셀을 그리는 기본 과정은 훨씬 천천히 바뀝니다. React, Vue, Svelte와 Next.js도 이 과정 위에서 서로 다른 개발 방식을 제공합니다.