비트베이크

[T3 Stack] 서류 없이 5분 만에 Next.js + tRPC SMS 본인인증 구현하기 (1인 개발자 추천)

2026-05-30T01:02:20.456Z

Hooded figure with digital code for a face, representing digital security and development.

사이드 프로젝트나 MVP를 개발할 때 가장 답답한 순간은 언제일까요? 바로 'SMS 본인인증'을 연동할 때입니다. 국내 대부분의 SMS API 서비스는 사업자등록증통신서비스 이용증명원 제출을 필수로 요구합니다. 1인 개발자나 아이디어를 빠르게 테스트해보고 싶은 팀에게는 시작부터 큰 진입장벽이 되죠.

이 글에서는 **서류 없이 5분 만에 연동 가능한 EasyAuth(이지어스)**를 활용하여, 최근 인기 있는 T3 Stack (Next.js + tRPC) 환경에서 SMS 인증을 구현하는 방법을 알아봅니다.

왜 EasyAuth를 선택해야 할까요?

  • 서류 전면 면제: 사업자등록증, 이용증명원 없이 즉시 가입 및 사용
  • 발신번호 자동 할당: 번호 사전 등록을 위해 통신사를 거칠 필요 없음
  • 간결한 구조: POST /send, POST /verify 두 개의 API로 끝
  • 합리적인 가격: 건당 15~25원으로 기존(30~50원) 대비 절반 수준, 가입 시 10건 무료 제공

이제 본격적으로 T3 Stack에 EasyAuth를 붙여보겠습니다.

1. tRPC 라우터 설정 (Backend)

T3 Stack에서는 별도의 API 라우트를 만들 필요 없이 tRPC의 Mutation을 사용합니다. 서버의 인증 로직을 담당할 src/server/api/routers/sms.ts 파일을 생성합니다.

import { z } from "zod";
import { createTRPCRouter, publicProcedure } from "~/server/api/trpc";

// EasyAuth API URL 설정
const EASYAUTH_API_URL = "https://api.easyauth.co.kr";
const API_KEY = process.env.EASYAUTH_API_KEY!;

export const smsRouter = createTRPCRouter({
  // 1. 인증번호 발송 (Send)
  sendOtp: publicProcedure
    .input(z.object({ phoneNumber: z.string().min(10) }))
    .mutation(async ({ input }) => {
      const response = await fetch(`${EASYAUTH_API_URL}/send`, {
        method: "POST",
        headers: {
          "Content-Type": "application/json",
          "Authorization": `Bearer ${API_KEY}`,
        },
        body: JSON.stringify({ to: input.phoneNumber }),
      });

      if (!response.ok) throw new Error("SMS 발송에 실패했습니다.");
      return { success: true, message: "인증번호가 발송되었습니다." };
    }),

  // 2. 인증번호 검증 (Verify)
  verifyOtp: publicProcedure
    .input(z.object({ 
      phoneNumber: z.string(),
      code: z.string().length(6) 
    }))
    .mutation(async ({ input }) => {
      const response = await fetch(`${EASYAUTH_API_URL}/verify`, {
        method: "POST",
        headers: {
          "Content-Type": "application/json",
          "Authorization": `Bearer ${API_KEY}`,
        },
        body: JSON.stringify({ 
          to: input.phoneNumber,
          code: input.code 
        }),
      });

      if (!response.ok) throw new Error("인증번호가 일치하지 않습니다.");
      return { success: true, message: "인증이 완료되었습니다." };
    }),
});

작성한 라우터를 src/server/api/root.ts의 메인 라우터에 추가해줍니다.

2. 프론트엔드 연동 (Frontend)

이제 Next.js 클라이언트 컴포넌트에서 tRPC 훅을 이용해 UI를 구성합니다. 상태 관리는 React의 기본 Hook을 사용했습니다.

import { useState } from "react";
import { api } from "~/utils/api";

export default function SmsAuth() {
  const [phoneNumber, setPhoneNumber] = useState("");
  const [code, setCode] = useState("");
  const [isSent, setIsSent] = useState(false);

  const sendOtpMutation = api.sms.sendOtp.useMutation({
    onSuccess: () => setIsSent(true),
    onError: (err) => alert(err.message),
  });

  const verifyOtpMutation = api.sms.verifyOtp.useMutation({
    onSuccess: () => alert("본인인증 성공!"),
    onError: (err) => alert(err.message),
  });

  const handleSend = () => sendOtpMutation.mutate({ phoneNumber });
  const handleVerify = () => verifyOtpMutation.mutate({ phoneNumber, code });

  return (
    <div>
      <h2>휴대폰 본인인증</h2>
      
      <div>
         setPhoneNumber(e.target.value)}
          disabled={isSent}
          className="flex-1 border p-2 rounded"
        /&gt;
        
          {isSent ? "재발송" : "인증번호 받기"}
        
      </div>

      {isSent &amp;&amp; (
        <div>
           setCode(e.target.value)}
            className="flex-1 border p-2 rounded"
          /&gt;
          
            확인
          
        </div>
      )}
    </div>
  );
}

마치며

복잡한 서류 작업이나 통신사 심사 없이, 단 2개의 API (/send, /verify)와 T3 Stack의 결합으로 순식간에 SMS 본인인증을 구현해보았습니다. 데이터베이스에 인증번호를 저장하고 만료 시간을 체크하는 등의 귀찮은 백엔드 로직조차 EasyAuth API가 모두 알아서 처리해줍니다.

토이 프로젝트나 MVP 개발을 진행 중이라면, **서류 없이 5분 만에 시작할 수 있는 EasyAuth(이지어스)**를 도입해보세요. 가입 즉시 테스트 가능한 10건의 무료 크레딧이 제공되며, 이후에도 건당 15~25원의 비용으로 서비스 유지가 가능합니다. 지금 바로 경험해보세요!

비트베이크에서 광고를 시작해보세요

광고 문의하기

다른 글 보기

2026-06-04T01:04:15.823Z

The 2026 E-Commerce New Product Launch Survival Formula: Dominating Platform Search Rankings in 7 Days via Reward-Based Trials and Purchase Verification

2026-06-04T01:04:15.800Z

2026 이커머스 신제품 론칭 생존 공식: 리워드형 체험단과 구매 인증으로 7일 만에 플랫폼 검색 랭킹 장악하기

2026-06-01T01:01:58.264Z

Surviving the 2026 Cookieless Era for B2C: Building Zero-Party Data with Reward-Based Quiz Marketing

2026-06-01T01:01:58.231Z

2026 쿠키리스 시대의 B2C 생존법: 리워드 기반 퀴즈 마케팅으로 제로파티 데이터 구축하기

서비스

피드자주 묻는 질문고객센터

문의

비트베이크

레임스튜디오 | 사업자 등록번호 : 542-40-01042

경기도 남양주시 와부읍 수례로 116번길 16, 4층 402-제이270호

트위터인스타그램네이버 블로그