개발 slecs

Cloudflare 유휴 타임아웃이 만든 장치 플래핑, 25초 핑으로 끊다

목차

오늘 저녁 작업은 딱 하나였는데, 그 하나가 꽤 오래 머릿속에 남아 있던 녀석이었다.

증상부터 다시 짚기

릴레이 서버를 통해 연결된 디바이스들이 간헐적으로 연결이 끊겼다 붙었다 하는 플래핑(flapping) 현상이 있었다. 딱 잘라 재현되지 않고, "어? 또 끊겼네" 수준으로 넘어가던 것들이 쌓이다 보니 더 이상 무시하기 어려워졌다.

로그를 뜯어보니 패턴이 보였다. 연결이 조용한 구간 — 즉 데이터 교환이 없는 유휴(idle) 상태가 대략 100초 안팎으로 이어지고 난 뒤 끊기고 있었다. 클라이언트가 먼저 끊는 게 아니라, 중간 어딘가에서 세션을 끊어버리는 것.

원인: Cloudflare의 유휴 커넥션 정책

릴레이가 Cloudflare를 경유하는 구조인데, Cloudflare는 약 100초 동안 유효한 트래픽이 없으면 커넥션을 강제로 닫는다. 이건 Cloudflare 측의 공식적인 동작이고, 바꿀 수 없다. 내가 제어할 수 있는 건 내 릴레이가 그 전에 먼저 뭔가를 보내느냐 뿐이다.

문제는 릴레이(relay/src/main.rs)가 순수하게 데이터 패스 역할만 하고 있어서, 디바이스와 호스트 사이에 실제 페이로드가 없으면 아무것도 보내지 않았다는 것이다. 덕분에 유휴 구간이 길어지는 세션은 Cloudflare에 의해 조용히 칼질당하고, 디바이스 입장에서는 연결이 갑자기 사라진 것처럼 보이는 플래핑이 됐다.

항목
Cloudflare 유휴 타임아웃 ~100초
기존 keepalive 없음
플래핑 발생 주기 유휴 ~100s 이후 간헐적

수정 내용

해결책은 단순하다. 25초마다 호스트 방향으로 keepalive ping을 보내는 것. 100초 타임아웃에 대해 여유 있게 4배 간격으로, 어떤 네트워크 지터가 끼어들어도 한 번쯤은 실패해도 괜찮을 만큼 넉넉한 주기다.

// relay/src/main.rs — 핵심 변경 요지
// 25초 인터벌로 호스트에 keepalive ping 전송
// → Cloudflare 유휴 타임아웃(~100s) 도달 전 트래픽 유지

Rust의 비동기 타이머로 백그라운드 태스크를 붙이는 방식이라 기존 데이터 패스 로직을 건드리지 않고 추가할 수 있었다. 사이드 이펙트 없이 깔끔하게 올라갔다.

이 작업을 지금 한 이유

"언젠가 고쳐야지" 리스트에 있던 것들 중 오늘 저녁 기준으로 가장 실사용 충격이 있는 것을 골랐다. 플래핑은 디바이스 입장에서 연결 신뢰성을 떨어뜨리고, 재연결 루프를 유발하면서 불필요한 부하를 만든다. 기능 이슈가 아니라 신뢰성 이슈이기 때문에, 새 기능보다 먼저 처리하는 게 맞다고 판단했다.

수정 자체는 작지만, 이 정도 크기의 핀포인트 픽스가 묵혀 있던 사용자 경험 노이즈를 한 번에 치우는 경우가 많다. 오늘이 딱 그런 케이스였다.


🛒 이 글과 어울리는 추천 상품

*위 링크는 쿠팡파트너스 활동의 일환이며, 일정액의 수수료를 제공받을 수 있습니다.

댓글 0

첫 댓글 달아줘.