Caddy 뒤에서 DiscourseHub 및 iOS Safari PWA용 Multipath TCP (MPTCP)

다음은 Caddy in front of app’s Nginx via Docker Compose 토론의 이어서입니다:

이전에 Discourse의 nginx 컨테이너 앞에 Caddy를 실행하여 HTTP/3와 QUIC 0-RTT를 제공하기 위한 논의를 진행한 바 있습니다. 이번에는 이와 관련이 있지만 별개의 질문을 조사해 보고 있습니다. 즉, Wi-Fi와 셀룰러 네트워크 간에 이동하는 iOS 사용자의 연결 연속성을 개선하기 위해 Multipath TCP(MPTCP)가 도움이 될 수 있는가 하는 것입니다.

이전 작업은 주로 초기 페이지 로딩 성능에 초점을 맞추었습니다. 이번 질문은 다릅니다. 저는 다양한 활동을 전환하면서 개인 Discourse 학습 아카이브에 정기적으로 접근하는데, 연결이 끊기거나 버퍼링이 발생하면 중요한 정보에 접근하는 데 지연이 생길 수 있습니다.

질문 배경

일부 장소에서는 Wi-Fi가 안정적이지만 셀룰러 수신 상태가 나쁘고, 다른 장소에서는 그 반대인 경우가 있습니다.

일반적인 iOS 네트워크 전환은 항상 제가 필요한 수준의 연속성을 제공하지는 못했습니다. 저는 이미 연결 회복력을 위해 별도의 네트워크 본딩/페일오버 기술을 사용하고 있지만, iOS 클라이언트와 제 Discourse 서버 간에 이러한 연속성의 일부가 네이티브로 달성될 수 있는지 이해하는 데 관심이 있습니다.

특히 대역폭을 두 개의 연결로 합산하는 것보다는, 연결 핸드오버와 요청 정체를 피하는 것에 관심이 있습니다.

지금까지 발견한 내용

Linux MPTCP 호환성 문서에 따르면, 운영체제 지원 여부에 따라 Caddy v2.10.0 이후 버전은 기본적으로 MPTCP를 지원합니다.

Apple의 MPTCP 문서는 애플리케이션이 URLSessionConfiguration을 통해 MPTCP를 선택적으로 사용할 수 있는 방법을 설명합니다.

그러나 Apple Developer Forums의 설명에서 WKWebView는 동등한 MPTCP 구성 옵션을 노출하지 않는다는 점을 발견했습니다.

이로 인해 HTTP/3 over QUIC가 사용 가능한 경우에도 DiscourseHub, Safari 또는 설치된 iOS PWA가 MPTCP의 혜택을 받을 수 있는지 불확실합니다.

확인된 서버 환경

읽기 전용 명령을 사용하여 프로덕션 VPS를 확인했으며, 구성은 변경하지 않았습니다.

  • 리버스 프록시: Caddy v2.11.4, 공식 caddy:2.11.4 Docker 이미지

  • 호스트: Ubuntu, Linux 커널 6.8.0-146-generic

  • 호스트 MPTCP: net.mptcp.enabled = 1

  • 컨테이너 MPTCP: /proc/sys/net/mptcp/enabled = 1

  • Docker 네트워크: caddy_default, 드라이버 bridge, 옵션 {}

  • Go 환경: GODEBUG 미설정

  • 게시된 포트: IPv4 및 IPv6에서 TCP 80, TCP 443, UDP 443

Discourse의 nginx는 Caddy 뒤에 위치하며, Caddy가 공개 HTTPS 및 HTTP/3 엔드포인트를 제공합니다.

이러한 확인 결과 서버에는 MPTCP 지원의 기본 전제 조건이 갖춰져 있는 것으로 보이지만, Docker의 게시 포트 포워딩을 통한 실제 MPTCP 협상이 검증되지는 않았습니다.

질문

  1. DiscourseHub: iOS 네트워킹이 MPTCP를 요청할 수 있는 구성 요소를 사용합니까, 아니면 주요 웹 콘텐츠가 이 기능을 노출하지 않는 네트워킹 API를 통해 처리됩니까?

  2. Safari 및 설치된 PWA: Discourse에 DiscourseHub, Safari, 설치된 iOS PWA를 통해 접근하는 것 사이에 차이가 있습니까? 클라이언트가 MPTCP를 명시적으로 요청해야 하는지, 아니면 이러한 접근 방식 중 어떤 것이 투명하게 혜택을 받을 수 있는지 궁금합니다.

  3. Docker 네트워킹: 브리지/NAT 구성이 초기 MPTCP 협상 및 추가 서브플로우를 유지할 수 있습니까, 아니면 이것이 연결을 일반 TCP로 되돌리게 할 수 있습니까?

  4. HTTP/3 대 MPTCP: HTTP/3가 UDP 기반의 QUIC를 사용하므로, 네트워크 전환 시 QUIC 연결 마이그레이션이 동등한 수준의 연속성을 제공할 수 있습니까? 이 상황에서 MPTCP 기반 HTTP/2와 QUIC 기반 HTTP/3 사이에 실질적인 차이가 있습니까?

  5. Discourse 측 복구: 기본 네트워크가 변경될 때 중단된 요청을 복구하기 위한 Discourse 또는 iOS 클라이언트 내 기존 메커니즘이 있습니까? iOS 클라이언트가 실제로 어떤 전송 프로토콜을 사용 중인지 확인하는 권장 방법이 있습니까?

