터널 연결 상태를 안전하게 마이그레이션하는 장면

Cloudflare Tunnel API connections 필드 제거에 대비한 상태 점검 마이그레이션

Cloudflare Tunnel API connections 제거가 2026년 10월 5일로 예고됐어요. cfd_tunnel 목록이나 단건 응답의 connections를 읽어 상태를 판단하던 코드라면 그 전에 손봐야 합니다. 다만 모든 터널마다 새 /connections API를 호출하는 식으로 바꾸면 요청만 잔뜩 늘어날 수 있음.

핵심은 필요한 정보의 깊이를 먼저 나누는 거예요. 터널이 서비스 가능한지만 보면 목록의 status, 연결 수나 colo·버전까지 필요하면 터널별 전용 /connections를 사용합니다. 이 글은 2026년 7월 31일 기준 Cloudflare 변경 공지와 API 문서를 대조해 정리했으며, 인증된 실제 계정 호출은 수행하지 않았어요. 실제 권한과 응답, 지연은 staging에서 따로 확인해야 합니다.

기존 connections 의존을 목록 status와 터널별 전용 API로 분리하는 흐름도

10월 5일에 사라지는 응답 필드부터 찾기

제거되는 건 Tunnel 상태 조회 기능 전체가 아니라 목록·단건 응답 안의 connections 배열입니다. 날짜가 지나면 상태를 못 보는 건 아님. 바뀌는 범위는 아래 네 요청이에요.

리소스 영향받는 요청 변경 내용
Cloudflare Tunnel GET /accounts/{account_id}/cfd_tunnel result[]connections 제거
Cloudflare Tunnel GET /accounts/{account_id}/cfd_tunnel/{tunnel_id} result.connections 제거
Cloudflare Mesh/WARP Connector GET /accounts/{account_id}/warp_connector result[]connections 제거
Cloudflare Mesh/WARP Connector GET /accounts/{account_id}/warp_connector/{tunnel_id} result.connections 제거

여기서 조금 애매한 부분도 있어요. changelog는 해당 필드를 더 이상 포함하지 않는다고 안내하지만, 일부 API 모델 설명과 예제에는 deprecated 필드나 빈 배열 설명이 남아 있습니다. 과도기 문서가 딱 맞아떨어지지 않는 상황.

그래서 회귀 테스트의 최종 기준은 connections: []가 아니라 키 자체가 없어도 정상 처리되는가로 잡는 편이 안전합니다. 전환 기간에는 기존 값, 빈 배열, 필드 부재를 모두 받아들이고 마지막에 구 필드 참조를 제거하면 돼요.

코드만 검색하고 끝내면 대시보드나 알림에서 뒤늦게 터질 수 있습니다. 아래 소비처를 같이 훑어보세요.

  • 애플리케이션 코드의 connections 존재 확인과 length 계산
  • 첫 원소를 바로 읽는 로직
  • connections를 required로 둔 역직렬화 타입
  • 대시보드 쿼리와 알림 규칙
  • 캐시 모델과 스냅샷 fixture
  • /cfd_tunnel, /warp_connector를 호출하는 배치

같은 changelog에는 CIDR 인코딩 route 엔드포인트 제거도 함께 안내돼 있습니다. 상태 점검 마이그레이션과 섞지는 말고, 같은 저장소에서 /teamnet/routes/network/{ip_network_encoded}를 쓰는지만 찾아 별도 작업으로 빼두면 깔끔함.

상태만 필요하면 목록의 status로 끝내기

전체 터널의 거친 운영 상태만 보여주는 화면이라면 GET /accounts/{account_id}/tunnels 같은 통합 목록 또는 해당 Cloudflared 목록에 남는 status를 사용하면 됩니다. List All Tunnels API가 정의한 값은 네 가지예요.

status 운영 의미
inactive 터널은 생성됐지만 실행된 적이 없음
healthy 활성 상태이며 트래픽을 서비스할 수 있음
degraded 서비스는 가능하지만 비정상 상태
down Cloudflare Edge 연결이 없어 서비스할 수 없음

connections.length === 0 같은 자체 규칙으로 상태를 만들었다면 우선 이 값으로 대체 가능한지 봅니다. 연결 상세가 필요하지 않은데 모든 터널의 /connections를 따라 호출할 이유는 없어요. 호출 수와 스키마 결합도만 늘어남.

주의할 점 하나. Cloudflare Tunnel 모니터링 문서의 상태는 cloudflared와 Cloudflare 네트워크 사이를 보여줍니다. healthy라고 해서 cloudflared가 내부 애플리케이션까지 정상적으로 연결할 수 있다는 보장은 아니에요. 내부 앱의 end-to-end 가용성이 목적이라면 Tunnel 상태와 별도 합성 모니터링이 필요합니다.

Cloudflare를 WordPress 앞단에 둔 운영 구성의 맥락은 기존 AWS Lightsail WordPress Cloudflare HTTPS 구축 글에서 이어서 볼 수 있어요. 다만 그 글은 DNS·HTTPS 구축이 목적이라 이번 Tunnel 상태 API 마이그레이션의 대체 절차는 아닙니다.

