a10d4b9517
병렬 진단 (BLE/thread + Compose lifecycle + null safety) 결과 HIGH
심각도 12건 중 crash 유발 가능성 높고 저비용 고효과인 것 우선 처리.
**H4 — coroutine leak**
- PiezoMonitoringView.kt BleDebugPanel: `while(true) { delay/refresh }` →
`while(isActive)`. LaunchedEffect 취소 후에도 refreshTick++ 이 계속
돌아 GC 방해.
- BladdyRiveView.kt 2곳: 동일 패턴 → isActive 로 통일.
**H1 — BleManager postDelayed 미취소**
- `fwFallbackTimer` (4초 mfv? fallback) + `cccdRetryTimer` (500ms CCCD
재시도) 를 Runnable 참조로 저장. disconnect / GATT_ERROR / watchdog
timeout 3곳에서 handler.removeCallbacks 로 명시적 취소.
- 이전에는 disconnect 후에도 4초 후 sendFirmwareVersionQuery() 가 발동
→ 이미 close 된 GATT 에 write → silent exception → state 오염.
**H2 — MeasurementService 콜백 leak**
- performNirsMeasurement/performPiezoMeasurement 는 singleton 에서
콜백 대입만 하고 정리 안 함. Self-clearing lambda 로 응답 1회 처리
후 자동 null. 시작 시 이전 stale 콜백도 clear.
- stop() 에서도 대기 중 콜백 취소.
**H3 — Watchdog race condition**
- watchdog thread 가 GATT disconnect/close + characteristic null 을
binder thread 에서 직접 실행 → UI thread 의 sendRaw 와 race.
- 정리 전부를 handler.post 로 UI thread 에 위임 → single-threaded.
- fwFallback/cccdRetry timer 도 여기서 함께 취소.
**H6 — PiezoMonitoringView measure() closure leak**
- DisposableEffect 에 piezoCollector.onMultiChannelComplete 정리 추가.
measure() 함수 안에서 이 콜백에 measureScope + channels + outer
state 를 다수 capture → 화면 이탈 후에도 GC 방해 + 재진입 시 stale
closure 가 새 상태 오염 위험.
**H9 — UrineCameraScreen NPE 위험**
- LaunchedEffect 안 while 루프에서 `currentDetection!!` 이 다른 recompose
가 detection 을 null 로 만들면 NPE. Local val snapshot 으로 fix.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>