Ajax를 이용한 휴대폰 SMS인증

민성재·2022년 2월 20일
0

Ajax란?

Ajax란 Asynchronous JavaScript and XML의 약자
Asynchronous는 비동기라는 의미인데, 기존의 동기 방식은 웹페이지를 리로드하여 데이터를 전부 받아오는 방식이지만 비동기는 리로드없이 원하는 데이터만 불러오는 방식이다.

즉, 다른 프로세스들의 업무 처리 순서와 관계없이 원하는 시점에 원하는 데이터를 낭비없이 보여준다는 것에서 큰 장점을 가진다.

물론 단점도 존재한다. 히스토리 관리가 되지않으며 페이지 이동없는 통신은 보안상의 문제가 있다.
또한 지원하는 Charset 도 한정되어있다.

휴대폰 SMS 인증 개발

관리하는 홈페이지의 마이페이지에서 휴대폰 SMS 인증 기능이 추가되어야 된다는 요청을 받았고 이를 개발하면서 배우고 공부했던 것을 정리 해두려고 한다.

위의 사진과 같이 사용자가 입력한 휴대폰 번호로 6자리의 난수로 만들어진 인증번호를 발송하고,
사용자가 홈페이지에 입력한 인증번호가 유효한지 검사하는 로직을 만들어야했다.

이를 위해 먼저 마이페이지의 UI를 간단하게 수정했다. 휴대폰 번호 input 태그 옆에 '인증하기'
버튼
을 추가했고, 사용자가 '인증번호를 적을 input 태그', '확인'버튼을 통해 유효한지 검사하기로 했다.

그리고 데이터베이스에 sms 인증에 필요한 테이블을 만들었다. 테이블을 이루는 칼럼은 4개로 구성했다.

1. 회원 아이디
2. 사용자 휴대폰번호
3. 랜덤 6자리 숫자(인증번호)
4. '인증하기' 버튼을 누른 시간

백엔드는 2가지 api로 구성했는데,

1. 사용자가 '인증하기' 버튼을 누르면 ajax로 받은 데이터로 사용자에게 인증번호를 보내는 기능
2. 사용자가 '확인' 버튼을 누르면 ajax로 받은 데이터로 유효한지 검사하는 기능이다.

그리고 프론트에서 '인증하기' 버튼을 누르면 회원 아이디는 로그인 되어있는 Session에서 뽑고, 사용자가 입력한 휴대전화 번호는 jquery를 이용해 $('#user_input_cellNum').val(); 와 같이 뽑았다.이 값을 쿼리스트링으로 만들어 백엔드로 보냈다.

이 api 함수에서는 회원 아이디, 사용자 휴대전화 번호를 프론트에서 ajax로 받고 6자리 랜덤 난수와 '인증하기' 버튼 누른 시간은 DB에서 생성했다.

SELECT ROUND (DBMS_RANDOM.VALUE (100000, 999999)) FROM DUAL;

이 쿼리를 사용하면 6자리 난수가 생성됨

'인증하기' 버튼을 누른 시간은 SYSDATE로 현재 날짜정보를 받아왔다.

그럼 이제 SMS인증 테이블에 필요한 4개의 칼럼이 준비됐다.
이 테이블에 4개의 값을 INSERT 해주었다.

그리고 회사에 이미 개발되어있던 SMS발송 함수를 조금 수정하여 사용자에게 직접 SMS 메시지를 보냈다.


다음은 사용자가 input 태그에 입력한 6자리 숫자와 DB에 저장된 6자리 난수가 동일한지, 유효시간 3분내에 '확인'을 눌렀는지 확인해야한다.

먼저 프론트에 '인증하기' 버튼을 누르면 유효시간 3분을 보여주는 타이머를 만들었다.

출처 : https://developer0809.tistory.com/149


이 블로그에 있는 타이머를 조금 수정해 썼다. 특정 버튼이 눌리면 유효시간을 설정하고
setInterval 함수를 1000ms (1초) 마다 반복 실행하여
03:00 -> 02:59 ... 이렇게 보여주고 3분이 지나면 시간초과라는 글씨가 뜨도록 하는 기능이다.

이제 '확인' 버튼을 누르면 회원아이디, 사용자 휴대폰번호, 사용자가 입력한 인증번호 3가지 정보를 ajax로 백엔드에 넘겨주었다.

백엔드에서는 DB 에서 회원아이디, 사용자 휴대폰번호를 조건으로, 가장 최근에 발송했던 6자리 난수를 SELECT 해온다.

SELECT RAND_NUM FROM SMS WHERE USER_ID = #ID# AND USER_CELL_NUM = #CELL_NUM#
ORDER BY SYSDATE DESC FETCH 1 ROW ONLY;

위와 비슷한 느낌으로 쿼리를 사용했던것 같다. 회원아이디, 휴대폰 번호로 조회하되 SYSDATE로 정렬하고 FETCH로 1개의 난수만 받아오도록 했다. (사용자가 여러번 반복해서 인증하기 버튼을 눌러 인증번호를 받을 수 있으므로)


이제 프론트에서 ajax로 받은 사용자가 입력한 인증번호와 위의 쿼리로 받아온 난수를 비교해야한다. 하지만 하나가 더 필요하다. 유효시간 3분내에 입력했는지를 알기 위해 아까 테이블에 '인증하기'버튼을 누른시간을 넣어뒀다.

그리고 지금은 '확인'버튼을 누른 시점이므로 테이블에서 '인증하기' 버튼을 누른시간을 SELECT 로 조회하고, 현재 시간인 SYSDATE와 비교하여 180초가 넘었는지 안 넘었는지를 확인해야한다.

3분이 넘지 않았으며 사용자 입력 인증번호와, 테이블에서 조회한 난수가 동일하다면 인증이 완료된것이다. 그렇다면 백엔드에서는 json.result 에 true라는 값을 담아 프론트에 보낸다.
프론트에서는 if(json.result)라면 '인증완료'라는 alert를 띄우는 식으로 개발했다.


자잘한 로직들과 디테일한 처리는 적지 않았지만 생각보다 신경써야할 것이 많았고
처음으로 회사에서 프론트, 백, 디비 사이클을 전부 도는 로직을 개발했기에 시간도 많이 걸렸던것 같다.

특히나 ajax 통신을 좀더 깊게 이해하고 jQuery를 유용하게 사용했다. 쿼리를 짜기 위해 고민하는 것도 나름대로 재밌었다.

profile
민성재 개발 블로그

1개의 댓글

comment-user-thumbnail
2022년 2월 22일

유익한 글 감사합니다~!

답글 달기