Redis를 사용하는 방법에는 두 가지가 있다.
- CrudRepository 상속
- Redis template 사용
CrudRepository
CrudRepository 인터페이스는 spring data commons 모듈에 선언된 인터페이스로 데이터베이스를 다루는 데 필요한 메서드를 모아둔 인터페이스입니다.
도메인 클래스 타입과 ID 타입을 제네릭 인자로 전달하고 CrudRepository 인터페이스를 상속하면 관계형 데이터베이스부터 NoSQL 데이터베이스까지 데이터 조회 기능과 갱신 기능을 편리하게 사용할 수 있습니다. Spring Data Redis Repository 역시 CrudRepository 인터페이스에 선언된 모든 메서드를 오버라이딩해 Redis Hash 데이터에 쉽게 접근할 수 있습니다.
@RedisHash(value = "refreshToken", timeToLive = 1000L * 60 * 60 * 24 * 14)
public class RefreshToken {
@Id
@Indexed
private String jwtRefreshToken;
private String authKey;
}
Redis Gui(Medis)를 통해 service 단에서 저장한 refreshToken 객체가 레디스 서버에 저장된 것을 확인할 수 있다.
Redis template
RedisTemplate은 Spring Data Redis에서 제공하는 기능 중 하나로, Redis 데이터베이스와 상호 작용하는 데 사용되는 템플릿입니다. Redis를 사용하여 데이터를 저장, 조회, 갱신 및 삭제하기 위한 메서드를 제공하며, Redis 데이터 구조에 데이터를 보다 쉽게 쓰고 읽을 수 있도록 돕습니다.
Redis Gui를 통해 CrudRepository와 달리 Key-value 형식으로 저장된 사실을 알 수 있다.
CrudRepository VS Redis template
저장 | 조회 - 데이터 없을 경우 | 조회 - 데이터 있는 경우 | |
CrudRepository | 5ms | 3ms | 3ms |
Redis template | 45ms | 3ms | 13ms |
CrudRepository 를 사용하면 Jpa와 유사한 사용법 때문에 쉽게 익히고 사용할 수 있지만
보시다시피 저장용량이나 속도에 있어서 Redis template가 훨씬 낫다는 점을 알 수 있다.
Redis template(Lettuce) 사용
build.gradle
implementation 'org.springframework.boot:spring-boot-starter-data-redis'
RedisConfig
@Configuration
public class RedisConfig {
@Value("${REDIS_HOST}")
private String host;
@Value("${REDIS_PORT}")
private int port;
@Value("${REDIS_PASSWORD}")
private String password;
@Bean
public RedisConnectionFactory redisConnectionFactory() {
RedisStandaloneConfiguration redisStandaloneConfiguration = new RedisStandaloneConfiguration();
redisStandaloneConfiguration.setHostName(host);
redisStandaloneConfiguration.setPort(port);
redisStandaloneConfiguration.setPassword(password);
return new LettuceConnectionFactory(redisStandaloneConfiguration);
}
@Bean
public RedisTemplate<?, ?> redisTemplate() {
RedisTemplate<?, ?> redisTemplate = new RedisTemplate<>();
redisTemplate.setKeySerializer(new StringRedisSerializer());
redisTemplate.setValueSerializer(new StringRedisSerializer());
redisTemplate.setConnectionFactory(redisConnectionFactory());
return redisTemplate;
}
}
RedisConnectionFactory 인터페이스를 통해 LettuceConnectionFactory를 생성하여 반환한다.
host, port, password(선택 유무)를 redisStandaloneConfiguration에 set하여 redis 서버와 connection을 생성한다.
RedisTemplate에 확장성을 두기 위해 <?,?>으로 선언하였고,
RedisTemplate를 사용할 때 Spring - Redis 간 데이터 (역)직렬화 시 사용하는 방식이 Jdk직렬화 방식으로
redis-cli를 통해 직접 데이터를 볼 때 알아볼 수 있는 형태로 출력 하기 위해 setKeySerializer, setValueSerializer를 설정한다.
@Service
@RequiredArgsConstructor
public class RedisUtil {
//선언부
private final RedisTemplate<String, Object> redisTemplate;
public void set(String key, Object o, Long duration) {
redisTemplate.setValueSerializer(new Jackson2JsonRedisSerializer(o.getClass()));
redisTemplate.opsForValue().set(key, o, duration, TimeUnit.MILLISECONDS);
}
public Object get(String key) {
return redisTemplate.opsForValue().get(key);
}
public void delete(String key) {
redisTemplate.delete(key);
}
public boolean hasKey(String key) {
return redisTemplate.hasKey(key);
}
}
RedisTemplate를 쉽게 사용하고 코드를 이해할 수 있도록 RedisUtil을 생성한다.
아래와 같이 사용하면 된다.
@Service
@RequiredArgsConstructor
@Transactional(readOnly = true)
public class AuthServiceImpl implements AuthService {
...
private final RedisUtil redisUtil;
...
//로그인 로직
@Override
public GetJwtDto login(PostLoginDto postLoginDto) {
...
redisUtil.set("RT:" + jwtToken.getJwtRefreshToken(), postLoginDto.getAuthKey(), 1000L * 60 * 60 * 24 * 14);
...
}
@Override
public void logout(PostJwtDto postJwtDto, User user) {
/**refreshToken 만료 여부 확인*/
if (!redisUtil.hasKey("RT:" + postJwtDto.getRefreshToken())) {
throw new UnauthorizedException(ErrorCode.INVALID_REFRESH_TOKEN);
}
redisUtil.delete("RT:" + postJwtDto.getRefreshToken());
...
SecurityContextHolder.clearContext();
}
}
https://wildeveloperetrain.tistory.com/32
'💻 프로젝트 > 🏕 캠퍼' 카테고리의 다른 글
[Campper] Spring Cloud Feign 사용하여 공공데이터 쉽게 관리하기 (0) | 2023.10.09 |
---|---|
[Campper] SpringSecurity + JWT + 로컬로그인 인증 구현하기 (0) | 2023.10.09 |