[P2P 브라우저] 모바일과 백그라운드는 왜 P2P 전송을 흔들까
데스크톱에서 파일 전송 데모가 잘 돌면 모바일도 비슷할 것 같았다. 같은 WebRTC이고 같은 DataChannel이면 차이는 화면 크기 정도라고 생각하기 쉽다. 실제로는 사용자가 잠깐 메신저를 확인하는 순간부터 조건이 바뀐다. 화면이 꺼지고, 탭이 뒤로 밀리고, OS는 배터리를 아끼고, 저장 권한은 브라우저마다 다르게 보인다. 브라우저만 있으면 나머지는 따라올 거라고 믿었다. 아래에서는 P2P을 중심으로, 깨진 가정과 다시 그은 경계를 순서대로 남긴다.

모바일 백그라운드가 커진 문제
고객 지원 관점에서도 이 구분은 중요하다. 모바일 문의는 재현이 어렵고, 사용자는 자신이 어떤 앱을 열었는지 정확히 기억하지 못할 때가 많다. support log에 background-risk와 permission-needed가 같은 trace 안에 있으면 안내 문구가 달라진다. 네트워크를 탓하기 전에 저장 권한과 탭 복귀 시각을 확인할 수 있다. 이 이름이 없으면 사용자는 대기, 실패, 재시작 가능성을 구분하지 못한다.
개발자는 DataChannel 상태를 보고 있고, 사용자는 파일이 사라졌는지 걱정한다. 둘 사이의 간격을 줄이는 일이 모바일 P2P의 절반이다. PonsWarp가 데스크톱에서 직접 전송을 잘 보여 주더라도 모바일에서 같은 문구를 그대로 쓰면 위험하다. “브라우저끼리 바로 전송합니다”라는 말은 간단하지만, 사용자가 탭을 닫아도 무조건 이어진다는 뜻으로 들릴 수 있다.
모바일에서는 직접 전송보다 안전한 중간 보관 경로가 더 나은 UX일 수 있다. 여기서 낮춰야 하는 것은 기술 목표가 아니라 사용자 기대다. 직접 경로가 가능하면 먼저 시도하되, 탭이 background로 내려가거나 저장 권한이 흔들리면 제품은 모드 전환을 말해야 한다. “상대가 돌아오면 이어받기”, “화면을 유지하면 더 빠름”, “저장 권한 확인 필요” 같은 문장은 P2P의 순수성을 약하게 만드는 문구가 아니라 실패를 설명하는 안전장치다.

처음에는 연결만 맺으면 끝날 줄 알았다
이 실험에서 중요한 결과는 “모바일도 된다”가 아니다. 어느 조건에서는 직접 전송을 약속해도 되고, 어느 조건에서는 더 안전한 대안을 보여 줘야 하는지 찾는 일이다. *모바일/브라우저 백그라운드 제약: 발견, 검증, 운영 경계를 한 장에 겹쳐 둔 흐름 노트. 파일 저장 권한과 다운로드 동작은 플랫폼마다 다르게 보인다. 데스크톱에서 다운로드가 자연스럽게 끝나는 흐름도 모바일에서는 저장 위치, 권한 요청, 브라우저 정책 때문에 다른 경험이 된다.
전송 자체가 성공했는데 저장에서 막히면 사용자는 네트워크가 아니라 제품을 의심한다. 모바일/브라우저 백그라운드 제약: 구현 전에 다시 볼 질문을 현장 노트처럼 정리한다. PonsWarp가 이 흐름을 제품에 붙인다면 모바일 배지는 기능 홍보가 아니라 조건 안내에 가까워야 한다. “모바일 지원”보다 “화면 유지 시 직접 전송, 이탈 시 이어받기 또는 임시 보관”이 더 길지만 정확하다.
기술적으로는 덜 멋져 보여도 사용자는 자신이 해야 할 행동을 더 빨리 이해한다.

