Skip to content

feat(Document): 스웨거 정리 및 스웨거 페이지별 그룹 처리(#78)#174

Merged
jaehyeok-code merged 2 commits intodevfrom
feat/#78
Aug 26, 2025
Merged

feat(Document): 스웨거 정리 및 스웨거 페이지별 그룹 처리(#78)#174
jaehyeok-code merged 2 commits intodevfrom
feat/#78

Conversation

@jaehyeok-code
Copy link
Contributor

@jaehyeok-code jaehyeok-code commented Aug 26, 2025

Summary by CodeRabbit

  • New Features

    • 채팅·알림에 Redis Pub/Sub 재활성화로 실시간 전달 안정성/확장성 향상(웹소켓 병행)
    • 채팅방 알림 페이로드에 type=ALERT 및 content 필드 추가
  • Documentation

    • 채팅·검색·드래프트·선수 등 다수 컨트롤러에 Swagger/OpenAPI 주석 추가
    • OpenAPI 그룹 문서 구성(채팅, 채팅 검색, 유저, 드래프트, 선수, 선수 캐시, 선수 검색, 매치, 팀, 라운드)
  • Bug Fixes

    • 드래프트 스쿼드 한도 조회 API 파라미터명 수정(elementTypeId)

@jaehyeok-code jaehyeok-code self-assigned this Aug 26, 2025
@jaehyeok-code jaehyeok-code added documentation Improvements or additions to documentation enhancement New feature or request labels Aug 26, 2025
@coderabbitai
Copy link

coderabbitai bot commented Aug 26, 2025

Caution

Review failed

The pull request is closed.

Walkthrough

Redis 기반 채팅 Pub/Sub 구성과 사용을 재활성화했다. 메시지/알림 흐름에 Redis 퍼블리셔를 주입해 발행하도록 변경했다. 다수의 컨트롤러에 OpenAPI/Swagger 문서를 추가하고, OpenApiConfig에 그룹 구성을 도입했다. 일부 요청 DTO/파라미터 정의를 명시화했다.

Changes

Cohort / File(s) Summary of changes
Redis Pub/Sub 활성화
backendProject/.../chat/bus/ChatRedisPublisher.java, backendProject/.../chat/bus/ChatRedisSubscriber.java, backendProject/.../chat/bus/RedisPubSubConfig.java
주석 처리된 @Component/@Configuration을 복구하여 스프링 빈 활성화. 퍼블리셔/서브스크라이버 및 리스너 컨테이너 구성 재가동. 로직 변경 없음.
채팅 발송 경로 Redis 연동
backendProject/.../chat/controller/ChatMessagingController.java, backendProject/.../chat/controller/ChatNotificationController.java, backendProject/.../chat/service/Impl/ChatNotificationServiceImpl.java
ChatRedisPublisher 필드 주입 추가 및 사용. 웹소켓 브로드캐스트 유지하면서 Redis 채널로도 발행. 알림 페이로드에 type, content 포함 확대(컨트롤러).
채팅 API 문서화 및 DTO 추가
backendProject/.../chat/controller/ChatHistoryController.java, backendProject/.../chat/controller/ChatReadController.java, backendProject/.../chat/controller/ChatRoomQueryController.java, backendProject/.../chat/elasticsearch/ChatReindexController.java, backendProject/.../chat/elasticsearch/controller/ChatSearchController.java
클래스/메서드/파라미터에 OpenAPI 애너테이션 추가. ChatRoomQueryController에 공개 중첩 DTO CreateChatRoomRequest 추가(필드 draftId). 런타임 로직 변경 없음.
선수 API 문서화
backendProject/.../player/cache/controller/PlayerCacheController.java, backendProject/.../player/elasticsearch/controller/PlayerEsController.java
OpenAPI 애너테이션 추가(클래스 태그, Operation, ApiResponses, Parameter). 동작 변경 없음.
드래프트 API 문서화/파라미터 정정
backendProject/.../draft/controller/DraftController.java
OpenAPI 애너테이션 추가. isWithinSquadLimits의 두번째 쿼리 파라미터명 정리(elementTypeId) 및 서비스 호출에 반영.
OpenAPI 그룹 구성 추가
backendProject/.../global/configuration/OpenApiConfig.java
GroupedOpenApi 빈 10개 추가(채팅, 채팅검색, 사용자, 드래프트, 선수, 캐시, 선수검색, 매치, 팀, 라운드). 기존 openAPI 설정 유지.

Sequence Diagram(s)

sequenceDiagram
  autonumber
  participant C as Client
  participant W as ChatMessagingController
  participant S as ChatService
  participant P as ChatRedisPublisher
  participant R as Redis
  participant B as ChatRedisSubscriber
  participant M as SimpMessagingTemplate

  C->>W: STOMP /app/chat/{roomId} 메시지 전송
  W->>S: 메시지 저장 및 페이로드 구성
  S-->>W: 저장 결과/페이로드
  W->>P: publishToRoom(roomId, payload)
  P->>R: PUBLISH chat:room:{roomId} payload(JSON)
  R-->>B: MESSAGE chat:room:{roomId}
  B->>M: convertAndSend(/topic/chat/{roomId}, payload)
  M-->>C: 구독자에게 브로드캐스트
  note over P,B: 재활성화된 Redis 퍼블리시/구독 흐름
Loading
sequenceDiagram
  autonumber
  participant Svc as ChatNotificationServiceImpl
  participant M as SimpMessagingTemplate
  participant P as ChatRedisPublisher
  participant R as Redis
  participant B as ChatRedisSubscriber

  Svc->>M: /topic/chat/{roomId} 알림 브로드캐스트
  Svc->>P: publishToRoom(roomId, alert-payload)
  P->>R: PUBLISH chat:room:{roomId}
  R-->>B: MESSAGE 전달
  B->>M: convertAndSend 재전송
  note over Svc,P: 서비스 레벨에서 Redis 발행 추가
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly related PRs

Suggested reviewers

  • hwichoi0317
  • Kim-Jaehyun0328
  • wjkim9
  • roode1017

Poem

귀 쫑긋, 버니가 말하네 — 채널이 다시 깨어났네 🥕
푸쉬 한 번에 톡, 페이로드가 춤추고,
구독자들 모여 토픽에서 박수 쳐, 싱그러운 밤.
문서엔 태그를 달아 길을 밝혔네,
우당탕, 대화는 다시 줄을 타고 흘러가네 ✨

Tip

🔌 Remote MCP (Model Context Protocol) integration is now available!

Pro plan users can now connect to remote MCP servers from the Integrations page. Connect with popular remote MCPs such as Notion and Linear to add more context to your reviews and chats.


📜 Recent review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

💡 Knowledge Base configuration:

  • MCP integration is disabled by default for public repositories
  • Jira integration is disabled by default for public repositories
  • Linear integration is disabled by default for public repositories

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between 9a26eb8 and 41a14db.

📒 Files selected for processing (1)
  • backendProject/src/main/java/likelion/mlb/backendProject/domain/draft/controller/DraftController.java (2 hunks)
✨ Finishing Touches
  • 📝 Generate Docstrings
🧪 Generate unit tests
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch feat/#78

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.

❤️ Share
🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.

Support

Need help? Create a ticket on our support page for assistance with any issues or questions.

CodeRabbit Commands (Invoked using PR/Issue comments)

Type @coderabbitai help to get the list of available commands.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Status, Documentation and Community

  • Visit our Status Page to check the current availability of CodeRabbit.
  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 5

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (5)
backendProject/src/main/java/likelion/mlb/backendProject/domain/chat/bus/ChatRedisSubscriber.java (2)

35-38: 예외 무시 금지: 최소한 경고 로그/메트릭 남겨주세요

현재 예외를 삼켜서 장애 원인 추적이 어렵습니다. 채널/바디를 포함한 경고 로그를 권장합니다.

아래처럼 수정:

-    } catch (Exception e) {
-      // 필요하면 로그 추가
-      // log.warn("Failed to handle chat redis msg: {}", body, e);
-    }
+    } catch (Exception e) {
+      log.warn("ChatRedisSubscriber failed to handle message. channel={}, body={}", channel, body, e);
+    }

