[3주차] 송유경/[feat] 게시글 도메인 API 구현#124
Hidden character warning
[3주차] 송유경/[feat] 게시글 도메인 API 구현#124yukyoungs wants to merge 3 commits intoLeets-Official:송유경/mainfrom
Conversation
|
각 서비스(health, post, user) 패키지를 구분하여, controller, dto, service를 정리한 이 인상 깊습니다! 저번 과제 리뷰에서 언급해주셨 domain 관련 구조 개선과 함께 배워 갑니다. 깔끔한 패키지 구조 덕분에 유지보수성이 크게 높아졌습니다. |
theSnackOverflow
left a comment
There was a problem hiding this comment.
도메인별 패키지 구조 리팩토링이 깔끔하게 잘 됐고, @Transactional(readOnly = true) + 변경 메서드 오버라이드 패턴, Post.update()로 dirty checking 활용, BaseResponse<T> 공통 응답 래퍼까지 전반적으로 완성도가 높네요. PostRequest를 inner static class로 Create/Update 분리한 것도 깔끔합니다.
몇 가지 확인해보시면 좋을 것 같은 부분 남겨봅니다!
| // 게시글 수정 (PATCH /api/posts/{id}) | ||
| @PatchMapping("/{id}") | ||
| public ResponseEntity<BaseResponse<PostResponse>> update(@Valid @PathVariable("id") Long id, @RequestBody PostRequest.Update request) { | ||
| PostResponse response = postService.update(id, request); |
There was a problem hiding this comment.
@Valid가 @PathVariable("id") Long id에 붙어있는데요, Long 타입의 PathVariable에는 @Valid가 아무 효과가 없습니다. 유효성 검사가 필요한 건 @RequestBody PostRequest.Update request 쪽이에요!
public ResponseEntity<BaseResponse<PostResponse>> update(
@PathVariable("id") Long id,
@Valid @RequestBody PostRequest.Update request
)| public PostResponse findById(Long id) { | ||
| Post post = postRepository.findById(id) | ||
| .orElseThrow(() -> new IllegalArgumentException(ErrorCode.POST_NOT_FOUND.getMessage())); | ||
| return new PostResponse(post); |
There was a problem hiding this comment.
게시글 미존재 시 IllegalArgumentException을 던지고 있는데요, GlobalExceptionHandler가 IllegalArgumentException을 400 Bad Request로 처리하고 있어서 실제로는 400이 반환됩니다. ErrorCode.POST_NOT_FOUND에 HttpStatus.NOT_FOUND를 이미 잘 정의해두셨으니 커스텀 예외 클래스를 만들어 연결해주시면 의도대로 404를 반환할 수 있어요!
public class PostNotFoundException extends RuntimeException {
public PostNotFoundException(Long id) {
super(ErrorCode.POST_NOT_FOUND.getMessage());
}
}
// GlobalExceptionHandler
@ExceptionHandler(PostNotFoundException.class)
public ResponseEntity<ErrorResponse> handle(PostNotFoundException e) {
return ResponseEntity.status(HttpStatus.NOT_FOUND)...;
}| import org.springframework.stereotype.Repository; | ||
|
|
||
| @Repository | ||
| public interface PostRepository extends JpaRepository<Post, Long> { |
There was a problem hiding this comment.
@Repository가 붙어있는데, Spring Data JPA는 JpaRepository를 상속하면 자동으로 빈 등록이 이루어져서 @Repository를 직접 붙이지 않아도 됩니다. 제거해도 동작은 동일해요!
| return postRepository.findAll().stream() | ||
| .map(PostResponse::new) | ||
| .collect(Collectors.toList()); | ||
| } |
There was a problem hiding this comment.
.collect(Collectors.toList())는 Java 16부터 .toList()로 대체할 수 있어요. Spring Boot 3.2.5는 Java 17 이상 기반이라 그냥 .toList() 쓰시면 됩니다!
|
각 도메인(post, user, comment)별로 패키지를 구분하고 controller, service, repository, dto를 체계적으로 분리한 구조가 좋은거 같습니다! JPA Auditing 설정도 깔끔하게 되어있고, Swagger UI까지 구현하셔서 API 문서화도 완벽한거 같네요 고생하셨습니다! |
1. 과제 요구사항 중 구현한 내용
2. 핵심 변경 사항
3. 실행 및 검증 결과
4. 완료 사항
5. 추가 사항
제출 체크리스트
{이름}/main브랜치다{이름}/{숫자}주차브랜치다Reviewer 참고