본문 바로가기
Q&A해결2026년 8월 18일1분 읽기

ALB 뒤 노드 서버가 간헐적으로 502를 뱉는데 재현이 안 돼서 미치겠어요

a
alb_junha
조회 352댓글 2

ECS(파게이트)에 노드 API를 올리고 앞에 ALB를 뒀는데, 평소엔 멀쩡하다가 어쩌다 한 번씩 502 Bad Gateway가 뜹니다. 재현하려고 부하 주면 또 안 나고, 트래픽 한가한 시간대에 오히려 잘 나는 느낌이에요.

ALB 액세스 로그 보면 이렇게 찍힙니다.

elb_status_code: 502  target_status_code: -
"GET /api/health HTTP/1.1"  target_processing_time: -1

타깃(노드) 앱 로그엔 해당 요청이 아예 안 남아 있습니다. 앱까지 도달을 안 한 것 같은데, 대체 어디서 502가 나는 걸까요?

댓글 2

김김영삼2개월 전
target_processing_time가 -1이고 target_status_code가 비어있는(-) 502는 요청이 타깃까지 도달을 못 했다는 뜻이에요. 앱 로그에 안 남는 것도 그래서고요. 이건 거의 항상 ALB와 백엔드 사이의 keep-alive 커넥션 타이밍 문제입니다.

ALB는 백엔드로의 TCP 커넥션을 재사용(keep-alive)하려고 잠깐 열어둬요. 그런데 노드 http 서버의 keepAliveTimeout이 ALB의 idle timeout보다 짧으면, 노드가 '이 커넥션 오래 놀았네' 하고 먼저 끊어버리는 순간에 ALB가 마침 그 커넥션으로 다음 요청을 보내면 레이스가 나요. ALB 입장에선 보내자마자 커넥션이 닫혀서 502가 나는 거예요. 트래픽 한가할 때 더 잘 나는 이유가 이거예요. 커넥션이 idle 상태로 오래 있다가 타이밍 맞아 끊기거든요.

해결은 노드쪽 keepAliveTimeout을 ALB idle timeout보다 크게 잡는 겁니다. ALB 기본이 60초니까 노드는 그보다 넉넉히 주세요.

const server = app.listen(3000)
server.keepAliveTimeout = 65000
server.headersTimeout = 66000

headersTimeout을 keepAliveTimeout보다 살짝 크게 두는 것도 잊지 마세요. 노드 특정 버전에서 headersTimeout이 더 작으면 그것 때문에 또 끊깁니다. 이렇게 항상 ALB보다 백엔드가 커넥션을 나중에 닫게 만들면 502가 사라져요. Express 기본 서버 그대로 쓰면 keepAliveTimeout이 ALB 60초보다 짧아서 이 문제 진짜 흔합니다.
aalb_junha(guest)2개월 전
이거였네요. keepAliveTimeout이랑 headersTimeout 65/66초로 잡으니 이틀째 502 한 번도 안 뜹니다. 간헐적이라 원인 못 잡고 있었는데 정확히 짚어주셔서 감사합니다!
Ctrl+Enter로 등록