실무에선 직접 캐싱 작업을 해본적이 없었다. 때문에 캐싱을 통한 조회성능 개선해보는 경험이 부족하다고 느껴서 진행 중인 프로젝트에 적용해 봤다.
캐싱은 작업의 결과를 임시 저장하는 것을 말한다. 보통 메모리에 저장해두고 사용하며 캐시된 데이터가 있다면 같은 작업을 여러번 하지 않고 빠르게 결과를 얻을 수 있는 장점이 있다.
데이터를 캐시해서 사용하는 것은 같은 작업을 여러번 하지 않도록 하는 것도 있지만 응답 속도를 높이는 목적도 있다 때문에 디스크보단 메모리에 저장해서 사용하는게 일반적이다.
그렇다면 전역변수를 하나 만들어서 저장하고 사용하면 되는 걸까? 서버를 하나만 띄운다면 별 상관은 없다고 생각하지만 다중서버를 고려한다면 틀린 답이 될 것이다.
때문에 제3의 영역에 메모리 엔진을 사용해서 모든 서버가 접근해서 사용하도록 하는 것이 일반적이다.
대표적으로 많이 사용되는 메모리 엔진은 Redis, Memcached 등 이 있다.
Gathering프로젝트는 Redis를 사용해서 캐싱하기로 했다.
위 2가지 이유로 Redis를 선택했다.
Gathering은 위 같은 정도로 기준을 잡고 모임 예약 장소와 시간을 조회하는 API에 사용하였다.
@Cacheable(key = "#date.toString()", value = "RoomSchedule", cacheManager = "cacheManager")
public List<RoomScheduleResDto> getDayRoomSchedule(LocalDate date) {
checkDateRange(date);
return reservationQueryRepository.findRoomScheduleByDate(date);
}
@Cacheable은 캐시 저장소에 값이 있다면 비즈니스 로직을 타지 않고 바로 값을 반환하고 값이 없다면 작업 후 반환된 값을 캐시 저장소에 저장 후 반환해준다.
때문에 제일 첫 작업은 비교적 느릴 수 있지만 그 이후 부터는 캐시된 데이터를 사용하니 빠른 응답을 받을 수 있다.
Gathering의 경우 예약 장소와 시간이 날짜 기준으로 항상 같은 값여서 DB에 접근하는 횟수를 줄이고자 캐싱하여 사용하기로 했다.
@CachePut(key = "#date.toString()", value = "RoomSchedule", cacheManager = "cacheManager")
public List<RoomScheduleResDto> updateDayRoomSchedule(LocalDate date) {
return reservationQueryRepository.findRoomScheduleByDate(date);
}
@CachePut은 캐시 저장소에 데이터가 있어도 반드시 작업을 진행하고 캐시 저장소에 업데이트 해주기 때문에 캐시 데이터에 변경사항이 적용 되야 할 때 사용해줘야한다.
Gathering의 경우 예약 장소와 시간을 날짜 기준으로 모두 뿌려주는데 해당 장소와 시간이 예약 된 경우 예약이 불가능 하다고 정보를 변경해 줘야 하기 때문에 사용하였다.
Medis라는 Redis GUI도구를 이용해 캐시데이터를 확인한다.
모임 장소를 예약하면 후 해당 장소와 시간예약에 불가능 하다는 정보가 업데이트 되어야한다.