[TIL] Spring Boot 프로젝트에 캐싱 적용하기

2024. 8. 9. 01:16·TIL

 

8/9 진행사항

✅ 알고리즘 5문제

✅ 인메모리 저장소 및 캐싱 전략 1-5 ~ 2-4

✅ 챕터1 과제 캐싱 기능 구현

 

 

Spring Boot 프로젝트에 캐싱 적용하기

 

1. build.gradle

dependencies {
    implementation 'org.springframework.boot:spring-boot-starter-data-jpa'
    // 레디스 추가
    implementation 'org.springframework.boot:spring-boot-starter-data-redis'
    implementation 'org.springframework.boot:spring-boot-starter-web'
    compileOnly 'org.projectlombok:lombok'
    runtimeOnly 'com.h2database:h2'
    annotationProcessor 'org.projectlombok:lombok'
    testImplementation 'org.springframework.boot:spring-boot-starter-test'
    testRuntimeOnly 'org.junit.platform:junit-platform-launcher'
}

redis 의존성 추가하기

 

2. application.yml

spring:
  data:
    redis:
      host: localhost
      port: 6379
      username: default
      password: systempass

redis 설정추가하기

 

3. CacheConfig

@Configuration
@EnableCaching
public class CacheConfig {
    @Bean
    public RedisCacheManager cacheManager(
        RedisConnectionFactory redisConnectionFactory
    ){
        // 설정 구성을 먼저 진행한다.
        // Redis를 이용해서 Spring Cache를 사용할 때
        // Redis 관련 설정을 모아두는 클래스
        RedisCacheConfiguration configuration = RedisCacheConfiguration
                .defaultCacheConfig()
                // null을 캐싱하는지
                .disableCachingNullValues()
                // 기본 캐시 유지 시간 (Time To Live)
                .entryTtl(Duration.ofSeconds(60))
                // 캐시를 구분하는 접두사 설정
                .computePrefixWith(CacheKeyPrefix.simple())
                // 캐시에 저장할 값을 어떻게 직렬화 / 역직렬화 할것인지
                .serializeValuesWith(
                        RedisSerializationContext.SerializationPair.fromSerializer(RedisSerializer.java())
                );
        return RedisCacheManager
                .builder(redisConnectionFactory)
                .cacheDefaults(configuration)
                .build();
    }
}

@EnableCaching : 캐싱을 조절할 수 있게 해주는 어노테이션

 

4. 캐시를 사용할 메서드에 @Cacheable 추가하기

4-1. 데이터 읽기

// @Cacheable : 이 메서드의 결과는 캐싱이 가능하다
// cacheNames: 적용할 캐시 규칙을 지정하기 위한 이름, 이 메서드로 인해서 만들어질 캐시를 지칭하는 이름
// key: 캐시 데이터를 구분하기 위해 활용하는 값
// return값을 Controller로 반환하기 전에 캐시로 보내준다.
// 캐싱 전략 : Cache-Aside
@Cacheable(cacheNames = "itemCache", key = "args[0]")
public ItemDto readOne(Long id) {
    log.info("read One: {}", id);
    return itemRepository.findById(id)
            .map(ItemDto::fromEntity)
            .orElseThrow(() ->
                    new ResponseStatusException(HttpStatus.NOT_FOUND));
}

@Cacheable (Cache Aside 방식)

처음에는 메서드를 실행해서 결과를 가져오고,

해당 반환값을 캐시에 저장한 뒤

캐시가 삭제되기 전까지 메서드를 실제로 실행하지않고 캐시에서 데이터를 반환한다.

 

Cache Aside 방식

Lazy Loading이라고도 하며, 데이터를 조회할 때 항상 캐시를 먼저 확인하는 전략이다.

캐시에 데이터가 있으면 캐시에서 데이터를, 없으면 원본에서 데이터를 가져온 뒤 캐시에 저장한다.

 

 

❗단건 조회시 TTL은 줄이고 TTI를 설정하여 

자주 조회되지 않는 데이터는 캐시에서 빠르게 제거하고

자주 조회되는 데이터는 캐시에 유지할 수 있다.

