본문 바로가기

Language/Spring

[Spring Boot] Redis를 이용한 이메일 인증 리팩토링

의존성 추가
implementation 'org.springframework.boot:spring-boot-starter-data-redis'

 

application.yml 설정 추가
spring:
  # 레디스
  redis:
    data:
      host: localhost
      port: 6379

 

RedisConfig
  • Configuration이 있는 클래스에 @EnableRedisRepositories 어노테이션을 추가하여 repository를 사용한다고 명시
@Configuration
@EnableRedisRepositories
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, Object> redisTemplate() {
        RedisTemplate<String, Object> redisTemplate = new RedisTemplate<>();
        redisTemplate.setConnectionFactory(redisConnectionFactory());
        // key,value를 Email,Authcode로 구현할 것이기 때문에 둘다 String으로 직렬화해도 무관
        redisTemplate.setKeySerializer(new StringRedisSerializer());
        redisTemplate.setValueSerializer(new StringRedisSerializer());

//         Hash를 사용할 경우 시리얼라이저
//        redisTemplate.setHashKeySerializer(new StringRedisSerializer());
//        redisTemplate.setHashValueSerializer(new StringRedisSerializer());

//        모든 경우
//        redisTemplate.setDefaultSerializer(new StringRedisSerializer());

        return redisTemplate;
    }
}

 


@Value 어노테이션 import 주의 사항

  • org.springframework.beans.factory.annotation.Value의 @Value 어노테이션을 사용하면 application.properties나 yml 또는 환경 변수 설정한 것을 주입할 때 사용이 됨
  • 하지만, 실수로 lombok의 @Value 어노테이션을 import하게 되면 아래와 같은 문구가 발생하므로 주의

 

 

RedisService
@Service
@RequiredArgsConstructor
public class RedisService {
    private final RedisTemplate<String, String> redisTemplate;

    // K : 이메일, V : 인증 코드
    public void setCode(String email, String authCode){
        ValueOperations<String, String> valueOperations = redisTemplate.opsForValue();
        // 유효 시간은 300, 단위는 초로 설정
        valueOperations.set(email, authCode, 300, TimeUnit.SECONDS);
    }
    
    // K(email)의 V(인증 코드)를 반환
    public String getCode(String email) throws AuthenticationException {
        ValueOperations<String, String> valueOperations = redisTemplate.opsForValue();
        String authCode = valueOperations.get(email);
        if(authCode == null)
            throw new AuthenticationException("인증 코드가 일치하지 않습니다.");
        return authCode;
    }
}
메소드 명 레디스 타입
opsForValue String
opsForList List
opsForSet Set
opsForZSet Sorted Set
opsForHash Hash

 

기존의 Auth, AuthRepository 삭제

 

MemberService 코드수정
  • 레디스는 Key, Value의 형태로 되어있기 때문에 동일한 Key값의 Value가 저장되면 덮어씌기
  • 자바 자료구조의 Map과 동일한 것으로 예상
    → 해당 내용은 아래의 테스트에서 확인
@Service
@RequiredArgsConstructor
public class MemberService {
    private final MemberRepository memberRepository;
    private final MailService mailService;
    private final RedisService redisService;

    (생략)

    public boolean sendAuthcode(String email) throws MessagingException {
        String authCode = mailService.sendSimpleMessage(email);
        redisService.setCode(email, authCode);
        return true;
    }

    public boolean validationAuthcode(String email, String authCode) throws AuthenticationException {
        String savedCode = redisService.getCode(email);
        return authCode.equals(savedCode);
    }
}

 


Postman 테스트
Redis 간단 명령어
  • keys * : 저장된 모든 key 값 출력
  • get [key값] : key 값에 해당하는 value 값 출력
  • ttl [key값] : 소멸까지 남은 시간 반환

 

인증 코드 발급 1회

 

인증 코드 발급 2회
  • 두 번째 발급 시 기존에 있던 Value의 값이 덮어쓰기
  • 유효 시간 초기화(5분)

 

인증 코드 확인

 

인증 유효 시간 초과 후 인증 코드 확인