인증번호와 같은 임시 데이터를 처리할 때 데이터베이스(DB)와 인메모리 데이터베이스(Redis) 사이에서 선택하는 것은 여러 요소를 고려해야 합니다. 여러분이 언급한 대로, 전통적인 관계형 데이터베이스를 사용하여 임시 데이터를 저장하고, 예약 작업(스케줄러)을 통해 만료된 데이터를 정리하는 방법도 가능합니다. 하지만, Redis 같은 인메모리 데이터베이스를 사용하는 것이 여러 이유로 더 효율적일 수 있습니다:
- 응답 속도: Redis와 같은 인메모리 데이터베이스는 메모리 기반으로 동작하기 때문에, 디스크 기반의 데이터베이스보다 데이터 접근 속도가 훨씬 빠릅니다. 인증번호 검증과 같은 빈번하고 빠른 응답이 필요한 작업에 적합합니다.
- 데이터 만료 처리: Redis는 EXPIRE 명령을 통해 키에 만료 시간을 설정할 수 있어, 설정한 시간이 지나면 자동으로 데이터를 삭제합니다. 이 기능은 임시 데이터를 자동으로 관리하는 데 매우 유용하며, 별도의 스케줄러 설정 없이도 데이터의 생명주기를 관리할 수 있습니다.
- 자원 사용 효율성: 임시 데이터를 관리하기 위해 별도의 데이터베이스 테이블을 유지하고, 스케줄러를 동작시키는 것은 서버 자원과 관리 측면에서 부담이 될 수 있습니다. Redis를 사용하면 이러한 관리가 간소화되어 시스템 자원을 보다 효율적으로 사용할 수 있습니다.
- 단순성과 유지 보수: Redis를 사용하면 복잡한 쿼리를 작성하거나, 데이터베이스 스키마를 변경하는 일 없이 간단하게 데이터를 저장하고 조회할 수 있습니다. 이는 개발 및 유지보수 과정을 간결하게 만들어 줍니다.
그렇다고 해서 모든 임시 데이터를 Redis에 저장해야 하는 것은 아닙니다. 데이터의 양, 요구되는 처리 속도, 기존 인프라와의 통합 등 다양한 요소를 고려해 결정해야 합니다. 만약 이미 관계형 데이터베이스가 구축되어 있고, 속도나 자원 문제가 크지 않다면 스케줄러를 통한 데이터 만료 처리 방식도 충분히 효과적일 수 있습니다. 그러나 효율성과 성능을 최우선으로 고려한다면, Redis 사용이 더 적합할 수 있습니다.
Google Setting
Build Gradle
// google email certification
implementation 'org.springframework.boot:spring-boot-starter-mail'
Dto
@Data
public class EmailCheckDto {
@Email
@NotEmpty(message = "이메일을 입력해 주세요")
private String email;
@NotEmpty(message = "인증 번호를 입력해 주세요")
private String authNum;
}
@Getter
@Setter
public class EmailRequestDto {
@Email
@NotEmpty(message = "이메일을 입력해 주세요")
private String email;
}
Controller
@RestController
@RequestMapping("/user")
@RequiredArgsConstructor
public class UserController {
private final UserService userService;
@PostMapping ("/email/send")
public String mailSend(@RequestBody @Valid EmailRequestDto emailDto){
System.out.println("이메일 인증 이메일 :"+emailDto.getEmail());
return userService.joinEmail(emailDto.getEmail());
}
@PostMapping("/email/check")
public String AuthCheck(@RequestBody @Valid EmailCheckDto emailCheckDto){
Boolean Checked = userService.checkAuthNum(emailCheckDto.getEmail(),emailCheckDto.getAuthNum());
if(Checked){
return "ok";
}
else{
throw new NullPointerException("뭔가 잘못!");
}
}
}
Service
@Transactional
@RequiredArgsConstructor
@Service
@Slf4j
public class UserService {
private final UserRepository userRepository;
private final BCryptPasswordEncoder bCryptPasswordEncoder;
private final RedisUtil redisUtil;
private final JavaMailSender mailSender;
private int authNumber;
//임의의 6자리 양수를 반환합니다.
public void makeRandomNumber() {
Random r = new Random();
String randomNumber = "";
for(int i = 0; i < 6; i++) {
randomNumber += Integer.toString(r.nextInt(10));
}
this.authNumber = Integer.parseInt(randomNumber);
}
//mail을 어디서 보내는지, 어디로 보내는지 , 인증 번호를 html 형식으로 어떻게 보내는지 작성합니다.
public String joinEmail(String email) {
makeRandomNumber();
String setFrom = "dionisos198@naver.com"; // email-config에 설정한 자신의 이메일 주소를 입력
String toMail = email;
String title = "회원 가입 인증 이메일 입니다."; // 이메일 제목
String content =
"나의 APP을 방문해주셔서 감사합니다." + //html 형식으로 작성 !
"<br><br>" +
"인증 번호는 " + authNumber + "입니다." +
"<br>" +
"인증번호를 제대로 입력해주세요"; //이메일 내용 삽입
mailSend(setFrom, toMail, title, content);
return Integer.toString(authNumber);
}
//이메일을 전송합니다.
public void mailSend(String setFrom, String toMail, String title, String content) {
MimeMessage message = mailSender.createMimeMessage();//JavaMailSender 객체를 사용하여 MimeMessage 객체를 생성
try {
MimeMessageHelper helper = new MimeMessageHelper(message,true,"utf-8");//이메일 메시지와 관련된 설정을 수행합니다.
// true를 전달하여 multipart 형식의 메시지를 지원하고, "utf-8"을 전달하여 문자 인코딩을 설정
helper.setFrom(setFrom);//이메일의 발신자 주소 설정
helper.setTo(toMail);//이메일의 수신자 주소 설정
helper.setSubject(title);//이메일의 제목을 설정
helper.setText(content,true);//이메일의 내용 설정 두 번째 매개 변수에 true를 설정하여 html 설정으로한다.
mailSender.send(message);
} catch (MessagingException e) {//이메일 서버에 연결할 수 없거나, 잘못된 이메일 주소를 사용하거나, 인증 오류가 발생하는 등 오류
// 이러한 경우 MessagingException이 발생
e.printStackTrace();//e.printStackTrace()는 예외를 기본 오류 스트림에 출력하는 메서드
}
redisUtil.setDataExpire(Integer.toString(authNumber),toMail,60*5L);
}
public boolean checkAuthNum(String email,String authNum){
System.out.println(authNum);
System.out.println(email);
if(redisUtil.getData(authNum)==null){
return false;
}
else if(redisUtil.getData(authNum).equals(email)){
return true;
}
else{
return false;
}
}
}
EmailConfig
import java.util.Properties;
@Configuration
public class EmailConfig {
@Bean
public JavaMailSender mailSender() {//JAVA MAILSENDER 인터페이스를 구현한 객체를 빈으로 등록하기 위함.
JavaMailSenderImpl mailSender = new JavaMailSenderImpl();//JavaMailSender 의 구현체를 생성하고
mailSender.setHost("smtp.gmail.com");// 속성을 넣기 시작합니다. 이메일 전송에 사용할 SMTP 서버 호스트를 설정
mailSender.setPort(587);// 587로 포트를 지정
mailSender.setUsername("");//구글계정을 넣습니다.
mailSender.setPassword("");//구글 앱 비밀번호를 넣습니다.
Properties javaMailProperties = new Properties();//JavaMail의 속성을 설정하기 위해 Properties 객체를 생성
javaMailProperties.put("mail.transport.protocol", "smtp");//프로토콜로 smtp 사용
javaMailProperties.put("mail.smtp.auth", "true");//smtp 서버에 인증이 필요
javaMailProperties.put("mail.smtp.socketFactory.class", "javax.net.ssl.SSLSocketFactory");//SSL 소켓 팩토리 클래스 사용
javaMailProperties.put("mail.smtp.starttls.enable", "true");//STARTTLS(TLS를 시작하는 명령)를 사용하여 암호화된 통신을 활성화
javaMailProperties.put("mail.debug", "true");//디버깅 정보 출력
javaMailProperties.put("mail.smtp.ssl.trust", "smtp.naver.com");//smtp 서버의 ssl 인증서를 신뢰
javaMailProperties.put("mail.smtp.ssl.protocols", "TLSv1.2");//사용할 ssl 프로토콜 버젼
mailSender.setJavaMailProperties(javaMailProperties);//mailSender에 우리가 만든 properties 넣고
return mailSender;//빈으로 등록한다.
}
}
Redis application.yml
spring:
data:
redis:
host: localhost
port: 6379
Build.gradle
// redis
implementation 'org.springframework.boot:spring-boot-starter-data-redis'
RedisUtil
@Service
@RequiredArgsConstructor
public class RedisUtil {
private final StringRedisTemplate redisTemplate;//Redis에 접근하기 위한 Spring의 Redis 템플릿 클래스
public String getData(String key){//지정된 키(key)에 해당하는 데이터를 Redis에서 가져오는 메서드
ValueOperations<String,String> valueOperations=redisTemplate.opsForValue();
return valueOperations.get(key);
}
public void setData(String key,String value){//지정된 키(key)에 값을 저장하는 메서드
ValueOperations<String,String> valueOperations=redisTemplate.opsForValue();
valueOperations.set(key,value);
}
public void setDataExpire(String key,String value,long duration){//지정된 키(key)에 값을 저장하고, 지정된 시간(duration) 후에 데이터가 만료되도록 설정하는 메서드
ValueOperations<String,String> valueOperations=redisTemplate.opsForValue();
Duration expireDuration=Duration.ofSeconds(duration);
valueOperations.set(key,value,expireDuration);
}
public void deleteData(String key){//지정된 키(key)에 해당하는 데이터를 Redis에서 삭제하는 메서드
redisTemplate.delete(key);
}
}
'redis' 카테고리의 다른 글
[Redis] Redis - Docker 설치 (0) | 2024.07.02 |
---|---|
[Redis] Redis 란? (1) | 2024.07.02 |
[Redis] Redis 세팅 및 명령어 (0) | 2024.06.27 |