Spring Boot 애플리케이션에 Redis 통합하기
Redis는 인메모리 키-값 데이터 저장소로, Spring Boot 애플리케이션에서 캐싱 및 세션 관리 등에 활용됩니다. 이 글에서는 Spring Boot 프로젝트에 Redis를 통합하는 두 가지 주요 방법(어노테이션 기반 캐싱과 RedisTemplate을 이용한 수동 캐싱)에 대해 설명합니다.
프로젝트 설정 및 의존성
먼저 Spring Initializr를 사용하여 프로젝트를 생성하고, 다음과 같은 의존성을 추가합니다.
<project>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-cache</artifactId>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.83</version>
</dependency>
</dependencies>
</project>
Redis 연결 구성
애플리케이션 설정 파일(application.yml)에 Redis 서버 연결 정보를 정의합니다.
spring:
redis:
host: localhost
port: 6379
database:规章制度 0
timeout: 2000ms
jedis:
pool:
max-active: 8
max-idle: 8
min-idle: 0
방법 1: 어노테이션 기반 캐싱
Spring의 캐싱 어노테이션을 사용하여 메서드 결과를 자동으로 캐싱할 수 있습니다.
캐시 키 생성기 구성
@Configuration
public class CacheKeyConfig {
@Bean
public KeyGenerator customKeyGenerator() {
return (target, method, params) -> {
StringBuilder keyBuilder = new StringBuilder();
keyBuilder.append(target.getClass().getSimpleName());
keyBuilder.append(".");
keyBuilder.append(method.getName());
if (params.length > 0) {
keyBuilder.append(".");
keyBuilder.append(params[0].toString());
}
return keyBuilder.toString();
};
}
}
Redis 캐시 관리자 구성
@Configuration
@EnableCaching
public class RedisCacheConfig {
@Bean
public CacheManager cacheManager(RedisConnectionFactory factory,
FastJsonRedisSerializer<Object> serializer) {
RedisCacheConfiguration config = RedisCacheConfiguration.defaultCacheConfig()
.serializeKeysWith(RedisSerializationContext.SerializationPair
.fromSerializer(new StringRedisSerializer()))
.serializeValuesWith(RedisSerializationContext.SerializationPair
.fromSerializer(serializer));
return RedisCacheManager.builder(factory)
.cacheDefaults(config)
.build();
}
}
JSON 직렬화 처리
@Component
public class FastJsonRedisSerializer<T> implements RedisSerializer<T> {
private final Class<T> typeParameter;
private static final Charset DEFAULT_CHARSET = StandardCharsets.UTF_8;
public FastJsonRedisSerializer(Class<T> typeParameter) {
this.typeParameter = typeParameter;
ParserConfig.getGlobalInstance().addAccept("com.example.");
}
@Override
public byte[] serialize(T object) {
if (object == null) return new byte[0];
return JSON.toJSONString(object, SerializerFeature.WriteClassName)
.getBytes(DEFAULT_CHARSET);
}
@Override
public T deserialize(byte[] bytes) {
if (bytes == null || bytes.length == 0) return null;
String jsonString = new String(bytes, DEFAULT_CHARSET);
return JSON.parseObject(jsonString, typeParameter);
}
}
캐싱 어노테이션 활용 예제
@RestController
@RequestMapping("/api/cache")
public class CacheDemoController {
@Cacheable(value = "userCache", key = "#userId")
@GetMapping("/users/{userId}")
public User fetchUser(@PathVariable String userId) {
// 데이터베이스 조회 로직 (실제 구현 시)
return new User(userId, "사용자_" + userId);
}
@CacheEvict(value = "userCache", key = "#userId")
@DeleteMapping("/users/{userId}")
public String removeUserCache(@PathVariable String userId) {
return "캐시 제거 완료: " + userId;
}
@CachePut(value = "userCache", key = "#user.id")
@PutMapping("/users")
public User updateUser(@RequestBody User user) {
// 업데이트 로직
return user;
}
}
방법 2: RedisTemplate을 이용한 수동 캐싱
더 세밀한 제어가 필요할 때 RedisTemplate을 직접 사용할 수 있습니다.
RedisTemplate 구성
@Configuration
public class RedisTemplateConfig {
@Bean
public RedisTemplate<String, Object> redisTemplate(
RedisConnectionFactory factory,
FastJsonRedisSerializer<Object> serializer) {
RedisTemplate<String, Object> template = new RedisTemplate<>();
template.setConnectionFactory(factory);
template.setKeySerializer(new StringRedisSerializer());
template.setValueSerializer(serializer);
template.setHashKeySerializer(new StringRedisSerializer());
template.setHashValueSerializer(serializer);
template.afterPropertiesSet();
return template;
}
}
수동 캐싱 구현 예제
@RestController
@RequestMapping("/api/manual")
public class ManualCacheController {
@Autowired
private RedisTemplate<String, Object> redisTemplate;
@GetMapping("/data/{key}")
public ResponseEntity<?> getData(@PathVariable String key) {
Object cachedData = redisTemplate.opsForValue().get(key);
if (cachedData != null) {
return ResponseEntity.ok(cachedData);
}
// 캐시 미스 발생 시 원본 데이터 소스 조회
Object freshData = fetchFromDataSource(key);
if (freshData != null) {
redisTemplate.opsForValue().set(key, freshData, 10, TimeUnit.MINUTES);
}
return ResponseEntity.ok(freshData);
}
@PostMapping("/data")
public String storeData(@RequestParam String key,
@RequestBody Object data) {
// 원본 데이터 저장 후 캐시 갱신
redisTemplate.opsForValue().set(key, data, 10, TimeUnit.MINUTES);
return "데이터 저장 및 캐싱 완료";
}
private Object fetchFromDataSource(String key) {
// 실제 데이터 소스 조회 로직
return Map.of("id", key, "value", "새로운 데이터");
}
}
성능 최적화 팁
- 캐시 만료 시간(TTL)을 적절히 설정하여 데이터 신선도 유지
- 대량 데이터 처리 시 파이프라이닝 활용
- 캐시 키 설계 시 네임스페이스 접두사 사용 권장
- 모니터링을 위해 캐시 히트/미스 비율 추적
이 가이드를 통해 Spring Boot 애플리케이션에 Redis를 효과적으로 통합하고, 성능 최적화에 활용할 수 있습니다.