@Configuration
@EnableCaching
public class CacheConfig {
    @Bean
    public RedisCacheManager cacheManager(
            RedisConnectionFactory redisConnectionFactory
    ) {
        //기본
        RedisCacheConfiguration configuration = RedisCacheConfiguration
                .defaultCacheConfig()
                .disableCachingNullValues()
                .entryTtl(Duration.ofSeconds(120))
                .computePrefixWith(CacheKeyPrefix.simple())
                .serializeValuesWith(
                        SerializationPair.fromSerializer(RedisSerializer.java())
                );

        //단일캐시
        RedisCacheConfiguration individual = RedisCacheConfiguration
                .defaultCacheConfig()
                .disableCachingNullValues()
                .entryTtl(Duration.ofSeconds(5))
                // 5초 이내에 다시 조회되는 캐시는 5초가 지났다고 바로 삭제 되지않고 5초를 다시 세게끔 만들어준다.
                .enableTimeToIdle()
                .computePrefixWith(CacheKeyPrefix.simple())
                .serializeValuesWith(
                        SerializationPair.fromSerializer(RedisSerializer.json())
                );

        return RedisCacheManager
                .builder(redisConnectionFactory)
                .cacheDefaults(configuration)
                //itemCache라는 이름의 캐시만 individual로 진행됨
                .withCacheConfiguration("itemCache", individual)
                .build();
    }
}

 

 

5. 데이터 생성

// 캐싱 전략 : Write-Through
@CachePut(cacheNames = "itemCache", key = "#result.id")
public ItemDto create(ItemDto dto) {
    return ItemDto.fromEntity(itemRepository.save(Item.builder()
            .name(dto.getName())
            .description(dto.getDescription())
            .price(dto.getPrice())
            .build()));
}

@CachePut (Write Through 방식)

항상 메서드를 실행하고 결과를 캐싱한다.

 

Write Through 방식

데이터를 작성할 때 항상 캐시에 작성하고, 원본에도 작성하는 전략이다.

 

 

6. 데이터 업데이트

// 업데이트 후 기존 가격 캐시 삭제
@CachePut(cacheNames = "itemCache", key = "args[0]")
@CacheEvict(cacheNames = "itemAllCache", allEntries = true)//itemAllCache로 시작하는 모든 캐시 삭제, 키 지정 key = "'readAll'"
public ItemDto update(Long id, ItemDto dto) {
    Item item = itemRepository.findById(id)
            .orElseThrow(() -> new ResponseStatusException(HttpStatus.NOT_FOUND));
    item.setName(dto.getName());
    item.setDescription(dto.getDescription());
    item.setPrice(dto.getPrice());
    return ItemDto.fromEntity(itemRepository.save(item));
}

@CacheEvict

주어진 정보를 바탕으로 저장된 캐시를 삭제한다.

아이템이 업데이트 되었으니 기존 정보를 갖고있는 캐시는 유효하지 않다.

 

7. 데이터 삭제

 // 삭제될 경우 단일 캐시, 전체 캐시 전부 초기화.
@Caching(evict = {
        @CacheEvict(cacheNames = "itemCache", key = "args[0]"),
        @CacheEvict(cacheNames = "itemAllCache", allEntries = true)
})
public void delete(Long id) {
    itemRepository.deleteById(id);
}

 

 

오늘의 tmi)

🤔

'TIL' 카테고리의 다른 글

[TIL] Docker란? | FeignClient DIP | Gateway FeignClient 순환참조  (0) 2024.08.13
[TIL] Spring Boot 로컬과 서버 환경 분리 | 정적 팩토리 메서드  (0) 2024.08.10
[TIL] 양방향 연관관계 매핑 | Feign client Error Decoder  (0) 2024.08.08
[TIL] Zipkin이란? | Redis란?  (0) 2024.08.06
[TIL] QueryDsl 사용방법  (0) 2024.08.06
'TIL' 카테고리의 다른 글
  • [TIL] Docker란? | FeignClient DIP | Gateway FeignClient 순환참조
  • [TIL] Spring Boot 로컬과 서버 환경 분리 | 정적 팩토리 메서드
  • [TIL] 양방향 연관관계 매핑 | Feign client Error Decoder
  • [TIL] Zipkin이란? | Redis란?
dev_ajrqkq
dev_ajrqkq
알고리즘 천재가 될 거야
  • dev_ajrqkq
    기록이 자산이다
    dev_ajrqkq
  • 전체
    오늘
    어제
    • 분류 전체보기 (147)
      • Front-end (0)
      • Back-end (11)
        • Spring (1)
        • Java (8)
      • CS (9)
        • 데이터베이스 (5)
        • 네트워크 (4)
      • Algorithm (80)
      • 이것저것 (0)
      • 버그잡기 (1)
      • TIL (37)
      • 후기 (1)
      • 취준 (0)
  • 블로그 메뉴

    • 링크

    • 공지사항

    • 인기 글

    • 태그

      99클럽
      개발자취업
      티스토리챌린지
      TypeScript
      항해99
      코딩테스트준비
      Til
      오블완
    • 최근 댓글

    • 최근 글

    • hELLO· Designed By정상우.v4.10.2
    dev_ajrqkq
    [TIL] Spring Boot 프로젝트에 캐싱 적용하기
    상단으로

    티스토리툴바