Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[LIME-67] 리뷰 좋아요 기능 추가 #30

Merged
merged 6 commits into from
Jan 30, 2024
Merged

Conversation

Curry4182
Copy link
Contributor

@Curry4182 Curry4182 commented Jan 26, 2024

📌 PR 종류

어떤 종류의 PR인지 아래 항목 중에 체크 해주세요.

  • 🐛 버그 수정
  • ✨ 기능 추가
  •  테스트 추가
  • 🎨 코드 스타일 변경 (formatting, local variables)
  • 🔨 리팩토링 (기능 변경 X)
  • 💚 빌드 관련 수정
  • 📝 문서 내용 수정
  • 그 외, 어떤 종류인지 기입 바람:

📌 어떤 기능이 추가 되었나요?

리뷰 좋아요 기능이 추가 되었습니다. 😊❤ 640505e

리뷰 목록 조회할 경우 좋아요가 반환 되도록 기능 추가하였습니다. 😊❤ 640505e

리뷰 좋아요 순으로 정렬되도록 기능 추가하였고 이전 commit( 640505e)에서 좋아요가 옳바르게 표시되지 않는 버그까지 수정하였습니다. 😊❤ 2b70173

Issue Number

LIME-67

기능 설명

리뷰 목록 조회 코드 설명 😊❤

  • 리뷰 목록 조회에 리뷰 관련 정보를 담는 ReviewSummary dto를 생성하기 위해서는 reviews, review_images, review_likes 테이블이 필요 합니다.
  • review와 review_images, review와 reveiw_likes를 두번 left join 하고 review 테이블의 아이디를 기준으로 group by를 합니다.
  • 이 후 필요한 값을 가져와 ReviewSummary를 만들고 반환 합니다.

좋아요 순 정렬 기능 코드 설명 😊❤

  • 좋아요 순 정렬은 join을 한 값을 group by를 이용하여 cursor id를 걸러줘야 했습니다.
  • group by의 조건을 걸기 위해 having을 사용하였고 기존 조건들은 where에 두고 정렬 조건에 따라 null이 반환 되도록 만들었습니다.

📌 기존에 있던 기능에 영향을 주나요?

  • 아니요

@Curry4182 Curry4182 added the enhancement New feature or request label Jan 26, 2024
@Curry4182 Curry4182 self-assigned this Jan 26, 2024
Comment on lines +64 to +71
Map<Long, ReviewInfo> reviewInfoMap = reviewRepository.getReviewInfo(reviewIds)
.stream()
.collect(Collectors.toMap(ReviewSummary::reviewId, Function.identity()));
.collect(Collectors.toMap(ReviewInfo::reviewId, Function.identity()));

// 리뷰 아이디를 이용하여 리뷰 이미지 정보를 가져옴
Map<Long, ReviewImageInfo> reviewImageInfoMap = reviewRepository.getReviewImageInfos(reviewIds)
.stream()
.collect(Collectors.toMap(ReviewImageInfo::reviewId, Function.identity()));
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

둘을 나눠서 조회해오는 이유가 궁금합니다!
db에서 정보는 공통으로 가져오고 reviewInfo와 ReviewImageInfo로 분산해도 되지 않을까 한번생각했습니다!

Copy link
Contributor Author

@Curry4182 Curry4182 Jan 29, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

reviews, review_images, review_likes 이 세개의 테이블을 join 해야 하는 상황 입니다.
review 기준으로 review_images, review_likes는 one to many 관계를 가집니다.

아래 글은 인프런 CTO로 근무하시고 QueryDsl을 실무에서 직접 사용하시는 이동욱님의 글입니다. 글에서 제시하는 문제 상황이 저희와 비슷해서 가져왔습니다.
https://jojoldu.tistory.com/457

위 글에서 fetch join 조건에 대해 중간 쯤에 언급 하는데 ToOne 관계의 join은 몇 개든 사용 가능 하지만 ToMany는 하나만 사용 가능하다고 주장합니다.

위와 같은 상황이 발생하는 근본적인 이유는 다중 join을 jpql로 실행할 경우 메모리에 데이터를 들고와서 join을 하는데 이 때 메모리에서는 객체가 카티전 곱으로 중복 발생합니다.
카티전 곱으로 발생하는 객체에 대해 집계 함수를 사용하면 정확한 값이 반환되지 않거나 예외가 발생하는 등의 문제가 발생했습니다.

이런 이유로 각각의 테이블을 분사하여 group by한 집계 함수 값을 가져왔습니다.

이 부분에 대해 리팩토링을 한다면 위에서 제시한 글의 핵심 주장 처럼 hibernate.default_batch_fetch_size 옵션을 활용하여, join이 아니라 where in으로 데이터를 가져오고 dto를 변환 하도록 해야하지 않을까 생각합니다.
그렇게 하려면 Review 엔티티에 리스트로 ReviewImage 엔티티와 ReviewLikes 엔티티를 추가 해야 하는 등 추가작업이 필요 합니다.

이 추가 작업을 하게 된다면 일정대로 작업이 안 되서 위와 같이 나눠서 호출 하도록 하였습니다. !! 😊😆

.selectFrom(review)
.where(review.id.in(reviewIds))
.leftJoin(reviewLike).on(review.eq(reviewLike.review))
.groupBy(review.id, review.rating, review.content, review.createdAt, review.modifiedAt)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

groupby필드에 값이 많이 바인딩되는게 신기한데, 이렇게 해줘야 했던 이유가 궁금합니다

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

기본적으로 mysql에서 select 절에 group by 절에서 명시하지 않는 컬럼들있으면 예외를 반환 합니다. 이 것을 해결하려면 only_full_group_by 옵션을 끄거나 위 코드처럼 group by 절에 모든 컬럼을 명시해야 합니다. 이 문제 대해서는 아래 노션 사이트에 정리하였습니다. https://www.notion.so/only_full_group_by-b351f6ea025240b6a6e41e490baa6532

Copy link
Member

@Yiseull Yiseull left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

병곤님 고생하셨습니다!! 궁금한 내용에 대해 코멘트 달아놨습니다~😆

Comment on lines +69 to +71
Map<Long, ReviewImageInfo> reviewImageInfoMap = reviewRepository.getReviewImageInfos(reviewIds)
.stream()
.collect(Collectors.toMap(ReviewImageInfo::reviewId, Function.identity()));
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

p5;
map을 사용한 이유가 궁금합니다! 이미지만 불러오고, 아래처럼 작성해도 되지 않나요??

new ReviewImageInfo(reviewId, images);

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

  • map을 사용한 이유는 82번 라인에 포함되어 있는 for문을 돌 때 O(N)을 만들기 위해서 저장하고 있습니다.😊
  • 말씀해주신 것 처럼 이미지를 리스트로 받고 순서대로 넣지 않는 이유는 이미 정렬된 아이디에 맞게 데이터를 넣어야 하기 때문입니다. 😊
  • 혹시 이해가 안된다면 화상으로 이야기 하는게 좋을 것 같아요 😊

@Curry4182 Curry4182 merged commit d733c12 into main Jan 30, 2024
@Curry4182 Curry4182 deleted the LIME-67--review-like-feat branch February 7, 2024 06:16
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants