문자 보내기는 아주 간단하다. Twilio
에서 제공해주는 테스트 코드만 따라해도 바로 보내기가 가능하다.
const Twilio = require('./admin').Twilio;
const twilio = require('twilio')(Twilio.account_sid, Twilio.auth_token);
await twilio.messages.create({
body: 'blah blah', // 문자로 보내고 싶은 내용
from: '-', // 위에서 발급 받은 전화번호
to: '-' // 받을 전화번호
}, function (err, message) {
if (err) console.log(err);
else console.log(message.sid);
});
이렇게 작성하고 실행만 하면 문자가 잘 보내진다.
넣고 싶은 적절한 라우터에 넣어주면 된다. 나는 문자 인증용 라우터를 따로 만들었다.
이제 문자 보내기는 완성 됐으니 SMS 인증 코드를 작성해보자!
인증 코드를 저장해야 사용자가 맞게 입력했는지, 아닌지를 확인할 수 있을텐데 어디에 저장해야 할지 고민이 많았다.
살펴본 바로 이렇게 4가지가 주로 사용되는 것 같았다.
나는 이 글을 보고 DB에 저장하기로 결정했다. (DB가 더 낫지 않냐는 추천도 받았고!)
이렇게 세 가지를 저장하는 DB 테이블을 하나 만들어 사용하기로 했다.
const Twilio = require('./admin').Twilio;
const twilio = require('twilio')(Twilio.account_sid, Twilio.auth_token);
app.post('/phone_check', async (req, res) => {
const body = req.body;
const phone_number = body.phone_number;
let code = '';
// 랜덤으로 4자리 인증 코드를 만든다.
for (let i = 0; i < 4; i++) code += Math.floor(Math.random() * 10);
try {
const [result] = await db.execute(`INSERT INTO sms_validation(phone_number, validation_code, expire)
VALUES (?, ?, NOW() + INTERVAL 3 MINUTE) ON DUPLICATE KEY
UPDATE validation_code = ?, expire = NOW() + INTERVAL 3 MINUTE`,
[phone_number, code, code]);
} catch (e) {
console.log(e);
}
await twilio.messages.create({
body: `${code}`, // 문자로 보내고 싶은 내용
from: '-', // 위에서 발급 받은 전화번호
to: '-' // 받을 전화번호
}, function (err, message) {
if (err) console.log(err);
else console.log(message.sid);
});
})
고민했던 부분은 사용자가 문자 인증을 여러 번 시도할 수 있기 때문에 DB에 계속 업데이트를 해야 됐는데, 이미 존재한다면 UPDATE를 존재하지 않는다면 CREATE를 하는 MySQL 구문이 있나? 싶었다. 찾아보니 있더라!
db.execute(`INSERT INTO sms_validation(phone_number, validation_code, expire)
VALUES (?, ?, NOW() + INTERVAL 3 MINUTE) ON DUPLICATE KEY
UPDATE validation_code = ?, expire = NOW() + INTERVAL 3 MINUTE`,
[phone_number, code, code]);
이렇게 ON DUPLICATE KEY
를 사용해주면 가능했다.
참고로 나는 인증 제한 시간을 3분으로 뒀기 때문에 3 MINUTE
를 추가했지만 원하는 만큼 자유롭게 바꿔서 사용하면 되겠다.
app.post('/phone_check/verify', async (req, res) => {
const body = req.body;
const code = body.verify_code;
const phone_number = body.phone_number;
let phone_valid = false;
try {
const [result, field] = await db.execute(`SELECT *
FROM sms_validation
WHERE phone_number = ?`, [phone_number]);
// JS의 Date 객체로 변환
const expire_time = new Date(result[0].expire);
const now = Date.now();
// 인증코드와 유효시간 모두 검사
if (code === result[0].validation_code && expire_time > now) {
phone_valid = true;
}
res.send({phone_valid: phone_valid});
} catch (e) {
console.log(e);
}
})
이렇게 해주면 코드의 완성이다. 테스트로 3분 후에 입력해봤더니 인증이 되지 않게끔 잘 구현됐다.