-
Notifications
You must be signed in to change notification settings - Fork 3
feat : 신고 기능 개발 #87
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
feat : 신고 기능 개발 #87
Conversation
## Walkthrough
신고 기능을 위한 도메인, 서비스, 컨트롤러, DTO, 레포지토리 등 전반적인 구조가 새롭게 추가 및 확장되었습니다. 신고 대상, 타입, 상태 등 엔티티 구조가 세분화되었으며, 신고 생성, 목록 조회, 상세 조회, 상태 변경 등 주요 API와 서비스 로직이 구현되었습니다.
## Changes
| 파일/경로 요약 | 변경 내용 요약 |
|---|---|
| .../report/dto/ReportChangeResponse.java<br>.../ReportDetailResponse.java<br>.../ReportListResponse.java<br>.../ReportRequest.java<br>.../ReportResponse.java<br>.../ReportStatusUpdateRequest.java | 신고 관련 DTO 및 요청/응답 record, 클래스 신규 추가 (상태 변경, 상세, 목록, 요청, 응답 등) |
| .../report/port/ReportRepository.java | 패키지 선언 후 공백 한 줄 추가 (기능 변화 없음) |
| .../report/service/ReportService.java | 신고 생성, 목록/상세 조회, 상태 변경을 담당하는 서비스 클래스 및 메서드 신규 추가 |
| .../domain/report/model/Report.java | 신고 엔티티 구조 변경: 신고 대상(User) → targetId(Long), targetType(enum)로 분리, 생성자 및 상태 변경 메서드 추가, imageUrl nullable 변경 등 |
| .../domain/report/model/ReportStatus.java | 상태 enum의 주석 제거, 예외 메시지 한글화, @JsonCreator 추가 |
| .../domain/report/model/ReportTargetType.java | 신고 대상 타입 enum 신설 (USER, PROBLEM, POST, COMMENT, OTHER) |
| .../domain/report/model/ReportType.java | 신고 타입 enum에 PROBLEM_ERROR 추가, from 메서드 파라미터명 및 예외 메시지 한글화 |
| .../domain/report/repository/ReportRepository.java | Spring Data JPA 기반 신고 레포지토리 인터페이스 신규 추가 |
| .../domain/report/service/ReportDomainService.java | 서비스 클래스화(@Service), 자기 자신 신고 방지 로직 추가 |
| .../presentation/ReportController.java | 기존 빈 컨트롤러 클래스 삭제 |
| .../presentation/report/ReportAdminController.java | 신고 관리자용 REST 컨트롤러 신규 추가: 목록, 상세, 상태 변경 API |
| .../presentation/report/ReportController.java | 신고 등록용 REST 컨트롤러 신규 추가: POST /api/reports |
| .../resources/application.properties | spring.application.name 값을 "min" → "ezcode"로 변경 |
## Sequence Diagram(s)
```mermaid
sequenceDiagram
participant 사용자
participant ReportController
participant ReportService
participant UserRepository
participant ReportRepository
사용자->>ReportController: POST /api/reports (신고 등록)
ReportController->>ReportService: submitReport(reporterId, request)
ReportService->>UserRepository: findById(reporterId)
UserRepository-->>ReportService: User 반환
ReportService->>ReportRepository: save(Report)
ReportRepository-->>ReportService: 저장된 Report 반환
ReportService-->>ReportController: ReportResponse 반환
ReportController-->>사용자: 신고 결과 응답sequenceDiagram
participant 관리자
participant ReportAdminController
participant ReportService
participant ReportRepository
관리자->>ReportAdminController: GET /api/reports/admin (신고 목록)
ReportAdminController->>ReportService: getReportList(pageable)
ReportService->>ReportRepository: findAll(pageable)
ReportRepository-->>ReportService: Page<Report> 반환
ReportService-->>ReportAdminController: Page<ReportListResponse> 반환
ReportAdminController-->>관리자: 신고 목록 응답
관리자->>ReportAdminController: PATCH /api/reports/admin/{id}/status (상태 변경)
ReportAdminController->>ReportService: updateReportStatus(reportId, request)
ReportService->>ReportRepository: findById(reportId)
ReportRepository-->>ReportService: Report 반환
ReportService-->>ReportAdminController: 상태 변경 결과 반환
ReportAdminController-->>관리자: 변경 메시지 응답
Suggested reviewers
Poem
✨ Finishing Touches
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. 🪧 TipsChatThere are 3 ways to chat with CodeRabbit:
SupportNeed help? Create a ticket on our support page for assistance with any issues or questions. Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments. CodeRabbit Commands (Invoked using PR comments)
Other keywords and placeholders
CodeRabbit Configuration File (
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 18
🧹 Nitpick comments (9)
src/main/java/org/ezcode/codetest/application/report/dto/ReportStatusUpdateRequest.java (1)
5-8: 추가 유효성 검증을 고려해보세요현재
@NotBlank만 적용되어 있지만, 유효한 상태값인지 검증하는 커스텀 검증 어노테이션을 추가하는 것을 고려해보세요. 예를 들어@ValidReportStatus와 같은 어노테이션을 만들어 ReportStatus enum의 유효한 값만 허용하도록 할 수 있습니다.public record ReportStatusUpdateRequest( + @ValidReportStatus @NotBlank String newStatus // 예시 RESOLVED(해결됨), REJECTED(거절) ) {}src/main/java/org/ezcode/codetest/application/report/dto/ReportDetailResponse.java (1)
3-14: API 문서화 및 타입 일관성을 개선하세요
- Swagger 문서화 어노테이션 추가를 고려해보세요.
- 날짜 필드의 타입 일관성을 확인하세요. 다른 DTO들과 동일한 패턴을 사용하는지 검토가 필요합니다.
+@Schema(name = "ReportDetailResponse", description = "신고 상세 조회 응답") public record ReportDetailResponse( + @Schema(description = "신고 ID") Long reportId, + @Schema(description = "신고자 이메일") String reporterEmail, // ... 다른 필드들에도 @Schema 추가 String createdAt, String modifiedAt ) {}src/main/java/org/ezcode/codetest/application/report/dto/ReportListResponse.java (1)
3-12: API 문서화를 추가하세요목록 조회용 DTO로서 적절한 필드 구성을 가지고 있지만, API 문서화를 위한 Swagger 어노테이션 추가를 고려해보세요.
+@Schema(name = "ReportListResponse", description = "신고 목록 조회 응답") public record ReportListResponse( + @Schema(description = "신고 ID") Long reportId, + @Schema(description = "신고자 이메일") String reporterEmail, // ... 다른 필드들에도 @Schema 추가 String createdAt ) {}src/main/java/org/ezcode/codetest/presentation/report/ReportController.java (1)
12-15: 중복된 import문을 정리해주세요.개별 import와 와일드카드 import가 중복되어 있습니다.
다음과 같이 정리해주세요:
-import org.springframework.web.bind.annotation.PostMapping; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.RestController; -import org.springframework.web.bind.annotation.*; +import org.springframework.web.bind.annotation.*;src/main/java/org/ezcode/codetest/presentation/report/ReportAdminController.java (4)
22-29: 페이징 기본값 확인 필요기본 페이지 크기가 10으로 설정되어 있습니다. 관리자 페이지에서는 더 많은 데이터를 한 번에 볼 필요가 있을 수 있습니다.
관리자용이므로 페이지 크기를 늘리는 것을 고려해보세요:
- @PageableDefault(size = 10, sort = "createdAt", direction = Sort.Direction.DESC) + @PageableDefault(size = 20, sort = "createdAt", direction = Sort.Direction.DESC)
23-29: 페이징 파라미터 검증을 추가하는 것이 좋습니다.페이징 기본값은 적절하지만, 최대 크기 제한을 추가하여 성능 문제를 예방할 수 있습니다.
- @PageableDefault(size = 10, sort = "createdAt", direction = Sort.Direction.DESC) + @PageableDefault(size = 10, sort = "createdAt", direction = Sort.Direction.DESC) + @Parameter(description = "페이지 정보 (최대 100개)") Pageable pageable) { + + if (pageable.getPageSize() > 100) { + pageable = PageRequest.of(pageable.getPageNumber(), 100, pageable.getSort()); + }
48-49: 불필요한 빈 줄을 제거하세요.파일 끝의 불필요한 빈 줄들을 제거해주세요.
- -} +}
38-46: 응답 메시지 생성 시 사용자 입력 검증을 강화하세요.44번 라인에서
request.newStatus()를 직접 문자열 연결에 사용하고 있습니다. 비록@Valid어노테이션으로 검증하고 있지만, 응답 메시지에 포함되기 전에 추가적인 검증이나 이스케이프 처리를 고려해보세요.- String message = request.newStatus() + "로 변경 완료되었습니다."; + String message = "상태가 " + request.newStatus() + "로 변경 완료되었습니다.";src/main/java/org/ezcode/codetest/application/report/service/ReportService.java (1)
55-55: 성능 최적화 고려사항
findAll(pageable)을 사용하고 있는데, 데이터가 많아질 경우 성능 이슈가 있을 수 있습니다. 필터링이나 검색 기능이 필요할 수 있습니다.향후 확장성을 위해 다음과 같은 개선을 고려해보세요:
- 상태별 필터링
- 날짜 범위 검색
- 신고 타입별 필터링
- 인덱스 최적화
현재는 승인하지만, 사용량이 늘어나면 쿼리 최적화가 필요할 것입니다.
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (18)
src/main/java/org/ezcode/codetest/application/report/dto/ReportChangeResponse.java(1 hunks)src/main/java/org/ezcode/codetest/application/report/dto/ReportDetailResponse.java(1 hunks)src/main/java/org/ezcode/codetest/application/report/dto/ReportListResponse.java(1 hunks)src/main/java/org/ezcode/codetest/application/report/dto/ReportRequest.java(1 hunks)src/main/java/org/ezcode/codetest/application/report/dto/ReportResponse.java(1 hunks)src/main/java/org/ezcode/codetest/application/report/dto/ReportStatusUpdateRequest.java(1 hunks)src/main/java/org/ezcode/codetest/application/report/port/ReportRepository.java(1 hunks)src/main/java/org/ezcode/codetest/application/report/service/ReportService.java(1 hunks)src/main/java/org/ezcode/codetest/domain/report/model/Report.java(1 hunks)src/main/java/org/ezcode/codetest/domain/report/model/ReportStatus.java(1 hunks)src/main/java/org/ezcode/codetest/domain/report/model/ReportTargetType.java(1 hunks)src/main/java/org/ezcode/codetest/domain/report/model/ReportType.java(2 hunks)src/main/java/org/ezcode/codetest/domain/report/repository/ReportRepository.java(1 hunks)src/main/java/org/ezcode/codetest/domain/report/service/ReportDomainService.java(1 hunks)src/main/java/org/ezcode/codetest/presentation/ReportController.java(0 hunks)src/main/java/org/ezcode/codetest/presentation/report/ReportAdminController.java(1 hunks)src/main/java/org/ezcode/codetest/presentation/report/ReportController.java(1 hunks)src/main/resources/application.properties(1 hunks)
💤 Files with no reviewable changes (1)
- src/main/java/org/ezcode/codetest/presentation/ReportController.java
⏰ Context from checks skipped due to timeout of 90000ms (1)
- GitHub Check: build
🔇 Additional comments (22)
src/main/java/org/ezcode/codetest/application/report/dto/ReportChangeResponse.java (1)
6-9: 단일 메시지 응답 DTO 검증
ReportChangeResponse는 변경 상태에 대한 단일message필드를 갖고 있으며, Lombok의@Getter와@AllArgsConstructor로 간결하게 구현되었습니다. 직렬화 전용 응답 DTO로서 적절하며, 추가 애노테이션 없이도 Jackson이 getter 기반으로 직렬화할 수 있습니다.src/main/resources/application.properties (1)
4-4: 애플리케이션 이름 변경 확인
spring.application.name을 기존"min"에서"ezcode"로 변경했습니다. 로깅, 모니터링(Actuator) 및 분산 트레이싱 시스템에 올바르게 반영되는지 검증이 필요합니다.src/main/java/org/ezcode/codetest/domain/report/model/ReportTargetType.java (1)
3-9: 리포트 대상 타입(Enum) 검토
USER,PROBLEM,POST,COMMENT,OTHER등 필요한 대상 타입이 모두 정의되었습니다. 문자열 매핑 시IllegalArgumentException이 발생할 수 있으므로, 서비스 계층에서 사용자 입력을ReportTargetType으로 변환·검증하는 로직이 완전한지 확인하세요.src/main/java/org/ezcode/codetest/domain/report/repository/ReportRepository.java (1)
6-7: 도메인 레포지토리 정의 확인
ReportRepository extends JpaRepository<Report, Long>로 표준 CRUD 및 페이징 기능을 제공하며, Spring Data JPA가 자동으로 빈으로 등록합니다. 추가 애노테이션 없이도 정상 작동합니다.src/main/java/org/ezcode/codetest/domain/report/model/ReportStatus.java (2)
9-13: 한국어 설명 추가가 적절합니다각 상태값에 대한 한국어 설명이 명확하게 추가되어 사용자 친화적인 인터페이스 구현에 도움이 됩니다.
20-25: 예외 메시지의 한국어 변경이 적절합니다사용자에게 더 친숙한 한국어 오류 메시지로 변경되어 사용성이 향상되었습니다. 대소문자를 구분하지 않는 변환 로직도 올바르게 구현되어 있습니다.
src/main/java/org/ezcode/codetest/application/report/dto/ReportResponse.java (1)
5-12: 잘 구현된 DTO입니다Swagger 문서화가 적절히 적용되어 있고, 신고 응답에 필요한 핵심 정보들이 잘 구성되어 있습니다. 다른 DTO들의 문서화 참고 모델로 활용할 수 있습니다.
src/main/java/org/ezcode/codetest/application/report/dto/ReportRequest.java (1)
6-20: DTO 구조와 검증이 적절하게 구현되었습니다.레코드 클래스를 사용한 불변 DTO 설계가 좋고, 필수 필드에 대한 검증 어노테이션도 적절히 적용되었습니다.
src/main/java/org/ezcode/codetest/domain/report/model/ReportType.java (1)
27-32: from() 메서드 리팩토링이 깔끔하게 구현되었습니다.파라미터명 변경과 에러 메시지 한국어 적용이 적절합니다.
src/main/java/org/ezcode/codetest/domain/report/service/ReportDomainService.java (1)
8-17: 도메인 서비스 구현이 적절합니다.비즈니스 규칙을 도메인 레이어에서 처리하고, 자기 자신 신고 방지 로직이 명확하게 구현되었습니다.
src/main/java/org/ezcode/codetest/presentation/report/ReportController.java (1)
25-31: REST 엔드포인트 구현이 적절합니다.인증 처리, 요청 검증, 응답 구조가 잘 구현되었습니다.
src/main/java/org/ezcode/codetest/domain/report/model/Report.java (3)
24-29: 엔티티 리팩토링이 적절하게 구현되었습니다.
target필드를targetId와targetType으로 분리하여 다양한 대상 타입을 지원할 수 있도록 개선되었습니다.
43-52: 생성자 업데이트가 새로운 필드 구조에 맞게 잘 구현되었습니다.새로운 필드들에 대한 초기화와 기본 상태 설정이 적절합니다.
54-57: 상태 변경 메서드가 적절하게 캡슐화되었습니다.
updateStatus메서드를 통해 상태 변경 로직을 캡슐화한 것이 좋습니다.src/main/java/org/ezcode/codetest/presentation/report/ReportAdminController.java (4)
14-19: 컨트롤러 구조 승인표준 Spring Boot 패턴을 잘 따르고 있습니다.
@RequiredArgsConstructor를 사용한 생성자 주입과 적절한 어노테이션 사용이 좋습니다.
1-19: 클래스 구조와 의존성 주입이 적절히 구현되었습니다.Spring Boot의 모범 사례를 잘 따르고 있으며,
@RequiredArgsConstructor를 사용한 생성자 주입 방식이 적절합니다.
22-29: 페이징 처리가 잘 구현되어 있습니다.
@PageableDefault를 사용하여 기본 페이지 크기와 정렬 조건을 설정한 것이 좋습니다. 생성일 기준 내림차순 정렬도 신고 관리에 적합합니다.
32-35: 단순하고 명확한 상세 조회 구현입니다.경로 변수를 통한 ID 전달과 서비스 호출이 적절히 구현되어 있습니다.
src/main/java/org/ezcode/codetest/application/report/service/ReportService.java (4)
14-20: 서비스 클래스 구조 승인적절한 어노테이션 사용과 의존성 주입 패턴이 잘 적용되어 있습니다.
1-20: 서비스 클래스 구조가 적절하게 설계되었습니다.의존성 주입과 어노테이션 사용이 Spring Boot 모범 사례를 잘 따르고 있습니다.
30-32: 자기 신고 방지 로직이 잘 구현되었습니다.비즈니스 규칙을 명확하게 검증하고 있어 좋습니다.
53-66: 트랜잭션 설정과 페이징 처리가 적절합니다.읽기 전용 트랜잭션 설정과 스트림을 활용한 DTO 매핑이 잘 구현되어 있습니다.
|
|
||
| public interface ReportRepository { | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
포트 인터페이스 구현 누락
application.report.port.ReportRepository는 서비스 레이어에서 의존할 포트 정의로 보이나, 메서드 시그니처가 없고 이를 구현한 인프라스트럭처 어댑터도 존재하지 않습니다. 이대로면 의존성 주입 시 빈 충돌 또는 NoSuchBeanDefinitionException이 발생할 수 있습니다.
🤖 Prompt for AI Agents
In
src/main/java/org/ezcode/codetest/application/report/port/ReportRepository.java
at lines 3 to 5, the ReportRepository interface is empty and lacks method
signatures, and there is no implementing infrastructure adapter. Define
appropriate method signatures in this interface that represent the required
report-related operations, then create a corresponding implementation class in
the infrastructure layer to implement these methods. This will ensure proper
dependency injection and avoid bean definition errors.
src/main/java/org/ezcode/codetest/domain/report/model/ReportType.java
Outdated
Show resolved
Hide resolved
| // 신고 상태 변경 | ||
| @PatchMapping("/{reportId}/status") | ||
| public ResponseEntity<ReportChangeResponse> changeStatus( | ||
| @PathVariable Long reportId, | ||
| @RequestBody @Valid ReportStatusUpdateRequest request) { | ||
|
|
||
| reportService.updateReportStatus(reportId, request); | ||
| String message = request.newStatus() + "로 변경 완료되었습니다."; | ||
| return ResponseEntity.ok(new ReportChangeResponse(message)); | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🛠️ Refactor suggestion
응답 메시지 생성 로직 개선 제안
컨트롤러에서 응답 메시지를 직접 생성하고 있습니다. 이는 관심사 분리 원칙에 맞지 않으며, 메시지 포맷 변경 시 여러 곳을 수정해야 할 수 있습니다.
메시지 생성을 서비스 레이어로 이동하거나 별도의 메시지 팩토리를 사용하는 것을 고려해보세요:
- reportService.updateReportStatus(reportId, request);
- String message = request.newStatus() + "로 변경 완료되었습니다.";
- return ResponseEntity.ok(new ReportChangeResponse(message));
+ ReportChangeResponse response = reportService.updateReportStatus(reportId, request);
+ return ResponseEntity.ok(response);Committable suggestion skipped: line range outside the PR's diff.
🤖 Prompt for AI Agents
In
src/main/java/org/ezcode/codetest/presentation/report/ReportAdminController.java
around lines 37 to 46, the response message is being created directly in the
controller, which violates separation of concerns. To fix this, move the message
creation logic into the service layer or a dedicated message factory. Modify the
service method to return the message or a response object containing the
message, and update the controller to use this returned value instead of
constructing the message itself.
🛠️ Refactor suggestion
응답 메시지 구성 방식을 개선해야 합니다.
문자열 연결을 통한 메시지 구성보다는 MessageSource를 활용하거나 상수를 사용하는 것이 좋습니다. 또한 경로 변수 검증도 추가해야 합니다.
+import jakarta.validation.constraints.Positive;
@PatchMapping("/{reportId}/status")
public ResponseEntity<ReportChangeResponse> changeStatus(
- @PathVariable Long reportId,
+ @PathVariable @Positive Long reportId,
@RequestBody @Valid ReportStatusUpdateRequest request) {
reportService.updateReportStatus(reportId, request);
- String message = request.newStatus() + "로 변경 완료되었습니다.";
+ String message = String.format("신고 상태가 %s로 변경되었습니다.", request.newStatus());
return ResponseEntity.ok(new ReportChangeResponse(message));
}📝 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.
| // 신고 상태 변경 | |
| @PatchMapping("/{reportId}/status") | |
| public ResponseEntity<ReportChangeResponse> changeStatus( | |
| @PathVariable Long reportId, | |
| @RequestBody @Valid ReportStatusUpdateRequest request) { | |
| reportService.updateReportStatus(reportId, request); | |
| String message = request.newStatus() + "로 변경 완료되었습니다."; | |
| return ResponseEntity.ok(new ReportChangeResponse(message)); | |
| } | |
| import jakarta.validation.constraints.Positive; | |
| // 신고 상태 변경 | |
| @PatchMapping("/{reportId}/status") | |
| public ResponseEntity<ReportChangeResponse> changeStatus( | |
| @PathVariable @Positive Long reportId, | |
| @RequestBody @Valid ReportStatusUpdateRequest request) { | |
| reportService.updateReportStatus(reportId, request); | |
| String message = String.format("신고 상태가 %s로 변경되었습니다.", request.newStatus()); | |
| return ResponseEntity.ok(new ReportChangeResponse(message)); | |
| } |
🤖 Prompt for AI Agents
In
src/main/java/org/ezcode/codetest/presentation/report/ReportAdminController.java
around lines 37 to 46, improve the response message construction by replacing
string concatenation with a MessageSource-based approach or using predefined
constants for localization and maintainability. Additionally, add validation for
the reportId path variable to ensure it meets expected criteria before
processing.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@positive가 뭐야?
양수만 들어오게 validation 하는건가?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Seems like the humans are having a chat. I'll hop back into my burrow for now. If you need me again, just tag @coderabbitai in a new comment, and I'll come hopping out!
| ReportStatus newStatus = ReportStatus.valueOf(req.newStatus().toUpperCase()); | ||
| report.updateStatus(newStatus); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Enum 변환 예외 처리 부족
valueOf() 메서드 사용 시 예외 처리가 없어 잘못된 상태값 전달 시 IllegalArgumentException이 발생할 수 있습니다.
예외 처리를 추가하세요:
- ReportStatus newStatus = ReportStatus.valueOf(req.newStatus().toUpperCase());
+ ReportStatus newStatus;
+ try {
+ newStatus = ReportStatus.valueOf(req.newStatus().toUpperCase());
+ } catch (IllegalArgumentException e) {
+ throw new IllegalArgumentException("유효하지 않은 신고 상태입니다: " + req.newStatus());
+ }🤖 Prompt for AI Agents
In
src/main/java/org/ezcode/codetest/application/report/service/ReportService.java
around lines 94 to 95, the use of ReportStatus.valueOf() lacks exception
handling, which can cause an IllegalArgumentException if an invalid status
string is passed. Add a try-catch block around the valueOf call to catch
IllegalArgumentException and handle it appropriately, such as logging the error
or throwing a custom exception with a clear message.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ㅇㅋ 해결했어
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@pokerbearkr 좋습니다! enum 변환 예외 처리 문제를 해결해 주셔서 감사합니다. 🎉
If you found this review helpful, would you consider giving us a shout-out on X?
Thank you for using CodeRabbit!
| if (targetType == ReportTargetType.USER && reporterId.equals(request.targetId())) { | ||
| throw new IllegalArgumentException("자기 자신은 신고할 수 없습니다."); | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🛠️ Refactor suggestion
🧩 Verification correct
비즈니스 로직 검증 개선 제안
자기 자신 신고 방지 로직이 있지만, AI 요약에 따르면 ReportDomainService에 이미 이 검증 로직이 캡슐화되어 있다고 합니다. 중복 검증을 피하고 도메인 서비스를 활용하는 것이 좋겠습니다.
ReportDomainService의 존재와 검증 로직을 확인해주세요:
🏁 Script executed:
#!/bin/bash
# ReportDomainService 클래스 존재 확인 및 검증 로직 조회
fd "ReportDomainService" --type f --exec cat {}Length of output: 642
비즈니스 로직 검증 개선 제안
자기 자신 신고 방지 로직이 있지만, AI 요약에 따르면 ReportDomainService에 이미 이 검증 로직이 캡슐화되어 있다고 합니다. 중복 검증을 피하고 도메인 서비스를 활용하는 것이 좋겠습니다.
ReportDomainService의 존재와 검증 로직을 확인해주세요:
#!/bin/bash
# ReportDomainService 클래스 존재 확인 및 검증 로직 조회
fd "ReportDomainService" --type f --exec cat {}🤖 Prompt for AI Agents
In
src/main/java/org/ezcode/codetest/application/report/service/ReportService.java
around lines 30 to 32, the self-report prevention logic is currently implemented
directly in the service. Since this validation is already encapsulated within
ReportDomainService, remove the duplicate check here and instead call the
appropriate validation method from ReportDomainService to handle this logic,
ensuring single responsibility and avoiding redundant validation.
| ReportTargetType targetType = ReportTargetType.valueOf(request.targetType().toUpperCase()); | ||
| ReportType reportType = ReportType.from(request.reportType()); | ||
|
|
||
| if (targetType == ReportTargetType.USER && reporterId.equals(request.targetId())) { | ||
| throw new IllegalArgumentException("자기 자신은 신고할 수 없습니다."); | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Enum 변환과 검증 로직을 개선해야 합니다.
Enum 변환에서 발생할 수 있는 예외 처리가 없고, 자기 자신 신고 방지 로직이 도메인 서비스에 있다고 명시되어 있지만 여기에 중복 구현되어 있습니다.
+import org.ezcode.codetest.domain.report.service.ReportDomainService;
@Service
@RequiredArgsConstructor
public class ReportService {
private final UserRepository userRepository;
private final ReportRepository reportRepository;
+ private final ReportDomainService reportDomainService;
@Transactional
public ReportResponse submitReport(Long reporterId, ReportRequest request) {
User reporter = userRepository.findUserById(reporterId)
.orElseThrow(() -> new IllegalArgumentException("신고자를 찾을 수 없습니다."));
- ReportTargetType targetType = ReportTargetType.valueOf(request.targetType().toUpperCase());
- ReportType reportType = ReportType.from(request.reportType());
-
- if (targetType == ReportTargetType.USER && reporterId.equals(request.targetId())) {
- throw new IllegalArgumentException("자기 자신은 신고할 수 없습니다.");
- }
+ ReportTargetType targetType;
+ ReportType reportType;
+
+ try {
+ targetType = ReportTargetType.valueOf(request.targetType().toUpperCase());
+ reportType = ReportType.from(request.reportType());
+ } catch (IllegalArgumentException e) {
+ throw new IllegalArgumentException("잘못된 신고 타입입니다.");
+ }
+
+ reportDomainService.validateReportSubmission(reporterId, request.targetId(), targetType);📝 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.
| ReportTargetType targetType = ReportTargetType.valueOf(request.targetType().toUpperCase()); | |
| ReportType reportType = ReportType.from(request.reportType()); | |
| if (targetType == ReportTargetType.USER && reporterId.equals(request.targetId())) { | |
| throw new IllegalArgumentException("자기 자신은 신고할 수 없습니다."); | |
| } | |
| // src/main/java/org/ezcode/codetest/application/report/service/ReportService.java | |
| import org.ezcode.codetest.domain.report.service.ReportDomainService; | |
| @Service | |
| @RequiredArgsConstructor | |
| public class ReportService { | |
| private final UserRepository userRepository; | |
| private final ReportRepository reportRepository; | |
| private final ReportDomainService reportDomainService; | |
| @Transactional | |
| public ReportResponse submitReport(Long reporterId, ReportRequest request) { | |
| User reporter = userRepository.findUserById(reporterId) | |
| .orElseThrow(() -> new IllegalArgumentException("신고자를 찾을 수 없습니다.")); | |
| ReportTargetType targetType; | |
| ReportType reportType; | |
| try { | |
| targetType = ReportTargetType.valueOf(request.targetType().toUpperCase()); | |
| reportType = ReportType.from(request.reportType()); | |
| } catch (IllegalArgumentException e) { | |
| throw new IllegalArgumentException("잘못된 신고 타입입니다."); | |
| } | |
| reportDomainService.validateReportSubmission(reporterId, request.targetId(), targetType); | |
| // ... 기존 로직 계속 (e.g., build & save Report, return response) ... | |
| } | |
| } |
🤖 Prompt for AI Agents
In
src/main/java/org/ezcode/codetest/application/report/service/ReportService.java
around lines 27 to 32, the enum conversion lacks exception handling and the
self-report prevention logic is duplicated here despite being in the domain
service. To fix this, add proper try-catch blocks or use safe enum conversion
methods to handle invalid values gracefully, and remove the self-report
validation from this service to avoid duplication, relying solely on the domain
service for that check.
🛠️ Refactor suggestion
Enum 변환 시 예외 처리를 개선해야 합니다.
valueOf() 메소드는 잘못된 문자열이 전달될 경우 IllegalArgumentException을 발생시킵니다. 더 명확한 에러 메시지를 제공하거나 커스텀 예외를 사용하는 것을 고려해보세요.
- ReportTargetType targetType = ReportTargetType.valueOf(request.targetType().toUpperCase());
- ReportType reportType = ReportType.from(request.reportType());
+ ReportTargetType targetType;
+ ReportType reportType;
+
+ try {
+ targetType = ReportTargetType.valueOf(request.targetType().toUpperCase());
+ reportType = ReportType.from(request.reportType());
+ } catch (IllegalArgumentException e) {
+ throw new IllegalArgumentException("유효하지 않은 신고 타입입니다: " + e.getMessage());
+ }📝 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.
| ReportTargetType targetType = ReportTargetType.valueOf(request.targetType().toUpperCase()); | |
| ReportType reportType = ReportType.from(request.reportType()); | |
| if (targetType == ReportTargetType.USER && reporterId.equals(request.targetId())) { | |
| throw new IllegalArgumentException("자기 자신은 신고할 수 없습니다."); | |
| } | |
| ReportTargetType targetType; | |
| ReportType reportType; | |
| try { | |
| targetType = ReportTargetType.valueOf(request.targetType().toUpperCase()); | |
| reportType = ReportType.from(request.reportType()); | |
| } catch (IllegalArgumentException e) { | |
| throw new IllegalArgumentException("유효하지 않은 신고 타입입니다: " + e.getMessage()); | |
| } | |
| if (targetType == ReportTargetType.USER && reporterId.equals(request.targetId())) { | |
| throw new IllegalArgumentException("자기 자신은 신고할 수 없습니다."); | |
| } |
🤖 Prompt for AI Agents
In
src/main/java/org/ezcode/codetest/application/report/service/ReportService.java
around lines 27 to 32, the use of ReportTargetType.valueOf() can throw an
IllegalArgumentException with a generic message if the input string is invalid.
To improve this, catch the exception thrown by valueOf(), then throw a new
exception with a clearer, custom error message or use a custom exception type to
indicate the invalid enum conversion more explicitly.
| public Page<ReportListResponse> getReportList(Pageable pageable) { | ||
| return reportRepository.findAll(pageable) | ||
| .map(r -> new ReportListResponse( | ||
| r.getId(), | ||
| r.getReporter().getEmail(), | ||
| r.getTargetId(), | ||
| r.getTargetType().name(), | ||
| r.getReportType().name(), | ||
| r.getReportStatus().name(), | ||
| r.getMessage(), | ||
| r.getCreatedAt().toString() | ||
| )); | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🛠️ Refactor suggestion
Null 안전성과 데이터 포맷팅을 개선해야 합니다.
Reporter 이메일에 대한 null 체크가 없고, 날짜를 문자열로 변환할 때 적절한 포맷팅이 필요합니다.
+import java.time.format.DateTimeFormatter;
+
+ private static final DateTimeFormatter DATE_FORMATTER = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
@Transactional(readOnly = true)
public Page<ReportListResponse> getReportList(Pageable pageable) {
return reportRepository.findAll(pageable)
.map(r -> new ReportListResponse(
r.getId(),
- r.getReporter().getEmail(),
+ r.getReporter() != null ? r.getReporter().getEmail() : "알 수 없음",
r.getTargetId(),
r.getTargetType().name(),
r.getReportType().name(),
r.getReportStatus().name(),
r.getMessage(),
- r.getCreatedAt().toString()
+ r.getCreatedAt().format(DATE_FORMATTER)
));
}📝 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.
| public Page<ReportListResponse> getReportList(Pageable pageable) { | |
| return reportRepository.findAll(pageable) | |
| .map(r -> new ReportListResponse( | |
| r.getId(), | |
| r.getReporter().getEmail(), | |
| r.getTargetId(), | |
| r.getTargetType().name(), | |
| r.getReportType().name(), | |
| r.getReportStatus().name(), | |
| r.getMessage(), | |
| r.getCreatedAt().toString() | |
| )); | |
| } | |
| import java.time.format.DateTimeFormatter; | |
| private static final DateTimeFormatter DATE_FORMATTER = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"); | |
| @Transactional(readOnly = true) | |
| public Page<ReportListResponse> getReportList(Pageable pageable) { | |
| return reportRepository.findAll(pageable) | |
| .map(r -> new ReportListResponse( | |
| r.getId(), | |
| r.getReporter() != null | |
| ? r.getReporter().getEmail() | |
| : "알 수 없음", | |
| r.getTargetId(), | |
| r.getTargetType().name(), | |
| r.getReportType().name(), | |
| r.getReportStatus().name(), | |
| r.getMessage(), | |
| r.getCreatedAt().format(DATE_FORMATTER) | |
| )); | |
| } |
🤖 Prompt for AI Agents
In
src/main/java/org/ezcode/codetest/application/report/service/ReportService.java
around lines 54 to 66, add a null check for reporter email to avoid potential
NullPointerException and format the createdAt date using a proper date formatter
instead of calling toString() directly. Use Optional or conditional checks to
safely handle null reporter emails and apply a standard date format like
ISO_LOCAL_DATE_TIME for createdAt before passing it to the ReportListResponse
constructor.
| r.getReportType().name(), | ||
| r.getReportStatus().name(), | ||
| r.getMessage(), | ||
| r.getCreatedAt().toString() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🛠️ Refactor suggestion
날짜 형식을 명시적으로 지정하세요.
toString() 메소드 사용 시 예측 가능한 형식이 보장되지 않습니다. 일관된 날짜 형식을 위해 DateTimeFormatter를 사용하는 것을 권장합니다.
- r.getCreatedAt().toString()
+ r.getCreatedAt().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"))클래스 상단에 다음 import를 추가해야 합니다:
import java.time.format.DateTimeFormatter;🤖 Prompt for AI Agents
In
src/main/java/org/ezcode/codetest/application/report/service/ReportService.java
at line 64, replace the use of r.getCreatedAt().toString() with formatting using
DateTimeFormatter to ensure a consistent and predictable date format. Import
java.time.format.DateTimeFormatter at the top of the file, define a formatter
with the desired pattern, and apply it to r.getCreatedAt() to convert the date
to a string.
| Report report = reportRepository.findById(reportId) | ||
| .orElseThrow(() -> new IllegalArgumentException("신고가 존재하지 않습니다.")); | ||
|
|
||
| ReportStatus newStatus = ReportStatus.valueOf(req.newStatus().toUpperCase()); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🛠️ Refactor suggestion
Enum 변환 시 예외 처리 개선이 필요합니다.
앞서 submitReport 메소드에서 언급한 것과 동일한 이슈입니다. 더 명확한 에러 메시지를 제공해주세요.
- ReportStatus newStatus = ReportStatus.valueOf(req.newStatus().toUpperCase());
+ ReportStatus newStatus;
+ try {
+ newStatus = ReportStatus.valueOf(req.newStatus().toUpperCase());
+ } catch (IllegalArgumentException e) {
+ throw new IllegalArgumentException("유효하지 않은 신고 상태입니다: " + req.newStatus());
+ }📝 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.
| ReportStatus newStatus = ReportStatus.valueOf(req.newStatus().toUpperCase()); | |
| ReportStatus newStatus; | |
| try { | |
| newStatus = ReportStatus.valueOf(req.newStatus().toUpperCase()); | |
| } catch (IllegalArgumentException e) { | |
| throw new IllegalArgumentException("유효하지 않은 신고 상태입니다: " + req.newStatus()); | |
| } |
🤖 Prompt for AI Agents
In
src/main/java/org/ezcode/codetest/application/report/service/ReportService.java
at line 94, the conversion from string to enum using ReportStatus.valueOf can
throw an exception if the input is invalid. To improve, wrap this conversion in
a try-catch block to catch IllegalArgumentException and throw a custom exception
or return a clear error message indicating the invalid status value, similar to
the approach used in the submitReport method.
| r.getCreatedAt().toString(), | ||
| r.getModifiedAt().toString() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🛠️ Refactor suggestion
날짜 형식 통일성을 위해 DateTimeFormatter 사용을 권장합니다.
앞서 언급한 것과 동일한 이슈입니다. 일관된 날짜 형식을 위해 포맷터를 사용하세요.
- r.getCreatedAt().toString(),
- r.getModifiedAt().toString()
+ r.getCreatedAt().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")),
+ r.getModifiedAt().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"))📝 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.
| r.getCreatedAt().toString(), | |
| r.getModifiedAt().toString() | |
| r.getCreatedAt().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")), | |
| r.getModifiedAt().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")) |
🤖 Prompt for AI Agents
In
src/main/java/org/ezcode/codetest/application/report/service/ReportService.java
around lines 83 to 84, the code converts dates to strings using toString(),
which leads to inconsistent date formats. Replace these calls with a
DateTimeFormatter instance to format the dates consistently according to a
defined pattern, ensuring uniform date representation throughout the
application.
작업 내용
변경 사항
트러블 슈팅
해결해야 할 문제
참고 사항
코드 리뷰 전 확인 체크리스트
type :)Summary by CodeRabbit
Summary by CodeRabbit