기타/개발일기

Spring Boot에서 Redis 사용하기

hu6r1s 2024. 3. 15. 21:23

Redis를 공부하게 된 계기는 프로젝트를 진행하면서 Refresh Token을 처리를 해줘야 하는데 이를 보통 Redis로 사용을 많이 한다고 한다. 하지만 Redis를 따로 사용해 본 적이 없어서 Database를 사용하여 Refresh Token을 관리해줬다.

Redis를 공부해놔야 할 것 같아 리팩토링을 통해 Redis를 사용하게 되었다.

Redis

레디스는 Mysql와 같은 RDS도 아니고, MongoDB와 같은 NoSQL도 아니다. 인메모리 형식의 키-값 구조를 가진 데이터 저장소이다.

주요 Redis 사용 사례로는 캐싱, 세션 관리, pub/sub 및 순위표라고 한다.

Spring Boot Redis

스프링 부트에서 공식적으로 레디스 기능을 제공해준다.

Spring Boot Redis에는 Jedis와 Lettuce가 있다.

Jedis란 성능과 사용성을 위해 만들어진 클라이언트 라이브러리이다. 하지만 동기 방식으로 작동하여 Blocking 이슈가 발생 가능하다는 단점이 있다.

Lettuce는 비동기(동기도 지원함) 및 리액티브 프로그래밍을 지원하여 더 뛰어난 성능과 확장성을 제공한다고 한다.

Spring Boot Redis에서는 기본적으로 Lettuce를 사용하도록 한다.

설정

Dependency 추가

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

 

redis를 사용할 수 있도록 의존성을 추가해준다.

Config

@Configuration
public class RedisConfig {

  @Value("${spring.data.redis.host}")
  private String host;
  @Value("${spring.data.redis.port}")
  private int port;

  @Bean
  public RedisConnectionFactory redisConnectionFactory() {
    return new LettuceConnectionFactory(host, port);
  }
  @Bean
  public RedisTemplate<String, String> redisTemplate() {
    RedisTemplate<String, String> redisTemplate = new RedisTemplate<>();
    redisTemplate.setKeySerializer(new StringRedisSerializer());
    redisTemplate.setValueSerializer(new StringRedisSerializer());
    redisTemplate.setConnectionFactory(redisConnectionFactory());
    return redisTemplate;
  }
}

 

RedisConnectionFactory를 통해 Lettuce를 사용할 수 있도록 설정해준다.

그리고 RedisTemplate을 사용할 수 있도록 Bean을 등록해준다. 키와 값의 타입을 자신이 넣을 데이터의 타입을 넣어주면 된다.

Refresh Token 적용

@Repository
@RequiredArgsConstructor
public class RefreshTokenRepository {

  private final RedisTemplate redisTemplate;

  @Resource(name = "redisTemplate")
  private ValueOperations<String, String> valueOperations;


  public void deleteToken(Long userId) {
    redisTemplate.delete(userId);
  }

  public void save(String userId, String refreshToken) {
    valueOperations.set(userId, refreshToken);
    redisTemplate.expire(userId, 7L, TimeUnit.DAYS);
  }

  public String findById(String userId) {
    String refreshToken = String.valueOf(valueOperations.get(userId));

    if (userId == null) {
      return null;
    }

    return refreshToken;
  }
}

 

기본적으로 데이터 저장, 조회, 삭제를 구현하였다.

key는 userId, value는 refresh token으로 사용하였다.

저장할 때, 만료 시간도 지정해 줄 수 있어, refresh token의 만료 시간만큼 지정해주었다.