AWS EKS 환경에서 AWS ALB Ingress Controller와 Node.js 백엔드를 운영하다 보면 502, 503, 504와 같은 HTTP 오류 코드를 마주하게 됩니다. 처음 이 오류들을 접하면 직관적으로 이해하기 어렵습니다. 503 오류가 발생했을 때 “로드 밸런서에 연결된 타겟이 없는 것인가?”라고 추측하거나, 502 오류를 보고 “애플리케이션이 죽었나?”라고 오해하기 쉽습니다. 하지만 실제 원인을 분석해보면 이 상태 코드들의 의미와 발생 조건은 미묘하게 다릅니다.
이 글에서는 HTTP 502 / 503 / 504 오류의 의미와 차이를 명확히 하고, AWS EKS + ALB Ingress + Node.js 아키텍처에서 발생하는 구체적인 원인과 해결 방법을 다룹니다. RFC 표준 정의와 AWS 공식 문서를 근거로 개념을 정립하고, 실무에서 바로 적용 가능한 트러블슈팅 가이드를 제공합니다.
1. 503 – 타겟이 없다는 뜻일까?
503 Service Unavailable 오류는 이름에서 알 수 있듯 “서비스를 이용할 수 없음”을 의미합니다. 처음에는 단순히 서버가 다운된 상황으로 생각하기 쉽지만, 로드 밸런서 환경에서는 조금 더 구체적인 의미를 가집니다.
정의와 원인
RFC 7231에 따르면 503 코드는 일시적인 과부하나 점검 등으로 서버가 요청을 처리할 수 없는 상태를 의미합니다.
“The 503 (Service Unavailable) status code indicates that the server is currently unable to handle the request due to a temporary overload or scheduled maintenance…”
— RFC 7231 Section 6.6.4
AWS ALB 환경에서 503 오류는 주로 로드 밸런서가 요청을 전달할 유효한 타겟(Target)을 찾지 못했을 때 발생합니다. AWS 공식 문서는 다음과 같은 상황을 명시합니다.
타겟 없음 (No Targets): Service의 Selector가 Deployment의 라벨과 일치하지 않아 Endpoints가 비어있는 경우 (kubectl get endpoints 결과가 <none>).
타겟 비활성 (Unhealthy Targets): Pod가 존재하지만 Readiness Probe를 통과하지 못해 트래픽을 받을 준비가 되지 않은 경우. 이 경우 ALB는 해당 타겟을 ‘Unhealthy’ 또는 ‘Unused’로 간주하여 요청을 보내지 않습니다.
Ingress 설정 오류: Ingress 리소스가 존재하지 않는 Service나 잘못된 포트를 가리키고 있을 때.
동작 흐름
sequenceDiagram
participant Client
participant ALB
participant TargetGroup
Client->>ALB: HTTP Request
ALB->>TargetGroup: Select Healthy Target
TargetGroup-->>ALB: No Healthy Targets Available
ALB-->>Client: 503 Service Unavailable
중요한 점은 503 오류가 항상 ALB에서 생성되는 것은 아니라는 사실입니다. 백엔드 애플리케이션이 직접 503 응답을 보낼 수도 있습니다. 이를 구분하기 위해서는 CloudWatch 지표를 확인해야 합니다.
HTTPCode_ELB_5XX 증가: ALB가 타겟을 찾지 못해 자체적으로 반환한 경우.
HTTPCode_Target_5XX 증가: 백엔드 애플리케이션이 503을 반환한 경우.
실무 팁: Readiness Probe 확인
503 오류 발생 시 가장 먼저 kubectl get endpoints <서비스명>을 확인하세요. 만약 Endpoints가 비어있다면 Service Selector를 점검해야 합니다. Endpoints는 있지만 접근이 안 된다면, Pod의 Readiness Probe 설정을 확인해야 합니다. 애플리케이션 구동 시간이 긴데 Probe 대기 시간이 짧다면, Pod가 영원히 Ready 상태가 되지 못해 503이 발생할 수 있습니다.
관련 개념: Readiness Probe, Kubernetes Service
2. 502 – Node.js 서버가 연결을 끊었나?
502 Bad Gateway 오류는 “잘못된 게이트웨이”라는 의미로, ALB가 백엔드 서버로부터 유효하지 않은 응답을 받았음을 나타냅니다.
정의와 원인
RFC 7231에서는 게이트웨이나 프록시가 상류 서버(Upstream Server)로부터 유효하지 않은 응답을 받았을 때 502를 반환한다고 정의합니다.
“The 502 (Bad Gateway) status code indicates that the server, while acting as a gateway or proxy, received an invalid response from an inbound server…”
— RFC 7231 Section 6.6.3
AWS EKS + Node.js 환경에서 502 오류의 가장 흔한 원인은 TCP 연결 종료 타이밍의 불일치(Keep-Alive Mismatch) 입니다.
Keep-Alive Timeout 불일치: Node.js의 기본 keepAliveTimeout은 5초인 반면, AWS ALB의 기본 idle timeout은 60초입니다.
시나리오: ALB는 60초 동안 연결이 유지될 것이라 기대하고 유휴 상태인 연결을 재사용하여 요청을 보냅니다. 하지만 Node.js는 5초가 지났으므로 이미 소켓 연결을 끊어버립니다(TCP RST 또는 FIN).
결과: ALB는 닫힌 소켓으로 요청을 보내려다 실패하고, 클라이언트에게 502 Bad Gateway를 반환합니다.
AWS 문서는 이를 다음과 같이 설명합니다:
“…if the application closes the TCP connection to the load balancer ungracefully, the load balancer might send a request to the application before it receives the packet indicating that the connection is closed.”
— Troubleshoot your Application Load Balancers: HTTP 502
이 외에도 애플리케이션 크래시(OOM 등) 로 인해 프로세스가 즉시 종료되거나, HTTP 헤더 크기 초과로 인해 ALB가 응답을 파싱 하지 못할 때도 502가 발생합니다.
동작 흐름
sequenceDiagram
participant ALB
participant NodeJs as Node.js App
ALB->>NodeJs: TCP Connection Established
Note over ALB, NodeJs: Idle (No traffic)
NodeJs->>NodeJs: Keep-Alive Timeout (5s) Exceeded
NodeJs--xALB: Close Connection (TCP RST/FIN)
Note over ALB: Still thinks connection is open (Idle < 60s)
ALB->>NodeJs: Send New Request on Closed Socket
NodeJs-->>ALB: Connection Reset / Closed
ALB-->>Client: 502 Bad Gateway
실무 팁: Node.js Keep-Alive 설정
Node.js 애플리케이션의 keepAliveTimeout을 ALB의 Idle Timeout(기본 60초)보다 길게 설정해야 합니다. AWS는 백엔드 타임아웃을 ALB보다 길게 가져갈 것을 권장합니다.
대부분의 애플리케이션 레벨 504 오류는 백엔드 처리 지연 때문입니다. 데이터베이스 쿼리가 느리거나, 외부 시스템 연동에서 타임아웃 처리가 미흡하여 Node.js의 이벤트 루프가 블로킹되면 60초를 넘기기 쉽습니다.
동작 흐름
sequenceDiagram
participant Client
participant ALB
participant NodeJs as Node.js App
Client->>ALB: HTTP Request
ALB->>NodeJs: Forward Request
Note over NodeJs: Processing (Heavy Query / External API)
rect rgb(255, 240, 240)
Note over ALB: Idle Timeout (60s) Exceeded
ALB--xNodeJs: Close Connection
ALB-->>Client: 504 Gateway Timeout
end
NodeJs-->>ALB: Response (Too Late)
Note over ALB: Ignored
실무 팁: 타임아웃 전략
단순히 ALB의 Idle Timeout을 늘리는 것은 미봉책입니다. 애플리케이션 내부의 타임아웃을 먼저 점검해야 합니다. 외부 API 호출이나 DB 쿼리에 명시적인 타임아웃(예: 5초)을 설정하여, 요청이 무한정 대기하다가 504로 이어지는 것을 방지하세요. 네트워크 문제(Security Group 등)로 인해 패킷이 드랍되는 경우에도 연결 타임아웃(10초)으로 504가 발생할 수 있음을 명심해야 합니다.
관련 개념: AWS ALB Timeouts, Security Group