From 43b65ac8ea3c507dcd2a121836d256961b03cde7 Mon Sep 17 00:00:00 2001 From: kimjihoon Date: Tue, 7 Apr 2026 01:00:33 +0900 Subject: [PATCH 01/15] =?UTF-8?q?[Feat]=20#93=20=EA=B2=8C=EC=8B=9C?= =?UTF-8?q?=EA=B8=80=20=EC=B6=94=EA=B0=80,=20=EC=88=98=EC=A0=95=20Request?= =?UTF-8?q?=20DTO=20=EC=83=9D=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../post/dto/request/CreatePostRequest.java | 18 ++++++++++++++++++ .../post/dto/request/UpdatePostRequest.java | 18 ++++++++++++++++++ 2 files changed, 36 insertions(+) create mode 100644 src/main/java/com/example/leets_7th/domain/post/dto/request/CreatePostRequest.java create mode 100644 src/main/java/com/example/leets_7th/domain/post/dto/request/UpdatePostRequest.java diff --git a/src/main/java/com/example/leets_7th/domain/post/dto/request/CreatePostRequest.java b/src/main/java/com/example/leets_7th/domain/post/dto/request/CreatePostRequest.java new file mode 100644 index 0000000..ba2f11a --- /dev/null +++ b/src/main/java/com/example/leets_7th/domain/post/dto/request/CreatePostRequest.java @@ -0,0 +1,18 @@ +package com.example.leets_7th.domain.post.dto.request; + +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.NotBlank; + +public record CreatePostRequest( + + @Schema(example = "제목") + @NotBlank + String title, + + @NotBlank + @Schema(example = "내용") + String content, + + Integer thumbnailIndex +) { +} diff --git a/src/main/java/com/example/leets_7th/domain/post/dto/request/UpdatePostRequest.java b/src/main/java/com/example/leets_7th/domain/post/dto/request/UpdatePostRequest.java new file mode 100644 index 0000000..7e674cb --- /dev/null +++ b/src/main/java/com/example/leets_7th/domain/post/dto/request/UpdatePostRequest.java @@ -0,0 +1,18 @@ +package com.example.leets_7th.domain.post.dto.request; + +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.NotBlank; + +public record UpdatePostRequest( + + @NotBlank + @Schema(example = "제목") + String title, + + @NotBlank + @Schema(example = "내용") + String content, + + Integer thumbnailIndex +) { +} From 7f349925ad2de6b181cc0909c4bfb86de2b4e82b Mon Sep 17 00:00:00 2001 From: kimjihoon Date: Tue, 7 Apr 2026 01:00:46 +0900 Subject: [PATCH 02/15] =?UTF-8?q?[Feat]=20#93=20=EA=B2=8C=EC=8B=9C?= =?UTF-8?q?=EA=B8=80=20=EC=B6=94=EA=B0=80,=20=EC=88=98=EC=A0=95=20Response?= =?UTF-8?q?=20DTO=20=EC=83=9D=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../domain/post/dto/response/CreatePostResponse.java | 6 ++++++ .../domain/post/dto/response/UpdatePostResponse.java | 8 ++++++++ 2 files changed, 14 insertions(+) create mode 100644 src/main/java/com/example/leets_7th/domain/post/dto/response/CreatePostResponse.java create mode 100644 src/main/java/com/example/leets_7th/domain/post/dto/response/UpdatePostResponse.java diff --git a/src/main/java/com/example/leets_7th/domain/post/dto/response/CreatePostResponse.java b/src/main/java/com/example/leets_7th/domain/post/dto/response/CreatePostResponse.java new file mode 100644 index 0000000..2c9643d --- /dev/null +++ b/src/main/java/com/example/leets_7th/domain/post/dto/response/CreatePostResponse.java @@ -0,0 +1,6 @@ +package com.example.leets_7th.domain.post.dto.response; + +public record CreatePostResponse( + Long postId, + String thumbnailUrl +) {} diff --git a/src/main/java/com/example/leets_7th/domain/post/dto/response/UpdatePostResponse.java b/src/main/java/com/example/leets_7th/domain/post/dto/response/UpdatePostResponse.java new file mode 100644 index 0000000..f98c0f2 --- /dev/null +++ b/src/main/java/com/example/leets_7th/domain/post/dto/response/UpdatePostResponse.java @@ -0,0 +1,8 @@ +package com.example.leets_7th.domain.post.dto.response; + +import java.time.LocalDateTime; + +public record UpdatePostResponse( + Long postId, + LocalDateTime updatedAt +) {} From 8b7ff54da8cc0789993a895999a5141faaf39eaa Mon Sep 17 00:00:00 2001 From: kimjihoon Date: Tue, 7 Apr 2026 01:01:02 +0900 Subject: [PATCH 03/15] =?UTF-8?q?[Feat]=20#93=20=EC=84=B1=EA=B3=B5,?= =?UTF-8?q?=EC=8B=A4=ED=8C=A8=20=EC=83=81=ED=83=9C=EC=BD=94=EB=93=9C=20?= =?UTF-8?q?=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../example/leets_7th/common/status/ErrorStatus.java | 10 +++++++++- .../leets_7th/common/status/SuccessStatus.java | 11 +++++++++-- 2 files changed, 18 insertions(+), 3 deletions(-) diff --git a/src/main/java/com/example/leets_7th/common/status/ErrorStatus.java b/src/main/java/com/example/leets_7th/common/status/ErrorStatus.java index d2cff0e..cdce48c 100644 --- a/src/main/java/com/example/leets_7th/common/status/ErrorStatus.java +++ b/src/main/java/com/example/leets_7th/common/status/ErrorStatus.java @@ -20,7 +20,15 @@ public enum ErrorStatus implements BaseStatus { FORBIDDEN(HttpStatus.FORBIDDEN, "COMM_403", "접근 권한이 없습니다."), NOT_FOUND(HttpStatus.NOT_FOUND, "COMM_404", "요청한 자원을 찾을 수 없습니다."), METHOD_NOT_ALLOWED(HttpStatus.METHOD_NOT_ALLOWED, "COMM_405", "허용되지 않은 메소드입니다."), - INTERNAL_SERVER_ERROR(HttpStatus.INTERNAL_SERVER_ERROR, "COMM_500", "서버 내부 오류입니다."); + INTERNAL_SERVER_ERROR(HttpStatus.INTERNAL_SERVER_ERROR, "COMM_500", "서버 내부 오류입니다."), + + // User + USER_NOT_FOUND(HttpStatus.NOT_FOUND,"USER_404","사용자를 찾을 수 없습니다."), + + + // Post + POST_NOT_FOUND(HttpStatus.NOT_FOUND,"POST_404","게시글을 찾을 수 없습니다."), + POST_ALREADY_DELETED(HttpStatus.BAD_REQUEST,"POST_400","이미 삭제된 게시글입니다."); private final HttpStatus httpStatus; private final String code; diff --git a/src/main/java/com/example/leets_7th/common/status/SuccessStatus.java b/src/main/java/com/example/leets_7th/common/status/SuccessStatus.java index 2b7478b..41915b8 100644 --- a/src/main/java/com/example/leets_7th/common/status/SuccessStatus.java +++ b/src/main/java/com/example/leets_7th/common/status/SuccessStatus.java @@ -10,8 +10,15 @@ public enum SuccessStatus implements BaseStatus { // test - HEALTH_CHECK_SUCCESS_STATUS(HttpStatus.OK,"TEST_200","OK"), - STRING_REPEAT_SUCCESS(HttpStatus.CREATED,"TEST_201","문자열을 성공적으로 출력했습니다."); + HEALTH_CHECK_SUCCESS_STATUS(HttpStatus.OK, "TEST_200", "OK"), + STRING_REPEAT_SUCCESS(HttpStatus.CREATED, "TEST_201", "문자열을 성공적으로 출력했습니다."), + + GET_ALL_POST_SUCCESS(HttpStatus.OK, "POST_2001", "게시글 목록 조회에 성공했습니다."), + GET_POST_DETAIL_SUCCESS(HttpStatus.OK, "POST_2002", "게시글 상세 조회에 성공했습니다."), + CREATE_POST_SUCCESS(HttpStatus.CREATED, "POST_2011", "게시글 생성에 성공했습니다."), + UPDATE_POST_SUCCESS(HttpStatus.CREATED, "POST_2003", "게시글 수정에 성공했습니다."), + DELETE_POST_SUCCESS(HttpStatus.OK, "POST_2004", "게시글 삭제에 성공했습니다."); + private final HttpStatus httpStatus; private final String code; From f20f533038500b779729608054e576b2022ab448 Mon Sep 17 00:00:00 2001 From: kimjihoon Date: Tue, 7 Apr 2026 01:01:39 +0900 Subject: [PATCH 04/15] =?UTF-8?q?[Chore]=20#93=20=EC=9D=B4=EB=AF=B8?= =?UTF-8?q?=EC=A7=80=20=EC=B6=94=EA=B0=80=20=EA=B4=80=EB=A0=A8=20S3=20?= =?UTF-8?q?=EA=B8=B0=EB=B3=B8=20=ED=8C=8C=EC=9D=BC=20=EC=84=B8=ED=8C=85?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../com/example/leets_7th/common/service/ImageService.java | 4 ++++ src/main/java/com/example/leets_7th/infra/s3/S3Service.java | 4 ++++ src/main/java/com/example/leets_7th/infra/s3/S3Uploader.java | 4 ++++ src/main/java/com/example/leets_7th/infra/s3/S3config.java | 4 ++++ 4 files changed, 16 insertions(+) create mode 100644 src/main/java/com/example/leets_7th/common/service/ImageService.java create mode 100644 src/main/java/com/example/leets_7th/infra/s3/S3Service.java create mode 100644 src/main/java/com/example/leets_7th/infra/s3/S3Uploader.java create mode 100644 src/main/java/com/example/leets_7th/infra/s3/S3config.java diff --git a/src/main/java/com/example/leets_7th/common/service/ImageService.java b/src/main/java/com/example/leets_7th/common/service/ImageService.java new file mode 100644 index 0000000..53da81b --- /dev/null +++ b/src/main/java/com/example/leets_7th/common/service/ImageService.java @@ -0,0 +1,4 @@ +package com.example.leets_7th.common.service; + +public class ImageService { +} diff --git a/src/main/java/com/example/leets_7th/infra/s3/S3Service.java b/src/main/java/com/example/leets_7th/infra/s3/S3Service.java new file mode 100644 index 0000000..0496819 --- /dev/null +++ b/src/main/java/com/example/leets_7th/infra/s3/S3Service.java @@ -0,0 +1,4 @@ +package com.example.leets_7th.infra.s3; + +public class S3Service { +} diff --git a/src/main/java/com/example/leets_7th/infra/s3/S3Uploader.java b/src/main/java/com/example/leets_7th/infra/s3/S3Uploader.java new file mode 100644 index 0000000..d506737 --- /dev/null +++ b/src/main/java/com/example/leets_7th/infra/s3/S3Uploader.java @@ -0,0 +1,4 @@ +package com.example.leets_7th.infra.s3; + +public class S3Uploader { +} diff --git a/src/main/java/com/example/leets_7th/infra/s3/S3config.java b/src/main/java/com/example/leets_7th/infra/s3/S3config.java new file mode 100644 index 0000000..a8aaff9 --- /dev/null +++ b/src/main/java/com/example/leets_7th/infra/s3/S3config.java @@ -0,0 +1,4 @@ +package com.example.leets_7th.infra.s3; + +public class S3config { +} From 02ee096e2b25aeeb22a82ebcee35a55c54401e32 Mon Sep 17 00:00:00 2001 From: kimjihoon Date: Tue, 7 Apr 2026 01:02:08 +0900 Subject: [PATCH 05/15] =?UTF-8?q?[Chore]=20#93=20=EC=A0=84=EC=B2=B4?= =?UTF-8?q?=EC=A1=B0=ED=9A=8C,=20=EC=83=81=EC=84=B8=EC=A1=B0=ED=9A=8C=20DT?= =?UTF-8?q?O=20=ED=8C=8C=EC=9D=BC=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../domain/post/dto/request/GetPostDetailRequest.java | 4 ++++ .../leets_7th/domain/post/dto/request/GetPostRequest.java | 4 ++++ .../domain/post/dto/response/GetPostDetailResponse.java | 4 ++++ .../leets_7th/domain/post/dto/response/GetPostResponse.java | 4 ++++ 4 files changed, 16 insertions(+) create mode 100644 src/main/java/com/example/leets_7th/domain/post/dto/request/GetPostDetailRequest.java create mode 100644 src/main/java/com/example/leets_7th/domain/post/dto/request/GetPostRequest.java create mode 100644 src/main/java/com/example/leets_7th/domain/post/dto/response/GetPostDetailResponse.java create mode 100644 src/main/java/com/example/leets_7th/domain/post/dto/response/GetPostResponse.java diff --git a/src/main/java/com/example/leets_7th/domain/post/dto/request/GetPostDetailRequest.java b/src/main/java/com/example/leets_7th/domain/post/dto/request/GetPostDetailRequest.java new file mode 100644 index 0000000..e867723 --- /dev/null +++ b/src/main/java/com/example/leets_7th/domain/post/dto/request/GetPostDetailRequest.java @@ -0,0 +1,4 @@ +package com.example.leets_7th.domain.post.dto.request; + +public record GetPostDetailRequest() { +} diff --git a/src/main/java/com/example/leets_7th/domain/post/dto/request/GetPostRequest.java b/src/main/java/com/example/leets_7th/domain/post/dto/request/GetPostRequest.java new file mode 100644 index 0000000..2a458f0 --- /dev/null +++ b/src/main/java/com/example/leets_7th/domain/post/dto/request/GetPostRequest.java @@ -0,0 +1,4 @@ +package com.example.leets_7th.domain.post.dto.request; + +public record GetPostRequest() { +} diff --git a/src/main/java/com/example/leets_7th/domain/post/dto/response/GetPostDetailResponse.java b/src/main/java/com/example/leets_7th/domain/post/dto/response/GetPostDetailResponse.java new file mode 100644 index 0000000..b1d54a3 --- /dev/null +++ b/src/main/java/com/example/leets_7th/domain/post/dto/response/GetPostDetailResponse.java @@ -0,0 +1,4 @@ +package com.example.leets_7th.domain.post.dto.response; + +public record GetPostDetailResponse() { +} diff --git a/src/main/java/com/example/leets_7th/domain/post/dto/response/GetPostResponse.java b/src/main/java/com/example/leets_7th/domain/post/dto/response/GetPostResponse.java new file mode 100644 index 0000000..fd69c58 --- /dev/null +++ b/src/main/java/com/example/leets_7th/domain/post/dto/response/GetPostResponse.java @@ -0,0 +1,4 @@ +package com.example.leets_7th.domain.post.dto.response; + +public record GetPostResponse() { +} From a1f6872a3c4c38f2fc65f464b86ae932e535bb8c Mon Sep 17 00:00:00 2001 From: kimjihoon Date: Tue, 7 Apr 2026 01:02:37 +0900 Subject: [PATCH 06/15] =?UTF-8?q?[Chore]=20#93=20=EB=8C=93=EA=B8=80=20?= =?UTF-8?q?=EC=BB=A8=ED=8A=B8=EB=A1=A4=EB=9F=AC=20=EC=84=B8=ED=8C=85?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../domain/comment/controller/CommentController.java | 6 ++++++ .../comment/controller/docs/CommentControllerDocs.java | 7 +++++++ 2 files changed, 13 insertions(+) create mode 100644 src/main/java/com/example/leets_7th/domain/comment/controller/CommentController.java create mode 100644 src/main/java/com/example/leets_7th/domain/comment/controller/docs/CommentControllerDocs.java diff --git a/src/main/java/com/example/leets_7th/domain/comment/controller/CommentController.java b/src/main/java/com/example/leets_7th/domain/comment/controller/CommentController.java new file mode 100644 index 0000000..7291324 --- /dev/null +++ b/src/main/java/com/example/leets_7th/domain/comment/controller/CommentController.java @@ -0,0 +1,6 @@ +package com.example.leets_7th.domain.comment.controller; + +import com.example.leets_7th.domain.comment.controller.docs.CommentControllerDocs; + +public class CommentController implements CommentControllerDocs { +} diff --git a/src/main/java/com/example/leets_7th/domain/comment/controller/docs/CommentControllerDocs.java b/src/main/java/com/example/leets_7th/domain/comment/controller/docs/CommentControllerDocs.java new file mode 100644 index 0000000..f946607 --- /dev/null +++ b/src/main/java/com/example/leets_7th/domain/comment/controller/docs/CommentControllerDocs.java @@ -0,0 +1,7 @@ +package com.example.leets_7th.domain.comment.controller.docs; + +import io.swagger.v3.oas.annotations.tags.Tag; + +@Tag(name = "Comment", description = "댓글 API") +public interface CommentControllerDocs { +} From da3daa50d4535b5c28b12718b074f4ff9867c1d0 Mon Sep 17 00:00:00 2001 From: kimjihoon Date: Tue, 7 Apr 2026 01:03:39 +0900 Subject: [PATCH 07/15] =?UTF-8?q?[Feat]=20#93=20=EA=B2=8C=EC=8B=9C?= =?UTF-8?q?=EA=B8=80=20=EC=97=94=ED=8B=B0=ED=8B=B0=20=EB=A9=94=EC=84=9C?= =?UTF-8?q?=EB=93=9C=20=EC=B6=94=EA=B0=80=20=EB=B0=8F=20deletedAt=20?= =?UTF-8?q?=ED=95=84=EB=93=9C=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../example/leets_7th/domain/post/entity/Post.java | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/src/main/java/com/example/leets_7th/domain/post/entity/Post.java b/src/main/java/com/example/leets_7th/domain/post/entity/Post.java index 9f2de6c..be5632f 100644 --- a/src/main/java/com/example/leets_7th/domain/post/entity/Post.java +++ b/src/main/java/com/example/leets_7th/domain/post/entity/Post.java @@ -6,6 +6,7 @@ import jakarta.persistence.*; import lombok.*; +import java.time.LocalDateTime; import java.util.ArrayList; import java.util.List; @@ -38,6 +39,9 @@ public class Post extends BaseEntity { @OneToMany(mappedBy = "post", cascade = CascadeType.ALL, orphanRemoval = true) private List comments = new ArrayList<>(); + @Column(name = "deleted_at") + private LocalDateTime deletedAt; + @Builder public Post(User user, String title, String content, String thumbnailImageUrl) { this.user = user; @@ -45,4 +49,13 @@ public Post(User user, String title, String content, String thumbnailImageUrl) { this.content = content; this.thumbnailImageUrl = thumbnailImageUrl; } + + public void update(String title, String content) { + this.title = title; + this.content = content; + } + + public void delete() { + this.deletedAt = LocalDateTime.now(); + } } From 74ef73454cb0710388cac93b8b18086390c263e5 Mon Sep 17 00:00:00 2001 From: kimjihoon Date: Tue, 7 Apr 2026 01:03:57 +0900 Subject: [PATCH 08/15] =?UTF-8?q?[Feat]=20#93=20=EA=B2=8C=EC=8B=9C?= =?UTF-8?q?=EA=B8=80=20=EC=BB=A8=ED=8A=B8=EB=A1=A4=EB=9F=AC=20=EC=9D=B8?= =?UTF-8?q?=ED=84=B0=ED=8E=98=EC=9D=B4=EC=8A=A4=20=EB=B0=8F=20=EA=B5=AC?= =?UTF-8?q?=ED=98=84=EC=B2=B4=20=EC=83=9D=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../post/controller/PostController.java | 80 +++++++++++++++++++ .../controller/docs/PostControllerDocs.java | 55 +++++++++++++ 2 files changed, 135 insertions(+) create mode 100644 src/main/java/com/example/leets_7th/domain/post/controller/PostController.java create mode 100644 src/main/java/com/example/leets_7th/domain/post/controller/docs/PostControllerDocs.java diff --git a/src/main/java/com/example/leets_7th/domain/post/controller/PostController.java b/src/main/java/com/example/leets_7th/domain/post/controller/PostController.java new file mode 100644 index 0000000..dafb208 --- /dev/null +++ b/src/main/java/com/example/leets_7th/domain/post/controller/PostController.java @@ -0,0 +1,80 @@ +package com.example.leets_7th.domain.post.controller; + +import com.example.leets_7th.common.response.ApiResponse; +import com.example.leets_7th.common.status.SuccessStatus; +import com.example.leets_7th.domain.post.controller.docs.PostControllerDocs; +import com.example.leets_7th.domain.post.dto.request.CreatePostRequest; +import com.example.leets_7th.domain.post.dto.request.UpdatePostRequest; +import com.example.leets_7th.domain.post.dto.response.CreatePostResponse; +import com.example.leets_7th.domain.post.dto.response.GetPostDetailResponse; +import com.example.leets_7th.domain.post.dto.response.GetPostResponse; +import com.example.leets_7th.domain.post.dto.response.UpdatePostResponse; +import com.example.leets_7th.domain.post.service.PostCommandService; +import com.example.leets_7th.domain.post.service.PostQueryService; +import jakarta.validation.Valid; +import lombok.RequiredArgsConstructor; +import org.springframework.http.ResponseEntity; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.*; + +@RequestMapping("/api/posts") +@RestController +@Validated +@RequiredArgsConstructor +public class PostController implements PostControllerDocs { + + private final PostCommandService postCommandService; + private final PostQueryService postQueryService; + + @Override + @GetMapping + public ResponseEntity> getAllPost( + @RequestParam Long userId, + @RequestParam int page, + @RequestParam int size + ) { + GetPostResponse response = postQueryService.getAllPost(page, size); + return ApiResponse.success(SuccessStatus.GET_ALL_POST_SUCCESS, response); + } + + @Override + @GetMapping("/{postId}") + public ResponseEntity> getDetailPost( + @RequestParam Long userId, + @Valid @PathVariable Long postId + ) { + GetPostDetailResponse response = postQueryService.getPostDetail(postId); + return ApiResponse.success(SuccessStatus.GET_POST_DETAIL_SUCCESS, response); + } + + @Override + @PostMapping + public ResponseEntity> createPost( + @RequestParam Long userId, + @RequestBody @Valid CreatePostRequest request + ) { + CreatePostResponse response = postCommandService.createPost(userId, request); + return ApiResponse.success(SuccessStatus.CREATE_POST_SUCCESS, response); + } + + @Override + @PatchMapping("/{postId}") + public ResponseEntity> updatePost( + @RequestParam Long userId, + @PathVariable Long postId, + @Valid @RequestBody UpdatePostRequest request + ) { + UpdatePostResponse response = postCommandService.updatePost(userId, postId, request); + return ApiResponse.success(SuccessStatus.UPDATE_POST_SUCCESS, response); + } + + @Override + @DeleteMapping("/{postId}") + public ResponseEntity> deletePost( + @RequestParam Long userId, + @Valid @PathVariable Long postId + ) { + postCommandService.deletePost(userId, postId); + return ApiResponse.success(SuccessStatus.DELETE_POST_SUCCESS); + } +} diff --git a/src/main/java/com/example/leets_7th/domain/post/controller/docs/PostControllerDocs.java b/src/main/java/com/example/leets_7th/domain/post/controller/docs/PostControllerDocs.java new file mode 100644 index 0000000..02d622b --- /dev/null +++ b/src/main/java/com/example/leets_7th/domain/post/controller/docs/PostControllerDocs.java @@ -0,0 +1,55 @@ +package com.example.leets_7th.domain.post.controller.docs; + +import com.example.leets_7th.common.response.ApiResponse; +import com.example.leets_7th.domain.post.dto.request.CreatePostRequest; +import com.example.leets_7th.domain.post.dto.request.UpdatePostRequest; +import com.example.leets_7th.domain.post.dto.response.CreatePostResponse; +import com.example.leets_7th.domain.post.dto.response.GetPostDetailResponse; +import com.example.leets_7th.domain.post.dto.response.GetPostResponse; +import com.example.leets_7th.domain.post.dto.response.UpdatePostResponse; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.tags.Tag; +import jakarta.validation.Valid; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.*; + +@Tag(name = "Post", description = "게시글 관련 API") +public interface PostControllerDocs { + + @Operation(summary = "게시글 목록 조회", description = "게시글 리스트를 조회합니다.") + @GetMapping + ResponseEntity> getAllPost( + @RequestParam Long userId, + @RequestParam int page, + @RequestParam int size + ); + + @Operation(summary = "게시글 상세 조회", description = "특정 게시글의 상세 정보를 조회합니다.") + @GetMapping("/{postId}") + ResponseEntity> getDetailPost( + @RequestParam Long userId, + @Valid @PathVariable Long postId + ); + + @Operation(summary = "게시글 생성", description = "새로운 게시글을 생성합니다.") + @PostMapping + ResponseEntity> createPost( + @RequestParam Long userId, + @RequestBody @Valid CreatePostRequest request + ); + + @Operation(summary = "게시글 수정", description = "기존 게시글을 수정합니다.") + @PatchMapping("/{postId}") + ResponseEntity> updatePost( + @RequestParam Long userId, + @PathVariable Long postId, + @Valid @RequestBody UpdatePostRequest request + ); + + @Operation(summary = "게시글 삭제", description = "게시글을 삭제합니다.") + @DeleteMapping("/{postId}") + ResponseEntity> deletePost( + @RequestParam Long userId, + @Valid @PathVariable Long postId + ); +} From 5297638e7fef211a570b3e599568d4ba4274d2c5 Mon Sep 17 00:00:00 2001 From: kimjihoon Date: Tue, 7 Apr 2026 01:04:24 +0900 Subject: [PATCH 09/15] =?UTF-8?q?[Feat]=20#93=20=EA=B2=8C=EC=8B=9C?= =?UTF-8?q?=EA=B8=80=20=EA=B4=80=EB=A0=A8=20=EA=B5=AC=ED=98=84=EC=B2=B4=20?= =?UTF-8?q?=EB=B0=8F=20=EB=A6=AC=ED=8F=AC=EC=A7=80=ED=86=A0=EB=A6=AC=20?= =?UTF-8?q?=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../post/repository/PostRepository.java | 7 ++ .../post/service/PostCommandService.java | 88 +++++++++++++++++++ .../domain/post/service/PostQueryService.java | 19 ++++ .../user/repository/UserRepository.java | 7 ++ 4 files changed, 121 insertions(+) create mode 100644 src/main/java/com/example/leets_7th/domain/post/repository/PostRepository.java create mode 100644 src/main/java/com/example/leets_7th/domain/post/service/PostCommandService.java create mode 100644 src/main/java/com/example/leets_7th/domain/post/service/PostQueryService.java create mode 100644 src/main/java/com/example/leets_7th/domain/user/repository/UserRepository.java diff --git a/src/main/java/com/example/leets_7th/domain/post/repository/PostRepository.java b/src/main/java/com/example/leets_7th/domain/post/repository/PostRepository.java new file mode 100644 index 0000000..108d4b0 --- /dev/null +++ b/src/main/java/com/example/leets_7th/domain/post/repository/PostRepository.java @@ -0,0 +1,7 @@ +package com.example.leets_7th.domain.post.repository; + +import com.example.leets_7th.domain.post.entity.Post; +import org.springframework.data.jpa.repository.JpaRepository; + +public interface PostRepository extends JpaRepository { +} diff --git a/src/main/java/com/example/leets_7th/domain/post/service/PostCommandService.java b/src/main/java/com/example/leets_7th/domain/post/service/PostCommandService.java new file mode 100644 index 0000000..d3b6161 --- /dev/null +++ b/src/main/java/com/example/leets_7th/domain/post/service/PostCommandService.java @@ -0,0 +1,88 @@ +package com.example.leets_7th.domain.post.service; + +import com.example.leets_7th.common.exception.GeneralException; +import com.example.leets_7th.common.status.ErrorStatus; +import com.example.leets_7th.domain.post.dto.request.CreatePostRequest; +import com.example.leets_7th.domain.post.dto.request.UpdatePostRequest; +import com.example.leets_7th.domain.post.dto.response.CreatePostResponse; +import com.example.leets_7th.domain.post.dto.response.UpdatePostResponse; +import com.example.leets_7th.domain.post.entity.Post; +import com.example.leets_7th.domain.post.repository.PostRepository; +import com.example.leets_7th.domain.user.entity.User; +import com.example.leets_7th.domain.user.repository.UserRepository; +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + + +@Service +@RequiredArgsConstructor +@Transactional +public class PostCommandService { + + private final PostRepository postRepository; + private final UserRepository userRepository; + + public CreatePostResponse createPost(Long userId, CreatePostRequest request) { + + User user = getUser(userId); + + Post post = Post.builder() + .user(user) + .title(request.title()) + .content(request.content()) + .thumbnailImageUrl(null) + .build(); + + postRepository.save(post); + + return new CreatePostResponse(post.getId(), null); + } + + public UpdatePostResponse updatePost(Long userId, Long postId, UpdatePostRequest request) { + + Post post = getPost(postId); + + validateOwner(post, userId); + validateNotDeleted(post); + + post.update(request.title(), request.content()); + + return new UpdatePostResponse( + post.getId(), + post.getUpdatedAt() + ); + } + + public void deletePost(Long userId, Long postId) { + + Post post = getPost(postId); + + validateOwner(post, userId); + validateNotDeleted(post); + + post.delete(); + } + + private User getUser(Long userId) { + return userRepository.findById(userId) + .orElseThrow(() -> new GeneralException(ErrorStatus.USER_NOT_FOUND)); + } + + private Post getPost(Long postId) { + return postRepository.findById(postId) + .orElseThrow(() -> new GeneralException(ErrorStatus.POST_NOT_FOUND)); + } + + private void validateOwner(Post post, Long userId) { + if (!post.getUser().getId().equals(userId)) { + throw new GeneralException(ErrorStatus.FORBIDDEN); + } + } + + private void validateNotDeleted(Post post) { + if (post.getDeletedAt() != null) { + throw new GeneralException(ErrorStatus.POST_ALREADY_DELETED); + } + } +} diff --git a/src/main/java/com/example/leets_7th/domain/post/service/PostQueryService.java b/src/main/java/com/example/leets_7th/domain/post/service/PostQueryService.java new file mode 100644 index 0000000..c652463 --- /dev/null +++ b/src/main/java/com/example/leets_7th/domain/post/service/PostQueryService.java @@ -0,0 +1,19 @@ +package com.example.leets_7th.domain.post.service; + +import com.example.leets_7th.domain.post.dto.response.GetPostDetailResponse; +import com.example.leets_7th.domain.post.dto.response.GetPostResponse; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +@Service +@Transactional(readOnly = true) +public class PostQueryService { + + public GetPostResponse getAllPost(int page, int size){ + return null; + } + + public GetPostDetailResponse getPostDetail(Long postId){ + return null; + } +} diff --git a/src/main/java/com/example/leets_7th/domain/user/repository/UserRepository.java b/src/main/java/com/example/leets_7th/domain/user/repository/UserRepository.java new file mode 100644 index 0000000..54f887a --- /dev/null +++ b/src/main/java/com/example/leets_7th/domain/user/repository/UserRepository.java @@ -0,0 +1,7 @@ +package com.example.leets_7th.domain.user.repository; + +import com.example.leets_7th.domain.user.entity.User; +import org.springframework.data.jpa.repository.JpaRepository; + +public interface UserRepository extends JpaRepository { +} From 59dbef3a3f4241c760a62e4214bdd049434ff35b Mon Sep 17 00:00:00 2001 From: jihoonkim501 Date: Tue, 7 Apr 2026 11:47:10 +0900 Subject: [PATCH 10/15] =?UTF-8?q?[Refactor]=20#93=20Request=20Validation?= =?UTF-8?q?=20=EB=A9=94=EC=84=B8=EC=A7=80=20=EA=B5=AC=EC=B2=B4=ED=99=94?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../leets_7th/domain/post/dto/request/CreatePostRequest.java | 5 +++-- .../leets_7th/domain/post/dto/request/UpdatePostRequest.java | 5 +++-- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/src/main/java/com/example/leets_7th/domain/post/dto/request/CreatePostRequest.java b/src/main/java/com/example/leets_7th/domain/post/dto/request/CreatePostRequest.java index ba2f11a..1407369 100644 --- a/src/main/java/com/example/leets_7th/domain/post/dto/request/CreatePostRequest.java +++ b/src/main/java/com/example/leets_7th/domain/post/dto/request/CreatePostRequest.java @@ -6,13 +6,14 @@ public record CreatePostRequest( @Schema(example = "제목") - @NotBlank + @NotBlank(message = "제목은 공백일 수 없습니다") String title, - @NotBlank @Schema(example = "내용") + @NotBlank(message = "내용은 공백일 수 없습니다") String content, Integer thumbnailIndex + ) { } diff --git a/src/main/java/com/example/leets_7th/domain/post/dto/request/UpdatePostRequest.java b/src/main/java/com/example/leets_7th/domain/post/dto/request/UpdatePostRequest.java index 7e674cb..69be829 100644 --- a/src/main/java/com/example/leets_7th/domain/post/dto/request/UpdatePostRequest.java +++ b/src/main/java/com/example/leets_7th/domain/post/dto/request/UpdatePostRequest.java @@ -5,14 +5,15 @@ public record UpdatePostRequest( - @NotBlank @Schema(example = "제목") + @NotBlank(message = "제목은 공백일 수 없습니다") String title, - @NotBlank @Schema(example = "내용") + @NotBlank(message = "내용은 공백일 수 없습니다") String content, Integer thumbnailIndex + ) { } From a42163103e65f4050f2fd3ad1160e5f052a193a6 Mon Sep 17 00:00:00 2001 From: jihoonkim501 Date: Tue, 7 Apr 2026 15:40:57 +0900 Subject: [PATCH 11/15] =?UTF-8?q?[Feat]=20#93=20=EA=B2=8C=EC=8B=9C?= =?UTF-8?q?=EA=B8=80=20=EC=A0=84=EC=B2=B4=EC=A1=B0=ED=9A=8C=20DTO=20?= =?UTF-8?q?=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../post/dto/request/GetPostRequest.java | 23 ++++++++++++++++++- .../post/dto/response/GetPostResponse.java | 19 ++++++++++++++- .../domain/post/dto/response/PostSummary.java | 23 +++++++++++++++++++ 3 files changed, 63 insertions(+), 2 deletions(-) create mode 100644 src/main/java/com/example/leets_7th/domain/post/dto/response/PostSummary.java diff --git a/src/main/java/com/example/leets_7th/domain/post/dto/request/GetPostRequest.java b/src/main/java/com/example/leets_7th/domain/post/dto/request/GetPostRequest.java index 2a458f0..825ea1b 100644 --- a/src/main/java/com/example/leets_7th/domain/post/dto/request/GetPostRequest.java +++ b/src/main/java/com/example/leets_7th/domain/post/dto/request/GetPostRequest.java @@ -1,4 +1,25 @@ package com.example.leets_7th.domain.post.dto.request; -public record GetPostRequest() { +import jakarta.validation.constraints.Max; +import jakarta.validation.constraints.Min; +import jakarta.validation.constraints.NotNull; +import org.springframework.data.domain.PageRequest; +import org.springframework.data.domain.Pageable; +import org.springframework.data.domain.Sort; + +public record GetPostRequest( + + @NotNull(message = "userId는 필수입니다") + Long userId, + + @Min(value = 1, message = "page는 1 이상이어야 합니다") + int page, + + @Min(value = 1, message = "size는 1 이상이어야 합니다") + @Max(value = 50, message = "size는 50 이하여야 합니다") + int size +) { + public Pageable toPageable() { + return PageRequest.of(page - 1, size, Sort.by("createdAt").descending()); + } } diff --git a/src/main/java/com/example/leets_7th/domain/post/dto/response/GetPostResponse.java b/src/main/java/com/example/leets_7th/domain/post/dto/response/GetPostResponse.java index fd69c58..74339b5 100644 --- a/src/main/java/com/example/leets_7th/domain/post/dto/response/GetPostResponse.java +++ b/src/main/java/com/example/leets_7th/domain/post/dto/response/GetPostResponse.java @@ -1,4 +1,21 @@ package com.example.leets_7th.domain.post.dto.response; -public record GetPostResponse() { +import java.util.List; + +public record GetPostResponse( + List posts, + int page, + int size, + long totalElements, + int totalPages +) { + public static GetPostResponse of( + List posts, + int page, + int size, + long totalElements, + int totalPages + ) { + return new GetPostResponse(posts, page, size, totalElements, totalPages); + } } diff --git a/src/main/java/com/example/leets_7th/domain/post/dto/response/PostSummary.java b/src/main/java/com/example/leets_7th/domain/post/dto/response/PostSummary.java new file mode 100644 index 0000000..f6cec11 --- /dev/null +++ b/src/main/java/com/example/leets_7th/domain/post/dto/response/PostSummary.java @@ -0,0 +1,23 @@ +package com.example.leets_7th.domain.post.dto.response; + +import com.example.leets_7th.domain.post.entity.Post; + +import java.time.LocalDateTime; + +public record PostSummary( + Long postId, + String title, + String thumbnailImageUrl, + String author, + LocalDateTime createdAt +) { + public static PostSummary from(Post post) { + return new PostSummary( + post.getId(), + post.getTitle(), + post.getThumbnailImageUrl(), + post.getUser().getName(), + post.getCreatedAt() + ); + } +} From 2eb3fd65fb697587cae7d868a9b55e676253a4af Mon Sep 17 00:00:00 2001 From: jihoonkim501 Date: Tue, 7 Apr 2026 15:41:50 +0900 Subject: [PATCH 12/15] =?UTF-8?q?[Refactor]=20#93=20PostController=20?= =?UTF-8?q?=ED=8C=8C=EB=9D=BC=EB=AF=B8=ED=84=B0=20->=20DTO=20=EB=A1=9C=20?= =?UTF-8?q?=EB=B3=80=ED=99=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../domain/post/controller/PostController.java | 11 +++++------ .../post/controller/docs/PostControllerDocs.java | 7 +++---- 2 files changed, 8 insertions(+), 10 deletions(-) diff --git a/src/main/java/com/example/leets_7th/domain/post/controller/PostController.java b/src/main/java/com/example/leets_7th/domain/post/controller/PostController.java index dafb208..2c526d3 100644 --- a/src/main/java/com/example/leets_7th/domain/post/controller/PostController.java +++ b/src/main/java/com/example/leets_7th/domain/post/controller/PostController.java @@ -4,6 +4,7 @@ import com.example.leets_7th.common.status.SuccessStatus; import com.example.leets_7th.domain.post.controller.docs.PostControllerDocs; import com.example.leets_7th.domain.post.dto.request.CreatePostRequest; +import com.example.leets_7th.domain.post.dto.request.GetPostRequest; import com.example.leets_7th.domain.post.dto.request.UpdatePostRequest; import com.example.leets_7th.domain.post.dto.response.CreatePostResponse; import com.example.leets_7th.domain.post.dto.response.GetPostDetailResponse; @@ -29,11 +30,9 @@ public class PostController implements PostControllerDocs { @Override @GetMapping public ResponseEntity> getAllPost( - @RequestParam Long userId, - @RequestParam int page, - @RequestParam int size + @Valid @ModelAttribute GetPostRequest request ) { - GetPostResponse response = postQueryService.getAllPost(page, size); + GetPostResponse response = postQueryService.getAllPost(request); return ApiResponse.success(SuccessStatus.GET_ALL_POST_SUCCESS, response); } @@ -41,9 +40,9 @@ public ResponseEntity> getAllPost( @GetMapping("/{postId}") public ResponseEntity> getDetailPost( @RequestParam Long userId, - @Valid @PathVariable Long postId + @PathVariable Long postId ) { - GetPostDetailResponse response = postQueryService.getPostDetail(postId); + GetPostDetailResponse response = postQueryService.getPostDetail(userId, postId); return ApiResponse.success(SuccessStatus.GET_POST_DETAIL_SUCCESS, response); } diff --git a/src/main/java/com/example/leets_7th/domain/post/controller/docs/PostControllerDocs.java b/src/main/java/com/example/leets_7th/domain/post/controller/docs/PostControllerDocs.java index 02d622b..63d0246 100644 --- a/src/main/java/com/example/leets_7th/domain/post/controller/docs/PostControllerDocs.java +++ b/src/main/java/com/example/leets_7th/domain/post/controller/docs/PostControllerDocs.java @@ -2,6 +2,7 @@ import com.example.leets_7th.common.response.ApiResponse; import com.example.leets_7th.domain.post.dto.request.CreatePostRequest; +import com.example.leets_7th.domain.post.dto.request.GetPostRequest; import com.example.leets_7th.domain.post.dto.request.UpdatePostRequest; import com.example.leets_7th.domain.post.dto.response.CreatePostResponse; import com.example.leets_7th.domain.post.dto.response.GetPostDetailResponse; @@ -19,16 +20,14 @@ public interface PostControllerDocs { @Operation(summary = "게시글 목록 조회", description = "게시글 리스트를 조회합니다.") @GetMapping ResponseEntity> getAllPost( - @RequestParam Long userId, - @RequestParam int page, - @RequestParam int size + @Valid @ModelAttribute GetPostRequest request ); @Operation(summary = "게시글 상세 조회", description = "특정 게시글의 상세 정보를 조회합니다.") @GetMapping("/{postId}") ResponseEntity> getDetailPost( @RequestParam Long userId, - @Valid @PathVariable Long postId + @PathVariable Long postId ); @Operation(summary = "게시글 생성", description = "새로운 게시글을 생성합니다.") From 66aeb5c84726cb06468a7e103db0a4a0fe74451e Mon Sep 17 00:00:00 2001 From: jihoonkim501 Date: Tue, 7 Apr 2026 15:42:30 +0900 Subject: [PATCH 13/15] =?UTF-8?q?[Feat]=20#93=20=EA=B2=8C=EC=8B=9C?= =?UTF-8?q?=EA=B8=80=20=EC=83=81=EC=84=B8=EC=A1=B0=ED=9A=8C=20DTO=20?= =?UTF-8?q?=EC=83=9D=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../dto/response/GetPostDetailResponse.java | 28 ++++++++++++++++++- 1 file changed, 27 insertions(+), 1 deletion(-) diff --git a/src/main/java/com/example/leets_7th/domain/post/dto/response/GetPostDetailResponse.java b/src/main/java/com/example/leets_7th/domain/post/dto/response/GetPostDetailResponse.java index b1d54a3..05e0a06 100644 --- a/src/main/java/com/example/leets_7th/domain/post/dto/response/GetPostDetailResponse.java +++ b/src/main/java/com/example/leets_7th/domain/post/dto/response/GetPostDetailResponse.java @@ -1,4 +1,30 @@ package com.example.leets_7th.domain.post.dto.response; -public record GetPostDetailResponse() { +import com.example.leets_7th.domain.post.entity.Image; +import com.example.leets_7th.domain.post.entity.Post; +import java.time.LocalDateTime; +import java.util.List; + +public record GetPostDetailResponse( + Long postId, + String title, + String content, + String thumbnailImageUrl, + String author, + List imageUrls, + LocalDateTime createdAt +) { + public static GetPostDetailResponse from(Post post) { + return new GetPostDetailResponse( + post.getId(), + post.getTitle(), + post.getContent(), + post.getThumbnailImageUrl(), + post.getUser().getName(), + post.getImages().stream() + .map(Image::getImageUrl) + .toList(), + post.getCreatedAt() + ); + } } From b52461f2d518859984064de579dd52a1004a5a3f Mon Sep 17 00:00:00 2001 From: jihoonkim501 Date: Tue, 7 Apr 2026 15:42:52 +0900 Subject: [PATCH 14/15] =?UTF-8?q?[Feat]=20#93=20=EA=B2=8C=EC=8B=9C?= =?UTF-8?q?=EA=B8=80=20=EC=A0=84=EC=B2=B4/=EC=83=81=EC=84=B8=20=EC=A1=B0?= =?UTF-8?q?=ED=9A=8C=20=EA=B5=AC=ED=98=84=EC=B2=B4=20=EC=83=9D=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../post/repository/PostRepository.java | 12 ++++++ .../domain/post/service/PostQueryService.java | 42 +++++++++++++++++-- .../domain/post/validator/PostValidator.java | 28 +++++++++++++ 3 files changed, 78 insertions(+), 4 deletions(-) create mode 100644 src/main/java/com/example/leets_7th/domain/post/validator/PostValidator.java diff --git a/src/main/java/com/example/leets_7th/domain/post/repository/PostRepository.java b/src/main/java/com/example/leets_7th/domain/post/repository/PostRepository.java index 108d4b0..7ce43bd 100644 --- a/src/main/java/com/example/leets_7th/domain/post/repository/PostRepository.java +++ b/src/main/java/com/example/leets_7th/domain/post/repository/PostRepository.java @@ -1,7 +1,19 @@ package com.example.leets_7th.domain.post.repository; import com.example.leets_7th.domain.post.entity.Post; +import com.example.leets_7th.domain.user.entity.User; +import org.springframework.data.domain.Page; +import org.springframework.data.domain.Pageable; +import org.springframework.data.jpa.repository.EntityGraph; import org.springframework.data.jpa.repository.JpaRepository; +import java.util.Optional; + public interface PostRepository extends JpaRepository { + + @EntityGraph(attributePaths = {"user"}) + Page findAllByUser(User user, Pageable pageable); + + @EntityGraph(attributePaths = {"user", "images"}) + Optional findById(Long postId); } diff --git a/src/main/java/com/example/leets_7th/domain/post/service/PostQueryService.java b/src/main/java/com/example/leets_7th/domain/post/service/PostQueryService.java index c652463..0f193b2 100644 --- a/src/main/java/com/example/leets_7th/domain/post/service/PostQueryService.java +++ b/src/main/java/com/example/leets_7th/domain/post/service/PostQueryService.java @@ -1,19 +1,53 @@ package com.example.leets_7th.domain.post.service; +import com.example.leets_7th.domain.post.dto.request.GetPostRequest; import com.example.leets_7th.domain.post.dto.response.GetPostDetailResponse; import com.example.leets_7th.domain.post.dto.response.GetPostResponse; +import com.example.leets_7th.domain.post.dto.response.PostSummary; +import com.example.leets_7th.domain.post.entity.Post; +import com.example.leets_7th.domain.post.repository.PostRepository; +import com.example.leets_7th.domain.post.validator.PostValidator; +import com.example.leets_7th.domain.user.entity.User; +import lombok.RequiredArgsConstructor; +import org.springframework.data.domain.Page; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; +import java.util.List; + @Service +@RequiredArgsConstructor @Transactional(readOnly = true) public class PostQueryService { - public GetPostResponse getAllPost(int page, int size){ - return null; + private final PostRepository postRepository; + private final PostValidator postValidator; + + public GetPostResponse getAllPost(GetPostRequest request) { + + User user = postValidator.validateUser(request.userId()); + + Page postPage = postRepository.findAllByUser(user, request.toPageable()); + + List postList = postPage.getContent().stream() + .map(PostSummary::from) + .toList(); + + return GetPostResponse.of( + postList, + postPage.getNumber() + 1, + postPage.getSize(), + postPage.getTotalElements(), + postPage.getTotalPages() + ); } - public GetPostDetailResponse getPostDetail(Long postId){ - return null; + public GetPostDetailResponse getPostDetail(Long userId, Long postId) { + + postValidator.validateUser(userId); + Post post = postValidator.validatePost(postId); + + return GetPostDetailResponse.from(post); } + } diff --git a/src/main/java/com/example/leets_7th/domain/post/validator/PostValidator.java b/src/main/java/com/example/leets_7th/domain/post/validator/PostValidator.java new file mode 100644 index 0000000..4a45f0e --- /dev/null +++ b/src/main/java/com/example/leets_7th/domain/post/validator/PostValidator.java @@ -0,0 +1,28 @@ +package com.example.leets_7th.domain.post.validator; + +import com.example.leets_7th.common.exception.GeneralException; +import com.example.leets_7th.common.status.ErrorStatus; +import com.example.leets_7th.domain.post.entity.Post; +import com.example.leets_7th.domain.post.repository.PostRepository; +import com.example.leets_7th.domain.user.entity.User; +import com.example.leets_7th.domain.user.repository.UserRepository; +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Component; + +@Component +@RequiredArgsConstructor +public class PostValidator { + + private final UserRepository userRepository; + private final PostRepository postRepository; + + public User validateUser(Long userId) { + return userRepository.findById(userId) + .orElseThrow(() -> new GeneralException(ErrorStatus.USER_NOT_FOUND)); + } + + public Post validatePost(Long postId) { + return postRepository.findById(postId) + .orElseThrow(() -> new GeneralException(ErrorStatus.POST_NOT_FOUND)); + } +} From 7cc50c8a4de58e4135fa86ea66bffcfdde9aae35 Mon Sep 17 00:00:00 2001 From: jihoonkim501 Date: Tue, 7 Apr 2026 16:30:32 +0900 Subject: [PATCH 15/15] =?UTF-8?q?[Fix]=20#93=20=EC=82=AD=EC=A0=9C=EB=90=9C?= =?UTF-8?q?=20=EA=B2=8C=EC=8B=9C=EA=B8=80=20=EA=B2=80=EC=A6=9D=20=EB=A1=9C?= =?UTF-8?q?=EC=A7=81=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../leets_7th/domain/post/repository/PostRepository.java | 6 +++--- .../leets_7th/domain/post/service/PostQueryService.java | 3 ++- .../leets_7th/domain/post/validator/PostValidator.java | 8 +++++++- 3 files changed, 12 insertions(+), 5 deletions(-) diff --git a/src/main/java/com/example/leets_7th/domain/post/repository/PostRepository.java b/src/main/java/com/example/leets_7th/domain/post/repository/PostRepository.java index 7ce43bd..848a632 100644 --- a/src/main/java/com/example/leets_7th/domain/post/repository/PostRepository.java +++ b/src/main/java/com/example/leets_7th/domain/post/repository/PostRepository.java @@ -11,9 +11,9 @@ public interface PostRepository extends JpaRepository { - @EntityGraph(attributePaths = {"user"}) - Page findAllByUser(User user, Pageable pageable); - @EntityGraph(attributePaths = {"user", "images"}) Optional findById(Long postId); + + @EntityGraph(attributePaths = {"user"}) + Page findAllByUserAndDeletedAtIsNull(User user, Pageable pageable); } diff --git a/src/main/java/com/example/leets_7th/domain/post/service/PostQueryService.java b/src/main/java/com/example/leets_7th/domain/post/service/PostQueryService.java index 0f193b2..fa4a0c6 100644 --- a/src/main/java/com/example/leets_7th/domain/post/service/PostQueryService.java +++ b/src/main/java/com/example/leets_7th/domain/post/service/PostQueryService.java @@ -27,7 +27,8 @@ public GetPostResponse getAllPost(GetPostRequest request) { User user = postValidator.validateUser(request.userId()); - Page postPage = postRepository.findAllByUser(user, request.toPageable()); + Page postPage = postRepository + .findAllByUserAndDeletedAtIsNull(user, request.toPageable()); List postList = postPage.getContent().stream() .map(PostSummary::from) diff --git a/src/main/java/com/example/leets_7th/domain/post/validator/PostValidator.java b/src/main/java/com/example/leets_7th/domain/post/validator/PostValidator.java index 4a45f0e..8b0392f 100644 --- a/src/main/java/com/example/leets_7th/domain/post/validator/PostValidator.java +++ b/src/main/java/com/example/leets_7th/domain/post/validator/PostValidator.java @@ -22,7 +22,13 @@ public User validateUser(Long userId) { } public Post validatePost(Long postId) { - return postRepository.findById(postId) + Post post = postRepository.findById(postId) .orElseThrow(() -> new GeneralException(ErrorStatus.POST_NOT_FOUND)); + + if (post.getDeletedAt() != null) { + throw new GeneralException(ErrorStatus.POST_ALREADY_DELETED); + } + + return post; } }