반응형

 

1. dependencies 의존성 추가

// Caffeine 캐시 의존성 추가
dependencies {
    implementation 'org.springframework.boot:spring-boot-starter-cache'
    implementation 'com.github.ben-manes.caffeine:caffeine:3.1.8'
}

위 버전은 2025년 기준 최신 안정 버전입니다. 필요시 최신 버전 확인 가능.


2단계: 캐시 설정 클래스 작성

@Getter
public enum CacheType {

    FEED_RECOMMENDS("recommends", 600, 1024),
    FEED_PAGE_NUMBER("pagenumber", 60, 500),
    MAX_PAGE_NUMBER("maxpage", 60, 500),
    REGION("region", 3600, 200);

    private final String name;
    private final int expireAfterWrite; // 초 단위
    private final int maximumSize;

    CacheType(String name, int expireAfterWrite, int maximumSize) {
        this.name = name;
        this.expireAfterWrite = expireAfterWrite;
        this.maximumSize = maximumSize;
    }
}


@Configuration
@EnableCaching
public class CacheConfig {

    @Bean
    public CacheManager cacheManager() {
        SimpleCacheManager cacheManager = new SimpleCacheManager();

        List<CaffeineCache> caches = Arrays.stream(CacheType.values())
                .map(cacheType -> new CaffeineCache(
                        cacheType.getName(),
                        Caffeine.newBuilder()
                                .expireAfterWrite(cacheType.getExpireAfterWrite(), TimeUnit.SECONDS)
                                .maximumSize(cacheType.getMaximumSize())
                                // .recordStats()  // 필요시 주석 해제
                                .build()))
                .toList();

        cacheManager.setCaches(caches);
        return cacheManager;
    }
}

3단계: 캐시 사용 예제 (서비스 클래스에서)

package com.example.service;

import com.example.model.Feed;
import com.example.repository.FeedRepository;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.CachePut;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;

import java.util.List;

@Service
public class FeedService {

    private final FeedRepository feedRepository;

    public FeedService(FeedRepository feedRepository) {
        this.feedRepository = feedRepository;
    }

    // 1. 캐시 조회: 동일한 userId로 요청 시 캐시된 추천 피드를 반환
    @Cacheable(value = "recommends", key = "#userId")
    public List<Feed> getRecommendedFeeds(Long userId) {
        return feedRepository.findRecommendedByUser(userId);
    }

    // 2. 캐시 갱신: 추천 피드 갱신 시 캐시도 갱신
    @CachePut(value = "recommends", key = "#userId")
    public List<Feed> refreshRecommendedFeeds(Long userId) {
        return feedRepository.refreshRecommendations(userId);
    }

    // 3. 캐시 삭제: 로그아웃이나 탈퇴 시 해당 캐시 제거
    @CacheEvict(value = "recommends", key = "#userId")
    public void evictRecommendedFeeds(Long userId) {
        // 캐시만 날리는 로직
    }
}


4단계: 결과 확인 방법

  • 애플리케이션이 처음 실행되어 getUserById(1L)을 호출하면 DB에서 조회됨
  • 이후 동일한 ID로 호출되면 DB를 거치지 않고 캐시에서 바로 반환됨
  • 10분이 지나거나 캐시 최대 크기를 넘어서면 자동으로 만료됨

용어 주석

  • @EnableCaching: 스프링의 캐시 기능을 사용하기 위한 설정 애너테이션
  • Caffeine: 고성능 캐시 라이브러리로 LRU 기반의 비동기 제거, TTL(Time to Live), 최대 크기 설정 등 지원
  • expireAfterWrite: 캐시에 저장된 후 일정 시간이 지나면 제거
  • maximumSize: 캐시에 저장 가능한 최대 항목 수
  • @Cacheable: 메서드 결과를 캐시에 저장하고, 같은 key가 들어오면 저장된 값을 반환
반응형

+ Recent posts