ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • Spring Boot 고급 시리즈 8편 – API 응답 캐싱 전략: Spring Cache + Redis 실전 가이드
    기술과 산업/언어 및 프레임워크 2025. 4. 22. 17:30
    728x90

    Spring Boot에서 API 응답을 캐싱하는 전략을 정리했습니다. Spring Cache 추상화와 Redis 연동, 캐시 키 관리와 TTL 설정까지 실무 적용법을 설명합니다.


    Spring Boot 고급 시리즈 8편 – API 응답 캐싱 전략: Spring Cache + Redis 실전 가이드

    API 성능 병목을 해결하고 서버 자원을 효율적으로 사용하는 방법 중 가장 효과적인 수단은 바로 **캐싱(Cache)**입니다.
    특히 읽기 빈도가 높고 변경 빈도는 낮은 데이터에 대해서는 응답 캐싱이 필수입니다.

    이번 글에서는 Spring Boot에서 Spring Cache 추상화, 그리고 Redis 연동을 통한 분산 캐시 설계를 중심으로
    실전 캐싱 전략을 소개합니다.


    🧠 1. 캐시를 도입해야 하는 이유

    • 데이터 조회 성능 극대화 (DB 호출 제거)
    • 트래픽 부하 감소 (동일 요청 재처리 방지)
    • 외부 API 요청 비용 절감 (유료 API 캐싱 활용)
    • 사용자 체감 속도 향상 (특히 모바일 환경에서 효과적)

    🔧 2. Spring Cache 추상화 기본 설정

    1️⃣ 의존성 추가 (Gradle)

    implementation 'org.springframework.boot:spring-boot-starter-cache'
    implementation 'org.springframework.boot:spring-boot-starter-data-redis'
    

    2️⃣ 캐시 활성화

    @SpringBootApplication
    @EnableCaching
    public class MyApp { ... }
    

    ✅ 3. @Cacheable 기본 사용법

    예제: 사용자 정보 조회 캐싱

    @Service
    @RequiredArgsConstructor
    public class UserService {
    
        private final UserRepository userRepository;
    
        @Cacheable(value = "userCache", key = "#userId")
        public UserDto getUserById(Long userId) {
            log.info("DB에서 사용자 조회: {}", userId);
            return userRepository.findById(userId)
                .map(UserDto::from)
                .orElseThrow(() -> new BusinessException(ErrorCode.USER_NOT_FOUND));
        }
    }
    

    ✅ 의미

    • value = "userCache" → 캐시 공간 이름
    • key = "#userId" → 메서드 파라미터 기반 키 생성
    • 캐시가 있으면 저장된 값 반환, 없으면 메서드 실행 후 결과 저장

    🔁 4. 캐시 무효화 및 강제 갱신

    1️⃣ 캐시 제거

    @CacheEvict(value = "userCache", key = "#userId")
    public void deleteUser(Long userId) {
        userRepository.deleteById(userId);
    }
    

    2️⃣ 캐시 갱신

    @CachePut(value = "userCache", key = "#userId")
    public UserDto updateUser(Long userId, UpdateUserRequest request) {
        // 수정 및 저장 로직
        return updatedUser;
    }
    
    • @CachePut은 항상 메서드를 실행하고 결과를 캐시에 저장합니다.
    • 업데이트 후 정확한 최신 캐시 동기화를 원할 때 사용

    🔌 5. Redis 연동 설정

    1️⃣ application.yml 설정

    spring:
      cache:
        type: redis
      redis:
        host: localhost
        port: 6379
    
    • spring.cache.type=redis 설정 시, Spring Cache의 구현체로 Redis 사용됨

    2️⃣ 커스텀 캐시 설정 (TTL 등)

    @Configuration
    public class CacheConfig {
    
        @Bean
        public RedisCacheManager cacheManager(RedisConnectionFactory factory) {
            RedisCacheConfiguration config = RedisCacheConfiguration.defaultCacheConfig()
                .entryTtl(Duration.ofMinutes(10))  // TTL 설정
                .disableCachingNullValues();
    
            return RedisCacheManager.builder(factory)
                .cacheDefaults(config)
                .build();
        }
    }
    

    📦 6. 실무에서의 캐시 설계 전략

    항목 전략

    캐시 범위 CRUD 중 Read 위주 서비스에 적용 (e.g. 상품 상세 조회)
    TTL(Time To Live) 일반적으로 1~30분 설정, 데이터 성격에 따라 조정
    Null 캐싱 방지 .disableCachingNullValues() 설정 권장
    캐시 Key 설계 user::123, product::A0001 형태로 prefix 관리
    캐시 갱신 전략 이벤트 기반(@EventListener), @CachePut, 또는 cron batch 활용

    🧠 확장 전략

    • 유저별 캐시: key = #user.id + ':' + #itemId 등 동적 조합
    • 멀티 레벨 캐시: 로컬(CacheManager) + Redis 이중 구조
    • 지리 기반 캐시: 위치별 인기 검색어 등 지역 분기 처리

    🧪 테스트 팁

    @Autowired
    private CacheManager cacheManager;
    
    @Test
    void 캐시_직접확인_가능() {
        Cache cache = cacheManager.getCache("userCache");
        assertNotNull(cache.get(1L)); // 캐시 조회
    }
    
    • 통합 테스트에서도 캐시 직접 검증 가능
    • spring.cache.cache-names 사전 등록 시 명시적 테스트 용이

    ✅ 마무리 요약

    항목 요약

    적용 대상 빈번한 조회, 외부 API, 트래픽 병목 API
    핵심 어노테이션 @Cacheable, @CacheEvict, @CachePut
    TTL 관리 5~30분 기준, RedisCacheConfig 활용
    확장성 멀티 키, 다중 레벨, 이벤트 기반 갱신
    실무 포인트 캐시 실패 시 fallback 전략 반드시 고려

    📌 다음 편 예고

    Spring Boot 고급 시리즈 9편: API 버전 분기 없이 유연한 기능 확장 – Feature Flag와 조건 분기 전략

     

    728x90
Designed by Tistory.