Notice
Recent Posts
Recent Comments
Link
DevKim
[ Webtooniverse ] 웹툰 상세 페이지 개발 - 웹툰 별점 등록하기 본문
728x90
[ 요구 사항 분석 ]
API | Method | request | response |
웹툰에 별점주기 클릭 | PUT | /api/v1/reviews/star { "webtoonId": 웹툰 id "userPointNumber": 4.5 } |
{ "reviewId": 리뷰 Id } |
[ 비즈니스 로직 ]
1. 유저가 해당 웹툰에 별점을 준적이 있는지 체크한다.
- 해당 유저의 FK와 해당 웹툰 FK를 가진 리뷰의 존재 유무를 확인한다.
Webtoon findWebtoon = webtoonRepository.findById(reviewStarDto.getWebtoonId()).orElseThrow(
() -> new IllegalArgumentException("해당 웹툰이 존재하지 않습니다")
);
Review findReview = reviewRepository.checkUserPointIsExist(findWebtoon, user);
2. 존재하지 않는다면 (별점을 누른적이 없다면)
2-1. review 생성
2-2. webtoon의 별점 개수 +1
2-3. webtoon의 평균 별점 변경
if(findReview==null)
{
Review review = Review.builder()
.userPointNumber(reviewStarDto.getUserPointNumber())
.build();
//총 별점 개수 늘려주기
findWebtoon.changeToonPointTotalNumber();
//별점 평균 점수 변경
findWebtoon.changeToonAvgPoint(reviewStarDto.getUserPointNumber());
//웹툰,유저 정보 넣기
review.insertWebToonAndUser(findWebtoon,user);
reviewRepository.save(review);
}
별점이 처음 등록되는 경우,
총 별점은 ( 이전까지의 전체 평점 점수의 합+ 새로 등록된 별점 ) / 별점 개수 로 구할 수 있다.
/**
* case : 별점을 처음 다는 유저
* 평균 별점 점수 계산
*/
public void changeToonAvgPoint(float userPoint) {
float totalPoint = this.toonAvgPoint * (this.totalPointCount - 1) + userPoint;
this.toonAvgPoint= (float) (Math.round(totalPoint/this.totalPointCount*100)/100.0);
}
3. 이미 존재한다면 (별점을 누른적이 있다면)
3-1. webtoon의 평균 별점 변경
3-2. review의 유저 별점 점수 변경
else
{
//유저의 변경전 별점 점수
float originalUserPoint =findReview.getUserPointNumber();
//웹툰 평균 별점 점수 변경(원래 점수, 변경될 점수)
findWebtoon.updateToonAvgPoint(originalUserPoint, reviewStarDto.getUserPointNumber());
//유저의 별점 점수 변경
findReview.changeUserPoint(reviewStarDto.getUserPointNumber());
}
별점을 수정하려는 유저에 대해서는,
별점의 개수는 변화가 없다.
/**
* case : 별점 수정하려는 유저
* - 별점 개수 변화 X
* - 평균 별점 점수 변경
*/
public void updateToonAvgPoint(float originalUserPoint,float userPoint)
{
float totalPoint = this.toonAvgPoint *(this.totalPointCount) - originalUserPoint +userPoint;
this.toonAvgPoint =(float) (Math.round(totalPoint/this.totalPointCount*100)/100.0);
}
[ 테스트 코드 ]
/**
* 웹툰에 좋아요 누르기 테스트
*/
@DisplayName("좋아요 처음 누르는 사용자의 경우")
@Test
public void clickWebtoonStar1() throws Exception{
//given
//임시 유저
User user = User.builder()
.userName("홍길동")
.userEmail("abc@naver.com")
.userImg(1)
.userGrade(UserGrade.FIRST)
.build();
em.persist(user);
em.flush();
//웹툰 생성
Webtoon w1 = createWebtoon("제목1", "작가1", "내용1",3.5F,25);
em.persist(w1);
em.flush();
//별점 정보
WebtoonPointRequestDto webtoonPointRequestDto= new WebtoonPointRequestDto(w1.getId(),3.0F);
//when
reviewService.clickWebtoonPointNumber(webtoonPointRequestDto,user);
//then
assertThat(w1.getToonAvgPoint()).isEqualTo(3.48F);
assertThat(w1.getTotalPointCount()).isEqualTo(26);
//when2 - 별점 수정하려는 사용자
//별점 정보2
WebtoonPointRequestDto webtoonPointRequestDto2= new WebtoonPointRequestDto(w1.getId(),2.0F);
reviewService.clickWebtoonPointNumber(webtoonPointRequestDto2,user);
assertThat(w1.getToonAvgPoint()).isEqualTo(3.44F);
assertThat(w1.getTotalPointCount()).isEqualTo(26);
}
[ Type issue ] - double/float VS. BigDecimal
테스트 코드의 결과값을 보면, 아래와 같이 정확하게 3.48이 나오지 않는 것을 확인할 수 있다.
그 이유는 내부적으로 수를 저장할 때, double과float는 이진수의 근사치를 저장하기 때문이다.
미세한 숫자의 변동도 허용하지 않는 돈과 소수점을 다룬다면 BigDecimal을 사용해야하지만,
BigDecimal은 비교적 속도가 느리다.
- 별점의 소수점 자체가 절대 틀리면 안되고 미세하게 다뤄야하는 것은 아니기에 ..
그냥 float형으로 가져가고 프론트 쪽에서 소수점을 떼고 화면에 보여주는 쪽으로 합의를 봤다.
728x90
'Spring Project > Webtooniverse' 카테고리의 다른 글
[ Webtooniverse ] Refactor - 정적 팩토리 메서드 (0) | 2021.08.03 |
---|---|
[ Webtooniverse ] 웹툰 상세 페이지 개발 - 비슷한 장르 웹툰 추천 ( feat. Querydsl ) (0) | 2021.08.03 |
[ Webtooniverse ] 웹툰 상세 페이지 개발 - 리뷰 좋아요 기능 & 리뷰 수정 및 삭제 (0) | 2021.08.01 |
[ Webtooniverse ] 웹툰 상세 페이지 개발 - 웹툰 장르, Review 리스트 (0) | 2021.07.30 |
[ Webtooniverse ] pymysql을 이용하여 Maria DB와 연동 & MySQL 쿼리문 (0) | 2021.07.28 |
Comments