-
DB 역정규화에 따라, 변경 감지를 사용하면 동시성 이슈가 발생합니다. 우선, BookmarkCount를 감소시키는 JPQL은 아래와 같이 구현하였습니다. // TopicRepoisotry.class
@Modifying(clearAutomatically = true)
@Query("update Topic t set t.bookmarkCount = t.bookmarkCount - 1 where t.id = :topicId")
void decreaseBookmarkCountById(@Param("topicId") Long topicId); 우리는 위 메서드를 활용해서, 즐겨찾기를 제거하는 서비스 로직을 아래와 같이 작성하게 됩니다. public void deleteTopicInBookmark(AuthMember authMember, Long topicId) {
validateBookmarkDeletingPermission(authMember, topicId);
BookmarkId bookmarkId = BookmarkId.of(topicId, authMember.getMemberId());
bookmarkRepository.deleteById(bookmarkId);
topicRepository.decreaseBookmarkCountById(topicId); // 이 부분은 이벤트로 변경될 수도 있습니다.
} 위 로직상에선 문제가 없지만, 만약 즐겨찾기 개수를 감소시키는 작업 외에 부가적인 작업을 수행해야한다면 어떻게 될까요 ? 위 코드를 그대로 가져와볼게요. public void deleteTopicInBookmark(AuthMember authMember, Long topicId) {
validateBookmarkDeletingPermission(authMember, topicId);
BookmarkId bookmarkId = BookmarkId.of(topicId, authMember.getMemberId());
Topic topic = getTopicById(topicId); // ---------------------(a)
bookmarkRepository.deleteById(bookmarkId);
topicRepository.decreaseBookmarkCountById(topicId);
//JPQL로 처리하여 DB상에는 topicCount는 변경됨.
// (a) 에서 조회한 topic 객체의 topicCount는 변경되지 않음.
} 위와 같은 문제가 발생할 수 있을 것 같아요. public void deleteTopicInBookmark(AuthMember authMember, Long topicId) {
validateBookmarkDeletingPermission(authMember, topicId);
BookmarkId bookmarkId = BookmarkId.of(topicId, authMember.getMemberId());
Topic topic = getTopicById(topicId); // ---------------------(a)
bookmarkRepository.deleteById(bookmarkId);
topicRepository.decreaseBookmarkCountById(topicId);
topic.decreaseCount(); // 추가 작업
//JPQL로 처리하여 DB상에는 topicCount는 변경됨.
// (a) 에서 조회한 topic 객체의 메서드 호출을 통해 topicCount를 같이 감소 시켜줌.
} 하지만, 위 코드는 동일한 작업을 중복해서 수행하는 듯하지 않나요 ? 그래서, 생각한 방안이 // Topic.class
public void decreaseBookmarkCount(TopicRepository topicRepository) {
topicRepository.decreaseBookmarkCountById(id);
bookmarkCount--;
} 위처럼 메서드를 작성하면, 앞서 말씀드렸던 문제점들을 해결할 수 있을 것 같아요. 위 방법과 관련하여 질문이나, 더 좋은 방법이 있으시다면 의견 부탁드릴게요. |
Beta Was this translation helpful? Give feedback.
Replies: 3 comments 2 replies
-
쥬니! 너무 좋은 아이디어입니다! 고민을 많이 해주셨나보군요. 다만 하지만, 현재로서는 아무래도 추후에 해당 의존관계가 유지보수에 영향을 주려나요? 킹치만, 저의 개인적인 생각으로는, 위 작업은 다른 애그리거트간의 상호작용이니, 말씀해주신 바와 같이 Event 를 발행하여, Topic 이 TopicRepository 를 의존하지 않으며, 특정 Service 에 의존하지 않는다는 두 마리의 토끼를 잡는 것이 좋지 않을까? 라는 생각도 해봅니다. 아래와 같은 형식으로요 @EventListener
public void removeBookmark(BookmarkDeleteEvent event) {
Topic topic = event.topic();
topic.decreaseBookmarkCount();
topicRepository.decreaseBookmarkCountById(topic.getId());
} 혹시 쥬니는 이벤트 발행방식보다, 위 방식을 택한 이유가 있을까요? 제가 고려하지 못한 사항이 있을까요? 있다면 죄송합니당 알러뷰 |
Beta Was this translation helpful? Give feedback.
-
말씀해주신 바와 같이.... Event 를 발행하여... 왜 제대로 안읽으셨죠?! 빨리 빵댕이나 흔드세요!
헐 맞네요 이 부분은 고려하지 못했어요 변경감지로 인해서 이런 문제가 발생하는군요
이 부분도 댓글 남기기전에 생각했지만, 그래도 방지하는 것이 좋다고 생각하긴 했어요. 하지만, 현재 오버엔지니어링이라고 판단되면 말씀하신 것처럼 Event 발행하면서 JPQL 로 Bookmark 카운트만 줄여도 괜찮을 것 같아요. 근데 갑자기 궁금한게 생겼어요 public void deleteTopicInBookmark(AuthMember authMember, Long topicId) {
validateBookmarkDeletingPermission(authMember, topicId);
BookmarkId bookmarkId = BookmarkId.of(topicId, authMember.getMemberId());
Topic topic = getTopicById(topicId); // ---------------------(a)
bookmarkRepository.deleteById(bookmarkId);
topicRepository.decreaseBookmarkCountById(topicId);
//JPQL로 처리하여 DB상에는 topicCount는 변경됨.
// (a) 에서 조회한 topic 객체의 topicCount는 변경되지 않음.
} a 에서 조회한 topic 객체의 bookmarkCount 가 변경되지 않아, 해당 메서드에서 Topic 을 재 사용할 때 문제가 되는 것 뿐만 아니라, 변경감지로 인하여 감소시킨 Bookmark Count 가 원래대로 돌아오는 현상이 발생하기도 할까요? 이건 순수 궁금증입니당. |
Beta Was this translation helpful? Give feedback.
-
해당 방식으로 진행하도록 하겠습니다.
JPQL로 작성된 메서드를 호출하게 되면, 변경감지 대상이 된 아이들(?)은 flush가 되게 됩니다. |
Beta Was this translation helpful? Give feedback.
해당 방식으로 진행하도록 하겠습니다.
JPQL로 작성된 메서드를 호출하게 되면, 변경감지 대상이 된 아이들(?)은 flush가 되게 됩니다.
이후에, 해당 메서드에
clearAutomatically
옵션을 주기 때문에, 영속성 컨텍스트를 비우게 되죠 !그래서, 원래대로 돌아오는 현상은 발생하지 않는답니당 ~