diff --git a/src/main/java/com/brainpix/post/controller/SavedPostController.java b/src/main/java/com/brainpix/post/controller/SavedPostController.java
index 2424c2c3..6d2a2ef9 100644
--- a/src/main/java/com/brainpix/post/controller/SavedPostController.java
+++ b/src/main/java/com/brainpix/post/controller/SavedPostController.java
@@ -14,26 +14,29 @@
import com.brainpix.post.dto.PostCollaborationResponse;
import com.brainpix.post.dto.PostIdeaMarketResponse;
import com.brainpix.post.dto.PostRequestTaskResponse;
+import com.brainpix.post.dto.SavePostResponseDto;
import com.brainpix.post.service.SavedPostService;
import com.brainpix.security.authorization.AllUser;
import com.brainpix.security.authorization.UserId;
import io.swagger.v3.oas.annotations.Operation;
+import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.RequiredArgsConstructor;
@RestController
@RequestMapping("/saved-posts")
@RequiredArgsConstructor
+@Tag(name = "게시글 저장 관련 API", description = "게시글을 저장 및 해제 하고, 저장된 게시글을 조회하는 API입니다.")
public class SavedPostController {
private final SavedPostService savedPostService;
- @Operation(summary = "게시글 저장", description = "현재 로그인한 사용자가 특정 게시글을 저장합니다.")
+ @Operation(summary = "게시글 저장 및 해제", description = "토글 형식으로 현재 로그인한 사용자가 특정 게시글을 저장 또는 해제 합니다.
이미 저장된 게시글은 해제되고, 그렇지 않다면 저장합니다.")
@AllUser
@PostMapping
- public ResponseEntity> savePost(@UserId Long userId, @RequestParam long postId) {
- savedPostService.savePost(userId, postId);
- return ResponseEntity.ok(ApiResponse.successWithNoData());
+ public ResponseEntity> savePost(@UserId Long userId, @RequestParam long postId) {
+ SavePostResponseDto result = savedPostService.savePost(userId, postId);
+ return ResponseEntity.ok(ApiResponse.success(result));
}
@Operation(summary = "저장된 요청 과제 조회", description = "현재 로그인한 사용자가 저장한 요청 과제를 조회합니다.")
diff --git a/src/main/java/com/brainpix/post/dto/SavePostResponseDto.java b/src/main/java/com/brainpix/post/dto/SavePostResponseDto.java
new file mode 100644
index 00000000..f139eb74
--- /dev/null
+++ b/src/main/java/com/brainpix/post/dto/SavePostResponseDto.java
@@ -0,0 +1,9 @@
+package com.brainpix.post.dto;
+
+public record SavePostResponseDto(
+ Boolean isSaved
+) {
+ public static SavePostResponseDto from(Boolean isSaved) {
+ return new SavePostResponseDto(isSaved);
+ }
+}
diff --git a/src/main/java/com/brainpix/post/repository/SavedPostRepository.java b/src/main/java/com/brainpix/post/repository/SavedPostRepository.java
index 4adfd2d8..e4fdd730 100644
--- a/src/main/java/com/brainpix/post/repository/SavedPostRepository.java
+++ b/src/main/java/com/brainpix/post/repository/SavedPostRepository.java
@@ -1,5 +1,7 @@
package com.brainpix.post.repository;
+import java.util.Optional;
+
import org.springframework.data.jpa.repository.JpaRepository;
import com.brainpix.post.entity.Post;
@@ -7,8 +9,8 @@
import com.brainpix.user.entity.User;
public interface SavedPostRepository extends JpaRepository, SavedPostRepositoryCustom {
-
- boolean existsByUserAndPost(User user, Post post);
-
+
Long countByPostId(Long postId);
+
+ Optional findByUserAndPost(User user, Post post);
}
\ No newline at end of file
diff --git a/src/main/java/com/brainpix/post/service/SavedPostService.java b/src/main/java/com/brainpix/post/service/SavedPostService.java
index 726f78c0..e1cea5d4 100644
--- a/src/main/java/com/brainpix/post/service/SavedPostService.java
+++ b/src/main/java/com/brainpix/post/service/SavedPostService.java
@@ -1,14 +1,19 @@
package com.brainpix.post.service;
+import java.util.Optional;
+
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
-import com.brainpix.api.code.error.SavedPostErrorCode;
+import com.brainpix.api.code.error.CommonErrorCode;
+import com.brainpix.api.code.error.PostErrorCode;
+import com.brainpix.api.exception.BrainPixException;
import com.brainpix.post.dto.PostCollaborationResponse;
import com.brainpix.post.dto.PostIdeaMarketResponse;
import com.brainpix.post.dto.PostRequestTaskResponse;
+import com.brainpix.post.dto.SavePostResponseDto;
import com.brainpix.post.entity.Post;
import com.brainpix.post.entity.SavedPost;
import com.brainpix.post.entity.collaboration_hub.CollaborationHub;
@@ -31,21 +36,30 @@ public class SavedPostService {
private final PostRepository postRepository;
@Transactional
- public void savePost(long userId, long postId) {
+ public SavePostResponseDto savePost(long userId, long postId) {
User user = userRepository.findById(userId)
- .orElseThrow(() -> new IllegalArgumentException(SavedPostErrorCode.USER_NOT_FOUND.getMessage()));
+ .orElseThrow(() -> new BrainPixException(CommonErrorCode.USER_NOT_FOUND));
Post post = postRepository.findById(postId)
- .orElseThrow(() -> new IllegalArgumentException(SavedPostErrorCode.POST_NOT_FOUND.getMessage()));
+ .orElseThrow(() -> new BrainPixException(PostErrorCode.POST_NOT_FOUND));
+
+ Optional savedPost = savedPostRepository.findByUserAndPost(user, post);
- validateNotDuplicate(user, post);
+ boolean isSaved;
+ if (savedPost.isEmpty()) {
+ savedPostRepository.save(new SavedPost(user, post)); // 즐겨찾기 등록
+ isSaved = true;
+ } else {
+ savedPostRepository.delete(savedPost.get()); // 즐겨찾기 해제
+ isSaved = false;
+ }
- savedPostRepository.save(new SavedPost(user, post));
+ return SavePostResponseDto.from(isSaved);
}
public Page findSavedRequestTasks(long userId, Pageable pageable) {
User user = userRepository.findById(userId)
- .orElseThrow(() -> new IllegalArgumentException(SavedPostErrorCode.USER_NOT_FOUND.getMessage()));
+ .orElseThrow(() -> new BrainPixException(CommonErrorCode.USER_NOT_FOUND));
return savedPostRepository.findSavedRequestTasksByUser(user, pageable)
.map(savedPost -> {
@@ -57,7 +71,7 @@ public Page findSavedRequestTasks(long userId, Pageable
public Page findSavedIdeaMarkets(long userId, Pageable pageable) {
User user = userRepository.findById(userId)
- .orElseThrow(() -> new IllegalArgumentException(SavedPostErrorCode.USER_NOT_FOUND.getMessage()));
+ .orElseThrow(() -> new BrainPixException(CommonErrorCode.USER_NOT_FOUND));
return savedPostRepository.findSavedIdeaMarketsByUser(user, pageable)
.map(savedPost -> {
@@ -69,7 +83,7 @@ public Page findSavedIdeaMarkets(long userId, Pageable p
public Page findSavedCollaborationHubs(long userId, Pageable pageable) {
User user = userRepository.findById(userId)
- .orElseThrow(() -> new IllegalArgumentException(SavedPostErrorCode.USER_NOT_FOUND.getMessage()));
+ .orElseThrow(() -> new BrainPixException(CommonErrorCode.USER_NOT_FOUND));
return savedPostRepository.findSavedCollaborationHubsByUser(user, pageable)
.map(savedPost -> {
@@ -84,10 +98,4 @@ public Page findSavedCollaborationHubs(long userId, P
occupiedQuantity);
});
}
-
- private void validateNotDuplicate(User user, Post post) {
- if (savedPostRepository.existsByUserAndPost(user, post)) {
- throw new IllegalStateException(SavedPostErrorCode.DUPLICATE_SAVED_POST.getMessage());
- }
- }
}