[클론 코딩] 네이버 카페 - 게시글 '좋아요' 등록, 취소
2024. 6. 6. 23:28ㆍProject/Naver Cafe
네이버 카페에는 마음에 드는 게시글에 '좋아요'를 남길 수가 있는데, 이번에는 이 '좋아요' 기능을 구현하고자 한다. 해당 기능은 '좋아요'를 등록, 취소할 수 있으며, 추가된 좋아요 정보들은 게시글이 삭제될 때, 같이 삭제 된다.
Favorite
package CloneCoding.NaverCafe.domain.favorite;
@Entity
@Table(name = "FAVORITE")
@Getter
@Builder
@NoArgsConstructor(access = AccessLevel.PROTECTED)
@AllArgsConstructor
public class Favorite {
@Id @GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "ID")
private Long id;
@Column(name = "PROFILE_IMAGE")
private String profileImage;
@Column(name = "ACCOUNT_ID")
private String accountId;
@Column(name = "NICKNAME")
private String nickname;
@Column(name = "ACTIVE_AT")
private LocalDateTime activeAt;
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "NORMAL_ID")
private Normal normalId;
public static Favorite create(CafeMember cafeMember, Normal normal) {
return Favorite.builder()
.profileImage(cafeMember.getProfileImage())
.accountId(cafeMember.getAccountId())
.nickname(cafeMember.getNickname())
.activeAt(LocalDateTime.now())
.normalId(normal)
.build();
}
}
- create() : Favorite 객체를 생성하고, 생성된 객체를 반환
FavoriteController
package CloneCoding.NaverCafe.domain.favorite.controller;
@Slf4j
@RestController
@RequiredArgsConstructor
@RequestMapping("/cafe/{cafe_url}/{normal_id}")
public class FavoriteController {
private final FavoriteService favoriteService;
@PostMapping("/favorite")
public String addFavorite(@PathVariable("cafe_url") String url,
@PathVariable("normal_id") Long id,
@RequestHeader("Authorization") String token) {
log.info("게시글 좋아요 추가 요청");
return favoriteService.addFavorite(url, id, token);
}
@DeleteMapping("/favorite")
public String subFavorite(@PathVariable("cafe_url") String url,
@PathVariable("normal_id") Long id,
@RequestHeader("Authorization") String token) {
log.info("게시글 좋아요 취소 요청");
return favoriteService.subFavorite(url, id, token);
}
}
- addFavorite() : 카페 url, 게시글 id, 토큰 정보로 FavoriteService의 addFavorite()를 호출 후 결과 메시지 반환
- subFavorite() : 카페 url, 게시글 id, 토큰 정보로 FavoriteService의 subFavorite()를 호출 후 결과 메시지 반환
FavoriteServiceImpl
package CloneCoding.NaverCafe.domain.favorite.service;
import static CloneCoding.NaverCafe.message.SystemMessage.ADD_FAVORITE_COMPLETE;
import static CloneCoding.NaverCafe.message.SystemMessage.SUB_FAVORITE_COMPLETE;
@Service
@RequiredArgsConstructor
public class FavoriteServiceImpl implements FavoriteService {
private final FavoriteRepository favoriteRepository;
private final CafeRepository cafeRepository;
private final NormalRepository normalRepository;
private final CafeMemberRepository cafeMemberRepository;
private final AesUtil aesUtil;
@Transactional
@Override
public String addFavorite(String url, Long id, String token) {
CafeMember user = checkCafeMember(url, token);
Normal article = normalRepository.findByIdWithLock(id)
.orElseThrow(() -> new NoSuchElementException("게시글 정보를 찾을 수 없습니다."));
Favorite favorite = Favorite.create(user, article);
article.addFavoriteCount();
favoriteRepository.save(favorite);
normalRepository.save(article);
return ADD_FAVORITE_COMPLETE.getMessage();
}
@Transactional
@Override
public String subFavorite(String url, Long id, String token) {
CafeMember user = checkCafeMember(url, token);
Normal article = normalRepository.findByIdWithLock(id)
.orElseThrow(() -> new NoSuchElementException("게시글 정보를 찾을 수 없습니다."));
Favorite findFavorite = favoriteRepository.findByAccountId(user.getAccountId());
article.subFavoriteCount();
favoriteRepository.delete(findFavorite);
normalRepository.save(article);
return SUB_FAVORITE_COMPLETE.getMessage();
}
private CafeMember checkCafeMember(String url, String token) {
String accountId = aesUtil.aesDecode(token);
Cafe findCafe = cafeRepository.findByUrl(url);
return cafeMemberRepository.findByAccountId(findCafe, accountId);
}
}
- addFavorite() : 생성한 Favorite 객체와 수정한 Normal 객체(엔티티)를 저장(수정) 후, 결과 메시지 반환
- subFavorite() : 조회한 Favorite 객체(엔티티) 삭제, 수정한 Normal 객체(엔티티) 저장 후, 결과 메시지 반환
QueryFavoriteRepositoryImpl
package CloneCoding.NaverCafe.domain.favorite.repository;
import static CloneCoding.NaverCafe.domain.favorite.QFavorite.favorite;
@Repository
@RequiredArgsConstructor
public class QueryFavoriteRepositoryImpl implements QueryFavoriteRepository {
private final JPAQueryFactory query;
@Override
public Favorite findByAccountId(String accountId) {
return Optional.ofNullable(query
.selectFrom(favorite)
.where(favorite.accountId.eq(accountId))
.fetchOne())
.orElseThrow(() -> new NoSuchElementException("좋아요 정보를 찾을 수 없습니다."));
}
}
- findByAccountId() : accountId 정보로 Favorite 객체(엔티티)를 조회 후, 조회한 객체 반환
API TEST
게시글에 '좋아요' 추가(등록) 요청에 대한 테스트 결과이다. 우선 API 요청에 대한 결과 메시지는 정상적으로 출력되었다. DB의 FAVORITE 테이블에 엔티티(레코드)가 추가 된걸 확인할 수 있으며, NORMAL 테이블에서 해당 게시글의 좋아요 개수가 '0'에서 '1'로 늘어난걸 확인할 수 있다.
게시글에 '좋아요' 취소 요청에 대한 테스트 결과이다. 우선 API 요청에 대한 결과 메시지는 정상적으로 출력되었다. DB의 FAVORITE 테이블에 엔티티(레코드)가 삭제 된걸 확인할 수 있으며, NORMAL 테이블에서 해당 게시글의 좋아요 개수가 '1'에서 '0'으로 줄어든걸 확인할 수 있다.
'Project > Naver Cafe' 카테고리의 다른 글
[클론 코딩] 네이버 카페 - 답글 작성 (0) | 2024.06.08 |
---|---|
[클론 코딩] 네이버 카페 - 댓글 작성 (0) | 2024.06.08 |
[클론 코딩] 네이버 카페 - (통합게시판) 태그 등록, 수정(삭제) (0) | 2024.06.04 |
[클론 코딩] 네이버 카페 - (통합게시판) 게시글 삭제 (0) | 2024.06.04 |
[클론 코딩] 네이버 카페 - (통합게시판) 게시글 읽기 (0) | 2024.06.01 |