클래스 상단에 로거를 추가해야 합니다:

// 상단 import
import lombok.extern.slf4j.Slf4j;

// 클래스 어노테이션
@Slf4j

31-33: Notification 컨트롤러·서비스에서 중복 STOMP 전송 제거

ChatNotificationController와 ChatNotificationServiceImpl에서 직접 STOMP 전송(messagingTemplate.convertAndSend(...))을 제거하고, Redis 퍼블리시 + ChatRedisSubscriber를 통한 브로드캐스트만 남기면 동일 노드에서 발생하는 2중 전송 문제를 해소할 수 있습니다.

수정 대상:

  • backendProject/src/main/java/likelion/mlb/backendProject/domain/chat/controller/ChatNotificationController.java (69행)
    삭제:
    messagingTemplate.convertAndSend("/topic/chat/" + roomId, payload);
  • backendProject/src/main/java/likelion/mlb/backendProject/domain/chat/service/Impl/ChatNotificationServiceImpl.java (87행)
    삭제:
    messagingTemplate.convertAndSend("/topic/chat/" + roomId, payload);
backendProject/src/main/java/likelion/mlb/backendProject/domain/chat/bus/ChatRedisPublisher.java (1)

19-25: 입력 payload 변이 방지 + 실패 로그 추가

현재 메서드가 호출 인자 Map을 변이합니다. 내부에서 복사본을 만들어 부작용을 제거하고, 실패 시 로그를 남기세요.

   public void publishToRoom(UUID roomId, Map<String, Object> payload) {
     try {
-      payload.put("_src", nodeId); // 루프 방지 태그
-      String json = objectMapper.writeValueAsString(payload);
+      var toSend = new java.util.HashMap<>(payload);
+      toSend.put("_src", nodeId); // 루프 방지 태그
+      String json = objectMapper.writeValueAsString(toSend);
       stringRedisTemplate.convertAndSend(ChatChannels.roomChannel(roomId), json);
-    } catch (Exception ignore) {
-    }
+    } catch (Exception e) {
+      log.warn("ChatRedisPublisher failed to publish. roomId={}, payloadKeys={}", roomId, payload.keySet(), e);
+    }
   }

로거 추가(없다면):

import lombok.extern.slf4j.Slf4j;

@Slf4j
public class ChatRedisPublisher { ... }
backendProject/src/main/java/likelion/mlb/backendProject/domain/chat/controller/ChatNotificationController.java (1)

61-71: 중복 브로드캐스트 제거 (Critical)
로컬 STOMP 브로드캐스트(messagingTemplate.convertAndSend)와 Redis 퍼블리시(chatRedisPublisher.publishToRoom) 후 Subscriber를 통한 STOMP 재전송이 동일 노드 내에서 중복 발생합니다. 아래 두 위치 모두 “Redis 경유 방송만” 사용하도록 수정해주세요.

수정 대상 파일 및 위치:

  • backendProject/src/main/java/likelion/mlb/backendProject/domain/chat/controller/ChatNotificationController.java (라인 69–70)
  • backendProject/src/main/java/likelion/mlb/backendProject/domain/chat/service/Impl/ChatNotificationServiceImpl.java (라인 87–88)

예시 diff:

--- a/backendProject/src/main/java/likelion/mlb/backendProject/domain/chat/controller/ChatNotificationController.java
+++ b/backendProject/src/main/java/likelion/mlb/backendProject/domain/chat/controller/ChatNotificationController.java
@@ -66,8 +66,7 @@ public class ChatNotificationController {
     // ✅ Redis fan-out (모든 노드에서 Subscriber가 STOMP 브로드캐스트)
     Map<String, Object> payload = Map.of(
         "id", saved.getId().toString(),
-        "chatRoomId", roomId.toString(),
-        messagingTemplate.convertAndSend("/topic/chat/" + roomId, payload);
-        chatRedisPublisher.publishToRoom(roomId, new HashMap<>(payload));
+        "chatRoomId", roomId.toString()
     );
     chatRedisPublisher.publishToRoom(roomId, new HashMap<>(payload));
 }
--- a/backendProject/src/main/java/likelion/mlb/backendProject/domain/chat/service/Impl/ChatNotificationServiceImpl.java
+++ b/backendProject/src/main/java/likelion/mlb/backendProject/domain/chat/service/Impl/ChatNotificationServiceImpl.java
@@ -84,8 +84,7 @@ public class ChatNotificationServiceImpl {
     // ✅ Redis fan-out (모든 노드에서 Subscriber가 STOMP 브로드캐스트)
     Map<String, Object> payload = Map.of(
         "id", saved.getId().toString(),
-        "chatRoomId", roomId.toString(),
-        messagingTemplate.convertAndSend("/topic/chat/" + roomId, payload);
-        chatRedisPublisher.publishToRoom(roomId, new HashMap<>(payload));
+        "chatRoomId", roomId.toString()
     );
     chatRedisPublisher.publishToRoom(roomId, new HashMap<>(payload));
 }

위 두 곳에서 messagingTemplate.convertAndSend(...) 호출을 제거하고, Redis 퍼블리시만 남겨 일관된 처리 흐름을 유지해주세요.

backendProject/src/main/java/likelion/mlb/backendProject/domain/chat/service/Impl/ChatNotificationServiceImpl.java (1)

61-89: 트랜잭션 커밋 전 브로드캐스트로 인한 일관성 위험(유령 메시지) — 커밋 후 전송으로 이동 필요

