hotfix: DB 테이블에 comment 추가 및 ClaudeClient 프롬프트 개선#554
Conversation
* feat: 채팅방 멤버 조회 응답 DTO 추가
- ChatRoomMemberResponse: 개별 멤버 정보 (userId, name, imageUrl, isOwner, joinedAt)
- ChatRoomMembersResponse: 멤버 목록 래퍼
클라이언트가 채팅방 참여자 정보를 확인할 수 있도록 응답 객체 정의
* feat: 활성 멤버 조회 Repository 메서드 추가
- findActiveMembersByChatRoomId: 채팅방 ID로 활성 멤버 조회
- JOIN FETCH로 User 정보를 한 번에 로딩 (N+1 방지)
- leftAt IS NULL 조건으로 나간 멤버 필터링
* feat: 채팅방 멤버 조회 Service 로직 구현
- getChatRoomMembers: 멤버 목록 조회 비즈니스 로직
- validateMembership: existsByChatRoomIdAndUserId로 권한 검증
- toMemberResponse: Entity → DTO 변환 (createdAt을 joinedAt으로 매핑)
비멤버 접근 시 FORBIDDEN_CHAT_ROOM_ACCESS 예외 발생
* feat: 채팅방 멤버 조회 API 엔드포인트 추가
- GET /chats/rooms/{chatRoomId}/members 엔드포인트 추가
- ChatApi 인터페이스: Swagger 문서화 (설명, 에러 코드)
- ChatController 구현체: @userid로 사용자 ID 주입
채팅방 접속 시 해당 방의 멤버 목록을 조회할 수 있는 API 제공
* test: 채팅방 멤버 조회 Service 단위 테스트 추가
- 멤버 조회 성공 케이스 검증
- 비멤버 접근 시 FORBIDDEN 예외 발생 검증
- 나간 멤버는 조회되지 않음 검증
Mockito를 사용하여 Repository 의존성 모킹
* refactor: 불필요한 주석과 import 제거
- Service: WHAT 설명 주석 제거 (메서드명이 충분히 표현)
- Service: 코드 변경 이력 주석 제거
- Test: 사용되지 않는 any import 제거
코드 리뷰 피드백 반영하여 가독성 개선
* feat: 탈퇴한 유저 필터링 추가
- getChatRoomMembers: 탈퇴한 유저(deletedAt != null) 제외
- Stream filter로 deletedAt == null인 멤버만 변환
탈퇴한 사용자는 채팅방 멤버 목록에 노출되지 않음
* feat: 어드민 시스템 어드민 방 멤버 조회 권한 추가
- getChatRoomMembers: 현재 사용자 정보를 UserRepository에서 조회
- validateMembership: 어드민이 시스템 어드민 방 조회 시 권한 검증 스킵
- NOT_FOUND_USER import 추가
- 테스트: UserRepository mock 설정 추가
어드민은 시스템 어드민 방의 멤버 목록을 조회할 수 있음
* fix: 존재하지 않는 채팅방 조회 시 404 반환
- getChatRoomMembers: 채팅방 존재 여부를 멤버십 검증 전에 확인
- 존재하지 않는 채팅방: NOT_FOUND_CHAT_ROOM (404)
- 비멤버 접근: FORBIDDEN_CHAT_ROOM_ACCESS (403)
- validateMembership 파라미터를 ChatRoom으로 변경
- 테스트: ChatRoomRepository mock 설정 추가
잘못된 순서로 인해 존재하지 않는 방도 403이 뜨던 문제 해결
* chore: 코드 포맷팅
* fix: 나간 멤버 권한 검증 로직 수정
- existsActiveByChatRoomIdAndUserId 메서드 추가 (leftAt IS NULL 조건)
- validateMembership에서 활성 멤버만 조회 가능하도록 변경
- 나간 멤버 접근 시 FORBIDDEN 예외 발생 테스트 추가
나간 멤버가 여전히 멤버로 인식되는 문제 해결
* test: ChatRoomMembershipService 테스트 커버리지 보강 - 멤버십 서비스의 public 메서드별 정상·예외 분기를 테스트로 고정해 회귀를 막는다 - 중복 생성과 접근 권한 같은 비정상 흐름도 함께 검증해 실제 서비스 로직의 의도를 드러낸다 - lastReadAt 갱신 기준과 system-admin 예외 경로를 명시적으로 확인해 경계 조건 누락을 방지한다 * chore: 코드 포맷팅 * chore: 코드 포맷팅 * test: 리뷰 코멘트의 primitive 타입 제안을 반영 - null 가능성이 없는 테스트 지역 변수는 primitive 타입으로 정리해 불필요한 boxing 경고를 없앤다 - roomId 선언을 int로 통일해 정적 분석 코멘트를 반영하면서 기존 테스트 동작은 그대로 유지한다 - 대상 테스트를 다시 실행해 리뷰 반영 이후에도 병합된 테스트 파일이 정상 동작함을 확인한다
- Logback 롤링 설정이 새로 생성되는 일별 로그를 즉시 gzip으로 압축하도록 조정 - 운영 중 특정 날짜 로그를 파일 단위로 확인하기 쉬운 구조는 유지하면서 디스크 사용량을 줄이도록 선택 - 별도 배치 압축 작업 없이도 backend 로그와 scheduler 로그가 동일한 방식으로 보관되도록 맞춤
|
Important Review skippedAuto reviews are disabled on base/target branches other than the default branch. Please check the settings in the CodeRabbit UI or the ⚙️ Run configurationConfiguration used: Path: .coderabbit.yaml Review profile: ASSERTIVE Plan: Pro Run ID: You can disable this status message by setting the Use the checkbox below for a quick retry:
✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
|
🧪 JaCoCo Coverage Report (Changed Files)Summary
Coverage by File
|
roomMatches와 동일하게 messageMatches 응답에도 읽지 않은 메시지 수와 알림 뮤트 여부를 포함하도록 수정 Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* fix: 완료된 SSE emitter 전송 예외를 정리하도록 처리 - 이미 complete된 emitter에 send를 시도하면 IllegalStateException이 발생할 수 있어 알림 전송 자체보다 끊어진 연결 정리를 우선하도록 변경 - IOException만 completeWithError로 마무리하고 IllegalStateException은 emitter 제거로만 끝내 이미 종료된 emitter를 다시 종료하면서 예외가 전파되는 상황을 막음 - 완료된 emitter가 맵에 남아 있어도 예외 없이 정리되는 단위 테스트를 추가해 재연 경로를 고정하고 회귀를 방지 * fix: SSE emitter 종료 경합 예외를 추가로 흡수 - send 실패 후 completeWithError 호출도 이미 종료된 emitter와 경합할 수 있어 정리 단계의 예외가 다시 상위로 전파되지 않도록 별도 보호 구문을 추가 - 알림 전송 실패 처리의 목적은 끊어진 emitter를 제거하는 것이므로 종료 경쟁에서 생기는 IllegalStateException은 로그만 남기고 삼키도록 선택 - 기존 단위 테스트를 다시 실행해 알림 inbox SSE 경로가 회귀 없이 유지되는지 확인 * test: 완료된 SSE emitter 테스트를 결정적으로 고정 - subscribe 경로의 completion callback 타이밍에 따라 테스트가 false positive가 될 수 있어 완료된 emitter를 직접 주입하는 방식으로 재현 조건을 고정 - 이번 테스트의 목적은 IllegalStateException 정리 분기를 안정적으로 검증하는 것이므로 구독 로직 부수효과보다 완료된 emitter 상태 자체를 최소 셋업으로 구성 - 수정 후 NotificationInboxSseService 단위 테스트를 다시 실행해 회귀 없이 통과함을 확인
* chore: OpenTelemetry Java agent 배선을 제거해 배포 이미지를 단순화 - Docker 이미지와 stage/prod 배포 워크플로우에서 OTel Java agent 의존성을 함께 제거해 런타임 추적 구성을 저장소 밖으로 정리한다. - CI 빌드가 더 이상 agent 캐시, checksum, 런타임 전용 환경변수 해제 흐름에 기대지 않도록 바꿔 이미지 빌드 경로를 단순하게 유지한다. * chore: Prometheus 노출 설정을 제거해 백엔드 모니터링 의존성을 정리 - Prometheus registry 의존성과 별도 monitoring 설정 파일을 제거해 애플리케이션이 더 이상 메트릭 수집 구성을 내장하지 않도록 정리한다. - Docker healthcheck가 여전히 /actuator/health 를 사용하므로 actuator 는 유지하고, 배포 안정성에 직접 영향이 큰 health 경로만 남긴다. * chore: 저장소에서 monitoring 스택 배포 자산을 제거 - Prometheus, Grafana, Loki, Promtail 배포 워크플로우와 compose 자산을 함께 제거해 저장소가 더 이상 별도 모니터링 스택을 관리하지 않도록 정리한다. - monitoring 전용 env 예외와 타깃 갱신 스크립트까지 함께 삭제해 남은 운영 진입점을 줄이고 제거 범위를 한 커밋 안에 묶는다.
* chore: 로그 추적 상관관계를 정리하고 OTel 흔적을 제거 - 요청 단위 추적이 로그와 비동기 작업 경계에서 끊기지 않도록 requestId 응답 헤더와 MDC 전파를 추가했다 - Datadog과 기존 MDC 키를 함께 읽는 로그 패턴으로 맞춰 배포 환경 차이 때문에 trace 상관관계가 깨지는 상황을 줄였다 - Dockerfile, 예시 환경변수, 배포 워크플로우에서 OpenTelemetry agent 관련 설정을 제거해 현재 운영 기준과 맞지 않는 추적 흔적이 남지 않게 했다 - 관련 단위 테스트를 추가하고 실행해 로깅 상관관계와 설정 회귀를 방지했다 * fix: CORS에서 request id 응답 헤더를 노출 - 응답에 내려주는 X-Request-ID를 브라우저가 읽지 못하면 프론트와 서버 로그를 같은 요청으로 묶기 어려워진다 - WebConfig의 exposedHeaders에 X-Request-ID를 추가해 cross-origin 환경에서도 요청 상관관계 헤더를 읽을 수 있게 했다 - 설정 회귀를 막기 위해 CORS 등록값을 직접 검증하는 단위 테스트를 추가했다 * fix: request id 헤더를 검증 후 로그에 반영 - 클라이언트가 보낸 X-Request-ID를 그대로 신뢰하면 로그 포맷 손상과 추적 품질 저하가 생길 수 있다 - request id를 trim한 뒤 허용 문자와 길이를 검증하고 실패하면 새 값을 발급하도록 바꿔 응답 헤더, 로그, MDC가 같은 정제된 값을 쓰게 했다 - 유효한 값, 공백 포함 값, 잘못된 값을 각각 검증하는 단위 테스트를 추가해 입력 검증 회귀를 막았다 * fix: Datadog 로그 패턴을 canonical key로 정리 - 여러 MDC 키를 이어붙이면 trace와 span 값이 하나의 문자열처럼 보일 수 있어 로그 파싱과 추적 연결이 불안정해진다 - 운영 로그 패턴을 dd.trace_id와 dd.span_id 기준으로 단순화해 한 종류의 canonical key만 출력하도록 정리했다 - 설정 파일 문자열 포함 여부가 아니라 실제 패턴 렌더링 결과를 검증하는 테스트로 바꿔 로그 포맷 회귀를 막았다 * chore: 코드 포맷팅
* fix: 채팅방 마지막 메시지 메타데이터를 DB에 즉시 동기화 - chat_room.last_message_*가 null로 남아 채팅방 목록과 실제 메시지 상태가 어긋나는 문제를 막는다 - 메시지 저장 직후 chat_room 메타데이터를 명시적으로 업데이트해 영속성 컨텍스트 clear 경로에 의존하지 않도록 정리한다 - 회원가입 환영 메시지처럼 같은 패턴을 쓰는 경로도 함께 맞춰 신규 방의 초기 메타데이터 누락을 방지한다 - 기존 운영 데이터는 Flyway 백필 마이그레이션과 회귀 테스트로 함께 보강해 재발을 막는다 * chore: 코드 포맷팅 * refactor: 마지막 메시지 동기화 코드를 읽기 쉽게 정리 - sendMessage의 명시적 readOnly=false 표기를 기본 @transactional로 단순화해 클래스 레벨 설정과의 관계만 남긴다 - ChatRoomRepository updateLastMessage 시그니처 타입 표기를 정리해 읽는 부담을 줄인다 - UserService의 환영 메시지 경로도 syncLastMessage 헬퍼를 사용하도록 맞춰 채팅 메타데이터 갱신 책임을 일관되게 유지한다 * fix: 리뷰 지적 반영해 마지막 메시지 갱신 조건을 보강 - last_message 메타데이터 갱신 쿼리에서 clearAutomatically를 제거해 direct room 복구 흐름의 엔티티 변경이 detach로 유실되지 않게 한다 - 최신 메시지보다 오래된 트랜잭션이 chat_room 마지막 메시지 요약을 덮어쓰지 못하도록 messageId tie-breaker 조건을 추가한다 - direct room 재노출과 조건부 메타데이터 갱신을 테스트로 고정해 리뷰에서 지적된 회귀를 막는다 * fix: 마지막 메시지 동기화의 자기 자신 비교를 제외 - 마지막 메시지 갱신 조건에서 현재 저장한 메시지 자신은 비교 대상에서 제외해 DB timestamp 정밀도 차이로 인한 오판을 막는다 - direct 채팅방 목록과 재입장 시나리오가 chat_room.last_message_* 컬럼에 의존하므로 간헐적으로 이전 메시지가 남는 상태를 방지한다 - CI에서 흔들리던 채팅방 나가기/마지막 메시지 메타데이터 테스트와 jacoco 경로를 로컬에서 다시 검증했다
* docs: 채팅 도메인 정책 가이드를 추가 - 채팅 도메인 작업 전에 AI가 먼저 읽어야 할 정책 중심 가이드를 chat 하위 AGENTS.md로 정리했다. - direct, group, club group, SYSTEM_ADMIN 문의방의 차이와 목록 요약, 읽음, 멤버십, 검색, 초대 정책을 한 문서에 모아 회귀 포인트를 드러냈다. - 마지막 메시지, unreadCount, visibleMessageFrom, 문의방 재사용처럼 수정 시 쉽게 놓치는 연쇄 영향을 명시해 안전한 변경 기준을 만들었다. * test: 채팅 정책 회귀 테스트를 보강 - 문의방 멤버 목록 조회, 문의방 admin 뮤트, 일반 group 검색 제외를 통합 테스트로 추가해 문서화한 정책을 직접 잠갔다. - 테스트 작성 과정에서 문의방 senderId 표현 정책이 문서처럼 단정적이지 않다는 점을 확인해 AGENTS 문구를 실제 동작 기준의 주의사항으로 낮췄다. - 문서와 테스트를 함께 조정해 채팅 도메인 가이드가 현재 구현과 어긋난 전제를 주입하지 않도록 정리했다. - 검증은 ChatApiTest 단위로 실행해 새 케이스와 기존 채팅 API 시나리오가 함께 통과하는지 확인했다. * docs: 문의방 senderId 문구 실제 동작 기준으로 조정 * test: ChatApiTest 타입 참조를 import로 정리 - parseChatRoomId와 extractRoomIds에서 fully-qualified 타입 참조를 제거해 테스트 가독성을 높였다. - MvcResult, JsonNode, ArrayList import를 추가하고 시그니처와 지역 변수 선언을 단순 타입으로 맞췄다. - 로직은 바꾸지 않고 표현만 정리해 리뷰 지적을 반영했다.
* docs(club): add club domain guide * test(club): add unit coverage for domain policies * chore: 코드 포맷팅 * test: 리뷰 코멘트 반영을 위해 club 권한 검증 근거를 보강 - 동아리 도메인 가이드에서 회원 제거 권한과 club_group 접근 검증 기준을 실제 구현 흐름에 맞춰 명확히 정리했다. - 어드민 비회원 사용자가 leader 권한 검증을 우회하는 정책은 서비스 테스트 목 대신 검증기 단위 테스트로 고정해 책임 경계를 분리했다. - removeMember 서비스 테스트에는 validateLeaderAccess 위임 검증을 추가해 서비스가 권한 판단을 자체 구현으로 우회하지 않도록 막았다. * chore: 코드 포맷팅
* fix: 운영 환경에서 Swagger를 비활성화 - 운영 서버에서 API 명세와 Swagger UI가 외부에 노출되지 않도록 prod 프로필에서 springdoc을 끈다 - Swagger 관련 Bean과 커스텀 initializer 컨트롤러도 prod에서는 생성되지 않게 막아 우회 노출 가능성을 줄인다 - stage/local 개발 편의성은 유지하고, 운영 환경에만 최소 범위로 적용한다 * chore: 코드 포맷팅
🔍 개요
🚀 주요 변경 내용
study_timer,study_time_*관련 테이블 설명 추가💬 참고 사항
✅ Checklist (완료 조건)