a7d7cf469f
2026-09-10 병원에서 600 업로드 24건이 실패했고, 앱을 다시 켜자 **올릴 길이 없어져** PC 로
꺼내 올려야 했다(39건). 사유가 셋이었고 그중 하나는 우리 쪽 결함이다.
12건 DNS 해석 실패 망
6건 TLS 인증서 신뢰 실패 망 (LTE 에서는 정상 접속 — 병원 망의 검사 프록시로 보인다)
6건 화면 이탈로 업로드 취소 **앱 결함**
## ① 화면을 떠나면 업로드가 잘렸다
측정 루프의 `launch { upload(file) }` 가 `LaunchedEffect` 스코프였다. 조합이 끝나고 화면을
떠나면 전송이 취소된다 — `The coroutine scope left the composition`. 정렬(601)은 같은 이유로
이미 오브젝트 스코프로 옮겼는데(8b3b5c0) **프로토콜(600)만 남아 있었다.**
`uploadAsync()` 를 만들어 옮겼다.
## ② [지금 업로드] 의 사정권이 한 폴더뿐이었다
`lastRunDir` 은 **이번 실행**의 폴더이고 `remember` 다. 그래서:
· 앱을 다시 켜면 null → **카드 자체가 사라진다** ← 39건이 고립된 직접 원인
· 폴더 하나만 훑음 → 어제 것은 6개 폴더에 흩어져 있었다
`allRunDirs()` · `pendingAll()` · `uploadAllPending()` 을 만들고, 화면은 진입할 때 전 폴더를
훑는다. 버튼도 **[미업로드 전부 올리기]**, 문구도 "미업로드 N건 (지난 측정 포함)".
매니페스트는 폴더마다 다르므로 `manifestParamsFor(csv)` 가 그 CSV 와 같은 폴더의 run json
에서 찾는다. 못 찾으면 null — CSV 헤더만으로도 페이로드는 만들어진다.
## ③ 망 오류 문구를 사람 말로
Java 예외를 그대로 흘리고 있었다(`Unable to resolve host ...`,
`CertPathValidatorException: Trust anchor ...`). 조작자가 할 일이 원인마다 다른데 알 수
없었다. **둘은 망을 바꾸면 되는 것이었다** — LTE 에서는 정상 접속된다.
TLS 차단 "보안 연결이 차단되었습니다 — 이 네트워크가 통신을 검사하고 있을 수
있습니다. 다른 망(LTE·테더링)으로 바꾼 뒤 [미업로드 전부 올리기] 를…
데이터는 폰에 그대로 있습니다."
DNS 실패 "서버 주소를 찾을 수 없습니다 — 인터넷이 끊겼거나 이 망이 외부 접속을…"
시간 초과 "서버 응답이 없습니다 — 잠시 뒤 다시…"
**인증서 검증을 느슨하게 하는 선택은 하지 않았다.** 의료기기에서 그건 보안 후퇴다. 대신
무엇을 해야 하는지 말해 준다 — "측정은 병원에서, 업로드는 망이 되는 곳에서"가 성립하려면
②가 있어야 하고, 이제 있다.
테스트 143개 통과.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>