주말에 오랜만에 놀았더니 오전에 집중하는 게 힘들었던 월요일입니다. 점심시간에 파워냅 1시간 하고 돌아와서 다시 정신 차리고 합니다. 오늘은 영하 15도까지 내려갔다고 하네요. 집에 보일러가 고장나서 슬픈 캥거루족입니다. 얼른 개발자로 취직해서 판교에서 자취하고 싶어요. 어제 오랜만에 대학 친구들을 만났는데 한 친구가 미국 온라인 대학원을 다니고 있다는 소식을 들었습니다. 오프라인과 같은 학위를 받지만 전체 온라인 수업이라 학비도 상대적으로 저렴했습니다. 저도 나중에 취업하고 다녀볼까봐요. BBA & 컴공 master?!
좋아요를 하고 취소하는 API를 만들어 놓고 정작 좋아요 갯수를 세는 기능이 없어서 오늘은 좋아요 갯수 세는 기능을 추가했습니다.
생각보다 간단해서 낮잠 자고 멀쩡한 정신으로 해결했습니다. 다음과 같이 @Service에 코드를 추가했습니다.
좋아요 취소 시 좋아요 수 -1
Long likeCount = likePostRepository.countByPostId(postId);
post.setLikecount(post.getLikeCount()-1);
좋아요 성공 시 좋아요 수 +1
Long likeCount = likePostRepository.countByPostId(postId);
post.setLikecount(post.getLikeCount()+1);
숫자를 저장할 Long 타입 변수를 만들고 해당 게시물 Id를 이용해서 좋아요 수를 저장했습니다.
post Entity에 있는 Likecount 변수에 넣어주었습니다.
Comment를 좋아요 한 변수는 처음에 0으로 설정해서 Nullpointerexception error를 방지합니다.
CASCADE 영속성 전이
조장님이 던져준 미션인 cascade.remove를 사용하지 않고 게시물 삭제와 동시에 연관된 좋아요, 댓글, 댓글좋아요를 삭제하는 방법에 대해 연구했습니다. Cascade를 사용하면 연관된 테이블이 자동으로 함께 지워진다는 편리함이 있지만 주의해야할 점이 있습니다.
이에 대해 인프런 JPA 강의 Q&A에서 김영한님의 친절한 답변이 다음과 같이 달렸습니다.
cascade 옵션은 단순히 생각하면, 그냥 persist() 호출을 줄여줄 수 있기 때문에, 유용해 보이지만, 반대로 생각하면, Order 엔티티를 저장할 때, 연관된 어떤 엔티티들이 함께 저장될까? 를 계속 코드를 보며 추적해야 합니다.
따라서 질문하신 것 처럼 어디까지는 cascade로 함께 저장하고, 어디까지는 함께 저장하면 안될까? 하는 명확한 기준이 필요합니다.
그래서 이런 기준을 잡기 애매한 경우에는 사실 사용하지 않는 것이 좋습니다.
통상적으로 권장하는 cascade 범위는, 완전히 개인 소유하는 엔티티일 때, 예를 들어서 게시판과 첨부파일이 있을 때 첨부파일은 게시판 엔티티만 참조하므로, 개인 소유 입니다. 이런 경우에는 사용해도 됩니다. 그럼 반대로 개인 소유하지 않는 엔티티는 무엇일까요? 예를 들어서, 회원, 상품 등등이 있습니다.
이 예제에서 Order -> OrderItem을 개인소유 하기 때문에 cascade를 사용했습니다. 그런데 Order 입장에서 Delivery는 좀 애매합니다. 여기서는 프로젝트 규모가 작기 때문에 매우 단순하게 표현했지만, 실무에서 프로젝트 규모가 커지면, Delivery로 여러곳에서 참조될 수 있습니다. 그러면 사용하면 안됩니다.
추가로 도메인 주도 설계(DDD)의 Aggregate Root 개념을 이해하고, 프로젝트 적용하면 여기에 맞추어 cascade 옵션을 더 잘 활용할 수 있습니다.
정리하면
1. 완전 개인 소유인 경우에 사용할 수 있다.
2. DDD의 Aggregate Root와 어울린다.
3. 애매하면 사용하지 않는다.
더 자세한 내용은 JPA 기본편 섹션 8에 있는 영속성 전이(CASCADE)와 고아 객체를 참고해주세요.
감사합니다.
출처:
https://www.inflearn.com/questions/31969/cascade-%EC%98%B5%EC%85%98-%EC%A7%88%EB%AC%B8
1. 완전 개인 소유인 경우에 사용할 수 있다.
2. DDD의 Aggregate Root와 어울린다.
3. 애매하면 사용하지 않는다.
제가 봉착한 문제는 Cascade의 저 조건에 부합하지 않는(완전 개인의 소유가 아닌)
comment(한 게시물에 여러 댓글 여러 회원)는 deleteAllByPostId로 삭제하고
postLike(포스트에는 댓글과 좋아요가 있음)도 deleteAllbyPostId로 삭제를 하고
comment(댓글은 게시글과 게시글좋아요와 댓글좋아요가 있음)도 deleteAllbyPostId로 삭제를하고
Likecomment는 ...
comment와 likecomment 뿐입니다.
post를 지울때 likecomment를 cascade를 사용하지 않고 지운다면
post의 모든 comment의 id값을 각각 불러와서 그에 맞는 like값을 deleteAllbycommentId를 해야하는데
commentlist를 조회해서 그들의 Id값을 뽑아서 그들의 Id값에 따른 Likelist를 찾아서 삭제를 해줘야합니다.
그래서 제가 생각한 것은 comment와 Likecomment만 cascade.remove를 사용해도 되지 않겠냐는 겁니다.
댓글과 댓글좋아요의 관계에서 댓글좋아요는 댓글만을 참조하기 때문에 cascade를 사용해도 되겠다고 판단했습니다.
저는 중첩 for문 돌리는 것을 그렇게 좋아하는 편은 아닙니다.
CASCADE를 사용한다면,
연관관계설정을 다시 한 후 해야겠고요.
기술매니저님께 여쭤본 결과, where in 이라는 방법으로 N+1 을 해결 할 수 있다고 합니다.
각각의 방법을 비교해서 정리해보라는 조언을 주셨습니다. 각 방법 별로 성능이 달라질 수도 있다고 합니다.
내일은 이것만 파야겠네요.
일단 끝.
Spring 강의 좀 보다가 자야겠습니다.
'TIL' 카테고리의 다른 글
TIL 자바가 모잘라 221221 (0) | 2022.12.22 |
---|---|
TIL Cascade 영속성 전이 비교 분석 221220 (0) | 2022.12.20 |
TIL/WIL CORS 221218 (0) | 2022.12.19 |
TIL 좋아요는 사랑입니다❤️ 221217 (0) | 2022.12.17 |
TIL 첫 포트폴리오 프로젝트 시작 221216 (0) | 2022.12.17 |