docs(dm): WebSocket lifecycle 검증을 기록한다

This commit is contained in:
2026-06-18 23:31:20 +09:00
parent 8f69c1ab82
commit f560adabfa

View File

@@ -684,7 +684,7 @@
### Phase 11: Lifecycle, reconnect, heartbeat, token 갱신 처리
- [ ] **Task 11.1: LEAVE_ROOM 후 socket close로 lifecycle 해제 전환**
- [x] **Task 11.1: LEAVE_ROOM 후 socket close로 lifecycle 해제 전환**
- Files:
- Modify: `app/src/main/java/kr/co/vividnext/sodalive/v2/main/chat/dm/DmChatRoomActivity.kt`
- Modify: `app/src/main/java/kr/co/vividnext/sodalive/v2/main/chat/dm/DmChatRoomViewModel.kt`
@@ -698,8 +698,10 @@
- 검증:
- Run: `./gradlew :app:testDebugUnitTest --tests "kr.co.vividnext.sodalive.v2.main.chat.dm.DmChatRoomActivitySourceTest" --tests "kr.co.vividnext.sodalive.v2.main.chat.dm.DmChatRoomViewModelTest" --max-workers=1`
- Expected: lifecycle stop에서 `LEAVE_ROOM` + close, 중복 방지, REST disconnect 미호출 테스트가 PASS.
- 검증 기록:
- 2026-06-18: `DmChatRoomViewModelTest``leave는 LEAVE_ROOM 전송 후 socket을 close하고 중복 호출은 무시한다` 테스트를 추가했다. 수정 전 `./gradlew :app:testDebugUnitTest --tests "kr.co.vividnext.sodalive.v2.main.chat.dm.DmChatRoomViewModelTest" --max-workers=1` 실행에서 중복 leave/close 및 이후 heartbeat/token 관련 RED 실패를 확인했다. 이후 `leaveRealtime()`에 활성 socket guard와 heartbeat/reconnect 정리를 추가해 `LEAVE_ROOM` 전송 후 socket close가 1회만 수행되도록 했다.
- [ ] **Task 11.2: WebSocket reconnect 정책 구현**
- [x] **Task 11.2: WebSocket reconnect 정책 구현**
- Files:
- Modify: `app/src/main/java/kr/co/vividnext/sodalive/v2/main/chat/dm/DmChatRoomViewModel.kt`
- Modify: `app/src/test/java/kr/co/vividnext/sodalive/v2/main/chat/dm/DmChatRoomViewModelTest.kt`
@@ -712,8 +714,10 @@
- 검증:
- Run: `./gradlew :app:testDebugUnitTest --tests "kr.co.vividnext.sodalive.v2.main.chat.dm.DmChatRoomViewModelTest" --max-workers=1`
- Expected: 화면 내부 오류 재연결, 재연결 후 `JOIN_ROOM`, 최신 메시지 동기화, 화면 밖 reconnect 취소 테스트가 PASS.
- 검증 기록:
- 2026-06-18: 기존 WebSocket failure 후 3초 재연결, 재연결 후 `JOIN_ROOM`, `JOINED` 후 최신 메시지 동기화, leave 이후 reconnect 취소 테스트를 유지하면서 reconnect 예약 실행 시 최신 token을 다시 읽도록 보강했다. `./gradlew :app:testDebugUnitTest --tests "kr.co.vividnext.sodalive.v2.main.chat.dm.DmChatRoomViewModelTest" --max-workers=1` 재실행 결과 PASS를 확인했다.
- [ ] **Task 11.3: PING/PONG heartbeat 구현**
- [x] **Task 11.3: PING/PONG heartbeat 구현**
- Files:
- Modify: `app/src/main/java/kr/co/vividnext/sodalive/v2/main/chat/dm/DmChatRoomViewModel.kt`
- Modify: `app/src/main/java/kr/co/vividnext/sodalive/v2/main/chat/dm/data/DmChatSocketClient.kt`
@@ -728,8 +732,11 @@
- 검증:
- Run: `./gradlew :app:testDebugUnitTest --tests "kr.co.vividnext.sodalive.v2.main.chat.dm.DmChatRoomViewModelTest" --tests "kr.co.vividnext.sodalive.v2.main.chat.dm.DmChatSocketClientTest" --max-workers=1`
- Expected: `PING` 주기 송신, `PONG` 수신 상태 유지, timeout reconnect, leave 시 timer 취소 테스트가 PASS.
- 검증 기록:
- 2026-06-18: `DmChatRoomViewModelTest``JOINED 이후 heartbeat는 PING을 보내고 PONG 수신 시 연결을 유지한다`, `heartbeat PONG timeout은 socket close 후 foreground 조건에서 reconnect를 예약한다`, `leave는 heartbeat timeout과 reconnect 예약을 취소한다` 테스트를 추가했다. RED 단계에서 `PING` 미전송과 timeout 미처리 assertion 실패를 확인했고, `JOINED` 이후 30초 주기 `PING`, 10초 `PONG` timeout, timeout 시 socket close 후 foreground 조건 재연결 예약, leave/onCleared heartbeat 취소를 구현했다. 서버 권장값이 없어 heartbeat 주기 30초, timeout 10초를 상수로 분리했다.
- 2026-06-18: 리뷰 게이트에서 `PONG` 수신 시 timeout을 재예약하면 다음 `PING` 전에 정상 연결도 닫힐 수 있다는 blocker가 발견됐다. `JOINED 이후 heartbeat는 PING을 보내고 PONG 수신 시 연결을 유지한다` 테스트를 `PONG` 수신 후 10초 초과, 다음 30초 `PING` 전까지 연결 유지 검증으로 강화했고, 수정 전 해당 단일 테스트가 RED로 실패함을 확인했다. 이후 `PONG` 수신 시 `heartbeatTimeoutDisposable`을 해제만 하도록 변경했고 같은 테스트가 GREEN으로 전환됨을 확인했다.
- [ ] **Task 11.4: access token refresh 시 WebSocket 재연결**
- [x] **Task 11.4: access token refresh 시 WebSocket 재연결**
- Files:
- Modify: `app/src/main/java/kr/co/vividnext/sodalive/v2/main/chat/dm/DmChatRoomViewModel.kt`
- Modify: `app/src/test/java/kr/co/vividnext/sodalive/v2/main/chat/dm/DmChatRoomViewModelTest.kt`
@@ -741,6 +748,10 @@
- 검증:
- Run: `./gradlew :app:testDebugUnitTest --tests "kr.co.vividnext.sodalive.v2.main.chat.dm.DmChatRoomViewModelTest" --max-workers=1`
- Expected: token 변경 감지, 기존 socket close, 새 Authorization header 연결, `JOIN_ROOM` 재전송, 화면 종료 시 중단 테스트가 PASS.
- 검증 기록:
- 2026-06-18: `DmChatRoomViewModelTest`에 mutable token provider 기반 `token이 변경되면 기존 socket을 close하고 새 token으로 다시 JOIN_ROOM을 보낸다`, `leave 이후 token이 변경되어도 socket reconnect를 진행하지 않는다` 테스트를 추가했다. RED 단계에서 기존 connected guard가 token 변경을 무시하는 assertion 실패를 확인했고, `connectRealtime()`에서 같은 room의 token 변경을 connected/joining 조기 return보다 먼저 감지해 기존 socket close 후 새 token으로 WebSocket handshake와 `JOIN_ROOM`을 수행하도록 수정했다. 화면 종료 후에는 `leaveRealtime()` guard로 reconnect가 진행되지 않음을 확인했다.
- 2026-06-18: Phase 11 최종 검증으로 `./gradlew :app:testDebugUnitTest --tests "kr.co.vividnext.sodalive.v2.main.chat.dm.DmChatRoomActivitySourceTest" --tests "kr.co.vividnext.sodalive.v2.main.chat.dm.DmChatRoomViewModelTest" --tests "kr.co.vividnext.sodalive.v2.main.chat.dm.DmChatSocketClientTest" --max-workers=1`, `./gradlew :app:testDebugUnitTest --tests "kr.co.vividnext.sodalive.v2.main.chat.dm.*" --max-workers=1`, `./gradlew :app:compileDebugKotlin --max-workers=1`, `./gradlew :app:ktlintCheck --max-workers=1`, `git diff --check` PASS를 확인했다. blocker 수정 후에도 `./gradlew :app:testDebugUnitTest --tests "kr.co.vividnext.sodalive.v2.main.chat.dm.*" --max-workers=1`, `./gradlew :app:compileDebugKotlin --max-workers=1`, `./gradlew :app:ktlintCheck --max-workers=1`, `git diff --check` PASS를 재확인했다. `ktlintCheck`에서는 기존 `.editorconfig``disabled_rules` deprecation warning만 출력됐다.
- 2026-06-18: Phase 11 코드 리뷰 및 재검증을 수행했다. `DmChatRoomViewModel``LEAVE_ROOM` 후 close, 중복 leave 방지, reconnect 예약 시 최신 token 사용, `JOINED` 이후 heartbeat 시작, `PONG` 수신 시 timeout 해제, heartbeat timeout 후 close/reconnect, token 변경 시 기존 socket close 후 새 token으로 `JOIN_ROOM` 재전송 흐름을 재검토했고 blocking issue는 발견하지 못했다. 재검증으로 `./gradlew :app:testDebugUnitTest --tests "kr.co.vividnext.sodalive.v2.main.chat.dm.DmChatRoomActivitySourceTest" --tests "kr.co.vividnext.sodalive.v2.main.chat.dm.DmChatRoomViewModelTest" --tests "kr.co.vividnext.sodalive.v2.main.chat.dm.DmChatSocketClientTest" --max-workers=1`, `./gradlew :app:testDebugUnitTest --tests "kr.co.vividnext.sodalive.v2.main.chat.dm.*" --max-workers=1`, `./gradlew :app:compileDebugKotlin --max-workers=1`, `./gradlew :app:ktlintCheck --max-workers=1`, `git diff --check` PASS를 확인했다. 최초 샌드박스 Gradle 실행은 `~/.gradle` wrapper lock 파일 접근 제한으로 실패해 승인된 Gradle 실행으로 재검증했다. Gradle deprecation warning은 출력됐지만 실패는 없었다.
### Phase 12: 푸시 진입과 제거 endpoint 회귀 검증