Fuwari Banner
지니제스트Tech Archive
Cloudflare7분 소요

Cloudflare Workers 서비스 배포 후 HTTP 522 오류 분석 및 해결

•
ggeniezst
•조회 1

Cloudflare Workers 배포 후 발생하는 HTTP 522 오류의 근본 원인인 Origin 서버 연결 시간 초과 문제를 심층 분석하고, 실제 환경에서 적용 가능한 해결 전략과 검증 절차를 상세히 다룹니다.

Sponsored

최근 Cloudflare Workers를 활용하여 기존 백엔드 API 서버 앞에 Edge 캐싱 및 요청 라우팅 로직을 구현하는 프로젝트를 진행했습니다. 개발 및 로컬 테스트 환경에서는 아무런 문제가 없었으나, 프로덕션 환경에 배포하자마자 간헐적으로 HTTP 522 에러가 발생하는 현상이 관측되었습니다. 특히 특정 API 호출에서 빈번하게 발생했고, 사용자 경험에 치명적인 영향을 미쳤습니다. Cloudflare 대시보드에서는 Origin Connection Timeout으로 표시되었지만, 백엔드 서버의 리소스 사용률은 정상 범위였고, 직접 백엔드 API를 호출했을 때는 응답이 매우 빨랐습니다. 이 미스터리한 HTTP 522 오류는 단순한 서버 부하 문제가 아님을 직감했습니다.


Cloudflare HTTP 522 오류의 근본 원인 분석

HTTP 522 오류는 Cloudflare가 Origin 서버(즉, 실제 백엔드 서버)에 연결하는 데 실패했음을 의미합니다. Cloudflare는 사용자의 요청을 받아 Edge Location에서 처리한 후, 필요한 경우 Origin 서버로 프록시하여 응답을 가져옵니다. 이 과정에서 Cloudflare와 Origin 서버 간의 TCP 연결이 설정되어야 하는데, 이 연결이 일정 시간 내에 완료되지 않거나, 연결이 설정된 후 데이터 전송이 지연될 경우 HTTP 522 오류가 발생합니다. Cloudflare의 기본 연결 시간 초과는 100초로 설정되어 있으며, Enterprise 플랜의 경우 최대 600초까지 조정 가능합니다.

저희의 경우, 백엔드 서버는 AWS EC2 인스턴스에서 동작하고 있었고, 로드 밸런서(ALB) 뒤에 위치했습니다. ALB는 정상적으로 트래픽을 처리하고 있었으며, EC2 인스턴스 또한 CPU, 메모리, 네트워크 I/O 지표 모두 양호했습니다. 문제는 Cloudflare Workers가 요청을 받아 Origin으로 포워딩하는 특정 로직에서 발생했습니다. Workers 스크립트 내부에서 fetch API를 사용하여 Origin 서버로 요청을 보낼 때, 일부 요청이 비정상적으로 지연되거나 타임아웃되는 현상이었습니다. 이는 Workers 환경과 Origin 서버 간의 네트워크 경로, 혹은 Workers 런타임의 특정 동작 방식과 관련이 있을 수 있다고 판단했습니다. 특히, Workers 스크립트 내에서 비동기 작업이 복잡하게 얽히거나, 외부 리소스 호출이 많을 때 이러한 문제가 심화될 가능성이 있었습니다.


Origin 서버의 연결 수용 능력 및 네트워크 경로 점검

Cloudflare HTTP 522 오류의 가장 흔한 원인 중 하나는 Origin 서버가 Cloudflare의 연결 요청을 제때 수락하지 못하는 경우입니다. 이는 서버의 부하, 방화벽 설정, 네트워크 경로 문제 등 다양한 원인으로 발생할 수 있습니다.

먼저, Origin 서버의 연결 큐(Connection Queue) 상태를 확인했습니다. Linux 시스템에서는 netstat 명령어를 통해 SYN_RECV 상태의 연결이나 LISTEN 큐 오버플로우를 확인할 수 있습니다.

