캐쉬도입
도입검토기준
1. 자주 사용될 것으로 예상되는 데이터
2. 변동이 잦지 않을 것으로 예상되는 데이터
위의 두가지 기준으로 캐쉬하고자 하는 데이터를 선택하고자 한다.
가장 빈번한 예상쿼리 : Map조회 기능 관련 쿼리
본 어플리케이션에서 가장 자주 사용될 것으로 예상되는 조회는 Map에 대한 조회라고 생각하였다. Map에 대한 조회는 한번 이루어지는 것이 아니라, 최초 Default Map에서 유저의 입맛에 맞게 축척을 변경하던지 Map의 Bounding Box를 변경하여 원하는 위치를 변경하여 여러번 조회하게 된다. Client가 요구하는 Bounding Box가 변경될때마다 DB에서 데이터를 꺼내는 것을 지양하고자 한다.
유저의 방문 유적지 정보를 캐슁
로그인 하였을 때 방문한 유적지를 캐쉬에 로딩하며, 해당 데이터의 변동시점은 방문처리를 하였을때 이므로 방문처리 로직과 캐쉬서버의 리스트 업데이트를 동시에 진행함.
주요 관광지인 서울과 경주 유적지 정보 캐슁
어플리케이션 동작시에 서울과 경주의 유적지 정보를 캐쉬서버에 저장한다. 그러나 Polygon 단위로 조회하기 때문에 단순히 Key-Value Pair로 Mapping하는 것이 아니라 Geospatial Index기능을 활용하여 진행한다.
(1) Redis Geospatial Data Structure 을 사용해서 Heritage Locations 데이터를 로드함
레디스는 Geospatial Data관련 API를 내장하고 있으며 redistemplate의 opsforgeo()를 통해서 데이터를 추가하고 로드할 수 있다.
// heritage site를 commonKeys에 저장
public void cacheHeritageEntity(HeritageDto heritageDto) {
redisTemplate.opsForGeo()
.add("commonKeys",
new Point(heritageDto.getLongitude(), heritageDto.getLatitude()),
heritageDto);
}
// 좌표가 특정 지역 내에 존재한다면 캐쉬에서 findHeritageWithinDistance 실행하기.
public GeoResults<GeoLocation<Object>> findHeritagesWithinDistance(
double longitude, double latitude) {
return redisTemplate.opsForGeo().radius("commonKeys",
new Circle(new Point(longitude, latitude),
new Distance(DISTANCE_METER, Metrics.METERS)));
}
(3) 서버가 처음 동작시에 경주와 서울지역의 heritageData를 불러와서 redis캐쉬에 저장함
@PostConstruct
public void preloadHeritageEntityData() {
List<HeritageDto> gyeonjuDtos = searchService.byPolygon(
geoLocationAdapter.boxToPolygon(GYEONGJU_NORTH_LAT, GYEONGJU_SOUTH_LAT,
GYEONGJU_EAST_LON, GYEONGJU_WEST_LON));
for (HeritageDto gyeonjuDto : gyeonjuDtos) {
this.cacheHeritageEntity(gyeonjuDto);
}
List<HeritageDto> seoulDtos = searchService.byPolygon(
geoLocationAdapter.boxToPolygon(SEOUL_NORTH_LAT, SEOUL_SOUTH_LAT,
SEOUL_EAST_LON, SEOUL_WEST_LON));
for (HeritageDto seoulDto : seoulDtos) {
this.cacheHeritageEntity(seoulDto);
}
}
(3) 특정지역의 heritageSite를 검색하는 비즈니스 로직 내에서, 경주와 서울지역이라고 하면 캐쉬로부터 데이터를 불러오는 로직추가
// Client 위치가 서울, 경주 내의 위치이면 Cach로부터 데이터 획득
// Check if the location is within Seoul's or Gyeongju's boundaries and fetch from cache if true
if ((clientLocation.getLatitudeY() <= RedisCacheService.SEOUL_NORTH_LAT
&& clientLocation.getLatitudeY() >= RedisCacheService.SEOUL_SOUTH_LAT
&& clientLocation.getLongitudeX() <= RedisCacheService.SEOUL_EAST_LON
&& clientLocation.getLongitudeX() >= RedisCacheService.SEOUL_WEST_LON)
||
(clientLocation.getLatitudeY() <= RedisCacheService.GYEONGJU_NORTH_LAT
&& clientLocation.getLatitudeY() >= RedisCacheService.GYEONGJU_SOUTH_LAT
&& clientLocation.getLongitudeX() <= RedisCacheService.GYEONGJU_EAST_LON
&& clientLocation.getLongitudeX() >= RedisCacheService.GYEONGJU_WEST_LON)) {
log.info("Client location is within Seoul or Gyeongju, fetching from cache.");
// Use Redis to fetch heritage sites from cache within the specified distance
GeoResults<GeoLocation<Object>> cachedHeritages = redisCacheService.findHeritagesWithinDistance(
clientLocation.getLongitudeX(), clientLocation.getLatitudeY());
// Convert GeoResults (from Redis) to HeritagePoint objects for further processing
return cachedHeritages.getContent().stream()
.map(result -> {
HeritageDto dto = (HeritageDto) result.getContent().getName();
return HeritagePoint.fromDto(dto);
})
.toList();
}
'개발 프로젝트 > 2024 제로베이스 프로젝트' 카테고리의 다른 글
제로베이스 팀프로젝트 진행록2 - 기능구현 (0) | 2024.10.28 |
---|---|
제로베이스 팀프로젝트 진행록1 - 개발기획과 팀프로젝트 (0) | 2024.10.23 |
제로베이스 개인프로젝트 진행록5 - 성능개선 리팩터링/멀티스레드 (2) | 2024.10.14 |
제로베이스 개인프로젝트 진행록4 - 기능구현 (0) | 2024.09.25 |
제로베이스 연습프로젝트 : 매장 테이블 예약 서비스 (3) 최적화 고려 (0) | 2024.09.22 |