Redis에 Object 를 저장 하기 위해서는 Serializer를 통해 직렬화해주어야한다.
Object Mapper를 통해 > json으로 변환해서 저장 시켜주어야 한다.
Spring에서는 Spring Data Redis 라이브러리를 이용하여 Redis에 접근할 수 있다.
이때 Redis를 접근할 수 있는 프레임워크로 Lettuce, Jedis가 있다.
Lettuce는 별도의 설정 없이 이용할 수 있고, Jedis는 별도의 의존성 추가가 필요하다.
🛠️ Code
@Configuration
public class RedisConfig {
@Value("${spring.data.redis.host}")
private String redisHost;
@Value("${spring.data.redis.port}")
private int redisPort;
@Bean
public RedisConnectionFactory redisConnectionFactory() {
return new LettuceConnectionFactory(redisHost, redisPort);
}
@Bean
public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory redisConnectionFactory){
RedisTemplate<String,Object> redisTemplate = new RedisTemplate<>();
redisTemplate.setKeySerializer(new StringRedisSerializer());
redisTemplate.setValueSerializer(new StringRedisSerializer());
redisTemplate.setDefaultSerializer(RedisSerializer.string());
redisTemplate.setConnectionFactory(redisConnectionFactory);
return redisTemplate;
}
@Bean
public RedisMessageListenerContainer redisMessageListener(RedisConnectionFactory connectionFactory){
RedisMessageListenerContainer container = new RedisMessageListenerContainer();
container.setConnectionFactory(connectionFactory);
return container;
}
}
RedisConnectionFactory 인터페이스를 사용한다.
RedisConnectionFactory 인터페이스를 통하여 LettuceConnectionFactory를 생성하여 반환한다.
-> 새로운 Connection이나 이미 존재하는 Connection 리턴
-> Jedis, Lettuce 등 Redis-client를 선택하여 연결 생성
📌 @Value 사용하기 때문에 미리 설정 파일에서 spring.redis.@@ 구조로 설정 필요
RedisTemplate, StringRedisTemplate bean 생성
- RedisTemplate: java Object를 redis에 저장하는 경우 사용
- StringRedisTemplate: 일반적인 String 값을 key, value로 사용하는 경우 사용
🖇 setKeySerializer, setValueSerializer 설정 이유는, RedisTemplate 사용 시에 Spring-Redis 간 데이터 직렬화, 역직렬화에 사용하는 방식이 Jdk 직렬화 방식이기 때문이다.
Serializer 설정하기
GenericJackson2JsonRedisSerializer
이 Serializer는 객체의 클래스 지정없이 직렬화해준다는 장점을 가지고있다. 하지만, 단점으로는 Object의 Class 및 package까지 전부 함께 저장하게 되어 다른 프로젝트에서 redis에 저장되어 있는 값을 사용하려면 package까지 일치시켜줘야하는 큰 단점이 존재한다.
Jackson2JsonRedisSerializer
serializer는 클래스를 지정해야해서, redis에 객체를 저장할 때 class 값을 저장하지 않는다.
따라서, pacakge 등이 일치할 필요가 없다는 장점이 있다.
하지만, class 타입을 지정하기 때문에 redisTemplate을
여러 쓰레드에서 접근하게 될 때 serializer 타입의 문제가 발생하는 경우가 발생한다.
StringRedisSerializer
이것을 사용하게 되면, JSON 형태로 직접 encoding, decoding을 해줘야한다는
단점이 있지만 위의 두 개의 serializer에서 발생할 수 있는 문제가 발생하지 않는다.
- class 타입의 지정이 필요하지 않다.
- package까지 일치할 필요가 없다.
- 쓰레드간의 문제가 발생하지 않는다.
ObjectMapper를 사용하여 JSON을 직접 encode해서 사용 해주어야 한다.
🛠️ Code
public <T> boolean saveData(String key, T data) {
try {
ObjectMapper mapper = new ObjectMapper();
String value = objectMapper.writeValueAsString(data);
redisTemplate.opsForValue().set(key, value);
return true;
} catch(Exception e){
log.error(e);
return false;
}
}
public <T> Optional<T> getData(String key, Class<T> classType) {
String value = redisTemplate.opsForValue().get(key);
if(value == null){
return Optional.empty();
}
try {
ObjectMapper mapper = new ObjectMapper();
return Optional.of(objectMapper.readValue(value));
} catch(Exception e){
log.error(e);
return Optional.empty();
}
}
'일-상 > 오류노트' 카테고리의 다른 글
[오류노트] kafka server.properties 연결이 안된다면 여기로 (0) | 2023.06.09 |
---|---|
[오류노트] log4j.properties 파일을 못찾을때 (0) | 2023.06.07 |
[오류노트] DDD 연관관계와 간접참조 (0) | 2023.01.03 |
[오류노트] If you want an embedded database (H2, HSQL or Derby), please put it on the classpath. (0) | 2022.12.14 |
[오류노트] Scanner InputMismatchException 에러 (1) | 2022.11.29 |