웹 서비스에서 사용자 인증은 중요한 보안 요소 중 하나다. 특히 회원가입 시 휴대폰 인증을 추가하면 불법적인 가입을 방지하고 계정을 안전하게 보호할 수 있다. React와 Spring Boot를 활용하여 휴대폰 인증 기능을 구현했다.
- React: 사용자가 휴대폰 번호를 입력하고, 인증번호 요청 및 검증 UI 구현
- Spring Boot: 인증번호를 생성하고, SMS로 전송한 후 사용자가 입력한 코드가 올바른지 검증
이제 구체적인 구현 방법을 코드와 함께 정리해보겠다.
React: 클라이언트 사이드 인증 요청 및 검증
React에서는 휴대폰 인증 UI를 구성하고, Axios를 사용해 Spring Boot 서버에 요청을 보냈다.
1. 휴대폰 번호 입력 및 인증번호 요청
사용자가 휴대폰 번호를 입력하고 ‘인증번호 요청’ 버튼을 누르면, React는 서버에 인증번호 요청 API를 호출한다.
// 인증번호 요청
const handleRequestCode = () => {
if (!phoneNumber) {
alert("휴대폰 번호를 입력해주세요.");
return;
}
axios.get(`${process.env.REACT_APP_API_URL}/api/check/phonenumber`, {
params: { phone_number: phoneNumber },
})
.then((response) => {
if (response.data.result !== "success") {
alert("이미 사용 중인 전화번호입니다.");
return;
}
axios.post(`${process.env.REACT_APP_API_URL}/api/auth/send/code`, {
phone_number: phoneNumber
})
.then((response) => {
if (response.data.result === "success") {
alert("인증번호가 발송되었습니다.");
setIsVerificationInputVisible(true);
} else {
alert("인증번호 발송에 실패했습니다.");
}
});
})
.catch((error) => console.error("전화번호 중복 확인 실패:", error));
};
- 전화번호 중복 확인 → 이미 가입된 번호인지 서버에서 체크
- SMS 전송 API 호출 → 중복이 없을 경우 인증번호를 생성하고 전송 요청
- 인증번호 입력 필드 활성화 → 인증번호 입력칸을 보이도록 변경
2. 인증번호 검증
사용자가 인증번호를 입력하고 ‘인증번호 확인’ 버튼을 누르면, 입력값을 서버로 전송하여 검증한다.
// 인증번호 검증
const handleVerifyCode = () => {
if (!inputCode) {
alert("인증번호를 입력해주세요.");
return;
}
axios.post(`${process.env.REACT_APP_API_URL}/api/auth/verify/code`, {
phone_number: phoneNumber,
code: inputCode
})
.then((response) => {
if (response.data.result === "success") {
alert("인증이 완료되었습니다!");
setIsPhoneVerified(true);
} else {
alert("인증번호가 일치하지 않습니다.");
}
})
.catch((error) => console.error(error));
};
- 입력된 인증번호를 서버로 전송하여 검증
- 일치하면 인증 성공 상태(setIsPhoneVerified) 변경
Spring Boot: 인증번호 생성, SMS 전송 및 검증
Spring Boot에서는 Twilio API를 사용하여 인증번호를 SMS로 전송하고, 사용자가 입력한 코드가 올바른지 확인했다.
1. 인증번호 전송 API (UserController)
SmsService의 sendVerificationCode()를 호출해 인증번호 생성 및 SMS 전송을 수행한다.
@PostMapping("/api/auth/send/code")
public JsonResult sendCode(@RequestBody JuUserVo juUserVo) {
String phoneNumber = juUserVo.getPhone_number();
if (phoneNumber == null || phoneNumber.isEmpty()) {
return JsonResult.fail("휴대폰 번호를 입력해주세요.");
}
boolean isSent = smsService.sendVerificationCode(phoneNumber);
return isSent ? JsonResult.success("인증번호가 전송되었습니다.") : JsonResult.fail("인증번호 전송 실패");
}
2. 인증번호 생성 및 SMS 전송 (SmsService)
사용자에게 인증번호를 포함한 SMS를 전송한다.
public boolean sendVerificationCode(String phoneNumber) {
String formattedPhoneNumber = formatPhoneNumber(phoneNumber);
String verificationCode = generateVerificationCode();
storeVerificationCode(formattedPhoneNumber, verificationCode);
return sendSms(formattedPhoneNumber, "인증번호는 " + verificationCode + " 입니다.");
}
- 전화번호를 국제 형식으로 변환 후 6자리 인증번호를 생성
- 인증번호 저장 후 Twilio API를 통해 SMS 전송
3. 인증번호 검증 API (UserController)
JuSmsService의 verifyCode()를 호출해 사용자가 입력한 코드가 올바른지 확인한다.
@PostMapping("/api/auth/verify/code")
public JsonResult verifyCode(@RequestBody JuUserVo juUserVo) {
String phoneNumber = juUserVo.getPhone_number();
String inputCode = juUserVo.getCode();
if (phoneNumber == null || inputCode == null) {
return JsonResult.fail("휴대폰 번호와 인증번호를 입력해주세요.");
}
boolean isVerified = smsService.verifyCode(phoneNumber, inputCode);
return isVerified ? JsonResult.success("인증이 완료되었습니다.") : JsonResult.fail("인증번호가 일치하지 않습니다.");
}
4. 인증번호 검증 (SmsService)
사용자가 입력한 인증번호와 저장된 코드를 비교하고 일치하면 인증 성공 및 코드 삭제한다.
public boolean verifyCode(String phoneNumber, String inputCode) {
String storedCode = verificationCodeStorage.get(formatPhoneNumber(phoneNumber));
if (storedCode != null && storedCode.equals(inputCode)) {
verificationCodeStorage.remove(phoneNumber);
return true;
}
return false;
}
마무리
이번 개발을 통해 React와 Spring Boot를 활용한 휴대폰 인증 시스템 구축을 경험할 수 있었다.
하지만 아직 부족한 점이 있어 몇 가지 개선이 필요하다.
향후 개선 방향
- 인증번호 만료 시간 적용: 일정 시간이 지나면 자동 만료되도록 설정
- 인증번호 요청 횟수 제한: 과도한 요청을 방지하기 위한 제한 적용
- 다른 SMS 서비스 테스트: Twilio 외의 서비스 비교 및 검토
'SpringBoot' 카테고리의 다른 글
[SpringBoot]AWS S3를 활용한 파일 업로드 구현하기 (0) | 2025.02.28 |
---|---|
[SpringBoot] Twilio를 활용한 기념일 알림 기능 개발 (0) | 2025.02.23 |
[SpringBoot] Spring Boot + React를 활용한 OAuth 2.0 로그인 구현 (카카오 기준) (0) | 2025.02.15 |
[SpringBoot] jsp 만들기 (0) | 2025.02.10 |
[SpringBoot] SpringBoot 설치부터 프로젝트 생성, 의존성 추가까지 (0) | 2025.02.09 |