전송 끊김이 선명해진 순간
모바일에서 가장 쉬운 문구는 “연결이 끊겼습니다”다. 하지만 이 문장은 많은 것을 숨긴다. 상대 피어가 사라졌는지, 내 탭이 background로 갔는지, OS가 작업을 늦췄는지, 저장 권한이 막혔는지, resume 기준이 없는지 알 수 없다. 사용자는 무엇을 다시 해야 하는지도 모른다. 모바일을 약한 데스크톱으로 보는 습관을 버리기 위한 노트다. 탭 수명, background 제한, battery 정책, resume state, permission을 한 줄에 넣지 않고 각각 다른 실패 이름으로 다룬다.
PonsWarp에서 모바일 전송을 켠다면, 멋진 직접 경로보다 끊겼을 때 사용자가 무엇을 할 수 있는지 먼저 보여 줘야 한다. 이 차이는 테스트 기기에서도 드러난다. 같은 iOS나 Android라는 말만으로 충분하지 않다. 브라우저 종류, 배터리 절약 설정, 화면 잠금 시간, 파일 다운로드 처리 방식이 모두 결과를 바꾼다. 운영 문서에는 최소한 테스트한 브라우저와 OS 버전, 절전 조건, 저장 권한 경로를 함께 적어야 한다.
그래야 나중에 “모바일에서 안 된다”는 문의가 들어왔을 때 재현 가능한 조건으로 좁힐 수 있다. 그래서 모바일 P2P를 볼 때 내 질문은 연결 성공률에서 시작하지 않는다. 모바일에서 직접 전송을 약속해도 되는 조건은 무엇인가? 직접 연결이 붙었다는 말은 탭이 계속 살아 있다는 뜻이 아니다. 사용자는 앱을 바꿨을 뿐인데 제품은 전송 상태와 저장 권한, 이어받기 기준을 동시에 잃을 수 있다.
모바일 브라우저 탭은 오래 켜진 서버가 아니다. 탭이 백그라운드로 가면 timer와 네트워크 작업이 제한될 수 있다. OS 절전 정책은 브라우저 코드가 직접 제어하기 어렵다. 이 사실을 뒤늦게 인정하면 P2P 실패가 “연결이 안 됨” 하나로 뭉친다. 먼저 인정하면 상태 이름이 달라진다. 1. 같은 파일을 데스크톱과 모바일에서 보내며 기준 시간을 잡는다.
- 수신 탭을 background로 보내고 전송량 변화를 기록한다. 3. 저장 권한을 거부했을 때
permission-needed가 남는지 본다. 4. 탭 복귀 뒤 resume token과 chunk verification으로 이어받는다. 5. 직접 전송 대신 중간 보관 경로를 제안할 기준을 정한다. P2P를 설명할 때 서버/클라이언트/사용자 중 누구 문장으로 말하는지 먼저 고르면 논쟁이 줄었다.
백그라운드 경계 나누기
배포도 한 번에 열지 않는 편이 낫다. 먼저 작은 파일과 짧은 세션에서만 모바일 직접 전송을 허용하고, 큰 파일이나 장시간 전송은 중간 보관 경로를 먼저 제안할 수 있다. 이 제한은 소극적인 선택처럼 보이지만 사용자에게 거짓 약속을 하지 않는 방법이다. 모바일 환경에서 성공률 숫자만 높이려고 실패 문구를 숨기면, 나중에 이어받기와 저장 권한 설계를 다시 갈아엎게 된다.
모바일 브라우저를 네이티브 앱처럼 상상하면 이 경계가 흐려진다. 네이티브 앱은 background 작업 권한, 알림, 파일 접근 정책을 더 넓게 설계할 수 있지만, 브라우저 탭은 사용자가 보는 표면과 OS 정책 사이에 더 얇게 놓인다. WebRTC 연결이 성립해도 JavaScript 실행, timer, 저장소 접근은 같은 속도로 유지된다고 말하기 어렵다. 그래서 모바일 P2P에서는 프로토콜 성공보다 실행 환경의 수명을 먼저 본다.
그래서 permission은 마지막 단계의 UI 문제가 아니다. 전송 전에 안내할 것, 전송 중에 보존할 것, 실패 뒤에 다시 요청할 것을 나눠야 한다. 예를 들어 큰 파일을 직접 받는 중 사용자가 앱을 전환했다면, 제품은 byte가 어디까지 안전하게 저장됐는지와 검증된 조각이 어디까지인지 알아야 한다. resume token과 chunk verification이 없으면 중간 복구가 거의 불가능하다. 모바일 브라우저 실험은 데스크톱 개발자 도구만으로 끝나지 않는다.
화면을 끄고, 앱을 전환하고, 배터리 절약 모드를 켜고, 저장 권한을 거부하고, 이동 중 네트워크를 바꿔야 한다. 직접 연결이 붙었다는 결과만으로는 실제 모바일 전송을 설명할 수 없다.
구현과 운영에 남긴 조건
- 탭이 background로 가면 timer와 네트워크 작업이 제한될 수 있음을 문구와 로그에 반영했는가.
- OS 절전 정책은 브라우저 코드가 직접 제어하기 어렵다는 전제를 테스트에 넣었는가.
- 파일 저장 권한과 다운로드 동작이 플랫폼마다 다르게 보일 수 있음을 분리했는가.
- resume token과 chunk verification 없이 이어받기를 약속하지 않는가.
- 직접 전송보다 안전한 중간 보관 경로가 더 나은 UX인 경우를 인정했는가.
- 사용자가 화면을 떠난 행동을 실패 원인으로 탓하지 않는가. 작은 제품에서는 이 기준을 완벽하게 맞추기보다 보수적으로 시작하는 편이 낫다. 직접 경로를 우선하되, 일정 시간 이상 background 상태가 이어지면 이어받기 기준을 저장하고 사용자에게 선택지를 보여 준다. 이때 선택지는 “다시 시도” 하나가 아니라 “화면 유지 후 계속”, “상대가 돌아오면 이어받기”, “임시 보관 모드 사용”처럼 분리되어야 한다. | 내부 상태 | 피해야 할 문구 | 더 나은 문구 | 다음 행동 | |---|---|---|---| |
background-risk| “네트워크 오류” | “화면이 닫혀 전송이 느려질 수 있습니다” | 앱을 다시 열기 | |permission-needed| “저장 실패” | “파일을 저장하려면 권한 확인이 필요합니다” | 권한 요청 다시 열기 | |resume-ready| “처음부터 다시 시작” | “검증된 조각부터 이어받을 수 있습니다” | 이어받기 버튼 | |cloud-handoff-offered| “P2P 실패” | “상대가 돌아오면 받을 수 있게 임시 보관할 수 있습니다” | 중간 보관 허용 | |failed-unrecoverable| “알 수 없는 오류” | “이어받을 기준이 없어 새 전송이 필요합니다” | 새 전송 시작 |
측정값은 완료율보다 중간 상태를 더 많이 봐야 한다. background 진입 후 유지 시간, permission 거절률, resume 성공률, 탭 복귀 후 재협상 시간, 저장소 쓰기 실패율이 필요하다. 여기에 사용자가 다시 누른 횟수와 support 문의 문구를 붙이면 기술 실패가 제품 언어로 바뀐다. PonsLink나 PonsWarp가 모바일 브라우저를 지원하려면 이 제약을 예외로 취급하면 안 된다. 탭이 멈추고 화면이 꺼지는 순간까지 전송 상태, 재개 조건, 사용자 문구가 같은 설계 안에 있어야 한다. '[P2P 브라우저 모바일과 백그라운드는 왜 P2P 전송을 흔들까'을 관통하는 질문은 이 섹션에서도 같았고, 답만 더 구체적이 됐다.
관측 포인트
상태 전환에는 시간 제한도 필요하다. background-risk가 몇 초 이상 지속되면 경고만 둘지, 전송 속도를 낮출지, cloud-handoff-offered로 넘어갈지 정해야 한다. 권한 요청도 마찬가지다. 사용자가 저장 권한을 거부한 뒤에도 byte를 계속 받으면 저장할 곳 없는 데이터를 모으게 된다. 반대로 너무 빨리 실패 처리하면 사용자는 잠깐의 앱 전환 때문에 전송을 잃는다. 문구는 짧아야 하지만 로그와 연결되어야 한다.
화면에 “이어서 받을 수 있습니다”라고 썼다면 내부에는 resume token, 검증된 chunk 범위, 마지막 상대 응답 시간이 남아 있어야 한다. “임시 보관할 수 있습니다”라고 썼다면 payload가 어디에 얼마나 머무는지와 만료 시간이 함께 보여야 한다. 말은 부드럽게 하더라도 약속은 구체적이어야 한다. 알림도 같은 기준으로 본다. 브라우저가 background에서 안정적으로 작업하지 못한다면, 사용자가 돌아와야 하는 시점과 이어받기 가능 시간을 알려 주는 장치가 필요하다.
꼭 네이티브 push가 아니어도 된다. 전송 화면, 공유 링크, 만료 안내, 상대방에게 보이는 상태 문구가 같은 정보를 말해야 한다. 한 화면에서는 전송 중이라고 하고 다른 화면에서는 만료됐다고 말하면 모바일 제약보다 제품 불일치가 더 큰 문제가 된다. 이 불일치를 줄이려면 모바일 상태를 서버 이벤트, 로컬 저장소, 사용자 문구가 같은 이름으로 읽어야 한다.
active-direct: 양쪽 탭이 살아 있고 직접 전송 중이다. -background-risk: 한쪽 탭이 뒤로 내려가 전송 지연 가능성이 있다. -permission-needed: 저장 권한 또는 다운로드 동작 확인이 필요하다. -resume-ready: 이어받기 token과 검증 기준이 남아 있다. -cloud-handoff-offered: 직접 전송 대신 안전한 중간 보관 경로를 제안한다. -failed-unrecoverable: 이어받을 기준이 없어 새 전송이 필요하다. | 축 | 실제로 흔들리는 것 | 제품이 말해야 할 것 | 로그에 남길 것 | |---|---|---|---| | tab life | 탭이 멈추거나 사라진다 | “화면을 다시 열면 이어받을 수 있습니다” | background 진입 시각, 복귀 시각 | | background | timer와 네트워크 작업이 제한된다 | “백그라운드에서는 전송이 느려질 수 있습니다” | 제한 이후 전송량, 재협상 시간 | | battery | OS가 절전 정책을 적용한다 | “배터리 상태에 따라 전송이 지연될 수 있습니다” | 절전 모드 여부, 대기 시간 | | permission | 파일 저장과 다운로드 동작이 달라진다 | “저장 권한을 확인해야 합니다” | 거절률, 저장소 쓰기 실패율 | | resume | 중간 상태를 되살려야 한다 | “이어서 받기 준비 중입니다” | resume token, chunk verification 결과 |
모바일에서도 데스크톱처럼 계속 열어 두면 된다고 설명하면 사용자의 실제 행동과 제품의 전송 모델이 바로 어긋난다.
마치며
데스크톱에서는 전송 창을 열어 두고 기다리는 행동을 어느 정도 기대할 수 있다. 모바일에서는 그 기대가 과하다. 사용자는 화면을 잠그고, 통화를 받고, 앱을 전환하고, 이동 중 네트워크를 바꾼다. 제품이 “탭을 계속 열어 두세요”라고 말할 수는 있지만, 그 문장은 기능 약속이 아니라 제한 고지에 가깝다. 이 표는 기술 설명을 줄이기 위한 장치가 아니다.
같은 “전송 실패”라도 재시도할 실패인지, 사용자의 행동이 필요한 실패인지, 안전한 중간 보관 경로로 바꿔야 하는 실패인지 가르는 기준이다. 이 정도로 나누면 모바일 제약을 사용자의 잘못으로 돌리지 않아도 된다. 탭을 바꾼 행동은 자연스럽다. 제품이 할 일은 그 행동 뒤에도 가능한 선택지를 정확히 남기는 것이다. 모바일 P2P의 기준은 더 강한 연결을 억지로 만드는 데 있지 않다.
직접 전송을 약속할 수 있는 조건과 포기해야 할 순간을 미리 말하는 데 있다. PonsWarp에서 이 기능을 켠다면, 첫 버튼보다 돌아왔을 때 이어받는 화면이 더 중요하다.