Next.js App Router로 5분 만에 SMS 본인인증 구현하기 (서류 제출 없음)
사이드 프로젝트에 SMS 인증을 붙이려다 포기하신 적 있나요?
토이 프로젝트나 스타트업 MVP를 개발할 때, 악성 유저를 막고 진짜 사용자를 구분하기 위해 휴대폰 SMS 본인인증은 필수적입니다. 하지만 막상 API를 찾아보면 시작부터 큰 벽에 부딪힙니다.
- "사업자등록증명원을 제출해 주세요."
- "통신서비스 이용증명원을 발급받아 오세요."
- "발신번호 사전등록이 필요합니다."
빠르게 가설을 검증해야 하는 1인 개발자나 사이드 프로젝트 팀에게 이런 복잡한 서류 작업은 너무 가혹합니다.
이 글에서는 복잡한 서류 제출 없이, 단 5분 만에 Next.js App Router 환경에서 SMS 인증을 구현하는 방법을 알아봅니다.
💡 왜 Next.js App Router인가요?
Next.js 13부터 도입된 App Router는 서버 사이드 로직(Route Handlers)과 클라이언트 컴포넌트를 아주 쉽게 분리할 수 있게 해줍니다. SMS 인증 번호 발송을 위한 API Key를 안전하게 서버에 숨기면서도, 사용자에게는 매끄러운 UI를 제공할 수 있습니다.
🛠️ 단계별 구현 가이드
SMS 인증 로직은 아주 단순합니다.
- 사용자가 번호를 입력하면 발송(Send)
- 사용자가 인증번호를 입력하면 검증(Verify)
이를 위해 두 개의 API 라우트와 하나의 클라이언트 컴포넌트를 만들어보겠습니다.
1. 인증번호 발송 API (Server)
먼저 app/api/auth/send/route.ts 파일을 생성합니다.
import { NextResponse } from 'next/server';
export async function POST(request: Request) {
try {
const { phone } = await request.json();
// 서류 없는 SMS API, EasyAuth 호출
const response = await fetch('https://api.easyauth.kr/send', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Authorization': `Bearer ${process.env.EASYAUTH_API_KEY}`
},
body: JSON.stringify({ phone })
});
if (!response.ok) throw new Error('발송 실패');
return NextResponse.json({ success: true, message: '인증번호가 발송되었습니다.' });
} catch (error) {
return NextResponse.json({ success: false, error: '서버 에러가 발생했습니다.' }, { status: 500 });
}
}
2. 인증번호 검증 API (Server)
다음으로 app/api/auth/verify/route.ts 파일을 만듭니다.
import { NextResponse } from 'next/server';
export async function POST(request: Request) {
try {
const { phone, code } = await request.json();
const response = await fetch('https://api.easyauth.kr/verify', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Authorization': `Bearer ${process.env.EASYAUTH_API_KEY}`
},
body: JSON.stringify({ phone, code })
});
const data = await response.json();
if (!data.success) {
return NextResponse.json({ success: false, message: '인증번호가 일치하지 않습니다.' }, { status: 400 });
}
return NextResponse.json({ success: true, message: '인증이 완료되었습니다.' });
} catch (error) {
return NextResponse.json({ success: false, error: '서버 에러가 발생했습니다.' }, { status: 500 });
}
}
3. SMS 인증 UI 컴포넌트 (Client)
이제 사용자가 상호작용할 프론트엔드 화면(app/page.tsx 또는 별도 컴포넌트)을 구현합니다.
'use client';
import { useState } from 'react';
export default function SmsAuth() {
const [phone, setPhone] = useState('');
const [code, setCode] = useState('');
const [step, setStep] = useState<'INPUT_PHONE' | 'INPUT_CODE'>('INPUT_PHONE');
const handleSend = async () => {
const res = await fetch('/api/auth/send', {
method: 'POST',
body: JSON.stringify({ phone }),
});
if (res.ok) setStep('INPUT_CODE');
};
const handleVerify = async () => {
const res = await fetch('/api/auth/verify', {
method: 'POST',
body: JSON.stringify({ phone, code }),
});
const data = await res.json();
if (data.success) {
alert('인증 성공! 🎉');
} else {
alert('인증번호를 다시 확인해주세요.');
}
};
return (
<div>
<h2>휴대폰 본인인증</h2>
<div>
setPhone(e.target.value)}
className="border p-2 rounded"
disabled={step === 'INPUT_CODE'}
/>
{step === 'INPUT_PHONE' ? (
인증번호 받기
) : (
<>
setCode(e.target.value)}
className="border p-2 rounded"
/>
인증하기
</>
)}
</div>
</div>
);
}
💡 실무 적용 팁과 Best Practices
- 번호 포맷팅: 사용자가
-기호를 넣어도 서버로 전송 전.replace(/[^0-9]/g, '')를 통해 숫자만 필터링하는 것이 좋습니다. - 어뷰징 방지 (Rate Limiting): API 라우트 단에서 동일한 IP나 번호로 연속해서 발송 요청이 오는 것을 막기 위해 Upstash 등의 Redis를 활용해 제한을 걸어두세요.
🚀 서류 없이 바로 쓰는 SMS API, EasyAuth(이지어스)
위 코드에서 사용된 api.easyauth.kr 엔드포인트는 개발자를 위한 초간단 SMS 인증 서비스 **EasyAuth(이지어스)**입니다.
기존 SMS API들이 복잡한 서류(사업자등록증, 이용증명원 등)와 발신번호 사전등록을 요구하는 것과 달리, EasyAuth는 가입 후 5분 만에 API 연동을 완료할 수 있습니다.
EasyAuth의 핵심 장점
- 🚫 서류 불필요: 대표번호 사전등록 없이 자동 발신번호 제공
- ⚡ 즉시 시작: 개인/1인 개발자도 가입 즉시 발송 가능
- 💰 합리적 가격: 건당 30~50원 하는 기존 업체 대비 저렴한 15~25원
- 🎁 무료 체험: 가입 시 테스트용 10건 무료 제공
스타트업 MVP나 토이 프로젝트에서 SMS 본인인증이 필요하다면, 서류 작업으로 시간을 낭비하지 마세요. 지금 바로 EasyAuth로 5분 만에 인증 로직을 완성해 보세요!