- Code Post에 북마크 기능 추가2025년 05월 10일 02시 56분 09초에 업로드 된 글입니다.작성자: do_hyuk728x90반응형
요구 사항
- member id를 통해 북마크된 post들을 조회할 수 있어야한다.
- 북마크 취소 시 soft delete 방식으로 진행한다.
일괄 삭제는 스케줄러를 통해 진행 - bookmark(n) : member(1) 관계이다.
- post 삭제 시에도 북마크에는 유지된다.
단, 해당 포스트 페이지로 이동 시 "존재하지 않는 페이지" 오류 호출
설계
Entity
@Getter @NoArgsConstructor @Entity public class CodePostBookmark extends BaseEntity { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; @ManyToOne(fetch = FetchType.LAZY) @JoinColumn private Member member; @Column(nullable = false) private Long codePostId; @ColumnDefault("false") @Column(nullable = false) private boolean isDeleted; @Builder public CodePostBookmark(Long codePostId, Member member) { this.codePostId = codePostId; this.member = member; } public void update() { this.isDeleted = !this.isDeleted; } }
Repository
@Query("SELECT b FROM CodePostBookmark b WHERE b.member.id = :memberId AND b.codePostId = :codePostId") Optional<CodePostBookmark> findById(@Param("memberId") Long memberId, @Param("codePostId") Long codePostId);
findById 쿼리는 특정 포스트에 사용자가 북마크를 이미 했는지를 알기 위한 로직이다.
@Query("SELECT new ... CodePostBookmarkResponseDto(b,c,m) " + "from CodePostBookmark b " + "JOIN CodePost c ON b.codePostId = c.id " + "JOIN Member m ON m.id = :memberId " + "WHERE b.isDeleted = FALSE") Page<CodePostBookmarkResponseDto> findAllByMemberId(@Param("memberId") Long memberId, Pageable pageable);
findAllByMemberId 쿼리는 사용자가 북마크한 모든 code_post를 조회하는 쿼리로, bookmark Entity에 member 가 연관 매핑 되어있지만 아래의 Dto에서 member의 닉네임을 불러오는 과정에서 N+1 문제가 발생할 가능성을 차단하기 위해 member를 직접 조인하여 dto로 넘겨준 것이다.
@Getter public class CodePostBookmarkResponseDto { private final Long id; private final String codePostTitle; private final int commentCount; private final String writer; private final LocalDateTime updateAt; public CodePostBookmarkResponseDto(CodePostBookmark bookmark, CodePost codePost, Member member) { this.id = bookmark.getId(); this.codePostTitle = codePost.getTitle(); this.commentCount = codePost.getCodePostCommentList().size(); this.writer = member.getNickname(); this.updateAt = bookmark.getUpdateDate(); } }
@Modifying @Query("DELETE FROM CodePostBookmark b WHERE b.isDeleted = TRUE") void deleteExpiredSoftDeletedBookmarks();
delete..쿼리는 batch delete와 비슷한 개념으로 한번의 쿼리로 모든 데이터를 삭제하기 위해 사용하였다.
@Modifying 어노테이션은 JPA에서 Select 외의 DML 명령어를 사용하기 위해서 쓰인다.
728x90반응형'포트폴리오 > AutoReview' 카테고리의 다른 글
Spring Boot 프로젝트에서 Github REST API로 Push 기능 구현하기 (0) 2025.05.17 🛠 GitHub 연동 기능 구현기 (0) 2025.05.15 게시글 공개 여부 기능 추가 (0) 2025.05.08 [트러블 슈팅] Nginx 502 Bad Gateway 에러 발생 (0) 2025.04.29 검색 쿼리 개선 (LIKE -> Full Text Search) (0) 2025.04.23 댓글 - member id를 통해 북마크된 post들을 조회할 수 있어야한다.