[3주차] 임성현/[feat] 게시글 도메인 API 구현#112
Hidden character warning
Conversation
theSnackOverflow
left a comment
There was a problem hiding this comment.
Mapper 분리로 엔티티-DTO 변환 로직을 서비스/컨트롤러에서 깔끔하게 빼주신 점이 좋았고, @Transactional(readOnly = true)를 클래스 레벨에 걸고 변경 메서드만 @Transactional로 오버라이드하는 패턴도 적절하게 적용해주셨네요. 목록용/상세용 DTO를 분리해서 필요한 데이터만 노출하는 구조도 잘 잡혀있습니다.
몇 가지 확인해보시면 좋을 것 같은 부분 남겨봅니다!
| // 게시글 작성 | ||
| @PostMapping | ||
| public Long createPost(@RequestBody PostRequest requestDto, @RequestParam Long userId) { | ||
| return postService.createPost(requestDto, userId); |
There was a problem hiding this comment.
@RequestBody에 @Valid가 빠져 있는데요, PostRequest에 @NotBlank 검증 어노테이션을 잘 달아주셨지만 컨트롤러에서 @Valid가 없으면 유효성 검사가 실제로 실행되지 않습니다. ApiExceptionHandler에서 MethodArgumentNotValidException 처리까지 해두셨으니, @Valid만 추가해주시면 바로 연결될 것 같아요!
public Long createPost(@RequestBody @Valid PostRequest requestDto, ...)updatePost의 @RequestBody에도 동일하게 적용해주시면 좋을 것 같아요!
|
|
||
| // 서비스 로직 에러 처리 ,403 Forbidden, 404 Not Found | ||
| @ExceptionHandler(RuntimeException.class) | ||
| public ResponseEntity<Map<String, String>> handleRuntimeException(RuntimeException ex) { |
There was a problem hiding this comment.
@ExceptionHandler(RuntimeException.class)로 처리하고 계신데요, 이렇게 하면 NullPointerException이나 IllegalStateException 같은 예상치 못한 런타임 예외까지 모두 이 핸들러에서 잡히게 됩니다. 의도하지 않은 에러가 비즈니스 에러 메시지 형태로 반환될 수 있어서, 커스텀 예외 클래스를 만들어서 사용해보시면 좋을 것 같아요!
public class PostNotFoundException extends RuntimeException { ... }
public class ForbiddenException extends RuntimeException { ... }
@ExceptionHandler(PostNotFoundException.class)
public ResponseEntity<Map<String, String>> handlePostNotFound(...) { ... }| .title(requestDto.getTitle()) | ||
| .content(requestDto.getContent()) | ||
| .status(PostStatus.valueOf(requestDto.getStatus())) | ||
| .user(user) // 📍 외래키 연결 |
There was a problem hiding this comment.
PostStatus.valueOf()로 문자열을 enum으로 변환하고 계신데요, 잘못된 값(예: "HELLO")이 들어오면 IllegalArgumentException이 발생하고, 이것이 RuntimeException 핸들러에 잡혀서 내부 에러 메시지가 그대로 500 응답으로 노출될 수 있습니다. status 필드를 DTO에서 String 대신 PostStatus enum 타입으로 직접 받거나, 변환 전에 별도 검증을 추가해주시면 좋을 것 같아요!
| } | ||
|
|
||
| post.update(requestDto.getTitle(), requestDto.getContent()); | ||
| } |
There was a problem hiding this comment.
updatePost에서 title과 content만 수정하고 있는데요, PostRequest에 status 필드도 포함되어 있으니 수정 시에도 status 변경이 반영되도록 post.update() 메서드에 status 파라미터를 추가해주시면 좋을 것 같아요!
| @RestController | ||
| @RequiredArgsConstructor | ||
| @RequestMapping("/api/posts") | ||
| public class PostController { |
There was a problem hiding this comment.
사소한 부분이긴 한데, Post API는 /api/posts, User API는 /api/v1/users로 경로 버전 체계가 다르게 되어 있는데요, 프로젝트 전체에서 일관된 URL 규칙을 사용해주시면 나중에 관리하기 더 편할 것 같아요!
| package com.example.blog7th; | ||
|
|
||
| import com.example.blog7th.domain.user.User; | ||
| import com.example.blog7th.repository.UserRepository; |
There was a problem hiding this comment.
User, UserRepository, CommandLineRunner, @Bean import가 추가되어 있지만 실제로 사용되는 곳이 없는 것 같아요. 혹시 개발 중에 테스트하시다가 남은 건가요? 사용하지 않는 import는 정리해주시면 좋을 것 같아요!
| private String content; | ||
|
|
||
| // 📍 이 부분을 추가하세요! | ||
| @NotBlank(message = "공개 여부는 필수입니다.") |
There was a problem hiding this comment.
개발 중 메모로 보이는 주석이 남아있는 것 같아요. 제출 전에 정리해주시면 좋을 것 같아요!
There was a problem hiding this comment.
매번 리뷰 감사합니다! 현재 달린 리뷰와 관련된 사항을 전부 수정했습니다. 또 추가로 기능별로 파일을 구별하여 정리했습니다.
|
BaseTimeEntity를 활용하여 createdAt, updatedAt을 자동으로 관리하고, GlobalExceptionHandler와 Custom Exception으로 예외처리를 중앙에서 일관성 있게 처리하는 부분이 인상 깊습니다 고생하셨습니다! |
|
전반적으로 계층 분리(Controller-Service-DTO)가 아주 깔끔하게 되어 있네요! 몇 가지 안정성을 높일 수 있는 부분들 의견드릴게요! |
1. 과제 요구사항 중 구현한 내용
2. 핵심 변경 사항
PostMapper 클래스 정의: 컨트롤러나 서비스 코드에 로직 섞이지 않도록 분리.
ApiExceptionHandler 수정: 비즈니스 예외와 유효성 검사 예외를 공통 처리.
3. 실행 및 검증 결과
userId 생성
post 생성
post 조회
post 수정
목록 조회
post 삭제
예외 처리 - 게시물 없음
예외 처리 - 잘못된 입력값 요청
4. 완료 사항
5. 추가 사항
#109
제출 체크리스트
{이름}/main브랜치다{이름}/{숫자}주차브랜치다