@Transactional(REQUIRES_NEW) 범위 안에서 WebSocket/Redis 전송이 이뤄져 DB 커밋이 실패할 경우, 실제로는 저장되지 않은 메시지가 전송될 수 있습니다. 커밋 이후(afterCommit)에 브로드캐스트하도록 변경하세요.

   @Transactional(propagation = Propagation.REQUIRES_NEW)
   protected void doDispatch(UUID playerId,
       UUID fixtureId,
       String eventType,
       Integer minute,
       Integer point,
       String fallbackText) {

     List<UUID> roomIds = routingRepo.findChatRoomIdsForEvent(playerId, fixtureId);
     if (roomIds.isEmpty()) return;

     String msgText = (fallbackText != null && !fallbackText.isBlank())
         ? fallbackText
         : formatText(eventType, minute, point);

-    for (UUID roomId : roomIds) {
-      // ✅ 서비스 경유 저장: AFTER_COMMIT 색인(ES)까지 자동 수행
-      var saved = chatMessageService.saveSystemAlert(roomId, msgText);
-
-      var payload = Map.of(
-          "id", saved.getId().toString(),
-          "chatRoomId", roomId.toString(),
-          "type", "ALERT",
-          "content", saved.getContent(),
-          "createdAt", saved.getCreatedAt().toString()
-      );
-      messagingTemplate.convertAndSend("/topic/chat/" + roomId, payload);
-      chatRedisPublisher.publishToRoom(roomId, new java.util.HashMap<>(payload));
-    }
+    // 1) 저장(트랜잭션 내)
+    final java.util.List<java.util.Map<String, Object>> payloads = new java.util.ArrayList<>();
+    for (UUID roomId : roomIds) {
+      var saved = chatMessageService.saveSystemAlert(roomId, msgText);
+      var payload = new java.util.HashMap<String, Object>();
+      payload.put("id", saved.getId().toString());
+      payload.put("chatRoomId", roomId.toString());
+      payload.put("type", "ALERT");
+      payload.put("content", saved.getContent());
+      payload.put("createdAt", saved.getCreatedAt().toString());
+      payloads.add(payload);
+    }
+
+    // 2) 커밋 후 브로드캐스트
+    org.springframework.transaction.support.TransactionSynchronizationManager.registerSynchronization(
+        new org.springframework.transaction.support.TransactionSynchronization() {
+          @Override
+          public void afterCommit() {
+            for (var payload : payloads) {
+              UUID roomId = java.util.UUID.fromString((String) payload.get("chatRoomId"));
+              try {
+                messagingTemplate.convertAndSend("/topic/chat/" + roomId, payload);
+                chatRedisPublisher.publishToRoom(roomId, new java.util.HashMap<>(payload));
+              } catch (Exception e) {
+                // 개별 방 전송 실패가 다른 방 전송을 막지 않도록 방어
+                // (필요 시 로깅 추가)
+              }
+            }
+          }
+        });

추가로, 장기적으로는 Outbox 패턴으로 전환하면 재시도/복구 가능성이 높아집니다(아래 별도 코멘트).

🧹 Nitpick comments (26)
backendProject/src/main/java/likelion/mlb/backendProject/domain/chat/bus/ChatRedisSubscriber.java (1)

25-27: Map.class 역직렬화 대신 TypeReference로 타입 안전성 확보

@SuppressWarnings("unchecked") 제거하고 TypeReference를 사용하면 경고 제거 및 스키마 일관성에 유리합니다.

아래처럼 변경 제안:

-      @SuppressWarnings("unchecked")
-      Map<String, Object> payload = objectMapper.readValue(body, Map.class);
+      Map<String, Object> payload = objectMapper.readValue(
+          body,
+          new com.fasterxml.jackson.core.type.TypeReference<Map<String, Object>>() {}
+      );
backendProject/src/main/java/likelion/mlb/backendProject/domain/chat/bus/RedisPubSubConfig.java (1)

17-23: 리스너 컨테이너에 ErrorHandler 추가 권장

런타임 예외 시 조용히 실패하지 않도록 컨테이너 레벨 ErrorHandler를 지정하세요.

아래처럼 보완:

   public RedisMessageListenerContainer redisMessageListenerContainer() {
     var container = new RedisMessageListenerContainer();
     container.setConnectionFactory(connectionFactory);
     container.addMessageListener(subscriber, new PatternTopic("chat:room:*"));
+    container.setErrorHandler(e -> log.warn("Redis chat listener error", e));
     return container;
   }

추가 로거 선언:

// 상단 import
import lombok.extern.slf4j.Slf4j;

// 클래스 어노테이션
@Slf4j
backendProject/src/main/java/likelion/mlb/backendProject/domain/chat/controller/ChatMessagingController.java (1)

24-24: 미사용 필드 제거 제안: SimpMessagingTemplate

현재 파일 내에서 messagingTemplate이 사용되지 않습니다(컴파일에는 영향 없음). 불필요한 주입 제거로 의존성 최소화 권장.

-  private final SimpMessagingTemplate messagingTemplate;

추가로 상단 import 정리:

// 사용하지 않으면 제거
import org.springframework.messaging.simp.SimpMessagingTemplate;
backendProject/src/main/java/likelion/mlb/backendProject/domain/chat/controller/ChatNotificationController.java (1)

54-58: 부작용 있는 동작은 POST가 적합

roomAlert는 DB 저장 및 브로드캐스트(부작용)를 수행합니다. 테스트용이라고 해도 HTTP语义 측면에서 POST가 더 적절합니다.

간단 변경:

-  @GetMapping("/room/{roomId}")
+  @PostMapping("/room/{roomId}")
-  public ResponseEntity<Map<String, Object>> roomAlert(
-      @Parameter(description = "채팅방 ID", required = true) @PathVariable UUID roomId,
-      @Parameter(description = "전송할 메시지 내용", required = true) @RequestParam String text) {
+  public ResponseEntity<Map<String, Object>> roomAlert(
+      @Parameter(description = "채팅방 ID", required = true) @PathVariable UUID roomId,
+      @Parameter(description = "전송할 메시지 내용", required = true) @RequestBody String text) {
backendProject/src/main/java/likelion/mlb/backendProject/domain/player/cache/controller/PlayerCacheController.java (3)

29-33: 용어 오타: “캐시링” → “캐싱”으로 교정 권장

요약/응답 설명의 “캐시링”은 맞춤법상 어색합니다. “캐싱” 또는 “캐시 로딩”으로 교정하면 문서 품질이 좋아집니다.

다음과 같이 변경을 제안합니다.

-    @Operation(summary = "선수 데이터 캐시링", description = "DB의 선수 데이터를 Redis 캐시로 로드합니다")
+    @Operation(summary = "선수 데이터 캐싱", description = "DB의 선수 데이터를 Redis 캐시에 로드합니다")
     @ApiResponses(value = {
-        @ApiResponse(responseCode = "200", description = "캐시링 성공"),
+        @ApiResponse(responseCode = "200", description = "캐싱 성공"),
         @ApiResponse(responseCode = "500", description = "내부 서버 오류")
     })

14-18: 응답 스키마를 기술하려면 media import 추가 필요

아래 제안처럼 응답 본문 스키마를 명시하려면 Content/ArraySchema/Schema import가 필요합니다.

 import io.swagger.v3.oas.annotations.Operation;
 import io.swagger.v3.oas.annotations.tags.Tag;
 import io.swagger.v3.oas.annotations.responses.ApiResponse;
 import io.swagger.v3.oas.annotations.responses.ApiResponses;
+import io.swagger.v3.oas.annotations.media.Content;
+import io.swagger.v3.oas.annotations.media.ArraySchema;
+import io.swagger.v3.oas.annotations.media.Schema;

40-44: 200 응답의 List 스키마 명시 권장

Swagger UI에서 응답 구조가 더 명확하도록 200 응답에 배열 스키마를 기술하세요.

-    @ApiResponses(value = {
-        @ApiResponse(responseCode = "200", description = "선수 목록 조회 성공"),
-        @ApiResponse(responseCode = "500", description = "내부 서버 오류")
-    })
+    @ApiResponses(value = {
+        @ApiResponse(
+            responseCode = "200",
+            description = "선수 목록 조회 성공",
+            content = @Content(array = @ArraySchema(schema = @Schema(implementation = PlayerDto.class)))
+        ),
+        @ApiResponse(responseCode = "500", description = "내부 서버 오류")
+    })
backendProject/src/main/java/likelion/mlb/backendProject/domain/chat/elasticsearch/controller/ChatSearchController.java (4)

14-19: 응답 스키마 표기를 위해 media import 추가 권장

200/403 응답의 본문 스키마를 명시하려면 Content/Schema import가 필요합니다.

 import io.swagger.v3.oas.annotations.Operation;
 import io.swagger.v3.oas.annotations.Parameter;
 import io.swagger.v3.oas.annotations.tags.Tag;
 import io.swagger.v3.oas.annotations.responses.ApiResponse;
 import io.swagger.v3.oas.annotations.responses.ApiResponses;
+import io.swagger.v3.oas.annotations.media.Content;
+import io.swagger.v3.oas.annotations.media.Schema;

29-34: 문서-런타임 불일치: 500 응답 제거 또는 에러 전파 필요

현재 Service는 IOException 등을 내부에서 삼키고 빈 결과를 반환하므로(컨트롤러는 200으로 응답), 500 응답 문서는 실제 동작과 불일치합니다. 아래 둘 중 하나로 정합성을 맞춰주세요.

  • 옵션 A(문서 정정): 500 응답을 제거하고 200/403만 명시
  • 옵션 B(동작 변경): Service에서 실패 시 예외를 던져 글로벌 예외 핸들러를 통해 500을 반환

또한 200/403의 본문 스키마를 명시하면 소비자가 이해하기 쉬워집니다.

옵션 A 적용 예:

   @Operation(summary = "채팅 메시지 검색", description = "지정된 채팅방에서 키워드로 메시지를 검색합니다")
   @ApiResponses(value = {
-      @ApiResponse(responseCode = "200", description = "검색 성공"),
-      @ApiResponse(responseCode = "403", description = "채팅방 멤버가 아님"),
-      @ApiResponse(responseCode = "500", description = "내부 서버 오류")
+      @ApiResponse(
+          responseCode = "200",
+          description = "검색 성공",
+          content = @Content(schema = @Schema(implementation = ChatSearchResult.class))
+      ),
+      @ApiResponse(
+          responseCode = "403",
+          description = "채팅방 멤버가 아님",
+          content = @Content(schema = @Schema(implementation = ChatSearchResult.class))
+      )
   })

37-41: limit 파라미터 제약을 스키마에 반영 + Authentication 숨김 처리 권장

  • limit는 1–50으로 클램핑되므로 스키마에 최소/최대/기본값을 기술하세요.
  • Swagger에서 Authentication 파라미터를 숨기면 문서가 깔끔합니다.
-      @Parameter(description = "조회할 메시지 개수 (1-50, 기본값: 20)") @RequestParam(defaultValue = "20") int limit,
-      Authentication authentication) {
+      @Parameter(
+          description = "조회할 메시지 개수",
+          schema = @Schema(minimum = "1", maximum = "50", defaultValue = "20")
+      )
+      @RequestParam(defaultValue = "20") int limit,
+      @Parameter(hidden = true) Authentication authentication) {

52-53: 상수 대신 HttpStatus 사용으로 가독성 개선

상수 403 대신 HttpStatus.FORBIDDEN 사용을 권장합니다.

-      return ResponseEntity.status(403).body(ChatSearchResult.builder()
+      return ResponseEntity.status(org.springframework.http.HttpStatus.FORBIDDEN).body(ChatSearchResult.builder()
backendProject/src/main/java/likelion/mlb/backendProject/domain/chat/controller/ChatRoomQueryController.java (4)

31-35: 200 응답의 배열 스키마 명시 권장 (ScoreboardItem[])

Swagger에서 응답 구조를 명확히 보여주도록 배열 스키마를 기술하세요.

   @Operation(summary = "채팅방 스코어보드 조회", description = "채팅방 참가자들의 점수와 순위를 조회합니다")
-  @ApiResponses(value = {
-      @ApiResponse(responseCode = "200", description = "스코어보드 조회 성공"),
-      @ApiResponse(responseCode = "404", description = "채팅방을 찾을 수 없음")
-  })
+  @ApiResponses(value = {
+      @ApiResponse(
+          responseCode = "200",
+          description = "스코어보드 조회 성공",
+          content = @Content(array = @ArraySchema(schema = @Schema(implementation = ScoreboardItem.class)))
+      ),
+      @ApiResponse(responseCode = "404", description = "채팅방을 찾을 수 없음")
+  })

필요한 import:

+import io.swagger.v3.oas.annotations.media.Content;
+import io.swagger.v3.oas.annotations.media.ArraySchema;
+import io.swagger.v3.oas.annotations.media.Schema;

41-45: 200 응답의 RosterResponse 스키마 명시 권장

로스터 응답도 스키마를 명시하면 문서 활용성이 높아집니다.

   @Operation(summary = "참가자 로스터 조회", description = "특정 참가자의 11명 로스터와 포메이션 정보를 조회합니다")
-  @ApiResponses(value = {
-      @ApiResponse(responseCode = "200", description = "로스터 조회 성공"),
-      @ApiResponse(responseCode = "404", description = "참가자를 찾을 수 없음")
-  })
+  @ApiResponses(value = {
+      @ApiResponse(
+          responseCode = "200",
+          description = "로스터 조회 성공",
+          content = @Content(schema = @Schema(implementation = RosterResponse.class))
+      ),
+      @ApiResponse(responseCode = "404", description = "참가자를 찾을 수 없음")
+  })

70-72: 요청 유효성 검증 추가(@Valid) 및 스키마 보완 권장

생성 요청 DTO에 제약이 없다면 400 응답을 기대하기 어렵습니다. @Valid를 붙이고 DTO에 제약을 추가하세요.

-  public ChatRoom createChatRoom(@Parameter(description = "채팅방 생성 요청") @RequestBody CreateChatRoomRequest request) {
+  public ChatRoom createChatRoom(
+      @Parameter(description = "채팅방 생성 요청") @Valid @RequestBody CreateChatRoomRequest request) {

DTO 측 제안은 아래 코멘트 참조.


77-82: 내부 static DTO의 제약/문서화 추가 및 분리 권장

  • 필수값이면 @NotNull을 추가하고 Swagger 스키마 설명을 붙이세요.
  • 추후 재사용을 고려하면 별도 패키지(dto)로 분리하는 것이 유지보수에 유리합니다.
-  public static class CreateChatRoomRequest {
-    private UUID draftId;
-    
-    public UUID getDraftId() { return draftId; }
-    public void setDraftId(UUID draftId) { this.draftId = draftId; }
-  }
+  public static class CreateChatRoomRequest {
+    @io.swagger.v3.oas.annotations.media.Schema(description = "드래프트 ID", required = true)
+    @jakarta.validation.constraints.NotNull
+    private UUID draftId;
+
+    public UUID getDraftId() { return draftId; }
+    public void setDraftId(UUID draftId) { this.draftId = draftId; }
+  }

필요 import:

+import jakarta.validation.Valid;
+import jakarta.validation.constraints.NotNull;
+import io.swagger.v3.oas.annotations.media.Schema;

추가로, 생성 성공 시 201 + Location 헤더를 반환하는 형태로의 전환도 고려해 볼 수 있습니다(선택).

backendProject/src/main/java/likelion/mlb/backendProject/domain/chat/service/Impl/ChatNotificationServiceImpl.java (1)

61-89: 아키텍처 제안: Outbox 패턴 도입 고려

  • 현재는 DB 트랜잭션과 브로드캐스트가 논리적으로만 결합되어 있습니다.
  • Outbox 테이블 + 비동기 퍼블리셔(스케줄러/스트리밍) 조합을 도입하면 재시도/모니터링/데드레터 처리 등이 쉬워집니다.
backendProject/src/main/java/likelion/mlb/backendProject/domain/draft/controller/DraftController.java (3)

83-87: 문서(404)와 실제 동작 정합성 점검

getAllPlayersByDraftId는 존재하지 않는 드래프트 ID일 때 404를 반환하지 않고 빈/예외로 끝날 수 있습니다. 문서와 일치하도록 404를 명시적으로 반환하거나, 문서에서 404를 제거하세요.


95-99: 요청 파라미터 검증 강화 제안

squadLimit는 두 파라미터가 필수입니다. @NotNull 스키마 제약을 추가하고, 잘못된 형식(UUID 파싱 실패 등)에 대한 400 처리 전략을 문서로 명확히 하세요.

예시:

-    @Parameter(description = "참여자 ID", required = true) @RequestParam(value="participantId") UUID participantId,
-    @Parameter(description = "엘리먼트 타입 ID", required = true) @RequestParam(value="elementTypeId")UUID elementTypeId)
+    @Parameter(description = "참여자 ID", required = true,
+        schema = @Schema(required = true, format = "uuid"))
+    @RequestParam(value="participantId") UUID participantId,
+    @Parameter(description = "엘리먼트 타입 ID", required = true,
+        schema = @Schema(required = true, format = "uuid"))
+    @RequestParam(value="elementTypeId") UUID elementTypeId)

필요 import:

+import io.swagger.v3.oas.annotations.media.Schema;

58-62: 404 문서와 예외 매핑 일관성 검토

참여자/드래프트 조회 계열 전반에서 “찾을 수 없음”을 404로 표현하려면, 서비스 계층의 IllegalStateException/NoSuchElementException을 컨트롤러에서 ResponseStatusException(HttpStatus.NOT_FOUND, ...)으로 변환하거나 전역 예외 핸들러에서 매핑하세요.

backendProject/src/main/java/likelion/mlb/backendProject/domain/chat/elasticsearch/ChatReindexController.java (2)

25-30: 문서화된 404/500 응답과 실제 동작 불일치 가능성

  • 현재 메서드는 void로 200 OK만 반환하고, 채팅방 존재 여부나 예외에 따른 4xx/5xx 응답 분기가 없습니다.
  • 404("채팅방을 찾을 수 없음")을 문서화하려면 ChatRoom 존재 확인(예: ChatRoomRepository.existsById(roomId)) 또는 멤버십 확인이 필요합니다. 그렇지 않다면 404 응답 항목을 제거하는 편이 정확합니다.

원하시면 room 존재 체크를 추가하는 간단한 패치를 제안드립니다.


31-35: 재인덱싱 엔드포인트: 결과/에러 표준화 및 부하/권한 고려 제안

  • 대용량 작업 특성상 202 Accepted + 비동기 처리를 고려하거나, 최소한 인덱싱 개수를 본문으로 반환하면 운영 관측이 수월합니다.
  • 보안/운영: reindex는 임의 호출 시 부하 유발 가능성이 큽니다. 관리자 전용(@PreAuthorize("hasRole('ADMIN')")) 또는 내부용으로 제한 권장.

아래처럼 간단히 카운트 반환으로 가시성을 높일 수 있습니다:

-  @PostMapping("/{roomId}/reindex")
-  public void reindex(@Parameter(description = "채팅방 ID", required = true) @PathVariable UUID roomId) {
-    // 대용량이면 Page로 분할 처리
-    repo.findAllByChatRoomIdOrderByCreatedAtAsc(roomId).forEach(indexer::index);
-  }
+  @PostMapping("/{roomId}/reindex")
+  public org.springframework.http.ResponseEntity<java.util.Map<String, Object>> reindex(
+      @Parameter(description = "채팅방 ID", required = true) @PathVariable UUID roomId) {
+    // TODO: 대용량이면 Page/스트리밍 처리
+    final int[] count = {0};
+    repo.findAllByChatRoomIdOrderByCreatedAtAsc(roomId).forEach(m -> { indexer.index(m); count[0]++; });
+    return org.springframework.http.ResponseEntity.ok(java.util.Map.of("indexed", count[0]));
+  }
backendProject/src/main/java/likelion/mlb/backendProject/domain/player/elasticsearch/controller/PlayerEsController.java (1)

32-37: 400 응답 문서화와 실제 구현 불일치 — 파라미터 검증 추가 권장

  • @ApiResponses에 400이 있으나 메서드 내 파라미터 검증이 없어 현재는 항상 200입니다.
  • 최소한 elementTypeId가 숫자가 아닐 때 400을 반환하거나, Bean Validation을 적용하는 쪽을 권장합니다.

아래처럼 가벼운 검증을 추가해 문서와 동작을 맞출 수 있습니다:

-    public ResponseEntity<List<PlayerEsDocument>> searchWithKeyword(
-            @Parameter(description = "검색 키워드 (선수명 등)") @RequestParam(value = "keyword", defaultValue = "") String keyword,
-            @Parameter(description = "엘리먼트 타입 ID") @RequestParam(value = "elementTypeId", defaultValue = "") String elementTypeId
-            ) {
-
-        return ResponseEntity.ok(playerEsService.search(keyword, elementTypeId));
+    public ResponseEntity<List<PlayerEsDocument>> searchWithKeyword(
+            @Parameter(description = "검색 키워드 (선수명 등)") @RequestParam(value = "keyword", defaultValue = "") String keyword,
+            @Parameter(description = "엘리먼트 타입 ID(숫자 문자열, 미지정 시 전체)") @RequestParam(value = "elementTypeId", defaultValue = "") String elementTypeId
+            ) {
+        if (!elementTypeId.isEmpty() && !elementTypeId.matches("\\d+")) {
+            return ResponseEntity.badRequest().build();
+        }
+        return ResponseEntity.ok(playerEsService.search(keyword, elementTypeId));
backendProject/src/main/java/likelion/mlb/backendProject/domain/chat/controller/ChatHistoryController.java (1)

24-33: limit 파라미터 문서에 범위 명시 권장 (서비스 로직과 일치)

  • 서비스(ChatHistoryServiceImpl)는 limit을 1~100으로 클램프합니다.
  • 현재 파라미터 설명은 기본값만 명시되어 있어, 소비자가 과도한 값 전송 시 혼란이 있을 수 있습니다.

아래처럼 설명을 보강해 주세요:

-      @Parameter(description = "조회할 메시지 개수 (기본값: 30)") @RequestParam(defaultValue = "30") int limit) {
+      @Parameter(description = "조회할 메시지 개수 (1-100, 기본값: 30)") @RequestParam(defaultValue = "30") int limit) {
backendProject/src/main/java/likelion/mlb/backendProject/global/configuration/OpenApiConfig.java (2)

47-54: Chat Search 그룹 경로 매칭 보강 제안 (기본 경로 포함 보장)

  • Ant 패턴으로도 현재 매칭될 가능성이 높지만, 명시적으로 base 경로도 포함시키면 오탐 방지와 가독성이 좋아집니다.

아래와 같이 pathsToMatch를 보강하는 것을 권장합니다:

-            .pathsToMatch("/api/chat-rooms/*/search/**", "/api/chat-rooms/*/reindex/**")
+            .pathsToMatch(
+                "/api/chat-rooms/*/search", "/api/chat-rooms/*/search/**",
+                "/api/chat-rooms/*/reindex", "/api/chat-rooms/*/reindex/**"
+            )

38-45: 그룹 정의 전반 — 중복 스캔/오버랩 가능성 점검 권장

  • 여러 그룹이 동일 패키지를 스캔하더라도 pathsToMatch가 좁게 설정되어 있어 실질 충돌은 드뭅니다. 다만, 일부 컨트롤러 경로가 변경될 경우 문서 그룹 이동이 발생할 수 있으니, CI에서 스웨거 경로 회귀 테스트를 추가하면 안정적입니다.

원하시면 간단한 스프링 부트 테스트로 그룹-경로 맵핑 스냅샷을 생성하는 스크립트를 제안드릴게요.

Also applies to: 56-63, 65-72, 74-81, 83-90, 92-99, 101-108, 110-117, 119-126

backendProject/src/main/java/likelion/mlb/backendProject/domain/chat/controller/ChatReadController.java (1)

73-76: RequestBody 문서화 방식 개선: @parameter 대신 @io.swagger.v3.oas.annotations.parameters.RequestBody 사용

  • 본문(payload) 설명에 Parameter를 사용하는 대신, OpenAPI의 RequestBody 애노테이션을 사용하는 것이 스키마/예시 문서화에 더 적합합니다.

아래와 같이 교체를 권장합니다:

-      @Parameter(description = "읽음 요청 데이터 (messageId 포함)") @RequestBody(required = false) Map<String, String> body,
+      @io.swagger.v3.oas.annotations.parameters.RequestBody(
+          required = false,
+          description = "읽음 요청 데이터 (messageId 포함). messageId가 없으면 '현재 시각' 기준으로 마킹됩니다."
+      )
+      @RequestBody(required = false) Map<String, String> body,

원하시면 DTO로 전환하여 스키마를 명확히 하는 리팩터도 지원 가능합니다.

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

💡 Knowledge Base configuration:

  • MCP integration is disabled by default for public repositories
  • Jira integration is disabled by default for public repositories
  • Linear integration is disabled by default for public repositories

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between 50ec78e and 9a26eb8.

📒 Files selected for processing (15)
  • backendProject/src/main/java/likelion/mlb/backendProject/domain/chat/bus/ChatRedisPublisher.java (1 hunks)
  • backendProject/src/main/java/likelion/mlb/backendProject/domain/chat/bus/ChatRedisSubscriber.java (1 hunks)
  • backendProject/src/main/java/likelion/mlb/backendProject/domain/chat/bus/RedisPubSubConfig.java (1 hunks)
  • backendProject/src/main/java/likelion/mlb/backendProject/domain/chat/controller/ChatHistoryController.java (1 hunks)
  • backendProject/src/main/java/likelion/mlb/backendProject/domain/chat/controller/ChatMessagingController.java (3 hunks)
  • backendProject/src/main/java/likelion/mlb/backendProject/domain/chat/controller/ChatNotificationController.java (3 hunks)
  • backendProject/src/main/java/likelion/mlb/backendProject/domain/chat/controller/ChatReadController.java (3 hunks)
  • backendProject/src/main/java/likelion/mlb/backendProject/domain/chat/controller/ChatRoomQueryController.java (2 hunks)
  • backendProject/src/main/java/likelion/mlb/backendProject/domain/chat/elasticsearch/ChatReindexController.java (1 hunks)
  • backendProject/src/main/java/likelion/mlb/backendProject/domain/chat/elasticsearch/controller/ChatSearchController.java (2 hunks)
  • backendProject/src/main/java/likelion/mlb/backendProject/domain/chat/service/Impl/ChatNotificationServiceImpl.java (3 hunks)
  • backendProject/src/main/java/likelion/mlb/backendProject/domain/draft/controller/DraftController.java (2 hunks)
  • backendProject/src/main/java/likelion/mlb/backendProject/domain/player/cache/controller/PlayerCacheController.java (1 hunks)
  • backendProject/src/main/java/likelion/mlb/backendProject/domain/player/elasticsearch/controller/PlayerEsController.java (1 hunks)
  • backendProject/src/main/java/likelion/mlb/backendProject/global/configuration/OpenApiConfig.java (2 hunks)
🧰 Additional context used
🧬 Code graph analysis (15)
backendProject/src/main/java/likelion/mlb/backendProject/domain/chat/elasticsearch/controller/ChatSearchController.java (3)
backendProject/src/main/java/likelion/mlb/backendProject/domain/chat/controller/ChatHistoryController.java (1)
  • Tag (16-49)
backendProject/src/main/java/likelion/mlb/backendProject/domain/chat/elasticsearch/service/ChatSearchService.java (2)
  • Slf4j (23-129)
  • search (34-114)
backendProject/src/main/java/likelion/mlb/backendProject/domain/chat/elasticsearch/dto/ChatSearchResult.java (1)
  • Getter (9-28)
backendProject/src/main/java/likelion/mlb/backendProject/domain/chat/bus/RedisPubSubConfig.java (3)
backendProject/src/main/java/likelion/mlb/backendProject/global/configuration/RedisConfig.java (3)
  • Configuration (19-67)
  • Bean (60-66)
  • Bean (32-38)
backendProject/src/main/java/likelion/mlb/backendProject/global/redis/RedisPublisher.java (1)
  • RequiredArgsConstructor (8-19)
backendProject/src/main/java/likelion/mlb/backendProject/global/redis/RedisSubscriber.java (1)
  • Service (14-36)
backendProject/src/main/java/likelion/mlb/backendProject/domain/chat/bus/ChatRedisPublisher.java (3)
backendProject/src/main/java/likelion/mlb/backendProject/domain/chat/bus/ChatRedisSubscriber.java (1)
  • Component (12-40)
backendProject/src/main/java/likelion/mlb/backendProject/global/redis/RedisPublisher.java (1)
  • RequiredArgsConstructor (8-19)
backendProject/src/main/java/likelion/mlb/backendProject/global/configuration/RedisConfig.java (1)
  • Configuration (19-67)
backendProject/src/main/java/likelion/mlb/backendProject/domain/chat/elasticsearch/ChatReindexController.java (2)
backendProject/src/main/java/likelion/mlb/backendProject/domain/chat/elasticsearch/controller/ChatSearchController.java (1)
  • Tag (20-62)
backendProject/src/main/java/likelion/mlb/backendProject/domain/chat/elasticsearch/ChatSearchIndexer.java (1)
  • Service (12-33)
backendProject/src/main/java/likelion/mlb/backendProject/domain/chat/controller/ChatMessagingController.java (2)
backendProject/src/main/java/likelion/mlb/backendProject/global/redis/RedisPublisher.java (1)
  • RequiredArgsConstructor (8-19)
backendProject/src/main/java/likelion/mlb/backendProject/domain/chat/service/Impl/ChatMessageServiceImpl.java (1)
  • Service (15-52)
backendProject/src/main/java/likelion/mlb/backendProject/global/configuration/OpenApiConfig.java (2)
backendProject/src/main/java/likelion/mlb/backendProject/global/configuration/OpenApiWsSchemasConfig.java (3)
  • Configuration (28-59)
  • openApi (36-45)
  • Bean (34-46)
backendProject/src/main/java/likelion/mlb/backendProject/global/security/config/SecurityConfig.java (2)
  • Configuration (20-68)
  • auth (38-57)
backendProject/src/main/java/likelion/mlb/backendProject/domain/player/cache/controller/PlayerCacheController.java (1)
backendProject/src/main/java/likelion/mlb/backendProject/domain/player/cache/service/PlayerCacheService.java (1)
  • Service (16-61)
backendProject/src/main/java/likelion/mlb/backendProject/domain/chat/bus/ChatRedisSubscriber.java (3)
backendProject/src/main/java/likelion/mlb/backendProject/domain/chat/bus/ChatRedisPublisher.java (1)
  • Component (11-31)
backendProject/src/main/java/likelion/mlb/backendProject/global/redis/RedisSubscriber.java (2)
  • Service (14-36)
  • Override (23-35)
backendProject/src/main/java/likelion/mlb/backendProject/global/configuration/RedisConfig.java (2)
  • Configuration (19-67)
  • Bean (60-66)
backendProject/src/main/java/likelion/mlb/backendProject/domain/chat/controller/ChatHistoryController.java (2)
backendProject/src/main/java/likelion/mlb/backendProject/domain/chat/service/Impl/ChatHistoryServiceImpl.java (1)
  • Service (19-91)
backendProject/src/main/java/likelion/mlb/backendProject/domain/chat/service/ChatHistoryService.java (1)
  • ChatHistoryService (7-13)
backendProject/src/main/java/likelion/mlb/backendProject/domain/chat/controller/ChatRoomQueryController.java (6)
backendProject/src/main/java/likelion/mlb/backendProject/domain/chat/controller/ChatHistoryController.java (1)
  • Tag (16-49)
backendProject/src/main/java/likelion/mlb/backendProject/domain/chat/controller/ChatNotificationController.java (1)
  • Tag (23-86)
backendProject/src/main/java/likelion/mlb/backendProject/domain/chat/controller/ChatReadController.java (1)
  • Tag (20-107)
backendProject/src/main/java/likelion/mlb/backendProject/domain/chat/elasticsearch/ChatReindexController.java (1)
  • Tag (17-36)
backendProject/src/main/java/likelion/mlb/backendProject/domain/chat/elasticsearch/controller/ChatSearchController.java (1)
  • Tag (20-62)
backendProject/src/main/java/likelion/mlb/backendProject/domain/chat/controller/ChatRoomController.java (2)
  • RestController (14-33)
  • GetMapping (24-32)
backendProject/src/main/java/likelion/mlb/backendProject/domain/chat/controller/ChatReadController.java (4)
backendProject/src/main/java/likelion/mlb/backendProject/domain/chat/elasticsearch/controller/ChatSearchController.java (1)
  • Tag (20-62)
backendProject/src/main/java/likelion/mlb/backendProject/domain/chat/service/Impl/ChatReadServiceImpl.java (2)
  • Override (29-47)
  • Service (15-57)
backendProject/src/main/java/likelion/mlb/backendProject/domain/chat/service/ChatReadService.java (1)
  • ChatReadService (7-16)
backendProject/src/main/java/likelion/mlb/backendProject/domain/chat/entity/ChatReadState.java (1)
  • Entity (8-48)
backendProject/src/main/java/likelion/mlb/backendProject/domain/draft/controller/DraftController.java (2)
backendProject/src/main/java/likelion/mlb/backendProject/domain/draft/service/DraftService.java (2)
  • Service (37-333)
  • updateNextTurn (231-282)
backendProject/src/main/java/likelion/mlb/backendProject/domain/draft/dto/DraftRequest.java (1)
  • Data (12-59)
backendProject/src/main/java/likelion/mlb/backendProject/domain/player/elasticsearch/controller/PlayerEsController.java (3)
backendProject/src/main/java/likelion/mlb/backendProject/domain/chat/controller/ChatHistoryController.java (1)
  • Tag (16-49)
backendProject/src/main/java/likelion/mlb/backendProject/domain/chat/elasticsearch/controller/ChatSearchController.java (1)
  • Tag (20-62)
backendProject/src/main/java/likelion/mlb/backendProject/domain/player/cache/controller/PlayerCacheController.java (1)
  • Tag (21-50)
backendProject/src/main/java/likelion/mlb/backendProject/domain/chat/controller/ChatNotificationController.java (1)
backendProject/src/main/java/likelion/mlb/backendProject/domain/chat/service/ChatNotificationService.java (1)
  • ChatNotificationService (6-12)
backendProject/src/main/java/likelion/mlb/backendProject/domain/chat/service/Impl/ChatNotificationServiceImpl.java (2)
backendProject/src/main/java/likelion/mlb/backendProject/global/redis/RedisPublisher.java (1)
  • RequiredArgsConstructor (8-19)
backendProject/src/main/java/likelion/mlb/backendProject/domain/chat/service/Impl/ChatMessageServiceImpl.java (1)
  • Service (15-52)
🔇 Additional comments (15)
backendProject/src/main/java/likelion/mlb/backendProject/domain/chat/bus/ChatRedisSubscriber.java (1)

12-12: Redis 구독자 빈 활성화 LGTM

주입 및 컨테이너 등록 전제에서 정상 동작합니다.

backendProject/src/main/java/likelion/mlb/backendProject/domain/chat/bus/RedisPubSubConfig.java (1)

10-12: 구성 클래스 활성화 LGTM

분리된 컨테이너 빈명(redisChatMessageListenerContainer)으로 글로벌 RedisConfig와 충돌 없이 공존합니다.

backendProject/src/main/java/likelion/mlb/backendProject/domain/chat/bus/ChatRedisPublisher.java (1)

11-13: 퍼블리셔 빈 활성화 LGTM

주입 경로 정리와 함께 컨트롤러/서비스에서 일관되게 사용 가능합니다.

backendProject/src/main/java/likelion/mlb/backendProject/domain/chat/controller/ChatMessagingController.java (1)

58-60: 웹소켓 직접 브로드캐스트 제거 + Redis 경유 전송 전환, 적절합니다

Publisher→Redis→Subscriber→STOMP 경로로 단일화되어 다중 노드 환경에서 일관성이 좋아집니다.

backendProject/src/main/java/likelion/mlb/backendProject/domain/chat/controller/ChatNotificationController.java (1)

23-23: Swagger 문서화 추가, 그룹 태깅까지 일관적 적용 좋아요

테스트/알림 API에 요약/응답 스키마와 태그가 명확해졌습니다. 스웨거 그룹 정리 목적과 부합합니다.

Also applies to: 35-41, 49-53

backendProject/src/main/java/likelion/mlb/backendProject/domain/player/cache/controller/PlayerCacheController.java (1)

21-21: 태그 메타데이터 추가 좋습니다

그룹화된 Swagger 문서에 잘 맞습니다. 별도 이슈 없습니다.

backendProject/src/main/java/likelion/mlb/backendProject/domain/chat/elasticsearch/controller/ChatSearchController.java (1)

20-20: 태그 메타데이터 추가 LGTM

그룹/분류가 명확해졌습니다.

backendProject/src/main/java/likelion/mlb/backendProject/domain/chat/controller/ChatRoomQueryController.java (1)

21-21: API 그룹 태깅 좋습니다

문서 그룹화 일관성 유지에 도움이 됩니다.

backendProject/src/main/java/likelion/mlb/backendProject/domain/chat/service/Impl/ChatNotificationServiceImpl.java (1)

31-31: Redis 퍼블리셔 주입 추가 LGTM

웹소켓 + Redis Pub/Sub 이중 브로드캐스트 경로 구성이 명확합니다.

backendProject/src/main/java/likelion/mlb/backendProject/domain/draft/controller/DraftController.java (2)

30-30: 드래프트 API 태깅 LGTM

문서 구조화에 기여합니다.


78-81: 컨트롤러 호출-서비스 시그니처 일치 확인됨

DraftService#getParticipantsByDraftId(UUID)만 정의되어 있어, 컨트롤러의 단일 인자 호출(draftService.getParticipantsByDraftId(draftId))이 정확합니다. 해당 검토 코멘트는 잘못된 시그니처 가정에 기반하고 있으므로 무시해도 됩니다.

Likely an incorrect or invalid review comment.

backendProject/src/main/java/likelion/mlb/backendProject/domain/chat/elasticsearch/ChatReindexController.java (1)

17-17: 클래스 태그 추가 적절 — Chat Search Management로 그룹핑 일관성 확보

스웨거 그룹 태깅이 다른 채팅 검색 컨트롤러들과 일관됩니다.

backendProject/src/main/java/likelion/mlb/backendProject/domain/player/elasticsearch/controller/PlayerEsController.java (1)

24-24: 스웨거 태그 추가 적절 — Player Search 그룹과 매칭

플레이어 ES 검색용으로 그룹을 명확히 했습니다.

backendProject/src/main/java/likelion/mlb/backendProject/domain/chat/controller/ChatHistoryController.java (1)

16-16: 클래스 태그 추가 적절 — Chat History 그룹에 자연스럽게 편입

스웨거 그룹 정리에 부합합니다.

backendProject/src/main/java/likelion/mlb/backendProject/global/configuration/OpenApiConfig.java (1)

38-45: Chat API 그룹 추가 적절 — 경로/패키지 매핑 타당

전반적으로 그룹 구성이 의도에 부합합니다.

Comment on lines +36 to +41
@Operation(summary = "이전 채팅 메시지 조회", description = "커서 기반으로 이전 메시지들을 조회합니다 (무한스크롤용)")
@ApiResponses(value = {
@ApiResponse(responseCode = "200", description = "메시지 조회 성공"),
@ApiResponse(responseCode = "400", description = "잘못된 커서 값"),
@ApiResponse(responseCode = "404", description = "채팅방을 찾을 수 없음")
})
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

⚠️ Potential issue

400(잘못된 커서 값) 응답 문서와 실제 동작 불일치 — 컨트롤러에서 변환 예외 매핑 필요

  • Service의 decodeCursor는 잘못된 형식일 때 IllegalArgumentException이 날 수 있고, 현재 컨트롤러에서 이를 400으로 변환하지 않아 500이 될 여지가 있습니다.

다음과 같이 400 매핑을 추가해 문서와 일치시키는 것을 권장합니다:

   @GetMapping("/{roomId}/messages/before")
   public ResponseEntity<ChatHistoryPage> before(
       @Parameter(description = "채팅방 ID", required = true) @PathVariable UUID roomId,
-      @Parameter(description = "페이지 커서 (이전 조회의 nextCursor 값)", required = true) @RequestParam String cursor,
-      @Parameter(description = "조회할 메시지 개수 (기본값: 30)") @RequestParam(defaultValue = "30") int limit) {
-
-    return ResponseEntity.ok(chatHistoryService.loadBefore(roomId, cursor, limit));
+      @Parameter(description = "페이지 커서 (이전 조회의 nextCursor 값)", required = true) @RequestParam String cursor,
+      @Parameter(description = "조회할 메시지 개수 (1-100, 기본값: 30)") @RequestParam(defaultValue = "30") int limit) {
+    try {
+      return ResponseEntity.ok(chatHistoryService.loadBefore(roomId, cursor, limit));
+    } catch (IllegalArgumentException ex) {
+      return ResponseEntity.badRequest().build();
+    }
   }
🤖 Prompt for AI Agents
In
backendProject/src/main/java/likelion/mlb/backendProject/domain/chat/controller/ChatHistoryController.java
around lines 36-41, the controller currently lets IllegalArgumentException from
service.decodeCursor bubble up (causing 500) while the API docs promise a 400
for invalid cursors; fix by mapping that exception to HTTP 400 — either wrap the
decodeCursor call in a try/catch that throws a
ResponseStatusException(HttpStatus.BAD_REQUEST, "Invalid cursor") on
IllegalArgumentException, or add an
@ExceptionHandler(IllegalArgumentException.class) in this controller (or a
controller advice) that returns a 400 response with an appropriate message so
runtime behavior matches the documented 400 response.

import io.swagger.v3.oas.annotations.tags.Tag;
import io.swagger.v3.oas.annotations.responses.ApiResponse;
import io.swagger.v3.oas.annotations.responses.ApiResponses;
@Tag(name = "Chat Read State", description = "채팅 만음 상태 관리 API")
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

오타: "채팅 만음 상태 관리 API" → "채팅 읽음 상태 관리 API"

사용자 노출 문구의 오탈자입니다. 스웨거 UI 가독성을 위해 즉시 수정 권장.

적용 예:

-@Tag(name = "Chat Read State", description = "채팅 만음 상태 관리 API")
+@Tag(name = "Chat Read State", description = "채팅 읽음 상태 관리 API")
🤖 Prompt for AI Agents
In
backendProject/src/main/java/likelion/mlb/backendProject/domain/chat/controller/ChatReadController.java
around line 20, the Swagger @Tag description contains a typo "채팅 만음 상태 관리 API";
update the string to "채팅 읽음 상태 관리 API" to correct the user-facing label in the
Swagger UI, preserving the existing annotation and formatting.

Comment on lines +30 to +36
@Operation(summary = "릶음 상태 조회", description = "사용자의 마지막 읽은 메시지와 미읽 개수를 조회합니다")
@ApiResponses(value = {
@ApiResponse(responseCode = "200", description = "읽음 상태 조회 성공"),
@ApiResponse(responseCode = "401", description = "인증되지 않은 사용자"),
@ApiResponse(responseCode = "403", description = "채팅방 멤버가 아님"),
@ApiResponse(responseCode = "500", description = "내부 서버 오류")
})
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

오타: "릶음 상태 조회" → "읽음 상태 조회"

스웨거 Operation 요약의 철자 오류입니다.

-  @Operation(summary = "릶음 상태 조회", description = "사용자의 마지막 읽은 메시지와 미읽 개수를 조회합니다")
+  @Operation(summary = "읽음 상태 조회", description = "사용자의 마지막 읽은 메시지와 미읽 개수를 조회합니다")
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
@Operation(summary = "릶음 상태 조회", description = "사용자의 마지막 읽은 메시지와 미읽 개수를 조회합니다")
@ApiResponses(value = {
@ApiResponse(responseCode = "200", description = "읽음 상태 조회 성공"),
@ApiResponse(responseCode = "401", description = "인증되지 않은 사용자"),
@ApiResponse(responseCode = "403", description = "채팅방 멤버가 아님"),
@ApiResponse(responseCode = "500", description = "내부 서버 오류")
})
@Operation(summary = "읽음 상태 조회", description = "사용자의 마지막 읽은 메시지와 미읽 개수를 조회합니다")
@ApiResponses(value = {
@ApiResponse(responseCode = "200", description = "읽음 상태 조회 성공"),
@ApiResponse(responseCode = "401", description = "인증되지 않은 사용자"),
@ApiResponse(responseCode = "403", description = "채팅방 멤버가 아님"),
@ApiResponse(responseCode = "500", description = "내부 서버 오류")
})
🤖 Prompt for AI Agents
In
backendProject/src/main/java/likelion/mlb/backendProject/domain/chat/controller/ChatReadController.java
around lines 30 to 36, fix the typo in the Swagger @Operation summary: change
the Korean text "릶음 상태 조회" to the correct "읽음 상태 조회" so the API documentation
displays the proper summary; update only the summary string literal to the
corrected spelling.

Comment on lines +59 to 62
public ChatRoom getChatRoomByDraft(@Parameter(description = "드래프트 ID", required = true) @PathVariable UUID draftId) {
return chatRoomRepository.findByDraftId(draftId)
.orElseThrow(() -> new IllegalArgumentException("ChatRoom not found for draft " + draftId));
}
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

문서(404)와 런타임 불일치: 404로 매핑되도록 예외 형식 변경 필요

현재는 IllegalArgumentException을 던져 500으로 번역될 수 있습니다. 문서대로 404를 보장하려면 ResponseStatusException(HttpStatus.NOT_FOUND, ...)로 변경하세요.

-    return chatRoomRepository.findByDraftId(draftId)
-        .orElseThrow(() -> new IllegalArgumentException("ChatRoom not found for draft " + draftId));
+    return chatRoomRepository.findByDraftId(draftId)
+        .orElseThrow(() -> new org.springframework.web.server.ResponseStatusException(
+            org.springframework.http.HttpStatus.NOT_FOUND, "ChatRoom not found for draft " + draftId));

필요 시 import 추가:

+import org.springframework.http.HttpStatus;
+import org.springframework.web.server.ResponseStatusException;
🤖 Prompt for AI Agents
In
backendProject/src/main/java/likelion/mlb/backendProject/domain/chat/controller/ChatRoomQueryController.java
around lines 59 to 62, the method currently throws IllegalArgumentException
which can produce a 500 response; replace that with throwing a
ResponseStatusException(HttpStatus.NOT_FOUND, "ChatRoom not found for draft " +
draftId) so the framework returns a 404 as documented, and add the required
import(s) (org.springframework.web.server.ResponseStatusException and
org.springframework.http.HttpStatus) if they are not present.

@Tag(name = "Player Search", description = "선수 검색 API (Elasticsearch)")
@RestController
@RequiredArgsConstructor
@RequestMapping("api/playerEs")
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

요청 매핑 경로 선행 슬래시 누락 — 실제 라우팅 오류 위험

  • @RequestMapping("api/playerEs")는 선행 "/"가 없어 다른 컨트롤러들과 불일치합니다. 스프링은 보통 선행 "/"를 사용하는 것이 표준이며, 일부 설정에 따라 의도치 않은 경로가 잡힐 수 있습니다.

즉시 아래 수정 권장:

-@RequestMapping("api/playerEs")
+@RequestMapping("/api/playerEs")
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
@RequestMapping("api/playerEs")
@RequestMapping("/api/playerEs")
🤖 Prompt for AI Agents
In
backendProject/src/main/java/likelion/mlb/backendProject/domain/player/elasticsearch/controller/PlayerEsController.java
around line 27, the @RequestMapping lacks a leading slash which can cause
inconsistent routing; update the annotation value to include a leading "/"
(e.g., "/api/playerEs") so the controller's base path matches other controllers
and avoids potential routing mismatches.

@jaehyeok-code jaehyeok-code merged commit 801f4b4 into dev Aug 26, 2025
1 check was pending
@jaehyeok-code jaehyeok-code deleted the feat/#78 branch August 26, 2025 19:11
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

documentation Improvements or additions to documentation enhancement New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant