Twilio를 이용한 SMS 인증 구현-준비

Odyssey·2025년 6월 25일
0

Next.js_study

목록 보기
46/58
post-thumbnail

2025.6.26 목요일의 공부기록

이번 글에서는 Next.js 애플리케이션에서 Twilio와 crypto 모듈을 활용하여 SMS 인증 기능을 구현한 내용을 다룬다.


📌 Twilio란?

Twilio는 SMS, 음성, 영상, 이메일 등 다양한 통신 서비스를 제공하는 클라우드 기반 플랫폼이다. 특히 SMS 서비스를 통해 개발자가 간편하게 문자 메시지를 전송하고 수신할 수 있도록 API를 제공한다.

🔗 Twilio 공식 웹사이트


SMS 인증 토큰 생성하기

SMS 인증에서 사용하는 토큰(인증 번호)은 중복되지 않고 예측 불가능한 랜덤 숫자로 만들어져야 한다. 이를 위해 Node.js의 내장 모듈인 cryptorandomInt(min, max) 메서드를 사용했다.

import crypto from "crypto";

async function getToken() {
  const token = crypto.randomInt(100000, 999999).toString(); // 6자리 랜덤 숫자 생성

  // 생성된 토큰이 이미 존재하는지 확인하여 중복 방지
  const existingToken = await db.sMSToken.findUnique({
    where: {
      token,
    },
    select: {
      id: true,
    },
  });
  if (existingToken) {
    // 중복된 토큰이라면 재귀적으로 새 토큰 생성
    return getToken();
  }

  return token;
}
  • crypto.randomInt(min, max)minmax 사이의 랜덤 정수를 반환한다.
  • 생성된 토큰이 DB에 이미 존재하면 재귀적으로 함수를 다시 호출해 중복 방지 처리를 한다.

🔗 Node.js crypto.randomInt 문서


actions.ts

사용자 인증 토큰 발급 및 저장

사용자가 인증을 요청하면 다음과 같은 프로세스가 진행된다:

  1. 기존에 해당 번호로 발급된 모든 SMS 토큰을 DB에서 삭제.
  2. 새 인증 토큰을 생성하고 사용자와 연결하여 DB에 저장.
  3. Twilio를 사용하여 생성된 토큰을 사용자의 휴대전화로 전송.

구체적인 구현 코드:

...
export async function smsLogIn(prevState: ActionState, formData: FormData) {
  const phone = formData.get("phone");
  const token = formData.get("token");

  if (!prevState.token) {
    const result = phoneSchema.safeParse(phone);
    if (!result.success) {
      return { token: false, error: result.error.flatten() };
    } else {
      // delete previous token
      await db.sMSToken.deleteMany({
        where: {
          user: {
            phone: result.data,
          },
        },
      });
      // create new token

      const token = await getToken();
      await db.sMSToken.create({
        data: {
          token,
          user: {
            connectOrCreate: {
              where: {
                phone: result.data,
              },
              create: {
                phone: result.data,
                username: crypto.randomBytes(10).toString("hex"),
              },
            },
          },
        },
      });
      // send token to phone using twilio
      return { token: true };
    }
  } else {
    const result = tokenSchema.safeParse(token);
    if (!result.success) {
      return {
        token: true,
        error: result.error.flatten(),
      };
    } else {
      redirect("/");
    }
  }
}

추가사항

  • 이전에 구현한 Zod를 사용하여 휴대폰 번호 형식을 검증하는 로직은 그대로 이미 적용되어 있다.
  • 사용자가 인증을 요청할 때마다 기존 토큰을 삭제하여 중복 방지와 보안을 유지한다.
  • connectOrCreate를 통해 사용자 정보가 없다면 자동으로 사용자 데이터를 생성한다. (username은 랜덤으로 생성됨)

SMS 토큰 인증 플로우 정리

단계설명비고
1클라이언트가 전화번호 입력 후 SMS 인증 요청전화번호 형식 검증
2기존 발급된 토큰 삭제중복 인증 방지
3새로운 토큰 생성 및 저장중복 검사 수행
4Twilio로 토큰 전송사용자에게 SMS 발송
5사용자로부터 입력받은 토큰 검증별도 검증 로직 필요
  • Twilio와 crypto.randomInt를 활용해 안전한 SMS 인증을 구현할 수 있다.
  • Zod를 사용하여 데이터의 유효성을 철저히 관리한다.
  • 인증 요청 시 기존의 SMS 인증 데이터를 삭제하고 새로운 데이터를 생성하여 보안을 유지한다.
  • Twilio API를 통해 실제 SMS를 전송하여 인증을 완료한다.

이 글을 기반으로 Next.js 프로젝트에 강력한 SMS 인증 기능을 손쉽게 추가할 수 있을 것이다.

0개의 댓글