Spring Boot에서 Redis 캐시 적용과 성능 최적화
Spring Boot과 Redis를 활용한 캐시 적용과 운영 환경에서의 성능 최적화 방법을 예제 코드와 설정 중심으로 쉽게 정리한 설명
목차
개요
애플리케이션 성능 개선을 위해 캐시 도입이 일반화된 상황에서 Redis는 높은 처리량과 낮은 지연 시간으로 널리 사용된다. 이 글은 spring boot redis 캐시 적용 사례를 중심으로 기본 설정부터 운영 환경에서 고려할 성능 최적화 요소까지 차근차근 설명한다. 처음 접하는 개발자도 이해하기 쉽게 예제와 함께 구성한다.
왜 Redis를 캐시로 사용하는가
Redis는 메모리 기반의 키-값 저장소로 빠른 읽기 성능이 장점이다. TTL, 다양한 자료구조, 복제와 영속성 옵션 등으로 캐시 용도에 적합하다. 특히 분산 환경에서 캐시 일관성 확보와 세션 공유가 필요할 때 장점이 크다.
Spring Boot와 Redis 통합 기본 흐름
필요한 의존성
Spring Cache 추상화와 Redis 연결을 위한 의존성이 필요하다. 다음은 Gradle 예제이다.
dependencies {
implementation 'org.springframework.boot:spring-boot-starter-web'
implementation 'org.springframework.boot:spring-boot-starter-data-redis'
implementation 'org.springframework.boot:spring-boot-starter-cache'
implementation 'com.fasterxml.jackson.core:jackson-databind'
}
application.yml 예시
spring:
redis:
host: localhost
port: 6379
cache:
type: redis
# 캐시별 기본 TTL 설정은 코드에서 관리하는 것을 권장
캐시 설정과 코드 적용
RedisCacheManager 설정
직접 캐시 매니저를 설정하면 TTL, 직렬화 방식, 캐시 별 설정을 세밀하게 제어할 수 있다. 다음 설정은 Jackson 직렬화를 사용하고, 기본 TTL을 설정하는 예제이다.
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Bean;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.cache.RedisCacheConfiguration;
import org.springframework.data.redis.cache.RedisCacheManager;
import org.springframework.data.redis.serializer.GenericJackson2JsonRedisSerializer;
import org.springframework.data.redis.serializer.RedisSerializationContext;
@Configuration
public class CacheConfig {
@Bean
public RedisCacheManager cacheManager(RedisConnectionFactory connectionFactory) {
RedisCacheConfiguration config = RedisCacheConfiguration.defaultCacheConfig()
.serializeValuesWith(RedisSerializationContext.SerializationPair.fromSerializer(new GenericJackson2JsonRedisSerializer()))
.entryTtl(java.time.Duration.ofMinutes(10));
return RedisCacheManager.builder(connectionFactory)
.cacheDefaults(config)
.transactionAware()
.build();
}
}
@Cacheable 사용 예
서비스 메서드에 @Cacheable을 붙이면 첫 호출 결과를 캐시에 저장하고, 이후 같은 키로 호출 시 캐시된 값을 반환한다. 키 설계와 null 처리에 유의한다.
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;
@Service
public class ProductService {
@Cacheable(value = "product", key = "#id")
public Product getProduct(Long id) {
// 실제로는 DB 호출
return findProductFromDb(id);
}
}
운영 환경 성능 최적화 포인트
-
커넥션 풀과 클라이언트 설정
Jedis 대신 Lettuce 사용 시 논블로킹 특성으로 성능 이점이 있다. 클라이언트 커넥션 풀, 최대 동시 연결 수, 타임아웃을 환경에 맞춰 조정한다.
-
직렬화 비용 최소화
값 직렬화/역직렬화는 CPU 비용을 유발한다. 자주 호출되는 객체는 경량 직렬화 형식 사용을 고려하고, 필요 이상으로 깊은 객체 그래프를 캐싱하지 않는다.
-
TTL과 캐시 만료 전략
캐시 무효화 정책을 명확히 한다. 키 별 TTL을 차등 적용하면 핫아이템의 부하 집중을 방지할 수 있다.
-
키 설계
충돌을 피하도록 네임스페이스(예: app:product:123)를 사용한다. 너무 많은 키 생성은 메모리 파편화를 유발할 수 있다.
-
모니터링
Redis의 명령별 지연, 메모리 사용량, 키 수 변화를 모니터링한다. slowlog, INFO 명령, Redis Exporter를 통한 메트릭 수집이 도움이 된다.
실전에서 흔한 문제와 대처
-
데이터 일관성 문제
읽기 후 쓰기 시 캐시와 DB의 순서로 인해 일관성 문제가 생길 수 있다. 중요한 업데이트는 캐시 무효화 전략을 명확히 한다.
-
캐시 히트율 저하
키 설계, TTL, 데이터 접근 패턴을 점검한다. 캐시를 무조건 늘리는 방식은 비용과 메모리 낭비로 이어진다.
-
메모리 부족
Eviction 정책(Avolatile-LRU 등)을 적절히 설정하고, 필요 없는 키를 정리한다.
테스트 및 검증
개발 환경에서 로드 테스트를 통해 캐시 도입 효과와 부하 변화를 확인한다. 간단한 redis-cli 명령으로 키와 TTL을 확인할 수 있다.
# 키 목록 일부 확인
redis-cli -h localhost -p 6379 KEYS "product:*"
# TTL 확인
redis-cli TTL product:123
마무리
spring cache redis 설정은 애플리케이션 성능 개선에 직접적인 영향을 준다. 기본 설정부터 직렬화, TTL, 모니터링까지 전반을 점검하면 안정적이고 효율적인 캐시 운영이 가능하다. 본문에서 제시한 redis spring boot 예제와 구성은 출발점이 되며, 실제 운영 환경에서는 트래픽 패턴에 맞춰 세부 값을 조정하는 과정이 필요하다.