본문 바로가기
Spring

Spring boot에서 Redis 연동

by runlearn 2023. 7. 24.

Spring boot에서 Redis 사용기 ..

Spring Boot에서 Redis를 사용한 것에 대해 기록하려고 한다.

레디스를 왜 사용할까 ?

서비스가 커지고 트래픽이 많아질 수록 백엔드 서버를 유지하기 위해서는 많은 것을 고려해야한다.

흔히 고려할 수 있는 포인트는 불필요한 I/O를 줄이는 것이다. 변하지 않는 결과를 굳이 DB에서 조회하기 보단 캐싱해서 빠르게 조회하는 것이 성능면에서 좋을 것이다.

물론 애플리케이션 내의 캐싱을 사용할 수 있지만, 서버를 여러개 띄우게 되면 해당 값들은 공유할 수 없다. redis를 사용하면 서버를 여러대 띄운 환경에서도 캐시 메모리를 공유할 수 있다.

레디스 특징

in-memory 데이터베이스
key-value 형태의 데이터베이스
single-thread
다양한 command제공
높은 availability를 위한 옵션이 존재 - 센티널, 레디스 클러스터

docker 에서 redis 환경 구축

  1. Docker에서 Redis Image pull
    docker image pull redis
  1. Docker에서 redis run
    sudo docker run -p 6379:6379 redis
  • Redis network 구축하는 방법도 있는데, 진행한 프로젝트에서는 필요가 없을 것 같아 사용하지 않았다.
  1. redis 컨테이너에 접속 후 redis-cli를 통해서 레디스의 데이터를 조회할 수 있다.

Spring boot와 redis 연결

Spring boot의 build.gradle에서 redis 관련 의존성을 추가한다.

implementation 'org.springframework.boot:spring-boot-starter-data-redis'

 

application.yml에 redis host&port 정보 기입

spring:
  redis:
     host: localhost
     port: 6379

Redis Configuration 클래스 정의

@Configuration
@EnableRedisRepositories
@RequiredArgsConstructor
public class RedisConfiguration {

    // application.yml에 레디스 정보 관리 prefix = "spring.redis"
    private final RedisProperties redisProperties;

    @Bean
    public RedisConnectionFactory redisConnectionFactory() {
        RedisURI redisURI = RedisURI.create(redisProperties.getHost(),redisProperties.getPort());
        // 레디스와 애플리케이션을 연결을 위한 라이브러리는 Jedis 와 Lettuce가 있다. 요즘은 Lettuce을 많이 사용한다.
        org.springframework.data.redis.connection.RedisConfiguration configuration = LettuceConnectionFactory.createRedisConfiguration(redisURI);
        LettuceConnectionFactory factory = new LettuceConnectionFactory(configuration);
        factory.afterPropertiesSet(); // initialized
        return factory;
    }


    // 레디스 커맨드를 쉽게 사용할 수 있는 클래스 RedisTemplate<Key,Value> , 데이터 변경이 잦은 데이터는 캐싱 장점이 없다.
    // 자주 사용하는 데이터를 캐싱하는 것이 좋다.
    @Bean // UserEntity보다 User를 캐싱하는 것이 더 좋다고 판단.
    public RedisTemplate<String, User> userRedisTemplate(RedisConnectionFactory redisConnectionFactory) {
        RedisTemplate<String, User> redisTemplate = new RedisTemplate<>();
        redisTemplate.setConnectionFactory(redisConnectionFactory); // setConnectionFactory - 실제 레디스 서버에 대한 정보를 가짐
        redisTemplate.setKeySerializer(new StringRedisSerializer()); // 레디스에 데이터 저장시 serializer 필요
        redisTemplate.setHashValueSerializer(new Jackson2JsonRedisSerializer<User>(User.class));

        return redisTemplate;
    }

}
  • RedisConnectionFactory 클래스를 Bean으로 등록
  • Spring Boot에서는 RedisTemplate<Key,Value>를 제공하는데 이를 사용하여 레디스를 간편히 사용할 수 있다.
  • setKeySerializer, setValueSerializer 설정하여 직렬화 방법을 지정해준다.

Redis로 데이터 조회하는 코드

@Slf4j
@Repository
@RequiredArgsConstructor
public class UserCacheRepository {

    private final RedisTemplate<String, User> userRedisTemplate;
    private static final Duration USER_CACHE_TTL = Duration.ofDays(3); // TTL 3일 설정

    // 레디스의 경우 TTL (일정 기간 지난 후 expired) 를 걸어두는 것이 좋다.
    // 사용 접근하지 않은 캐시를 계속 가지고 있을 필요는 없다. 레디스 공간을 효율적 사용을 위해... TTL 설정

    // redisTemplate.opsForValue(); ->기본적인 get/set 제공
    public void setUser(User user) {
        String key = getKey(user.getUsername());
        log.info("Set User to Redis {}:{}",key,user);
        userRedisTemplate.opsForValue().set(getKey(user.getUsername()),user,USER_CACHE_TTL);
    }

    public Optional<User> getUser(String userName) {
        String key = getKey(userName);
        User user = userRedisTemplate.opsForValue().get(key);
        log.info("Get data from Redis {} , {}",key,user);
        return Optional.ofNullable(user);
    }

    // 서비스가 커지면 user 정보뿐만 아니라 다양한 데이터를 캐싱하게 된다. 이 때 구분을 위해 레디스 내에서  prefix를 지정하여 사용하는 것이 좋다.
    private String getKey(String userName) {
        return "USER:" + userName;
    }
}

'Spring' 카테고리의 다른 글

[JPA] 프록시  (1) 2023.10.09
[JPA]영속성 컨텍스트  (0) 2023.09.24
[JPA] 더티체킹  (0) 2023.09.11
Spring profile  (0) 2023.07.09

댓글