Discourse 자체가 여러 네트워크 인터페이스를 관리해야 한다고 제안하는 것이 아닙니다. iOS 클라이언트, 전송 프로토콜, Docker/Caddy, Discourse 간에 책임이 어디에 있는지, 그리고 활용할 수 있는 기존 기능이 있는지 이해하려고 노력하고 있습니다.

제 이해에 대한 지적이나 교정해 주시면 감사하겠습니다.

감사합니다!

후속: 중단된 iOS 게시물 편집 및 HTTP/3 연결 연속성

제가 이전에 질문했던 연결 연속성 문제의 실제 사례를 이제 마주하게 되었습니다.

2026년 10월 21일, iPhone 16 Pro에서 Safari PWA를 사용하여 제 개인 Discourse 인스턴스에서 게시물을 편집하던 중 파란색 저장 중(Saving) 바가 멈춰 버렸습니다. 저는 방금 강의 노트를 음성 입력으로 추가한 상태였습니다.

편집기(composer)에 더 이상 접근할 수 없었으며, 파란색 저장 중 바를 터치해도 마찬가지였습니다. 따라서 저장되지 않은 텍스트를 다른 곳으로 복사할 수 없었습니다.

보통보다 긴 시간 동안 기다린 후, 셀룰러 네트워크 연결을 시도하기 위해 Wi-Fi를 수동으로 비활성화했습니다. 페이지는 즉시 변하지 않았고, 이후의 탐색 시도도 모두 멈춘 것처럼 보였습니다.

그 후 Caddy와 nginx 로그 및 해당 게시물의 수정 이력을 확인했습니다.

BST 12:20:08 시점:

  • Caddy는 대학 Wi-Fi 연결에서 온 HTTP/3 PUT /posts/70695 요청을 기록했으며, 요청 본문 1,000바이트 전체는 수신되었으나 상태 코드는 0이었습니다.

  • nginx는 해당 요청을 HTTP 400으로 기록했으며, Discourse 라우트나 업스트림 처리 시간이 기록되지 않았습니다.

  • 셀룰러 연결에서 발생한 다른 두 개의 iPhone 요청도 같은 초에 HTTP 400 응답을 받았습니다.

  • 그 시점에 성공적으로 기록된 게시물 수정본은 없었습니다.

이후 BST 12:20:55에 이루어진 다음 편집은 성공했지만, 음성 입력으로 작성한 텍스트는 사라져 있었습니다.

또한 BST 12:19:44에 Discourse 초안 자동 저장이 성공적으로 수행되었으나, 그 안에 누락된 텍스트가 포함되어 있었는지 확인할 수는 없습니다.

Wi-Fi를 수동으로 비활성화하는 것이 미완료된 요청들을 중단시켰을 수 있다는 점은 이해합니다. 하지만 원래의 저장 작업은 제가 네트워크 연결을 변경하기 전에 이미 멈춰 있는 상태였습니다.

이는 제 원본 게시물과 관련된 두 가지 질문을 제기합니다:

  1. QUIC 연결 마이그레이션: iOS 브라우저가 새로운 연결을 설정하거나 미완료된 요청을 포기하는 대신 기존 HTTP/3 연결의 마이그레이션을 시도했는지 여부를 파악하는 권장 방법이 있습니까?

  2. Discourse 편집기 복구: 게시물 편집 요청이 멈추거나 중단될 경우, 편집기는 ‘저장 중’ 상태 뒤에 가려져 접근 불가능한 상태로 유지되는 것이 정상적인가요? 저장되지 않은 텍스트를 보존해야 할 타임아웃, 재시도 또는 복구 메커니즘이 이미 존재합니까?

저는 연결성을 회복하려고 시도하기 전에 편집기로 돌아가서 제 작업을 복사할 수 없었기 때문에 특히 두 번째 질문에 관심이 많습니다.

이 사고로 인해 Caddy, nginx 또는 HTTP/3 설정을 변경하지 않았습니다. 현재까지의 증거로는 초기 저장 작업이 왜 멈췄는지 아직 명확히 식별할 수 없기 때문입니다.