안녕하세요 오늘은 Redis
직렬화 방식에 대해 살펴보겠습니다 💪
우리는 앞서 Spring Data Redis
의존성과 함께 다양한 방법으로 Spring 서버에서 Redis
를 사용해보았습니다. Redis에 대해 알아봅시다(응용편) 를 참고해주세요!
Redis에 대해 알아봅시다.(이론편) & Redis에 대해 알아봅시다.(응용편) 을 먼저 본다면 더욱 빠른 이해를 할 수 있습니다.
앞서 살펴본바와 같이 Spring 에서 Redis 를 사용하기 위해서는 먼저 Spring Data Redis
의존성을 추가해주고, RedisTemplate
혹은 RedisRepository
을 통해 Redis 서버에 접근합니다.
이때 우리가 실행시키고 있는 스프링 서버와 외부에서 실행 중인 레디스 서버는 다른 어플리케이션이기 때문에 데이터에 대한 작업을 위해서는 직렬화/역직렬화
과정이 필요합니다.
이번 포스팅에서는 RedisTemplate
Bean 생성시 직렬화 구현체에 대해 알아보겠습니다 ❗️
대표적으로 4가지 JdkSerializationRedisSerializer
, GenericJackson2JsonRedisSerializer
, Jackson2JsonRedisSerializer
,StringRedisSerializer
가 존재합니다.
JdkSerializationRedisSerializer
는 Default로 적용되는 Serializer로 기본 자바 직렬화 방식을 사용합니다.
자바에서는 Serializable
인터페이스만 구현하면 별도의 작업 없이 사용가능합니다. 하지만 여러가지 단점이 있습니다.
SerialVersionUID
설정을 하지 않으면 클래스의 기본 해시값을 SerialVersionUID
로 사용합니다. 따라서 클래스 구조가 조금이라도 변경시 SerialVersionUID
가 달라서 역직렬화에 실패할 수 있습니다.
만약 개발자가 주의를 가지고 SerialVersionUID
를 설정한다고 하여도, 클래스 내부 필드 타입이 변경되면 역시 역직렬화가 실패할 수 있습니다.
기본적으로 타입에 대한 정보 등 클래스 메타 정보들을 가지고 있기 때문에 직렬화시 용량이 비대해집니다.
따라서, 클래스의 변경이 잦은 경우에는 JdkSerializationRedisSerializer
를 사용하는 것은 지양해야 합니다.
GenericJackon2JsonSerializer
는 Class Type 을 지정할 필요 없이 자동으로 객체를 Json 형식으로 직렬화해주는 장점이 있습니다. 하지만 직렬화된 데이터가 Class Type 을 포함한다는 단점이 있습니다.
또한 직렬화시 @class
필드에는 해당 class 의 패키지까지 함께 저장됩니다.
따라서, 어떤 Application 이던 해당 데이터를 꺼내오기 위해서는 해당 루트, 경로에 같은 이름으로 해당 DTO Class 를 생성해야만 사용이 가능해집니다.
만약 MSA
구조를 가지는 여러 Application 이 상호작용하며 동일한 Domain을 가진다면 MSA API
가 Class Type 에 묶인다는 문제가 발생합니다 🥲
Jackson2JsonRedisSerializer
은 @class
필드를 포함하지 않고 Json 으로 저장해줍니다.
하지만 항상 Class Type 정보를 Serializer 에 함께 지정해주어야합니다.
이는 앞서 살펴보았던 GenericJackson2JsonRedisSerializer
와 반대 특징을 가집니다.
이때문에 RedisTemplate 객체를 저장하는 DTO 타입 별로 생성해서 각각의 Serializer의 Class Type 을 지정해주어야 합니다.
@Bean
public RedisTemplate<?,?> redisTemplate() {
RedisTemplate<?,?> redisTemplate = new RedisTemplate<>();
redisTemplate.setConnectionFactory(redisConnectionFactory());
redisTemplate.setEnableTranscationSupport(true); // 트랜잭션 지원 가능
// class Type 지정
redisTemplate.setKeySerializer(new Jackson2JsonRedisSerializer(String.class));
redisTemplate.setValueSerializer(new Jackson2JsonRedisSerializer(DTO.class));
return redisTemplate;
}
만약 사용하는 Class Type 종류가 많아진다면 큰 단점으로 작용할 수 있습니다 🥲
결론부터 말하자면 StringRedisSerialier
를 직렬화 구현체로 선택하는 것이 가장 단점을 최소화할 수 있는 방법입니다.
StringRedisSerializer
는 String 값을 그대로 저장하는 Serializer 입니다.
그렇기에 Json 타입으로 별도로 변환하는 과정이 필요하지만 앞서 살펴본 직렬화 구현체들의 단점을 보완할 수 있습니다 ❗️
Spring RedisTemplate Serializer 설정
Spring Boot Redis 두 가지 사용방법 RedisTemplate, RedisRepository
RestTemplate CastClassException 이슈