test #426

Merged
klaus merged 415 commits from test into main 2026-06-27 00:35:30 +00:00
Showing only changes of commit d506ad9c39 - Show all commits

View File

@@ -80,6 +80,7 @@
- WebSocket 텍스트 메시지 저장/전달용 application method를 추가하고 SSE 의존성을 제거한다.
- Test: `src/test/kotlin/kr/co/vividnext/sodalive/v2/usercreatorchat/UserCreatorChatServiceTest.kt`
- Test: `src/test/kotlin/kr/co/vividnext/sodalive/v2/usercreatorchat/websocket/UserCreatorChatWebSocketHandlerTest.kt`
- Test: `src/test/kotlin/kr/co/vividnext/sodalive/v2/usercreatorchat/websocket/UserCreatorChatWebSocketHandshakeIntegrationTest.kt`
### 푸시 payload
- Modify: `src/main/kotlin/kr/co/vividnext/sodalive/fcm/FcmEvent.kt`
@@ -340,7 +341,7 @@ spring:
### Phase 1: WebSocket 의존성과 인증 handshake 기반 추가
- [ ] **Task 1.1: WebSocket 의존성 추가**
- [x] **Task 1.1: WebSocket 의존성 추가**
- Files:
- Modify: `build.gradle.kts`
- RED: `src/test/kotlin/kr/co/vividnext/sodalive/v2/usercreatorchat/websocket/UserCreatorChatWebSocketConfigTest.kt`를 추가해 `/ws/v2/user-creator-chat` handler bean 등록을 기대한다.
@@ -352,8 +353,13 @@ spring:
- Run: `./gradlew tasks --all`
- Expected: `BUILD SUCCESSFUL`
- REFACTOR: 의존성 추가 외 다른 dependency 정렬/버전 변경은 하지 않는다.
- 검증 기록:
- 무엇: `spring-boot-starter-websocket` 의존성을 추가했다.
- 왜: raw WebSocket endpoint와 handshake interceptor 타입을 사용하기 위해서다.
- 어떻게: WebSocket 타입 부재로 `compileTestKotlin` RED를 확인한 뒤 의존성을 추가하고 Phase 1 focused 테스트를 재실행했다.
- 결과: `./gradlew --no-daemon test -Dkotlin.compiler.execution.strategy=in-process --tests kr.co.vividnext.sodalive.v2.usercreatorchat.websocket.UserCreatorChatWebSocketConfigTest --tests kr.co.vividnext.sodalive.v2.usercreatorchat.websocket.UserCreatorChatWebSocketAuthInterceptorTest``BUILD SUCCESSFUL in 1m 11s`로 통과했다.
- [ ] **Task 1.2: WebSocket config와 handler 등록**
- [x] **Task 1.2: WebSocket config와 handler 등록**
- Files:
- Create: `src/main/kotlin/kr/co/vividnext/sodalive/v2/usercreatorchat/websocket/UserCreatorChatWebSocketConfig.kt`
- Create: `src/main/kotlin/kr/co/vividnext/sodalive/v2/usercreatorchat/websocket/UserCreatorChatWebSocketHandler.kt`
@@ -367,8 +373,13 @@ spring:
- Run: `./gradlew test --tests kr.co.vividnext.sodalive.v2.usercreatorchat.websocket.UserCreatorChatWebSocketConfigTest`
- Expected: `BUILD SUCCESSFUL`
- REFACTOR: CORS origin은 기존 `WebConfig`의 허용 origin 정책과 어긋나지 않게 제한한다.
- 검증 기록:
- 무엇: `/ws/v2/user-creator-chat` endpoint를 `WebSocketConfigurer`로 등록하고 `TextWebSocketHandler` 기반 handler를 추가했다.
- 왜: 채팅방 화면 진입 중 유지되는 raw WebSocket 연결 기반을 만들기 위해서다.
- 어떻게: `UserCreatorChatWebSocketConfigTest`에서 endpoint path 등록을 검증했다.
- 결과: Phase 1 focused 테스트가 `BUILD SUCCESSFUL`로 통과했다. allowed origin은 기존 `WebConfig` origin 목록과 동일하게 제한했다.
- [ ] **Task 1.3: WebSocket handshake JWT 인증 추가**
- [x] **Task 1.3: WebSocket handshake JWT 인증 추가**
- Files:
- Create: `src/main/kotlin/kr/co/vividnext/sodalive/v2/usercreatorchat/websocket/UserCreatorChatWebSocketAuthInterceptor.kt`
- Test: `src/test/kotlin/kr/co/vividnext/sodalive/v2/usercreatorchat/websocket/UserCreatorChatWebSocketAuthInterceptorTest.kt`
@@ -382,6 +393,11 @@ spring:
- Run: `./gradlew test --tests kr.co.vividnext.sodalive.v2.usercreatorchat.websocket.UserCreatorChatWebSocketAuthInterceptorTest`
- Expected: `BUILD SUCCESSFUL`
- REFACTOR: JWT parsing 로직을 새로 만들지 않고 기존 `TokenProvider`를 재사용한다.
- 검증 기록:
- 무엇: `Authorization: Bearer <token>` handshake 인증 interceptor를 추가했다.
- 왜: WebSocket session attributes에 인증 member id와 authentication을 저장해 이후 room join/message 처리에서 사용할 수 있게 하기 위해서다.
- 어떻게: `TokenProvider.validateToken(token)``TokenProvider.getAuthentication(token)`을 재사용하고, `MemberAdapter.member.id``memberId` attribute로 저장했다.
- 결과: 유효 token 성공, Authorization header 누락 실패, invalid token 실패 테스트가 Phase 1 focused 테스트에서 통과했다.
---
@@ -521,6 +537,23 @@ spring:
- Expected: `BUILD SUCCESSFUL`
- REFACTOR: close와 LEAVE_ROOM 정리 로직은 같은 private method를 사용한다.
- [ ] **Task 4.5: WebSocket client handshake 통합 테스트 추가**
- Files:
- Test: `src/test/kotlin/kr/co/vividnext/sodalive/v2/usercreatorchat/websocket/UserCreatorChatWebSocketHandshakeIntegrationTest.kt`
- Modify: `src/main/kotlin/kr/co/vividnext/sodalive/configs/SecurityConfig.kt` (필요한 경우에만)
- Modify: `src/main/kotlin/kr/co/vividnext/sodalive/v2/usercreatorchat/websocket/UserCreatorChatWebSocketAuthInterceptor.kt` (필요한 경우에만)
- RED: `@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)`에서 실제 서버 포트를 띄우고 `StandardWebSocketClient``/ws/v2/user-creator-chat`에 접속하는 테스트를 작성한다.
- RED: 유효한 `Authorization: Bearer <accessToken>` header가 있으면 handshake가 성공하고, header가 없거나 유효하지 않으면 handshake가 실패하는 테스트를 작성한다.
- RED: 유효 token은 테스트 member를 저장한 뒤 기존 `TokenProvider.createToken(...)`으로 생성해, `JwtFilter`, `SecurityConfig`, `UserCreatorChatWebSocketAuthInterceptor`가 함께 동작하는 경계를 검증한다.
- 실패 확인:
- Run: `./gradlew test --tests kr.co.vividnext.sodalive.v2.usercreatorchat.websocket.UserCreatorChatWebSocketHandshakeIntegrationTest`
- Expected: 통합 테스트 파일 부재 또는 실제 client handshake 경계 미구현으로 실패한다.
- GREEN: 테스트가 실패하면 최소 수정만 적용한다. 예를 들어 security filter가 `/ws/v2/user-creator-chat` handshake를 interceptor까지 통과시키지 못하는 경우에만 해당 경로 정책을 조정한다.
- 통과 확인:
- Run: `./gradlew test --tests kr.co.vividnext.sodalive.v2.usercreatorchat.websocket.UserCreatorChatWebSocketHandshakeIntegrationTest`
- Expected: `BUILD SUCCESSFUL`
- REFACTOR: 단위 테스트가 이미 검증하는 token parsing 세부 로직을 중복하지 않고, 실제 client handshake 성공/실패와 security/interceptor 연결 경계만 검증한다.
---
### Phase 5: 기존 SSE 제거와 REST 경계 정리
@@ -590,6 +623,8 @@ spring:
- Expected: `BUILD SUCCESSFUL`
- Run: `./gradlew test --tests kr.co.vividnext.sodalive.v2.usercreatorchat.*`
- Expected: `BUILD SUCCESSFUL`
- Run: `./gradlew test --tests kr.co.vividnext.sodalive.v2.usercreatorchat.websocket.UserCreatorChatWebSocketHandshakeIntegrationTest`
- Expected: `BUILD SUCCESSFUL`
- Run: `./gradlew test --tests kr.co.vividnext.sodalive.fcm.FcmServiceTest`
- Expected: `BUILD SUCCESSFUL`
- Run: `./gradlew ktlintCheck`