BASH
# Origin 서버에서 SYN_RECV 상태의 연결 개수 확인
# SYN_RECV는 TCP 3-way handshake 도중 서버가 SYN-ACK를 보냈으나 클라이언트로부터 ACK를 받지 못한 상태
sudo netstat -nat | grep SYN_RECV | wc -l

# LISTEN 큐 오버플로우 통계 확인 (Linux 커널 파라미터)
# listen_queue_overflows 값이 증가한다면, 서버가 들어오는 연결을 처리하지 못하고 있음을 의미
sudo netstat -s | grep "listen_queue_overflows"

만약 SYN_RECV가 과도하게 많거나 listen_queue_overflows가 증가하고 있다면, Origin 서버의 네트워크 스택 또는 애플리케이션이 새로운 연결을 충분히 빠르게 수락하지 못하고 있다는 증거입니다. 이 경우, 커널 파라미터 튜닝을 고려할 수 있습니다.

BASH
# /etc/sysctl.conf 파일 수정 예시
# net.core.somaxconn: LISTEN 큐의 최대 크기 (기본 128)
# net.ipv4.tcp_max_syn_backlog: SYN 큐의 최대 크기 (기본 1024)
# 더 많은 동시 연결을 수용하기 위해 값을 증가시킬 수 있음
echo "net.core.somaxconn = 65535" | sudo tee -a /etc/sysctl.conf
echo "net.ipv4.tcp_max_syn_backlog = 65535" | sudo tee -a /etc/sysctl.conf
sudo sysctl -p # 변경 사항 적용

저희 시스템에서는 위 지표들이 정상 범위였으므로, Origin 서버 자체의 연결 수용 능력 문제는 아니라고 판단했습니다. 다음으로는 Cloudflare와 Origin 서버 간의 네트워크 경로를 진단했습니다. traceroute나 mtr 같은 도구는 Cloudflare Edge Location에서 직접 실행할 수 없으므로, Cloudflare 대시보드의 "Network" -> "Traffic" -> "Troubleshooting" 섹션에서 제공하는 도구를 활용하거나, Cloudflare Workers의 fetch API에서 cf 객체를 통해 얻을 수 있는 정보를 분석해야 합니다. 특히, cf.colo (Cloudflare PoP 위치)와 Origin 서버의 지리적 위치 간의 네트워크 지연을 고려해야 합니다.


Cloudflare Workers fetch API의 cf 옵션 활용 및 타임아웃 설정

Cloudflare Workers에서 Origin 서버로 요청을 보낼 때 fetch API를 사용합니다. 이 fetch API는 표준 Web API와 유사하지만, Cloudflare Workers 환경에 특화된 추가 옵션들을 cf 객체를 통해 제공합니다. 특히, cf 객체 내의 connectionTimeout 옵션은 Origin 서버로의 TCP 연결 설정 시간을 제어하는 데 매우 중요합니다.

기본적으로 Workers의 fetch는 Origin 서버로의 연결 시도에 100초의 타임아웃을 적용합니다. 하지만 특정 상황, 특히 Origin 서버가 일시적으로 높은 부하를 겪거나 네트워크 경로에 불안정성이 있을 때 이 기본 타임아웃이 충분하지 않을 수 있습니다. 혹은 반대로, 너무 긴 타임아웃이 불필요한 지연을 유발할 수도 있습니다.

저희의 경우, 특정 API 호출이 복잡한 데이터베이스 쿼리나 외부 서비스 연동으로 인해 응답 시간이 길어지는 경향이 있었습니다. Workers는 Origin 서버로부터 응답을 기다리는 동안에도 타임아웃이 발생할 수 있습니다. 이럴 때 cf.connectionTimeout과 더불어 cf.responseTimeout을 함께 고려해야 합니다.

