Skip to content

Refactor : 응답 DTO 개선#44

Merged
lejuho merged 2 commits into
developfrom
refactor/프론트에-맞춰-명세-수정
Aug 21, 2025

Hidden character warning

The head ref may contain hidden characters: "refactor/\ud504\ub860\ud2b8\uc5d0-\ub9de\ucdb0-\uba85\uc138-\uc218\uc815"
Merged

Refactor : 응답 DTO 개선#44
lejuho merged 2 commits into
developfrom
refactor/프론트에-맞춰-명세-수정

Conversation

@c5ln

@c5ln c5ln commented Aug 21, 2025

Copy link
Copy Markdown
Member

Notion API 명세 정리 과정에서 사소한 수정

수정된 파일 :
src/main/java/com/example/cp_main_be/domain/admin/dto/AdminResponseDTO.java
src/main/java/com/example/cp_main_be/domain/admin/presentation/AdminController.java
src/main/java/com/example/cp_main_be/domain/mission/quiz/dto/QuizRequestDTO.java
src/main/java/com/example/cp_main_be/domain/mission/user_daily_mission/service/UserDailyMissionService.java
src/main/java/com/example/cp_main_be/domain/mission/user_daily_mission/presentation/UserDailyMissionController.java

Summary by CodeRabbit

  • Refactor
    • 관리자 사용자/신고 응답을 경량 DTO로 통일해 사용자 목록·신고 목록·신고 상태 갱신의 반환 필드를 명확화했습니다.
  • New Features
    • 퀴즈 제출 요청에 quizType(문항 유형)과 selectedOptionId(선택 옵션 ID)를 추가하여 입력 형식을 확장했습니다.
  • Bug Fixes
    • 일일미션 사진 업로드 엔드포인트가 multipart/form-data를 명시적으로 요구하도록 수정해 업로드 호환성을 개선했습니다.

@c5ln c5ln requested review from lejuho and xoruddl August 21, 2025 07:01
@c5ln c5ln self-assigned this Aug 21, 2025
@c5ln c5ln added the enhancement 기존 기능 개선 label Aug 21, 2025
@c5ln c5ln linked an issue Aug 21, 2025 that may be closed by this pull request
@coderabbitai

coderabbitai Bot commented Aug 21, 2025

Copy link
Copy Markdown

Walkthrough

Admin 응답 DTO(UserResDTO, ReportResDTO)를 추가하고 AdminController의 사용자/신고 조회 및 신고 상태 변경 반환을 DTO로 변경했습니다. QuizRequestDTO는 answerNumber를 제거하고 quizType·selectedOptionId를 추가했으며 서비스는 비교 기준을 selectedOptionId로 변경했습니다. 사진 업로드 엔드포인트는 multipart/form-data를 명시했습니다.

Changes

Cohort / File(s) Summary
Admin 응답 DTO 및 컨트롤러 반환 타입 변경
src/main/java/.../admin/dto/AdminResponseDTO.java, src/main/java/.../admin/presentation/AdminController.java
AdminResponseDTO에 UserResDTO, ReportResDTO 추가. AdminController의 getUsers/getAllReports/updateReportStatus가 도메인 엔티티 대신 해당 DTO를 반환하도록 스트림 매핑 및 빌더 사용으로 변경. 일부 경로 변수 이름 표준화(주석·매핑 수준).
퀴즈 요청/서비스 변경
src/main/java/.../mission/quiz/dto/QuizRequestDTO.java, src/main/java/.../mission/user_daily_mission/service/UserDailyMissionService.java
QuizRequestDTO: answerNumber 제거, quizType(enum) 및 selectedOptionId 추가. UserDailyMissionService의 summitAnswer 로직에서 선택 비교 기준을 answerNumberselectedOptionId로 변경.
사진 업로드 Content-Type 명시
src/main/java/.../mission/user_daily_mission/presentation/UserDailyMissionController.java
uploadPictureForMission 매핑에 consumes = MediaType.MULTIPART_FORM_DATA_VALUE 추가(엔드포인트 경로 및 메서드 시그니처 불변).

Sequence Diagram(s)

sequenceDiagram
  autonumber
  actor Admin as 관리자
  participant AC as AdminController
  participant AS as AdminService
  participant AR as AdminRepository
  note over Admin,AC: 사용자/신고 조회 → DTO 매핑 후 반환
  Admin->>AC: GET /admin/users
  AC->>AS: findAllUsers()
  AS->>AR: load users
  AR-->>AS: List<User>
  AS-->>AC: List<User>
  AC->>AC: map to UserResDTO
  AC-->>Admin: ApiResponse<ListResponse<UserResDTO>>

  Admin->>AC: GET /admin/reports
  AC->>AS: findAllReports()
  AS->>AR: load reports
  AR-->>AS: List<Reports>
  AS-->>AC: List<Reports>
  AC->>AC: map to ReportResDTO
  AC-->>Admin: ApiResponse<ListResponse<ReportResDTO>>

  Admin->>AC: PATCH /admin/reports/{id}/status
  AC->>AS: updateStatus(id, payload)
  AS->>AR: save report
  AR-->>AS: Reports
  AS-->>AC: Reports
  AC->>AC: build ReportResDTO
  AC-->>Admin: ApiResponse<ReportResDTO>
