upstream sent too big header (nginx)
nginx가 502를 내며 이 에러를 남기는 건 백엔드 응답 헤더가 proxy_buffer_size를 넘쳤기 때문입니다. 무료 즉시 진단으로 원인을 가르세요.
내 도메인에 이 문제가 있는지 지금 확인
무료, 가입 불필요. 이 가이드가 다루는 항목을 바로 검사하고 조치 방법을 알려드립니다.
Problem
방문자에게 502 Bad Gateway가 뜨고, nginx 에러 로그에 upstream sent too big header while reading response header from upstream이 찍힙니다. 백엔드는 문제가 없습니다 — 요청을 받아 유효한 응답을 보냈습니다. nginx가 그 응답을 넘겨주기 전에 거부한 것인데, 응답의 헤더가 nginx가 읽으려고 잡아 둔 단일 버퍼보다 컸기 때문입니다. 가장 흔한 방아쇠는 로그인이나 OAuth 콜백이 거대한 Set-Cookie를 응답에 쌓는 경우입니다. 먼저 답할 질문은, 이게 특정 한 경로에서만(콜백의 큰 쿠키) 터지는지 아니면 모든 요청에서(버퍼가 진짜 작음) 터지는지입니다 — 그게 설정을 어디까지 손댈지를 가릅니다.
Symptoms
- 클라이언트는 밋밋한
502 Bad Gateway를 보고, nginx 에러 로그엔upstream sent too big header while reading response header from upstream이 남는다. - 백엔드 자체는 건강해 보인다 — nginx가 502로 바꿔 버린 그 요청을 백엔드는 정상
200/302로 로깅한다. - 경로별로 다르다: 로그인, OAuth2/SSO 콜백, 세션을 초기화하는 엔드포인트만 실패하고 나머지는 멀쩡하다.
- 인증을 추가하거나 새 SSO를 붙이거나 쿠키를 더 세팅하는 미들웨어를 넣은 직후 시작됐다.
- 백엔드를 재시작하거나 스케일해도 안 바뀐다 — 애초에 백엔드가 문제가 아니었으니까.
What This Error Actually Means
nginx가 요청을 프록시할 때, 업스트림 응답의 첫 부분 — 상태 줄과 모든 응답 헤더 — 을 고정 버퍼 하나에 읽어들입니다. HTTP 프록시에서 그 버퍼가 proxy_buffer_size이고, 기본값은 메모리 한 페이지입니다: 대부분 플랫폼에서 4KB, 일부에서 8KB. 헤더 블록 전체가 그 버퍼 하나 안에 들어가야 합니다. 업스트림이 그보다 큰 헤더를 보내면 nginx는 응답을 파싱하지 못해 통째로 버리고 502 Bad Gateway를 돌려줍니다.
사람들이 걸려 넘어지는 건 두 지시어의 역할 차이입니다. proxy_buffer_size는 응답 헤더용 하나짜리 버퍼입니다. proxy_buffers는 응답 본문용 별도 풀입니다(기본 4KB/8KB 버퍼 8개). proxy_buffers를 키워도 헤더 오버플로에는 소용없습니다 — 헤더는 전부 proxy_buffer_size에 삽니다. 그리고 본문이 아니라 헤더라서 proxy_buffering off로도 못 피합니다 — proxy_buffer_size가 여전히 헤더 읽기를 제한합니다. 그래서 해결은 거의 항상 “proxy_buffer_size를 키운다” 아니면 “백엔드가 그렇게 큰 헤더를 못 내보내게 한다”이고, 이 둘을 가려내는 게 실제 작업입니다.
업스트림이 평범한 HTTP 프록시가 아니라 PHP-FPM, uwsgi 위의 파이썬 앱, gRPC라면 같은 실패가 대응 지시어에서 나타납니다 — fastcgi_buffer_size, uwsgi_buffer_size, scgi_buffer_size, grpc_buffer_size. 같은 버퍼, 다른 프로토콜 접두사입니다.
Top 3 Causes
- 로그인·OAuth 콜백의 거대한
Set-Cookie. 압도적으로 흔합니다. SSO/OAuth 흐름, 세션 라이브러리, 또는 상태를 쿠키에 저장하는 프레임워크가 콜백 응답에 크고 여러 개인Set-Cookie헤더를 씁니다. 헤더 블록이 기본 4KB/8KB 버퍼를 넘어서 nginx가 그 한 경로만 502를 냅니다. 신호: 인증 관련 엔드포인트만 실패하고, 인증을 추가·변경한 시점에 시작됐다. - 헤더가 많은 앱인데 버퍼가 기본값 그대로. 한 페이지 기본값은 평범한 앱엔 충분하고, 큰 헤더를 정당하게 내보내는 앱엔 작습니다 — 되돌려 보내는 큰 JWT, 많은 쿠키, 모든 응답에 붙는 장황한 커스텀 헤더. 신호: 한 경로가 아니라 전부 터진다.
- 프록시·WAF·디버그 계층이 응답 헤더를 부풀림. nginx와 클라이언트 사이의 중간 장비, 또는 디버그 모드의 앱 프레임워크가 자기 헤더를 덧붙입니다(추적 ID, 헤더에 쑤셔 넣은 스택 트레이스, 잔뜩 쌓인 보안 헤더). 응답이 앱에선 작았다가 nginx가 읽을 즈음 커집니다. 신호: 한 환경(디버그 켜진 스테이징)에서만 뜨거나 프록시·WAF 변경 후에 뜬다.
Diagnose with DechoNet
- HTTP 점검은 외부에서 URL을 요청해 실제로 통과하는 상태와 응답 헤더를 보여줍니다. 사이트 대부분에선 깨끗한
200인데 로그인·콜백 경로에서만502가 나오면, 실패가 경로별이라는 걸 확인한 셈입니다 — 전역적으로 버퍼가 작은 게 아니라 그 응답의 큰Set-Cookie를 가리킵니다. 결정적 후속은 서버에서 하세요: 실패하는 경로에 대해 nginx를 우회해 업스트림에 직접curl -sI를 날려 응답 헤더를 재보세요 —Set-Cookie나 헤더 블록이 현재proxy_buffer_size보다 크면 범인을 찾은 겁니다.
Resolution Checklist
- nginx 에러 로그에서 정확한 문구를 확인하세요:
upstream sent too big header while reading response header from upstream. 이 문구는 클라이언트 요청 헤더가 아니라 응답 쪽 문제라는 뜻입니다. - HTTP 점검으로 범위를 잡으세요: 한 경로만 502인가, 전부인가? 한 경로 → 그 응답의 큰 쿠키·헤더. 전부 → 앱에 비해 버퍼가 작음.
- 범인을 재세요. 서버에서 실패 경로에 업스트림 직접
curl -sI를 날려 총 헤더 크기, 특히Set-Cookie를 보세요. 현재proxy_buffer_size와 비교하세요. - 본문 풀이 아니라 헤더 버퍼를 키우세요: 해당
location/http블록에proxy_buffer_size 16k;(아주 큰 토큰이면32k)를 넣고,proxy_busy_buffers_size를 최소 같은 값으로 두세요. PHP-FPM/uwsgi/gRPC면 대응하는fastcgi_buffer_size/uwsgi_buffer_size/grpc_buffer_size를 쓰세요. nginx를 reload합니다. - 헤더가 정말 비대하면 근원을 고치는 게 낫습니다: 세션 상태를 쿠키에서 서버측 저장소로 옮기거나, OAuth/SSO 계층이 쓰는 걸 줄여, 매 요청마다 킬로바이트짜리 쿠키를 나르지 않게 하세요.
- 만능 해결이랍시고 모든 연결에 거대한 버퍼를 주지 마세요 — 연결당 과대 버퍼는 메모리·DoS 지뢰입니다. 실제 헤더 총량에 여유분만 더해 크기를 잡고, 살찐 쿠키는 근원에서 고치세요.
When to Escalate
- 관측된 헤더에 비해 버퍼가 충분한데도 간헐적으로만 502가 나면, 앱과 nginx 사이에서 헤더를 재작성·중복시키는 중간 장비나 업스트림과의 keep-alive·HTTP 버전 불일치를 찾으세요 — 단순 헤더 오버플로와는 다른 실패입니다.
proxy_buffer_size를 키워 해소됐는데 쿠키가 시간이 갈수록 계속 커지면, 그건 결국 어떤 버퍼든 넘길 애플리케이션 설계 문제(무한정 커지는 쿠키 상태)입니다 — 숫자를 계속 올리지 말고 앱에서 고치세요.
관련 도구
관련 가이드
가이드 공유