지난번에 인증코드를 DB에서 관리하여 스프링으로 이메일 인증을 구현해봤다 (https://velog.io/@wellbeing-dough/spring-%EC%9C%BC%EB%A1%9C-%EB%A9%94%EC%9D%BC-%EC%9D%B8%EC%A6%9D-%EA%B5%AC%ED%98%84)
하지만 DB에서 인증코드를 관리하면
1. DB Io작업이 빈번하게 일어난다
2. 만료설정이 유연하게 되지않는다
내장 cache (Ehcache) 를 사용할 수 있지만 내장 데이터는 배포할때마다 값이 초기화되기 때문에 rds처럼 외부에서 따로 관리하게 해 두었습니다
고로 Redis를 사용하여 제한 시간 예외처리와 DB커넥션 최소화,Redis의 빠른 응답시간과 유연한 만료 설정을 위해 인증코드를 효과적으로 관리할 수 있게 해보자
redis 설치가 끝나고
spring:
redis:
host: localhost
port: 6379
이렇게 6379포트로 redis를 열어두었습니다 배포된 환경에서는 elasticache를 사용했습니다
@Configuration
public class RedisConfig {
@Value("${spring.redis.host}")
private String redisHost;
@Value("${spring.redis.port}")
private String redisPort;
@Bean
public RedisConnectionFactory redisConnectionFactory() {
RedisStandaloneConfiguration redisStandaloneConfiguration = new RedisStandaloneConfiguration();
redisStandaloneConfiguration.setHostName(redisHost);
redisStandaloneConfiguration.setPort(Integer.parseInt(redisPort));
return new LettuceConnectionFactory(redisStandaloneConfiguration);
}
@Bean
public RedisTemplate<Long, String> redisTemplate() {
RedisTemplate<Long, String> redisTemplate = new RedisTemplate<>();
redisTemplate.setConnectionFactory(redisConnectionFactory());
redisTemplate.setKeySerializer(new GenericToStringSerializer<>(Long.class));
redisTemplate.setValueSerializer(new StringRedisSerializer());
return redisTemplate;
}
@Bean
public StringRedisTemplate stringRedisTemplate(){
StringRedisTemplate stringRedisTemplate= new StringRedisTemplate();
stringRedisTemplate.setKeySerializer(new StringRedisSerializer());
stringRedisTemplate.setValueSerializer(new StringRedisSerializer());
stringRedisTemplate.setConnectionFactory(redisConnectionFactory());
return stringRedisTemplate;
}
}
기존 코드(https://velog.io/@wellbeing-dough/spring-%EC%9C%BC%EB%A1%9C-%EB%A9%94%EC%9D%BC-%EC%9D%B8%EC%A6%9D-%EA%B5%AC%ED%98%84)에서 바뀐 부분은
@Service
@RequiredArgsConstructor
public class EmailCacheService {
private final StringRedisTemplate redisTemplate;
public String getAndCacheAuthCode(String email) {
Random random = new Random();
StringBuilder key = new StringBuilder();
for(int i=0;i<8;i++) {
key.append(random.nextInt(10));
}
redisTemplate.opsForValue().set(email, key.toString(), 1000L * 60 * 5, TimeUnit.MILLISECONDS);
return key.toString();
}
}
여기서 랜덤으로 인증코드를 만들어서 redis에 넣고
public boolean validEmail(ValidMailInfo info) {
String cachedAuthCode = redisTemplate.opsForValue().get(info.getEmail()); // 캐시된 인증 코드 가져오기
log.info("**************************캐싱된 인증 코드" + cachedAuthCode);
log.info("**************************입력된 인증 코드" + info.getAuthCode());
return cachedAuthCode != null && cachedAuthCode.equals(info.getAuthCode());
}
유저의 이메일을 기반으로 인증코드를 검증하는 로직을 추가하면 된다
Timer AOP로 테스트를 해보았다
기존에 DB에서 인증할때는
15미리 세컨드였는데
redis를 사용한 인증 방식에서는
5미리 세컨드가 되었다