JAVASCRIPT
// Cloudflare Workers 스크립트 예시 (JavaScript)
addEventListener('fetch', event => {
  event.respondWith(handleRequest(event.request));
});

async function handleRequest(request) {
  const url = new URL(request.url);
  const originUrl = `https://your-origin-server.com${url.pathname}${url.search}`;

  // Origin 서버로 요청을 보낼 때 cf 옵션 활용
  const response = await fetch(originUrl, {
    method: request.method,
    headers: request.headers,
    body: request.body,
    cf: {
      // Origin 서버로의 TCP 연결 설정 타임아웃 (초 단위)
      // 기본값 100초. 특정 API가 더 오래 걸린다면 늘려볼 수 있음.
      // 너무 길게 설정하면 사용자 경험 저하.
      connectionTimeout: 150, // 150초로 설정 (예시)

      // Origin 서버로부터 전체 응답을 받는 데 걸리는 타임아웃 (초 단위)
      // 기본값 100초. 대용량 데이터 전송이나 복잡한 계산에 필요할 수 있음.
      responseTimeout: 300, // 300초로 설정 (예시)

      // Cloudflare 캐싱 동작 제어 (필요에 따라 설정)
      cacheEverything: true,
      cacheTtl: 3600, // 1시간 캐시
    },
  });

  return response;
}

위 코드에서 connectionTimeout은 TCP 연결 설정에만 적용되며, responseTimeout은 연결 설정 이후 Origin 서버로부터 첫 바이트를 받기 시작하여 전체 응답을 완료할 때까지의 시간을 제어합니다. 저희는 특정 API의 평균 응답 시간을 분석하여, 이 두 값을 적절히 조정함으로써 HTTP 522 오류 빈도를 현저히 줄일 수 있었습니다. 특히, responseTimeout을 충분히 확보하는 것이 중요했습니다.


Origin 서버의 Keep-Alive 설정과 Cloudflare의 연결 재사용

Cloudflare와 Origin 서버 간의 HTTP 522 오류는 TCP 연결 설정 비용과도 관련이 있습니다. 매 요청마다 새로운 TCP 연결을 설정하는 것은 비효율적이며, 특히 짧은 시간 내에 많은 요청이 발생할 경우 Origin 서버에 부하를 줄 수 있습니다. HTTP Keep-Alive는 이미 설정된 TCP 연결을 재사용하여 이러한 오버헤드를 줄이는 메커니즘입니다.

Cloudflare는 기본적으로 Origin 서버와의 Keep-Alive 연결을 적극적으로 활용합니다. 하지만 Origin 서버가 Keep-Alive를 제대로 지원하지 않거나, Keep-Alive 타임아웃이 Cloudflare의 Keep-Alive 타임아웃보다 짧을 경우 문제가 발생할 수 있습니다.

Origin 서버(예: Nginx, Apache, Node.js 애플리케이션)의 Keep-Alive 설정을 확인하고 조정해야 합니다.

NGINX
# Nginx 설정 예시 (nginx.conf 또는 해당 서버 블록)
http {
    ...
    keepalive_timeout 65; # Cloudflare의 기본 Keep-Alive 타임아웃(60초)보다 길게 설정
    keepalive_requests 1000; # 한 연결에서 처리할 최대 요청 수
    ...
}

Nginx의 keepalive_timeout은 서버가 비활성 Keep-Alive 연결을 닫기 전에 기다릴 시간을 정의합니다. Cloudflare는 일반적으로 60초의 Keep-Alive 타임아웃을 사용하므로, Origin 서버의 keepalive_timeout을 이보다 길게 설정하는 것이 좋습니다 (예: 65초 이상). 이렇게 하면 Cloudflare가 기존 연결을 재사용하려 할 때 Origin 서버가 이미 연결을 닫아버리는 상황을 방지할 수 있습니다.

