부제: 순정 nginx 대신 OpenResty를 쓰게 된 이유

리버스 프록시로 순정 nginx를 쓰고 있었다. rate limit도 nginx 기본 기능(limit_req)으로 IP 기준으로 걸어 뒀다. 처음엔 충분했는데, 트래픽 구조 때문에 한 가지 문제가 생겼다.
출발점
백엔드(BE) 하나가 자기 IP·API 키 하나로 여러 end-user의 요청을 한데 모아 보낸다. 그러다 보니 동시성이 잠깐 치솟으면, 정상적인 BE 트래픽인데도 IP 기준 rate limit에 걸려 429가 났다. 진짜 과한 호출이 아니라 집약 구조 때문에 생긴 false positive였다.
그래서 방향을 정했다. 유효한 API 키로 들어온 요청은 rate limit에서 면제하고, IP 제한은 그 외에만 적용하자.
왜 순정 nginx로는 부족했나
면제 조건이 까다로웠다. 헤더에 X-API-Key가 그냥 있다고 면제해 주면, 아무 값이나 헤더에 끼워 우회할 수 있다. 그래서 admin-server가 발급한, DB에 있는 유효한 키일 때만 면제해야 했다.
이걸 하려면 요청을 받는 시점에 키 값을 sha256으로 해시하고, 그게 유효 키 목록에 있는지 대조하는 로직이 필요하다.
순정 nginx 설정 문법으로는 이런 계산과 조회를 표현하기 어렵다. 요청 초기 단계(preaccess)에서 해시 계산이나 외부 저장소 조회를 끼워 넣을 자리가 없다. 조건문 몇 개로 되는 일이 아니었다.
OpenResty 채택
그래서 nginx에 Lua를 얹은 OpenResty로 바꿨다. edge에서 Lua로 직접 해시를 계산하고 대조할 수 있기 때문이다.
흐름은 이렇게 정리했다.
- agent-server: 활성·미만료 키의 sha256 해시 묶음을 Redis에 주기적으로 내보낸다(best-effort). 서버 기동 시점에도 한 번 내보내서, 켜지자마자 면제 판정이 동작한다(cold-start 공백 없음).
- nginx(Lua): 요청이 오면 X-API-Key를 sha256으로 해시해서, Redis를 짧게 미러링한 shared dict와 대조한다. 유효하면 rate-limit 키를 비워 면제하고, 아니면 IP를 키로 쓴다.
- zone 구분: 일반 API·업로드는 유효 키면 면제, 인증(auth)·관리자(admin) 경로는 키가 있어도 항상 IP 기준으로 제한한다.
여기서 면제는 어디까지나 rate limit 면제일 뿐, 실제 키 검증(주 경로)을 대신하지는 않는다. edge는 "제한을 풀지 말지"만 보고, 진짜 인증은 그대로 백엔드가 한다.
결과
같은 부하로 확인했다.
- 유효한 DB 키 120요청 → 429 0건 (면제됨)
- junk 키 → IP 제한이 걸려 429 다수
- 익명 요청 → IP 제한으로 429 다수
집약 구조 때문에 정상 트래픽이 막히던 문제는 사라지고, 헤더만 끼워 우회하려는 요청은 그대로 IP 제한에 걸린다.
정리
- 순정 nginx의 rate limit은 IP 기준이라, 트래픽이 한 IP로 집약되면 정상 요청도 막힐 수 있다
- "유효 키만 면제"는 해시·조회 로직이 필요해서 순정 nginx 설정 문법으로는 표현하기 어려웠다
- edge에서 그 로직을 넣기 위해 OpenResty(nginx + Lua)를 채택했다
- 단, edge의 면제는 rate limit 한정이고 실제 인증은 백엔드가 그대로 담당한다
nginx로 충분한 일은 nginx로 두고, 설정 문법으로 표현이 안 되는 판단이 필요할 때만 Lua를 얹는 선이 적당했다.
'Infra' 카테고리의 다른 글
| [nginx] docker-compose command override envsubst 미실행 ${VAR} (0) | 2026.06.25 |
|---|---|
| [Prometheus] Docker 컨테이너 자원 cgroup v2 직독 cAdvisor 대체 (0) | 2026.06.25 |
| [Docker] bind-mount 설정 미반영 원인 force-recreate (0) | 2026.06.25 |
| [Grafana] 무트래픽 구간 spanNulls 보간 제거 rate 0 채움 (0) | 2026.06.25 |
| [Langfuse] Self-Hosted v3: ClickHouse 서버 리소스 최적화 (0) | 2026.02.09 |