20241129 TIL : Redis의 직렬화 방법

MCS·2024년 11월 29일

TIL

목록 보기
15/45

오늘 학습한 내용

  • Redis의 직렬화 방법
    • JdkSerializationRedisSerializer
    • GenericJackson2JsonRedisSerializer
    • Jackson2JsonRedisSerializer
    • StringRedisSerializer

Redis의 직렬화 방법

Spring에서 Redis에 접근하기 위해 RedisTemplate 혹은 extends CrudRepository를 사용할 수 있다.
Key를 직접 설정하고 자료형도 직접 선택해 가면서 Redis를 활용하고 싶다면, RedisTemplate을 사용할 수 있다. RedisTemplate을 정의하면서 Key와 Value로 사용될 Java 클래스를 정하고, 이후 사용할 세부 작업을 RedisOperations를 이용해 가져오는 방식이다.

Redis와 자바가 서로 데이터를 주고받기 위해서는 직렬화/역직렬화 과정이 필수적이다. 이를 위해 사용하는 방법들을 알아보자.

JdkSerializationRedisSerializer

  • JdkSerializationRedisSerializer는 기본으로 적용되는 Serializer로 기본 자바 바이트코드 직렬화 방식을 사용
  • Serializable 인터페이스만 구현하면 별도의 작업 없이 쉽게 사용할 수 있음
  • SerialVersionUID 설정을 하지 않으면 클래스의 기본 해시값을 SerialVersionUID로 사용함. 따라서 클래스 구조 변경시 SerialVersionUID가 달라져 역직렬화에 실패할 수 있음
  • 기본적으로 타입에 대한 정보 등 클래스 메타 정보들을 가지고 있기 때문에 직렬화시 용량이 큼
  • 클래스의 변경이 잦은 경우에는 JdkSerializationRedisSerializer를 사용하는 것을 지양

GenericJackson2JsonRedisSerializer

  • GenericJackon2JsonSerializer 는 Class Type 을 지정할 필요 없이 자동으로 객체를 Json 형식으로 직렬화해줌
  • 직렬화된 데이터가 Class Type을 포함
  • 직렬화시 @class 필드에는 해당 class의 패키지까지 함께 저장
    따라서, 어떤 Application이던 해당 데이터를 꺼내오기 위해서는 해당 경로에 같은 이름으로 해당 DTO Class 를 생성해야만 사용 가능
  • MSA 구조를 가지는 여러 Application이 상호작용하며 동일한 Domain을 가진다면 MSA API가 Class Type 에 묶임. 즉 MSA 환경에서 적절하지 않을 수 있음.

Jackson2JsonRedisSerializer

  • 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

  • StringRedisSerializer는 String 값을 그대로 저장하는 Serializer
  • Json 타입으로 별도로 변환하는 과정이 필요하지만 앞서 살펴본 직렬화 구현체들의 단점을 보완 가능
  • Class Type을 별도 지정할 필요가 없으며, Package 정보를 포함할 필요가 없음
  • 용량을 최소화하여 저장할 수 있음

StringRedisSerializer로 역직렬화 시 ClassCastException 발생

StringRedisSerializer를 value의 Serializer로 지정 시, RedisTemplate에서 값을 String이 아닌 값(Integer 등)으로 가져오는 경우 ClassCastException가 발생할 수 있다.

이는 deserialize 메서드가 강제로 String 타입으로 변환해 반환하고 있기 때문이다. Operations의 메서드가 어떤 타입으로 값을 리턴하던 간에 String 타입이 되어버리기 때문에 ClassCastException이 발생하는 것이다.

해결법 : GenericToStringSerializer

Value의 Serializer를 다음의 예시와 같이 GenericToStringSerializer로 설정한다.
redisTemplate.setHashValueSerializer(new GenericToStringSerializer<>(Integer.class));



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

profile
백엔드를 잘 하고 싶은 사람

0개의 댓글