🕶️ 캐시 적용 전략
버블 전체 조회, 버블 검색
- 조회시 첫 페이지만 캐시하고 이후, Bubble의 등록, 수정, 삭제가 발생할 때 캐시의 데이터를 삭제합니다.
- 첫 페이지만 캐시하는 이유는 이 후 유저가 더 많은 페이지로 이동할 것이라는 분석 가능한 데이터가 없기 때문에 우선 첫 페이지만 캐시 처리를 하기로 결정하였습니다.
- 등록 / 수정 / 삭제 시 캐시의 데이터를 모두 지우고 새로운 첫 페이지를 DB에서 Select하는 이유는 캐시된 데이터가 항상 정합성/최신성을 보장할 수 있게 만들기 위함입니다.
- 이러한 캐시의 조회와 갱신 과정은 Redis에서 제공하는 자료구조인
String 과 Spring-starter-cache에서 제공하는 @Cahceable, @CacheEvict, spring-boot-starter-data-redis 에서 제공하는 RedisCacheManager를 활용하여 적용할 수있었습니다.
RedisTemplate 대신 RedisCacheManager + @Cacheable, @CacheEvict 를 사용한 이유는 다음과 같습니다.
- redisTemplate을 활용한 캐시 로직이 비즈니스 로직에 포함된다면, 캐시 로직과 비즈니스 로직을 따로 구분해서 보는 것이 힘들 것이라고 판단하였습니다.
- 이를
@Cacheable, @CacheEvict 를 사용하여 해결한다면, 비즈니스 로직 / 캐시 로직의 분리를 통한 직관적인 코드가 만들어지고, 캐시의 적용을 명시적으로 확인할 수 있기 때문에 코드를 분리하는 데 더욱 용이하다고 판단하였습니다.
인기 검색어 목록 조회
-
조회 방법 (Cache Aside)
- 인기 검색어 목록 조회는 오직 캐시를 조회하여 그 데이터를 가져옵니다.
- 캐시 데이터를 가져올 수 없는 상황에는 DB를 통해 10분 전 데이터를 가져옵니다.
-
등록 및 업데이트 방법(Write Back)
- 유저가 키워드를 통해 검색할 때,
[”검색한 키워드” : “0”] 로 캐시에 그 값을 저장하고 Score를 업데이트 합니다.
- 이후, 같은 키워드로 검색이 되면 해당 검색 키워드의 Score는 1씩 업데이트 됩니다.
- 캐시에 담긴 인기 검색어는 10분 단위로 DB에 Flush되며, DB에는 캐시 데이터의 스냅샷이 남게 됩니다.
👾 Redis 사용 시 직렬화/역직렬화 문제
SerializationException: Could not read JSON: Cannot construct instance of "org.springframework.data.domain.SliceImpl”
com.fasterxml.jackson.databind.exc.InvalidDefinitionException: Cannot construct instance of org.springframework.data.domain.Pageable (no Creators, like default constructor, exist): abstract types either need to be mapped to concrete types, have custom deserializer, or contain additional type information
→ JdkSerializationRedisSerializer 사용
- JdkSerializationRedisSerializer 사용 시 객체가 변경되면 역직렬화가 불가능하고, 상대적으로 저장하는 데이터의 용량이 커져 부담이 될 수도 있지만,
첫 페이지만 캐시하기 때문에 용량은 크게 신경쓰지 않아도 될 것 같아 적용하기로 하였습니다.
Refactor: Redis 캐시 적용 리팩토링 by back-seung · Pull Request #46 · team-sparta-a01-team-pr/sparta-bubble-club
🫥 nGrinder JDK 버전
- nGrinder는 JDK 1.8 ~ 11 버전 까지만 지원합니다. 따라서 Windows, CentOS, Linux 등 모든 환경에서 nGrinder를 설치할 때는 JDK의 버전을 1.8 ~ 11로 변경해야 설치가 원할해집니다.