사이드 프로젝트 : 중고 거래 플랫폼 - 좋아요 수정
레디스 적용 이유
좋아요 기능은 빈번하게 발생하는 기능으로 사용할 때마다 데이터베이스에 연결해서 좋아요 수치를 조정하면 많은 부하가 발생할 수 있다. 그렇기 때문에 레디스를 이용해서 캐시를 사용하면 해당 문제를 해결할 수 있다.
레디스 사용시 값을 String으로 사용한 이유
좋아요 수치를 캐시로 사용 시 set타입으로 게시글 및 댓글의 아이디를 키로 잡고 값을 사용자의 아이디를 추가해 해당 사용자가 게시글 및 댓글의 좋아요 여부를 표시할 수 있다.
좋아요 여부를 확인 하기 위해서 키를 이용해서 set에 들어있는 값을 조회해 확인할 수 있는데, set의 경우는 원하는 값 하나를 지정해서 출력할 수 없기 때문에 set 전체를 가져온 다음 set.contains()를 이용해 값을 가지고 있는지를 확인해야 한다.
하지만, 사용자 아이디를 long으로 넣을 경우 포함된 값으로 찾을 수가 없어 String을 이용해서 포함된 값이 있을 경우를 찾을 수 있어 String을 사용해 구성했었다.
Set<Object> boardLikeList = redisRepository.getSetValues("board:like:" + board.getId());
if (boardLikeList.contains(user.getId() + "")) {
redisRepository.deleteSetValue("board:like:" + board.getId(), user.getId() + "");
MessageResponseDto responseEntity = new MessageResponseDto("게시글 좋아요를 취소하였습니다.",200);
return ResponseEntity.status(HttpStatus.OK).body(responseEntity);
}
redisRepository.saveSet("board:like:" + board.getId(), user.getId() + "");
MessageResponseDto responseEntity = new MessageResponseDto("게시글 좋아요를 성공하였습니다.",200);
return ResponseEntity.status(HttpStatus.OK).body(responseEntity);
레디스 사용 값 변경
레디스 set의 contains가 어떻게 구현되어 있는지를 찾지를 못해 정확히 알 수는 없지만, 객체 관련으로 비교하는 부분이 달라 아마 기본적인 set과는 다른 느낌이다.
Set<Object> boardLikeList = redisRepository.getSetValues("board:like:" + board.getId());
for (Object o : boardLikeList) {
System.out.println("boardLikeList.isEmpty() = " + boardLikeList.contains(user.getId())); // false
System.out.println("boardLikeList.isEmpty() = " + boardLikeList.contains(o)); // true
System.out.println("boardLikeList.isEmpty() = " + boardLikeList.contains(user.getId() + "")); // true
}
여러 테스트를 해보면서 확인 결과 set의 값을 long 타입으로 넣은 상태에서도 set.contains를 string으로 찾으면 포함여부를 확인을 할 수 있어 set의 값을 string으로 사용하지 않아도 된다.
또한, 조회 후 포함여부를 확인하지 않고 바로 키와 값으로 해당 키의 set안에 값이 포함되는 여부를 바로 확인을 할 수 있어 수정을 하였다.
if (redisRepository.isEmptySetValue("board:like:" + board.getId(), user.getId())) {
redisRepository.deleteSetValue("board:like:" + board.getId(), user.getId());
MessageResponseDto responseEntity = new MessageResponseDto("게시글 좋아요를 취소하였습니다.",200);
return ResponseEntity.status(HttpStatus.OK).body(responseEntity);
}
redisRepository.saveSet("board:like:" + board.getId(), user.getId());
MessageResponseDto responseEntity = new MessageResponseDto("게시글 좋아요를 성공하였습니다.",200);
return ResponseEntity.status(HttpStatus.OK).body(responseEntity);
// ---
public Boolean isEmptySetValue(String key, long value) {
SetOperations<String, Object> setOperations = redisTemplate.opsForSet();
return setOperations.isMember(key, value);
}