Loading
sequenceDiagram
  autonumber
  actor User as 사용자
  participant C as UserDailyMissionController
  participant S as UserDailyMissionService
  participant Q as QuizOptionRepository
  note over User,C: 퀴즈 답안 제출 (selectedOptionId 사용)
  User->>C: POST /missions/quiz/answer { quizType, selectedOptionId }
  C->>S: summitAnswer(request)
  S->>Q: load quiz options
  Q-->>S: List<QuizOption>
  S->>S: if option.optionOrder == selectedOptionId then select
  S->>S: 판단(isCorrect) 및 저장/점수 처리
  S-->>C: 결과
  C-->>User: ApiResponse
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Suggested reviewers

  • xoruddl

Poem

귀 쫑긋 버니가 말하네, DTO를 포근히 안고,
사용자와 신고는 새 옷을 입었네.
퀴즈는 번호 말고 선택으로 찰칵찰칵,
사진은 멀티파트로 탁! 올려주오.
바삭한 코드밭에 귀성한 작은 발자국 🐇✨

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 632f27a and 5f86967.

📒 Files selected for processing (1)
  • src/main/java/com/example/cp_main_be/domain/mission/quiz/dto/QuizRequestDTO.java (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • src/main/java/com/example/cp_main_be/domain/mission/quiz/dto/QuizRequestDTO.java
✨ Finishing Touches
  • 📝 Generate Docstrings
🧪 Generate unit tests
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch refactor/프론트에-맞춰-명세-수정

🪧 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.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 1

Caution

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

⚠️ Outside diff range comments (5)
src/main/java/com/example/cp_main_be/domain/admin/presentation/AdminController.java (4)

51-59: @PathVariable 이름 불일치로 런타임 바인딩 실패 가능

경로 변수는 {dailyMissionMasterId}인데 파라미터 명이 id라서 매핑 실패/400 발생 가능성이 높습니다. 아래처럼 파라미터 명을 맞추고 서비스 호출 인자도 교정하세요. 또한 본 파일 전반에 Spotless 포맷 위반이 있어 아래 수정 후 ./gradlew spotlessApply 실행이 필요합니다.

-  @PutMapping("/missions/daily/{dailyMissionMasterId}")
-  @Operation(summary = "일일 미션(미션마스터) 수정 API")
-  public ResponseEntity<ApiResponse<AdminResponseDTO.DailyMissionMastersResDTO>> updateDailyMission(
-      @RequestBody AdminRequestDTO.UpdateMissionRequestDTO requestDTO, @PathVariable Long id) {
-    DailyMissionMaster response = adminService.updateDailyMissionMasters(requestDTO, id);
+  @PutMapping("/missions/daily/{dailyMissionMasterId}")
+  @Operation(summary = "일일 미션(미션마스터) 수정 API")
+  public ResponseEntity<ApiResponse<AdminResponseDTO.DailyMissionMastersResDTO>> updateDailyMission(
+      @RequestBody AdminRequestDTO.UpdateMissionRequestDTO requestDTO,
+      @PathVariable(name = "dailyMissionMasterId") Long dailyMissionMasterId) {
+    DailyMissionMaster response =
+        adminService.updateDailyMissionMasters(requestDTO, dailyMissionMasterId);

108-116: 요청 본문 바인딩 누락 — @RequestBody 추가 필요

JSON 바디를 받는 API인데 requestDTO@RequestBody가 없어 415/400이 발생할 수 있습니다. 아래처럼 명시적으로 추가하세요.

   @Operation(summary = "식물 정보 수정 API")
   public ResponseEntity<ApiResponse<AdminResponseDTO.PlantMasterResDTO>> updatePlantMasters(
-      @PathVariable(name = "plantId") Long plantId,
-      AdminRequestDTO.UpdatePlantMasterRequestDTO requestDTO) {
+      @PathVariable(name = "plantId") Long plantId,
+      @RequestBody AdminRequestDTO.UpdatePlantMasterRequestDTO requestDTO) {

91-97: 요청 본문 바인딩 누락 — @RequestBody 추가 필요

퀴즈 선지 등록 API도 바디를 받으므로 @RequestBody가 필요합니다.

   @Operation(summary = "퀴즈 선지 등록 API")
   public ResponseEntity<ApiResponse<QuizOptions>> createQuizOption(
-      AdminRequestDTO.CreateQuizRequestDTO requestDTO) {
+      @RequestBody AdminRequestDTO.CreateQuizRequestDTO requestDTO) {

99-106: 요청 본문 바인딩 누락 — @RequestBody 추가 필요

새 식물 등록 API에도 @RequestBody가 없습니다.

   @Operation(summary = "새 식물 등록 API")
   public ResponseEntity<ApiResponse<AdminResponseDTO.PlantMasterResDTO>> createNewPlant(
-      AdminRequestDTO.CreatePlantMasterRequestDTO requestDTO) {
+      @RequestBody AdminRequestDTO.CreatePlantMasterRequestDTO requestDTO) {
src/main/java/com/example/cp_main_be/domain/mission/user_daily_mission/service/UserDailyMissionService.java (1)

76-81: 선택 옵션 식별자 비교 로직 오류 — optionOrder가 아니라 optionId로 비교해야 함

요청 필드명이 selectedOptionId로 바뀌었는데 여전히 optionOrder와 비교하고 있어 항상 매칭 실패하거나 오작동할 수 있습니다. 옵션의 PK(ID)로 비교하도록 수정하세요. 또한 DTO 측 타입(Long)과 일치시켜 NPE 없이 비교하는 것이 안전합니다.

-    for (QuizOptions quizOptions : quizOptionsList) {
-      if (quizOptions.getOptionOrder() == request.getSelectedOptionId()) {
-        selectedOption = quizOptions;
-        isCorrect = quizOptions.isCorrect();
-        break;
-      }
-    }
+    for (QuizOptions quizOptions : quizOptionsList) {
+      if (java.util.Objects.equals(quizOptions.getId(), request.getSelectedOptionId())) {
+        selectedOption = quizOptions;
+        isCorrect = quizOptions.isCorrect();
+        break;
+      }
+    }

추가로, DTO의 selectedOptionId 타입을 Long으로 변경하는 수정이 함께 필요합니다(아래 DTO 코멘트 참고).

🧹 Nitpick comments (4)
src/main/java/com/example/cp_main_be/domain/admin/presentation/AdminController.java (2)

71-79: 컨트롤러에서 DTO 매핑 로직 분리 권장(가독성/재사용성)
현재 스트림 내부에서 직접 빌더를 호출하고 있어 컨트롤러 메서드가 장황해집니다. Mapper(정적 팩토리 또는 전용 Mapper 클래스)로 추출하면 재사용과 테스트가 용이합니다.

예: AdminResponseDTO.UserResDTO from(User u) 정적 메서드 도입 후 users.stream().map(AdminResponseDTO.UserResDTO::from).toList()


120-132: 변수명 혼동: report 스트림에서 request 사용

신고 엔티티를 매핑하는 람다 변수명이 request라 가독성이 떨어집니다. report로 변경해 의미 명확히 하세요.

-    ListResponse<AdminResponseDTO.ReportResDTO> listResponse = new ListResponse<>(reports.stream()
-            .map(request -> AdminResponseDTO.ReportResDTO.builder()
-                    .reportReason(request.getReason())
-                    .reportDate(request.getCreatedAt())
-                    .reportId(request.getId())
-                    .status(request.getStatus())
-                    .reviewDate(request.getReviewedAt())
-                    .reviewerId(request.getReviewerId())
-                    .build()
-            ).toList());
+    ListResponse<AdminResponseDTO.ReportResDTO> listResponse = new ListResponse<>(
+        reports.stream()
+            .map(report -> AdminResponseDTO.ReportResDTO.builder()
+                .reportReason(report.getReason())
+                .reportDate(report.getCreatedAt())
+                .reportId(report.getId())
+                .status(report.getStatus())
+                .reviewDate(report.getReviewedAt())
+                .reviewerId(report.getReviewerId())
+                .build())
+            .toList());
src/main/java/com/example/cp_main_be/domain/mission/user_daily_mission/service/UserDailyMissionService.java (1)

59-105: 메서드명 오탈자(summitAnswer → submitAnswer) 정정 제안

외부 공개 API와 서비스 전반에 동일 오탈자가 퍼질 수 있어 조기 교정 권장합니다. 컨트롤러의 호출부도 함께 변경 필요.

src/main/java/com/example/cp_main_be/domain/mission/user_daily_mission/presentation/UserDailyMissionController.java (1)

67-71: 멀티파트 파일 파라미터는 @RequestPart 사용 권장

현재도 동작하지만, 멀티파트 본문에서 파일을 받는 경우 @RequestPart가 더 명시적이며 Swagger 문서에도 잘 반영됩니다.

-  public ResponseEntity<ApiResponse<String>> uploadPictureForMission(
-      @RequestParam MultipartFile file,
+  public ResponseEntity<ApiResponse<String>> uploadPictureForMission(
+      @RequestPart("file") MultipartFile file,
       @PathVariable(name = "userDailyMissionId") Long userDailyMissionId) {
📜 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 b3113a8 and 632f27a.

📒 Files selected for processing (5)
  • src/main/java/com/example/cp_main_be/domain/admin/dto/AdminResponseDTO.java (2 hunks)
  • src/main/java/com/example/cp_main_be/domain/admin/presentation/AdminController.java (4 hunks)
  • src/main/java/com/example/cp_main_be/domain/mission/quiz/dto/QuizRequestDTO.java (1 hunks)
  • src/main/java/com/example/cp_main_be/domain/mission/user_daily_mission/presentation/UserDailyMissionController.java (2 hunks)
  • src/main/java/com/example/cp_main_be/domain/mission/user_daily_mission/service/UserDailyMissionService.java (1 hunks)
🧰 Additional context used
🧬 Code graph analysis (1)
src/main/java/com/example/cp_main_be/domain/admin/presentation/AdminController.java (1)
src/main/java/com/example/cp_main_be/domain/admin/dto/AdminResponseDTO.java (1)
  • AdminResponseDTO (12-56)
🪛 GitHub Actions: Spring Boot CI/CD with AWS
src/main/java/com/example/cp_main_be/domain/admin/dto/AdminResponseDTO.java

[error] 1-1: Spotless formatting violation: Java imports out of order / duplicate imports in AdminResponseDTO.java. Run './gradlew spotlessApply' to fix.

src/main/java/com/example/cp_main_be/domain/mission/user_daily_mission/presentation/UserDailyMissionController.java

[error] 1-1: Spotless formatting violation detected in UserDailyMissionController.java. Run './gradlew spotlessApply' to fix.

src/main/java/com/example/cp_main_be/domain/admin/presentation/AdminController.java

[error] 1-1: Spotless formatting violation detected in AdminController.java (import alignment and code formatting). Run './gradlew spotlessApply' to fix.

🔇 Additional comments (5)
src/main/java/com/example/cp_main_be/domain/admin/dto/AdminResponseDTO.java (2)

38-55: 신규 응답 DTO(UserResDTO, ReportResDTO) 추가 적절

필드 구성과 명명 일관성 좋습니다. 프론트 요구사항과 매핑도 명확합니다.


5-9: JAVA_HOME 설정 후 Spotless 자동 포맷 적용 필요

  • 대상 파일: src/main/java/com/example/cp_main_be/domain/admin/dto/AdminResponseDTO.java (Lines 5–9)
    Spotless import 정렬 규칙(그룹별 빈 줄, 알파벳 순 등)을 위반하여 CI가 실패 중입니다.

  • 로컬에서 Spotless를 실행하려면 Java 설치 및 JAVA_HOME 환경 변수를 올바르게 설정해야 합니다. 예시:

    # Java 설치 경로에 맞춰 수정
    export JAVA_HOME=/path/to/your/java
    ./gradlew spotlessApply && ./gradlew spotlessCheck
  • 위 과정을 완료한 후 CI가 통과되는지 확인 부탁드립니다.

src/main/java/com/example/cp_main_be/domain/admin/presentation/AdminController.java (1)

137-151: 신고 상태 변경 응답을 DTO로 통일 — 일관성 좋아요

도메인 엔티티를 직접 노출하지 않고 DTO로 응답하도록 맞춘 점이 좋습니다.

src/main/java/com/example/cp_main_be/domain/mission/user_daily_mission/presentation/UserDailyMissionController.java (2)

63-65: 멀티파트 소비 명시 좋습니다

프론트-백엔드 간 Content-Type 불일치 이슈를 방지하는 좋은 변경입니다.


13-13: Spotless 포맷 적용 필요

본 파일도 Spotless 포맷 위반으로 CI가 실패했습니다. ./gradlew spotlessApply로 정렬/개행을 맞춰주세요.

Comment thread src/main/java/com/example/cp_main_be/domain/mission/quiz/dto/QuizRequestDTO.java Outdated

@lejuho lejuho left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

LGTM

@lejuho lejuho merged commit 7103b3d into develop Aug 21, 2025
5 of 6 checks passed
@lejuho lejuho deleted the refactor/프론트에-맞춰-명세-수정 branch August 25, 2025 08:13
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement 기존 기능 개선

Projects

None yet

Development

Successfully merging this pull request may close these issues.

프론트에 맞춰 명세 수정

2 participants