- Redis의 직렬화 방법
- JdkSerializationRedisSerializer
- GenericJackson2JsonRedisSerializer
- Jackson2JsonRedisSerializer
- StringRedisSerializer
Spring에서 Redis에 접근하기 위해 RedisTemplate 혹은 extends CrudRepository를 사용할 수 있다.
Key를 직접 설정하고 자료형도 직접 선택해 가면서 Redis를 활용하고 싶다면, RedisTemplate을 사용할 수 있다. RedisTemplate을 정의하면서 Key와 Value로 사용될 Java 클래스를 정하고, 이후 사용할 세부 작업을 RedisOperations를 이용해 가져오는 방식이다.
Redis와 자바가 서로 데이터를 주고받기 위해서는 직렬화/역직렬화 과정이 필수적이다. 이를 위해 사용하는 방법들을 알아보자.
- JdkSerializationRedisSerializer는 기본으로 적용되는 Serializer로 기본 자바 바이트코드 직렬화 방식을 사용
- Serializable 인터페이스만 구현하면 별도의 작업 없이 쉽게 사용할 수 있음
- SerialVersionUID 설정을 하지 않으면 클래스의 기본 해시값을 SerialVersionUID로 사용함. 따라서 클래스 구조 변경시 SerialVersionUID가 달라져 역직렬화에 실패할 수 있음
- 기본적으로 타입에 대한 정보 등 클래스 메타 정보들을 가지고 있기 때문에 직렬화시 용량이 큼
- 클래스의 변경이 잦은 경우에는 JdkSerializationRedisSerializer를 사용하는 것을 지양
- GenericJackon2JsonSerializer 는 Class Type 을 지정할 필요 없이 자동으로 객체를 Json 형식으로 직렬화해줌
- 직렬화된 데이터가 Class Type을 포함
- 직렬화시 @class 필드에는 해당 class의 패키지까지 함께 저장
따라서, 어떤 Application이던 해당 데이터를 꺼내오기 위해서는 해당 경로에 같은 이름으로 해당 DTO Class 를 생성해야만 사용 가능- MSA 구조를 가지는 여러 Application이 상호작용하며 동일한 Domain을 가진다면 MSA API가 Class Type 에 묶임. 즉 MSA 환경에서 적절하지 않을 수 있음.
- Jackson2JsonRedisSerializer은 @class 필드를 포함하지 않고 Json으로 저장
- 항상 Class Type 정보를 Serializer 에 함께 지정해야 함
- 따라서 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;
}
- StringRedisSerializer는 String 값을 그대로 저장하는 Serializer
- Json 타입으로 별도로 변환하는 과정이 필요하지만 앞서 살펴본 직렬화 구현체들의 단점을 보완 가능
- Class Type을 별도 지정할 필요가 없으며, Package 정보를 포함할 필요가 없음
- 용량을 최소화하여 저장할 수 있음
StringRedisSerializer를 value의 Serializer로 지정 시, RedisTemplate에서 값을 String이 아닌 값(Integer 등)으로 가져오는 경우 ClassCastException가 발생할 수 있다.

이는 deserialize 메서드가 강제로 String 타입으로 변환해 반환하고 있기 때문이다. Operations의 메서드가 어떤 타입으로 값을 리턴하던 간에 String 타입이 되어버리기 때문에 ClassCastException이 발생하는 것이다.
Value의 Serializer를 다음의 예시와 같이 GenericToStringSerializer로 설정한다.
redisTemplate.setHashValueSerializer(new GenericToStringSerializer<>(Integer.class));



GenericToStringSerializer는 내부적으로 넘어온 클래스타입으로 변환을 수행한다.
따라서 필요한 타입을 지정해 ClassCastException를 방지할 수 있다.