From 1c0f669b5a2b4241cad30b24e51d75e0de34a5e1 Mon Sep 17 00:00:00 2001 From: donghyukseo Date: Fri, 15 Aug 2025 21:11:05 +0900 Subject: [PATCH 1/3] =?UTF-8?q?refactor=20:=20PostController=20=EB=8B=A8?= =?UTF-8?q?=EC=9D=BC=20=EA=B2=8C=EC=8B=9C=EA=B8=80=20=EC=A1=B0=ED=9A=8C=20?= =?UTF-8?q?=EB=A9=94=EC=84=9C=EB=93=9C=20=EC=BD=94=EB=93=9C=20=EC=88=98?= =?UTF-8?q?=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .gitignore | 2 +- .../tuzamate/domain/post/controller/PostController.java | 5 ++++- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/.gitignore b/.gitignore index 028fb02..6ea9293 100644 --- a/.gitignore +++ b/.gitignore @@ -36,7 +36,7 @@ out/ ### VS Code ### .vscode/ -/src/main/resources/*.env +*.env *.yml /src/main/generated/ diff --git a/src/main/java/naughty/tuzamate/domain/post/controller/PostController.java b/src/main/java/naughty/tuzamate/domain/post/controller/PostController.java index 2967fa8..34a2acc 100644 --- a/src/main/java/naughty/tuzamate/domain/post/controller/PostController.java +++ b/src/main/java/naughty/tuzamate/domain/post/controller/PostController.java @@ -38,7 +38,10 @@ public CustomResponse createPost( @GetMapping("/boards/{boardType}/posts/{postId}") @Operation(summary = "단일 게시글 조회", description = "단일 게시글을 조회합니다.") - public CustomResponse getPost(@PathVariable Long postId) { + public CustomResponse getPost( + @PathVariable Long postId, + @AuthenticationPrincipal PrincipalDetails principalDetails + ) { PostResDTO.PostPreviewDTO resDTO = postQueryService.getPost(postId); return CustomResponse.onSuccess(GeneralSuccessCode.OK, resDTO); From b34a91d5bdf3d55f1e6a57860f02aa29699b8d7d Mon Sep 17 00:00:00 2001 From: donghyukseo Date: Sat, 16 Aug 2025 22:23:46 +0900 Subject: [PATCH 2/3] =?UTF-8?q?refactor=20:=20=EB=8B=A8=EC=9D=BC=20?= =?UTF-8?q?=EA=B2=8C=EC=8B=9C=EA=B8=80=20=EC=A1=B0=ED=9A=8C=EC=8B=9C=20?= =?UTF-8?q?=EC=8A=A4=ED=81=AC=EB=9E=A9=20=EB=B0=8F=20=EC=A2=8B=EC=95=84?= =?UTF-8?q?=EC=9A=94=20=EC=9C=A0=EB=AC=B4=20=ED=99=95=EC=9D=B8=20=EA=B0=80?= =?UTF-8?q?=EB=8A=A5=20=EC=BD=94=EB=93=9C=EB=A1=9C=20=EB=B3=80=EA=B2=BD=20?= =?UTF-8?q?/=20FireBaseConfig=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../post/controller/PostController.java | 4 ++-- .../domain/post/converter/PostConverter.java | 17 +++++++++++++++ .../tuzamate/domain/post/dto/PostResDTO.java | 17 +++++++++++++++ .../post/service/query/PostQueryService.java | 3 ++- .../service/query/PostQueryServiceImpl.java | 15 +++++++++++-- .../repository/PostLikeRepository.java | 1 + .../repository/PostScrapRepository.java | 1 + .../global/config/FireBaseConfig.java | 21 +++++++++++++++---- 8 files changed, 70 insertions(+), 9 deletions(-) diff --git a/src/main/java/naughty/tuzamate/domain/post/controller/PostController.java b/src/main/java/naughty/tuzamate/domain/post/controller/PostController.java index 34a2acc..c3ab81c 100644 --- a/src/main/java/naughty/tuzamate/domain/post/controller/PostController.java +++ b/src/main/java/naughty/tuzamate/domain/post/controller/PostController.java @@ -38,11 +38,11 @@ public CustomResponse createPost( @GetMapping("/boards/{boardType}/posts/{postId}") @Operation(summary = "단일 게시글 조회", description = "단일 게시글을 조회합니다.") - public CustomResponse getPost( + public CustomResponse getPost( @PathVariable Long postId, @AuthenticationPrincipal PrincipalDetails principalDetails ) { - PostResDTO.PostPreviewDTO resDTO = postQueryService.getPost(postId); + PostResDTO.PostDTO resDTO = postQueryService.getPost(postId, principalDetails); return CustomResponse.onSuccess(GeneralSuccessCode.OK, resDTO); } diff --git a/src/main/java/naughty/tuzamate/domain/post/converter/PostConverter.java b/src/main/java/naughty/tuzamate/domain/post/converter/PostConverter.java index 2821964..0523daa 100644 --- a/src/main/java/naughty/tuzamate/domain/post/converter/PostConverter.java +++ b/src/main/java/naughty/tuzamate/domain/post/converter/PostConverter.java @@ -33,6 +33,23 @@ public static PostResDTO.CreatePostResponseDTO toCreatePostResponseDTO(Post post .build(); } + // Post Entity -> PostDTO + public static PostResDTO.PostDTO toPostDTO(Post post, boolean liked, boolean scraped) { + return PostResDTO.PostDTO.builder() + .id(post.getId()) + .title(post.getTitle()) + .content(post.getContent()) + .likeNum(post.getLikeNum()) + .author(post.getUser().getNickname()) + .commentNum((long) post.getComments().size()) // 댓글 수 + .isRead(post.isRead()) + .liked(liked) + .scraped(scraped) + .createdAt(post.getCreatedAt()) + .updatedAt(post.getUpdatedAt()) + .build(); + } + // Post Entity -> PostPreviewDTO public static PostResDTO.PostPreviewDTO toPostPreviewDTO(Post post) { return PostResDTO.PostPreviewDTO.builder() diff --git a/src/main/java/naughty/tuzamate/domain/post/dto/PostResDTO.java b/src/main/java/naughty/tuzamate/domain/post/dto/PostResDTO.java index 2455831..4201057 100644 --- a/src/main/java/naughty/tuzamate/domain/post/dto/PostResDTO.java +++ b/src/main/java/naughty/tuzamate/domain/post/dto/PostResDTO.java @@ -14,6 +14,23 @@ public record CreatePostResponseDTO( ){ } + @Builder + public record PostDTO( + Long id, + String title, + String content, + Long likeNum, + // 작성자 닉네임, 댓글 수 필드 추가 + String author, + Long commentNum, + boolean isRead, + boolean liked, + boolean scraped, + LocalDateTime createdAt, + LocalDateTime updatedAt + ){ + } + @Builder public record PostPreviewDTO( Long id, diff --git a/src/main/java/naughty/tuzamate/domain/post/service/query/PostQueryService.java b/src/main/java/naughty/tuzamate/domain/post/service/query/PostQueryService.java index 91c63e7..e7c3114 100644 --- a/src/main/java/naughty/tuzamate/domain/post/service/query/PostQueryService.java +++ b/src/main/java/naughty/tuzamate/domain/post/service/query/PostQueryService.java @@ -1,10 +1,11 @@ package naughty.tuzamate.domain.post.service.query; +import naughty.tuzamate.auth.principal.PrincipalDetails; import naughty.tuzamate.domain.post.dto.PostResDTO; import naughty.tuzamate.domain.post.enums.BoardType; public interface PostQueryService { - PostResDTO.PostPreviewDTO getPost(Long postId); + PostResDTO.PostDTO getPost(Long postId, PrincipalDetails principalDetails); PostResDTO.PostPreviewListDTO getPostList(BoardType boardType, Long cursor, int size); } diff --git a/src/main/java/naughty/tuzamate/domain/post/service/query/PostQueryServiceImpl.java b/src/main/java/naughty/tuzamate/domain/post/service/query/PostQueryServiceImpl.java index 2148e42..0dda854 100644 --- a/src/main/java/naughty/tuzamate/domain/post/service/query/PostQueryServiceImpl.java +++ b/src/main/java/naughty/tuzamate/domain/post/service/query/PostQueryServiceImpl.java @@ -1,11 +1,16 @@ package naughty.tuzamate.domain.post.service.query; import lombok.RequiredArgsConstructor; +import naughty.tuzamate.auth.principal.PrincipalDetails; import naughty.tuzamate.domain.post.converter.PostConverter; import naughty.tuzamate.domain.post.dto.PostResDTO; import naughty.tuzamate.domain.post.entity.Post; import naughty.tuzamate.domain.post.enums.BoardType; import naughty.tuzamate.domain.post.repository.PostRepository; +import naughty.tuzamate.domain.postLike.repository.PostLikeRepository; +import naughty.tuzamate.domain.postScrap.repository.PostScrapRepository; +import naughty.tuzamate.domain.user.entity.User; +import naughty.tuzamate.domain.user.repository.UserRepository; import naughty.tuzamate.global.error.GeneralErrorCode; import naughty.tuzamate.global.error.exception.CustomException; import org.springframework.data.domain.PageRequest; @@ -13,6 +18,7 @@ import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; +import java.security.Principal; import java.util.List; @Service @@ -20,9 +26,11 @@ public class PostQueryServiceImpl implements PostQueryService { private final PostRepository postRepository; + private final PostLikeRepository postLikeRepository; + private final PostScrapRepository postScrapRepository; @Override - public PostResDTO.PostPreviewDTO getPost(Long postId) { + public PostResDTO.PostDTO getPost(Long postId, PrincipalDetails principalDetails) { Post post = postRepository.findById(postId) .orElseThrow(() -> new CustomException(GeneralErrorCode.NOT_FOUND_404)); @@ -30,7 +38,10 @@ public PostResDTO.PostPreviewDTO getPost(Long postId) { post.setIsRead(); } - return PostConverter.toPostPreviewDTO(post); + boolean liked = postLikeRepository.existsByPostIdAndUserId(postId, principalDetails.getId()); + boolean scraped = postScrapRepository.existsByPostIdAndUserId(postId, principalDetails.getId()); + + return PostConverter.toPostDTO(post, liked, scraped); } @Override diff --git a/src/main/java/naughty/tuzamate/domain/postLike/repository/PostLikeRepository.java b/src/main/java/naughty/tuzamate/domain/postLike/repository/PostLikeRepository.java index 3330412..ce603ac 100644 --- a/src/main/java/naughty/tuzamate/domain/postLike/repository/PostLikeRepository.java +++ b/src/main/java/naughty/tuzamate/domain/postLike/repository/PostLikeRepository.java @@ -13,6 +13,7 @@ public interface PostLikeRepository extends JpaRepository { public boolean existsByPostAndUser(Post post, User user); public PostLike findByPostAndUser(Post post, User user); + public boolean existsByPostIdAndUserId(Long postId, Long userId); // 커서가 없는 경우 최신순 조회 @Query("select pl from PostLike pl join fetch pl.post p where pl.user.id = :userId order by pl.id desc") diff --git a/src/main/java/naughty/tuzamate/domain/postScrap/repository/PostScrapRepository.java b/src/main/java/naughty/tuzamate/domain/postScrap/repository/PostScrapRepository.java index 2e06fc6..c2c9e6f 100644 --- a/src/main/java/naughty/tuzamate/domain/postScrap/repository/PostScrapRepository.java +++ b/src/main/java/naughty/tuzamate/domain/postScrap/repository/PostScrapRepository.java @@ -14,6 +14,7 @@ public interface PostScrapRepository extends JpaRepository { public boolean existsByPostAndUser(Post post, User user); public PostScrap findByPostAndUser(Post post, User user); + public boolean existsByPostIdAndUserId(Long postId, Long userId); // 커서가 없는 경우 최신순 조회 @Query("select ps from PostScrap ps join fetch ps.post p where ps.user.id = :userId order by ps.id desc") diff --git a/src/main/java/naughty/tuzamate/global/config/FireBaseConfig.java b/src/main/java/naughty/tuzamate/global/config/FireBaseConfig.java index 085e9fa..9ec86ce 100644 --- a/src/main/java/naughty/tuzamate/global/config/FireBaseConfig.java +++ b/src/main/java/naughty/tuzamate/global/config/FireBaseConfig.java @@ -12,30 +12,43 @@ import java.io.FileInputStream; import java.io.IOException; +import java.io.InputStream; @Slf4j @Configuration public class FireBaseConfig { @Value("${firebase.service-account.path}") - private String SERVICE_ACCOUNT_PATH; + private String serviceAccountPath; @Bean public FirebaseApp firebaseApp() { - try (FileInputStream serviceAccount = new FileInputStream(SERVICE_ACCOUNT_PATH)) { + try (InputStream serviceAccount = getServiceAccountStream()) { + FirebaseOptions options = FirebaseOptions.builder() .setCredentials(GoogleCredentials.fromStream(serviceAccount)) .build(); - log.info("Successfully initialized firebase app"); + log.info("✅ Successfully initialized firebase app"); return FirebaseApp.initializeApp(options); } catch (IOException exception) { - log.error("Fail to initialize firebase app: {}", exception.getMessage(), exception); + log.error("❌ Fail to initialize firebase app: {}", exception.getMessage(), exception); return null; } } + private InputStream getServiceAccountStream() throws IOException { + // 절대경로면 FileInputStream, 아니면 classpath + if (serviceAccountPath.startsWith("/") || serviceAccountPath.contains(":")) { + log.info("Using absolute path for Firebase service account: {}", serviceAccountPath); + return new FileInputStream(serviceAccountPath); + } else { + log.info("Using classpath resource for Firebase service account: {}", serviceAccountPath); + return new ClassPathResource(serviceAccountPath).getInputStream(); + } + } + @Bean public FirebaseMessaging firebaseMessaging(FirebaseApp firebaseApp) { return FirebaseMessaging.getInstance(firebaseApp); From cd7fb8b796bb4f79d825a55e3c17c1b60ab246ab Mon Sep 17 00:00:00 2001 From: donghyukseo Date: Sat, 16 Aug 2025 22:24:44 +0900 Subject: [PATCH 3/3] =?UTF-8?q?refactor=20:=20FireBaseConfig=20=EC=88=98?= =?UTF-8?q?=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/naughty/tuzamate/global/config/FireBaseConfig.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/java/naughty/tuzamate/global/config/FireBaseConfig.java b/src/main/java/naughty/tuzamate/global/config/FireBaseConfig.java index 9ec86ce..bb33066 100644 --- a/src/main/java/naughty/tuzamate/global/config/FireBaseConfig.java +++ b/src/main/java/naughty/tuzamate/global/config/FireBaseConfig.java @@ -29,11 +29,11 @@ public FirebaseApp firebaseApp() { .setCredentials(GoogleCredentials.fromStream(serviceAccount)) .build(); - log.info("✅ Successfully initialized firebase app"); + log.info(" Successfully initialized firebase app"); return FirebaseApp.initializeApp(options); } catch (IOException exception) { - log.error("❌ Fail to initialize firebase app: {}", exception.getMessage(), exception); + log.error(" Fail to initialize firebase app: {}", exception.getMessage(), exception); return null; } }