또한, Origin 서버의 애플리케이션 레벨에서 Keep-Alive 헤더(Connection: keep-alive)를 제대로 응답하는지 확인해야 합니다. 만약 Origin 서버가 Connection: close 헤더를 보내면, Cloudflare는 해당 연결을 재사용하지 않고 즉시 닫게 됩니다.


사이드 이펙트 방지 및 트러블슈팅 FAQ

Q. HTTP 522 오류가 발생하는데, Origin 서버 로그에는 아무런 기록이 없습니다. 왜 그런가요?

A. HTTP 522는 Cloudflare가 Origin 서버에 TCP 연결을 시도했으나 실패했음을 의미합니다. 즉, 요청이 Origin 서버의 애플리케이션 레벨까지 도달하지 못했을 가능성이 큽니다. 이 경우, Origin 서버의 네트워크 스택, 방화벽(보안 그룹, ACL 등), 로드 밸런서 설정 또는 서버의 리소스 고갈로 인해 연결 자체가 거부되거나 타임아웃되었을 수 있습니다. Cloudflare의 IP 대역이 Origin 서버의 방화벽에서 허용되었는지, 로드 밸런서의 상태 확인(Health Check)이 정상인지 등을 우선적으로 점검해야 합니다.

Q. Cloudflare Workers의 fetch cf 옵션에서 connectionTimeout과 responseTimeout을 너무 길게 설정하면 어떤 문제가 발생할 수 있나요?

A. 두 타임아웃 값을 너무 길게 설정하면 사용자 경험이 저하될 수 있습니다. 사용자는 응답을 무한정 기다리지 않으며, 브라우저나 클라이언트 앱 자체의 타임아웃에 먼저 도달하여 불필요한 지연 후에 오류를 받게 될 수 있습니다. 또한, Workers 스크립트의 실행 시간 제한(기본 50ms, 최대 30초)에도 영향을 미칠 수 있습니다. 합리적인 수준에서, 실제 Origin 서버의 최대 응답 시간을 고려하여 최소한으로 필요한 값을 설정하는 것이 중요합니다.

Q. Origin 서버의 IP 주소가 변경되었는데, Cloudflare DNS 설정은 업데이트했습니다. 그런데도 HTTP 522가 발생합니다.

A. Cloudflare DNS 설정이 업데이트되었더라도, Cloudflare Edge Location의 DNS 캐시가 갱신되는 데 약간의 시간이 소요될 수 있습니다. 특히 TTL(Time To Live) 값이 높게 설정되어 있다면 갱신이 더딜 수 있습니다. 또한, Origin 서버의 방화벽 설정(예: AWS Security Group)에서 Cloudflare의 새로운 IP 대역을 허용했는지 다시 한번 확인해야 합니다. 간혹, 로드 밸런서 뒤에 있는 Origin 서버의 경우, 로드 밸런서 자체의 설정이나 Health Check 문제로 인해 HTTP 522가 발생하기도 합니다. Cloudflare 대시보드에서 해당 도메인의 "DNS" 섹션으로 이동하여 A/AAAA 레코드가 올바른지 다시 확인하고, 필요하다면 캐시를 비워보는 것도 방법입니다.


Cloudflare Workers 환경에서 HTTP 522 오류는 단순히 Origin 서버의 부하 문제만을 의미하지 않습니다. Cloudflare와 Origin 서버 간의 네트워크 경로, TCP 연결 설정 및 유지 방식, Workers fetch API의 동작 방식 등 복합적인 요인을 고려해야 합니다. 이번 트러블슈팅을 통해 Cloudflare Workers의 cf 옵션을 활용하여 타임아웃을 정교하게 제어하고, Origin 서버의 Keep-Alive 설정을 최적화하는 것이 안정적인 서비스 운영에 얼마나 중요한지 다시 한번 깨달았습니다. 항상 시스템의 각 구성 요소가 어떻게 상호작용하는지 깊이 이해하고 접근하는 것이 문제 해결의 핵심입니다.

Sponsored