항해99/실전프로젝트
항해99-실전프로젝트 02(좋아요, 북마크)
연어조아
2021. 12. 6. 18:58
728x90
ER 다이어그램
문제점
- 어떤 사용자가
어떤 게시글에 좋아요
를 눌렀는지 모른다.
해결방법
- 어떤 사용자가 어떤 게시글에 좋아요를 눌렀는지
저장하는 테이블
을 만든다.
DB 예시
- 게시판 입장에서
- 4206번 게시판은 1번 유저와 32865번 유저가 좋아요를 눌렀다는 것을 알게된다.
- 이를 이용해 만약 4206번 게시판에 1번 유저가 또 좋아요를 누른다면 반대로 좋아요를 취소하는 로직을 구현하면 된다.
- 유저 입장에서
- 1번 유저는 4206번 게시물과 33964번 게시물에 좋아요를 눌렀다.
- 북마크를 위에 동일한 로직으로 구성하게 된다면 쉽게 북마크를 만들 수 있다
소스코드
소스코드 - 좋아요 누르기
//좋아요
@PostMapping("/board/like")
public ResponseDto LikeInfo(@RequestParam Long cardId, @AuthenticationPrincipal UserDetailsImpl userDetails){
LikeResponseDto likeResponseDto = likeService.LikeInfo(cardId, userDetails.getUser());
if(likeResponseDto.getLikeCheck().equals(false)){
return new ResponseDto(201L, "좋아요가 취소되었습니다..", likeResponseDto);
}
else{
return new ResponseDto(200L, "좋아요가 등록되었습니다..", likeResponseDto);
}
}
- 좋아요를 누르면 해당하는 게시글 아이디와 로그인한 유저의 유저정보를 가지고
서비스 계층
으로 이동한다. - 후에 서비스 계층에서의 리턴 값을 확인하여 취소 혹은 등록 로직의 결과값을 리턴한다.
@Transactional
public LikeResponseDto LikeInfo(Long boardId, User user){
Board findBoard = boardRepository.findById(boardId).orElseThrow(
() -> new NullPointerException("해당하는 게시글이 존재하지 않습니다.")
);
List<Like> findDuplicateLike = likeRepository.findAllByBoardAndUser(findBoard, user);
// 좋아요 삭제
if(findDuplicateLike.size() != 0){
Like findLike = findDuplicateLike.get(0);
deleteLike(findLike);
int count = likeRepository.countByBoard(findBoard) ;
findBoard.setLikeCount(Long.valueOf(count));
LikeResponseDto likeResponseDto = new LikeResponseDto(boardId, false, Long.valueOf(count));
return likeResponseDto;
}
//좋아요 증가
else{
Like newLike = new Like(findBoard,user);
saveLike(newLike);
int count = likeRepository.countByBoard(findBoard);
findBoard.setLikeCount(Long.valueOf(count));
LikeResponseDto likeResponseDto = new LikeResponseDto(boardId, true, Long.valueOf(count));
return likeResponseDto;
}
}
List<Like> findDuplicateLike = likeRepository.findAllByBoardAndUser(findBoard, user);
- 게시물id와 user 정보를 통해서 둘다 해당하는 좋아요 데이터를 찾는다. 만약
존재한다면 이미 유저가 해당하는 게시물에 좋아요를 눌렀다
라는 것이며 없다면좋아요를 누르지 않았다는 소리가 된다
- 게시물id와 user 정보를 통해서 둘다 해당하는 좋아요 데이터를 찾는다. 만약
- if 문을 통해서 좋아요를 새로 넣거나 기존에 있던 데이터를 삭제하고 다시 좋아요를 count하여
board
필드의likeCount
필드에 데이터를 업데이트 한다. - likeCheck를 통해서 해당 게시물의 하트에 색을 채울 것 인지 뺄 것 인지 판단한다.
소스코드 - 한 게시물의 좋아요 수, 결과 값 출력하기
new QCommunityDtoCustom(
board.id,
QUser.user.nickname,
board.title,
location.cityName,
board.address,
board.img,
board.content,
board.modifiedAt,
boardLikeCount(),
(userDetails == null) ? setFalse() : distinguishLikeExistUser(userDetails.getUser()),
(userDetails == null) ? setFalse() : distinguishBookmarkExistUser(userDetails.getUser())
)
private JPQLQuery<Long> boardLikeCount() {
return JPAExpressions
.select(like.count())
.from(like)
.where(boardIdEqLikeBoardId());
}
- 한 게시물의 상세페이지를 조회할 때 likeCount 정보와 likeCheck 정보가 필요하다
- 위는 querydsl을 통해서 count query를 날리는 문법이다.
- 좋아요 수는 해당 함수에 서브 쿼리를 통해서 좋아요 수를 계산하여 사용자에게 제공한다.
private BooleanExpression distinguishLikeExistUser(User user) {
return JPAExpressions
.select(like)
.from(like)
.where(userIdEqLikeUserId(user).and(boardIdEqLikeBoardId()))
.exists();
}
private BooleanExpression setFalse() {
return Expressions.asBoolean(false);
}
- likeCheck 또한 exists() 함수를 통해 true false 값을 가져올 수 있다.
- 또한 만약 로그아웃 상황일땐 삼항연산자를 통해서 false 만을 리턴한다.
게시판 필드 내의 - likeCount
해당 필드는 게시판 조회할 때 좋아요 수를 가져오는 것이 아는 좋아요 순으로 정렬하기 위해서 필드를 만들었다.
private OrderSpecifier<? extends Serializable> getOrderBy(String sort) {
if(sort.equals("star"))
return star.starGazing.desc();
else if(sort.equals("like"))
return board.likeCount.desc();
else if(sort.equals("latest"))
return board.modifiedAt.desc();
else
return null;
}
도메인 설계를 하고 나서 바로 설계된 내용으로 API 개발을 하기 보다는 좋아요와 북마크를 개발할 때 고민했었던 내용들을 적어놓고 싶어 이 게시물을 작성하였다.
다음 게시물은 아마 기본적인 JPA를 이용한 API 개발 방식을 포스팅 할 것 같다.
깃허브 : https://github.com/salmon2/StarProject
GitHub - salmon2/StarProject
Contribute to salmon2/StarProject development by creating an account on GitHub.
github.com
프로젝트 홈페이지 : https://stellakorea.co.kr/
별보러가지않을래?
캠핑 차박하실때 불멍만 즐기셨나요? 이제는 별도 구경해보세요! 별이 잘보이는 장소,날씨 정보보시고 나만의 캠핑,차박 장소도 공유 해보세요!
stellakorea.co.kr