연결 상세는 전용 API의 중첩 구조로 옮기기

연결 수, connector 또는 cloudflared 버전, colo, 연결 시작 시각이 필요하다면 터널별 전용 요청으로 옮깁니다.

GET /client/v4/accounts/{account_id}/cfd_tunnel/{tunnel_id}/connections
Authorization: Bearer {API_TOKEN}

실제 토큰 값은 로그나 fixture에 남기지 않는 게 기본. account ID, tunnel UUID, origin_ip도 공개 샘플에서는 가상값으로 바꾸거나 삭제해야 해요.

URL만 교체하고 기존 타입을 그대로 재사용하면 여기서 사고가 납니다. 전용 connections APIresult[]는 연결 목록이 아니라 connector/client 목록이고, 실제 엣지 연결은 각 connector의 conns[] 아래에 들어가거든요.

result[]                         # connector/client 단위
  id
  arch
  version
  run_at
  config_version
  features[]
  conns[]                       # 해당 connector의 엣지 연결
    id / uuid
    client_id
    client_version
    colo_name
    opened_at
    origin_ip
    is_pending_reconnect

result.length를 연결 수로 표시하면 connector 수와 엣지 연결 수를 혼동합니다. 연결 목록이 필요할 때는 모든 result[].conns[]를 펼치되 어느 connector에서 온 항목인지 식별자와 메타데이터를 함께 보존하는 구조가 낫습니다.

is_pending_reconnect: true도 그냥 활성 연결로 세면 안 돼요. 이미 끊겼지만 재연결 최적화를 위해 수분간 추적되는 항목이기 때문입니다. 활성 연결 수 정책에서 따로 구분하고, 이 필드가 optional이므로 누락된 경우까지 처리해야 합니다. 이거 은근 함정.

WARP Connector는 /accounts/{account_id}/warp_connector/{tunnel_id}/connections를 사용합니다. Cloudflared와 허용 권한 및 conns 세부 필드가 일부 다르므로 같은 변환 함수를 무조건 공유하기보다 tun_type별 adapter로 분리하는 편이 안전해요.

전용 connections 응답의 conns 배열을 connector 메타데이터와 함께 펼치는 구조도

페이지네이션과 N+1 호출을 같이 정리하기

계정 전체를 점검할 때 목록 한 페이지만 읽는 가정도 버려야 합니다. 통합 터널 목록은 pageper_page를 지원하고, per_page 범위는 1~1000이에요. 응답의 result_info.page, per_page, total_count를 기준으로 마지막 페이지까지 순회합니다.

반면 전용 connections REST 문서에는 pageper_page 입력 파라미터가 명시돼 있지 않고, 공식 TypeScript·Go SDK는 이 조회를 SinglePage로 표현합니다. 반환 envelope에 optional result_info 모델이 보이더라도 목록의 페이지 옵션을 임의로 붙이지 않는 게 맞아요. 문서 생성기의 공통 envelope인지 내부 구현인지는 공식 설명이 없어 단정할 수 없습니다.

상세 조회는 결국 목록 페이지 수 + 상세가 필요한 터널 수만큼 호출을 만들 수 있어요. 모든 터널에 붙이면 전형적인 N+1 구조. 상태 화면은 status만 사용하고, 상세 패널을 열거나 비정상 터널을 진단할 때 /connections를 조회하는 식으로 범위를 줄이면 됩니다.

Cloudflare가 문서화한 기본 Client API 제한은 사용자/account token 기준 5분당 1,200회, IP 기준 초당 200회입니다. 초과하면 429가 발생하며 Ratelimit, Ratelimit-Policy, retry-after 헤더를 참고할 수 있어요. 다만 계정별 예외나 엔드포인트별 제한이 있을 수 있으니 실제 응답 헤더를 우선해야 합니다.

운영 코드에는 동시성 제한, 필요한 범위의 캐시, 429 backoff를 둡니다. API 실패를 곧바로 터널 down으로 바꾸면 인증 문제 하나가 전체 장애처럼 보일 수 있으니 401/403, 429, 연결 상태를 분리하는 것도 중요함.

읽기 권한과 회귀 테스트를 배포 조건으로 묶기

전용 connections 엔드포인트는 문서상 다음 권한의 Read 또는 Write를 허용합니다.

  • Cloudflare One Connectors Read / Write
  • Cloudflare One Connector: cloudflared Read / Write
  • Cloudflare Tunnel Read / Write

상태 점검이라면 조직 표준과 호출 범위에 맞는 Read 최소 권한을 우선하세요. API Token의 account scope가 대상 계정과 맞는지도 staging에서 확인합니다. 권한 이름과 최신 permission group은 배포 전에 API token permissions 문서에서 다시 보는 편이 마음 편-안.

