[Spring] Redis 사용해서 이메일 검증하기, SJ Coding Helper 프로젝트 리펙토링 (4)

TaesunPark·2023년 1월 21일
0

기존 방법 : Session 이용. HttpSession을 여러 개 생성해서 이용해서 이메일을 검증했다.

문제점 : Key 값 중복 위험이 있음.

해결 방법 : Key, Value값의 맵을 사용하는 Redis를 이용한다.

이점 : 캐시 서버이기 때문에 빠름. DB의 부하를 줄여줌.

Redis 설치 방법

도커를 이용하면 간편하다.

docker run -p 6379:6379 --name redis -d redis

6379는 redis의 기본 포트 번호이다.

-p [내 서버 port] : [redis port] 로 내 서버 port에 접근하면 redis 포트로 접근한다는 의미이다.

docker ps

→ 현재 가동중인 컨테이너 리스트를 반환해주는 명령어.

docker exec -it abbf49a1cd90 bash

→ 가동중인 컨테이너 내부에 들어가는 명령어

저기 있는 abbf49 ~ 이건 CONTAINER ID이다. docker ps를 입력하면 알 수 있다.

redis-cli

→ 레디스 컨테이너 안에서 redis-cli를 입력하면 redis 클라이언트로 접속을 할 수 있다.

→ 여기서 레디스에 저장된 정보들을 보거나 삭제하거나, 입력하거나 등 작업을 할 수 있다.

도커를 이용해 redis 설치를 완료했다. 이 redis를 이제 WAS에 연동시켜보겠다.

스프링 부트는 redis에 대한 빈 설정들을 자동으로 제공해주고 우리가 하는 일은 classpath를 추가하고 bean을 가져다가 쓰기만 하면 된다.

  1. gradle을 통해 redis 관련 라이브러리들을 다운받아 적용시킨다.

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

    dependencies {
        // spring data redis
        implementation 'org.springframework.boot:spring-boot-starter-data-redis'
    }
  2. application.properties 또는 yml에 가서 spring.redis에 관련된 설정을 해준다.

    #application.properties
    #redis
    spring.redis.host=localhost
    spring.redis.port=6379
  1. Redis와 연결시킬 dao 생성

    package com.example.testlocal.module.user.domain.repository;
    
    import lombok.RequiredArgsConstructor;
    import org.springframework.data.redis.core.StringRedisTemplate;
    import org.springframework.stereotype.Repository;
    
    import java.time.Duration;
    
    @RequiredArgsConstructor
    @Repository
    public class EmailCertificationDao {
        private final String REDIS_EMAIl_PREFIX = "email:"; // Redis에 저장되는 Key값이 중복되지 않도록 상수 선언
        private final int LIMIT_TIME = 10 * 60; // Redis에서 해당 데이터의 유효시간(TTL)을 설정
        private final StringRedisTemplate stringRedisTemplate;
    
        public void createCodeCertification(String email, String certificationNumber){
            stringRedisTemplate.opsForValue()
                    .set(REDIS_EMAIl_PREFIX + email, certificationNumber, Duration.ofSeconds(LIMIT_TIME));
        }
    
        // 이메일에 해당하는 인증번호 가져오기
        public String getCodeCertification(String email){
            return stringRedisTemplate.opsForValue().get(REDIS_EMAIl_PREFIX + email);
        }
    
        // 인증이 완료되었을 경우 메모리 관리를 위해 인증번호 삭제
        public void removeCodeCertification(String email){
            stringRedisTemplate.delete(REDIS_EMAIl_PREFIX + email);
        }
    
        // Redis에 이메일(KEY)로 저장된 인증번호(VALUE)가 존재하는지 확인
        public boolean hasKey(String email){
            return stringRedisTemplate.hasKey(REDIS_EMAIl_PREFIX + email);
        }
    }

    StringRedisTemplate를 주입 받음으로써 redis와 연동할 수 있다.

    StringRedisTemplate에 대한 정보는 추후에 작성하겠다.

  2. EmailService 부분 리팩토링

    public SendEmailResponse sendSejongEmail(SendEmailRequest sendEmailRequest, HttpServletRequest request) throws MessagingException {
            String authCode = getAuthCode();
            sendEmail(sendEmailRequest.getEmail(), authCode);
            createCodeInRedis(sendEmailRequest.getEmail() + "@sju.ac.kr", authCode);
            //setSession(request, authCode);
            return SendEmailResponse.of(sendEmailRequest.getEmail());
    }
    
    public void createCodeInRedis(String email, String authCode){
            emailCertificationDao.createCodeCertification(email, authCode);
    }

    getAuthCode() 메소드로 인증번호 난수를 생성하고

    controller에서 sendSejongEmail을 호출하면 sendEmail() 메소드를 통해 이메일을 보낸 후

    setSession() 메소드를 통해 HttpSession을 만들어줘서 인증번호를 저장했었는데

    setSession()을 지우고 createCodeInRedis()를 호출함으로써 이메일과 인증번호를 저장하게끔 설정했다.

  3. 테스트

    package com.example.testlocal.module.user.domain.repository;
    
    import org.junit.jupiter.api.AfterEach;
    import org.junit.jupiter.api.Assertions;
    import org.junit.jupiter.api.DisplayName;
    import org.junit.jupiter.api.Test;
    import org.junit.jupiter.api.extension.ExtendWith;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.boot.test.context.SpringBootTest;
    import org.springframework.data.redis.core.StringRedisTemplate;
    import org.springframework.test.context.junit.jupiter.SpringExtension;
    import org.springframework.test.context.web.WebAppConfiguration;
    
    import java.time.LocalDateTime;
    
    import static org.assertj.core.api.Assertions.assertThat;
    import static org.junit.jupiter.api.Assertions.*;
    
    @WebAppConfiguration
    @SpringBootTest
    class EmailCertificationDaoTest {
        @Autowired
        private EmailCertificationDao emailCertificationDao;
    
        private final String email = "tovbsvb@sju.ac.kr";
    
        @AfterEach
        public void tearDown() throws Exception {
            emailCertificationDao.removeCodeCertification(email);
        }
    
        @DisplayName("기본_등록_조회기능")
        @Test
        public void createCodeCertification() {
            //given
            emailCertificationDao.createCodeCertification(email, "12345");
            assertThat(emailCertificationDao.getCodeCertification(email)).isEqualTo("12345");
        }
    }
  4. 결과

성공한 모습을 볼 수 있다.

0개의 댓글