
Cloudflare 공식 기술 블로그에 따르면 회사는 자사 Images 서비스 장애 분석 과정에서 Rust 오픈소스 HTTP 라이브러리 hyper의 HTTP/1 구현에 응답 본문이 일부만 전송될 수 있는 경합 조건이 있음을 확인했다. 관련 수정은 hyper GitHub 저장소의 PR #4018로 병합됐다.
문제는 Cloudflare Images binding에서 큰 이미지 변환 요청이 간헐적으로 실패하면서 드러났다. Cloudflare는 일부 요청이 HTTP 200 상태를 반환했지만 실제 이미지 데이터는 Content-Length가 예고한 크기보다 훨씬 적게 도착했다고 설명했다. 브라우저나 후단 파이프라인 입장에서는 정상 응답처럼 보이는 연결에서 본문이 중간에 끊기는 셈이다.
Cloudflare가 공개한 분석에 따르면 원인은 hyper의 HTTP/1 연결 처리 과정에 있었다. hyper는 응답 본문을 내부 버퍼에 넣은 뒤 소켓으로 flush하는데, 읽는 쪽이 잠시라도 느려져 소켓 버퍼가 가득 차면 flush가 아직 끝나지 않은 상태가 될 수 있다. 이때 연결 종료 판단이 먼저 진행되면 남은 데이터가 소켓으로 나가기 전에 shutdown이 호출될 수 있었다.
회사는 이 문제가 특정 Cloudflare 코드만의 문제라기보다 hyper 라이브러리의 HTTP/1 구현에서 발생할 수 있는 경합 조건이라고 설명했다. Cloudflare는 hyper 0.14, 1.7, 1.8 계열을 시험했지만 같은 문제가 재현됐다고 밝혔다. 다만 일반적인 curl 요청처럼 수신 측이 데이터를 빠르게 읽는 환경에서는 소켓 버퍼가 가득 차지 않아 문제가 쉽게 드러나지 않았다.
버그가 발견된 경로도 주목된다. Cloudflare는 2025년 말 Images binding 구조를 바꿔 Workers 런타임과 Images 서비스를 더 직접적으로 연결했다. 이 변화가 버그를 새로 만든 것은 아니지만, 응답을 읽는 쪽의 속도와 타이밍이 달라지면서 기존에 숨어 있던 문제가 노출됐다는 것이 회사의 설명이다.
Cloudflare는 애플리케이션 로그와 분산 추적만으로는 원인을 찾기 어려웠다고 밝혔다. 서비스 관점에서는 응답이 정상적으로 만들어지고 HTTP 200으로 나갔기 때문이다. 회사는 strace로 시스템 호출을 추적해 일부 실패 요청에서 큰 응답 중 첫 조각만 sendto로 전송된 뒤 곧바로 shutdown이 호출되는 장면을 확인했다고 설명했다.
수정 방향은 shutdown 전에 남아 있는 버퍼를 먼저 flush하도록 하는 것이다. hyper PR #4018은 “filled sockets” 상황에서 pending buffered data가 있는 연결을 종료할 수 있는 문제를 다루며, 최종적으로 poll_shutdown 경로에서 flush가 완료되도록 하는 방식으로 병합됐다. GitHub 기록상 해당 PR은 2026년 6월 11일 master 브랜치에 병합됐다.
이번 사례는 오픈소스 인프라 라이브러리의 작은 상태 전이 문제가 대규모 엣지 서비스에서 실제 데이터 손실 형태로 나타날 수 있음을 보여준다. 특히 HTTP 상태 코드와 애플리케이션 로그가 정상으로 보이는 경우에도, 소켓 버퍼와 shutdown 순서 같은 낮은 계층의 동작이 사용자 경험을 좌우할 수 있다.
다만 Cloudflare는 해당 수정이 future hyper release에 포함될 것이라고 설명했다. 따라서 hyper를 직접 사용하는 서비스 운영자는 향후 공식 릴리스 노트와 의존성 업데이트 시점을 확인할 필요가 있다. Cloudflare는 현재 내부 fork에 패치를 적용해 운영 중이라고 밝혔다.
출처: Cloudflare Blog https://blog.cloudflare.com/hyper-bug/
출처: hyper GitHub PR #4018 https://github.com/hyperium/hyper/pull/4018