직접 API를 호출해 검증한 결과가 아니라 공식 스키마에서 도출한 테스트 설계라는 점을 전제로, 최소 회귀 테스트는 아래처럼 잡을 수 있습니다.

  • 목록 fixture에 connections 키가 없어도 파싱과 상태 화면이 성공한다.
  • status 네 값과 알 수 없는 미래 값을 명시적으로 처리한다. unknown을 자동으로 down 처리하지 않는다.
  • connector가 2개이고 각 conns가 여러 개일 때 connector 수와 연결 수를 혼동하지 않는다.
  • conns가 비었거나 누락된 경우를 처리한다.
  • is_pending_reconnect가 true, false, 누락인 경우를 각각 처리한다.
  • 목록이 두 페이지 이상이어도 마지막 페이지까지 읽고 중복·누락이 없다.
  • 401/403은 인증·권한 오류, 429는 호출 제한으로 분리한다.
  • 429 재시도는 retry-after와 rate-limit 헤더를 따른다.
  • 일부 상세 조회 실패는 마지막 정상값의 시각과 stale 상태로 표시하고 전체 단절로 오판하지 않는다.
  • Tunnel이 healthy여도 내부 애플리케이션까지 정상이라고 단정하지 않는다.

connections 필드 제거에 대비한 응답 구조와 오류별 회귀 테스트 매트릭스

제거일 전에 끝내는 마이그레이션 순서

실제 작업은 아래 순서로 진행하면 됩니다.

  1. 코드, 대시보드, 알림, 캐시 타입, fixture에서 connections, /cfd_tunnel, /warp_connector 참조를 찾습니다.
  2. 각 소비처의 목적을 전체 상태, 활성 연결 수, colo·버전·connector 상세, 내부 앱 가용성으로 분류합니다.
  3. 전체 상태는 목록의 status로 바꾸고, 내부 앱 가용성은 별도 검사로 분리합니다.
  4. 상세가 꼭 필요한 터널만 /connections를 호출해 result[].conns[]를 내부 모델로 변환합니다.
  5. 목록 페이지를 끝까지 순회하고 상세 요청의 호출량을 측정합니다.
  6. API Token을 읽기 전용 최소 권한과 올바른 account scope로 staging에서 확인합니다.
  7. 동시성 제한, 캐시, 429 backoff와 오류 상태 분리를 적용합니다.
  8. connections가 아예 없는 fixture로 테스트한 뒤 짧은 호환 기간을 거쳐 구 필드 참조를 없앱니다.
  9. 2026년 10월 5일 전에 배포·관찰하고, 배포 직전 changelog와 OpenAPI 또는 SDK를 다시 확인합니다.

이번 변경은 새 URL 하나 붙이는 작업처럼 보이지만, 실제로는 상태의 의미와 응답 모델을 나누는 마이그레이션이에요. 상태만 필요한 곳은 status로 가볍게, 상세가 필요한 곳만 중첩 /connections로 옮기면 과한 호출을 피할 수 있습니다. 다만 실제 계정의 권한 조합과 호출 지연, 제거 이후 응답은 아직 확인하지 못했으니 staging 검증은 남겨둬야 함.

체크리스트를 마쳤다면 배포 직전 Cloudflare Tunnel changelogconnections API 문서에서 일정과 스키마를 다시 확인해보세요.

FAQ

2026년 10월 5일 이후 connections는 빈 배열로 남나요?

최종 구현은 필드 자체가 없어지는 경우를 정상으로 받아들여야 합니다. changelog는 목록·단건 응답이 connections를 더 이상 포함하지 않는다고 안내하지만, 일부 과도기 API 모델에는 빈 배열 설명이나 예제가 남아 있어요. 전환 중에는 기존 값, 빈 배열, 필드 부재를 모두 허용하고 제거 이후 계약은 필드 부재에 맞추는 편이 안전합니다.

터널이 Healthy인지 보려고 모든 /connections를 호출해야 하나요?

아니요. 전체 터널의 서비스 가능 상태만 필요하다면 목록의 status를 사용하면 됩니다. /connections는 연결 수, colo, 버전, connector 상세처럼 더 깊은 정보가 필요한 터널에만 호출하세요.

전용 /connections 응답에서 실제 연결 수는 어떻게 계산하나요?

최상위 result[]는 connector 배열이므로 그 길이를 연결 수로 쓰면 안 됩니다. 각 connector 아래의 conns[]를 펼쳐 계산하되 is_pending_reconnect: true인 항목을 현재 활성 연결과 구분하고, conns나 해당 플래그가 누락되는 경우도 처리해야 합니다.

터널이 1000개를 넘으면 목록은 어떻게 순회하나요?

목록 API의 page, per_page와 응답의 result_info.page, per_page, total_count를 사용해 마지막 페이지까지 읽습니다. per_page 최대값이 1000이라고 해서 계정 전체가 항상 한 번에 반환된다고 가정하면 안 돼요.

WARP Connector도 같은 마이그레이션이 필요한가요?

네. warp_connector 목록·단건 응답의 connections도 같은 날짜에 제거될 예정입니다. 다만 WARP Connector의 전용 URL과 허용 권한, conns 상세 필드는 Cloudflared와 일부 다르므로 tun_type별 adapter로 분리해 검증하는 편이 안전합니다.

비슷한 글

답글 남기기

이메일 주소는 공개되지 않습니다. 필수 필드는 *로 표시됩니다