[Next.js] 서류 없이 5분 만에 회원가입 SMS 본인인증 구현하기
😫 SMS 인증, 도입이 망설여지는 이유
토이 프로젝트나 스타트업 MVP를 개발하다 보면, 스팸 유저를 막거나 신뢰성 있는 서비스를 위해 **회원가입 단계에서 SMS 본인인증(OTP)**을 도입해야 하는 순간이 옵니다.
하지만 막상 기존 SMS API를 연동하려고 하면 높은 진입장벽을 마주하게 됩니다.
- 복잡한 서류 제출: 사업자등록증, 통신서비스 이용증명원 등 제출 필수
- 사전 심사: 발신번호 사전등록을 위한 심사 대기 시간 소요
- 비싼 단가: 건당 30~50원으로 초기 프로젝트에 부담되는 비용
1인 개발자나 사이드 프로젝트, 빠르게 가설을 검증해야 하는 스타트업에게 이런 과정은 너무 큰 병목입니다.
💡 해결책: 서류 없이 5분 만에 끝내는 SMS 인증
이 글에서는 복잡한 서류 심사나 발신번호 등록 없이, Next.js (App Router) 환경에서 단 5분 만에 SMS 인증을 구현하는 방법을 알아봅니다.
초간단 SMS 인증 API인 **이지어스(EasyAuth)**를 활용하면 Send(발송)와 Verify(검증) 단 두 개의 엔드포인트로 인증 로직을 완성할 수 있습니다.
🛠️ Next.js SMS 인증 단계별 구현 가이드
Next.js 14+ App Router를 기준으로, 서버 사이드 보안을 위해 API Route Handler를 구성하고 클라이언트(UI)와 연동해 보겠습니다.
Step 1. 환경 변수 설정
먼저 프로젝트 루트의 .env.local 파일에 API 키를 설정합니다.
EASYAUTH_API_KEY=your_easyauth_api_key_here
Step 2. 인증번호 발송 API (/api/send)
app/api/send/route.ts 파일을 생성합니다. 클라이언트에서 전화번호를 받아 이지어스 API로 발송을 요청하는 서버 측 엔드포인트입니다.
import { NextResponse } from 'next/server';
export async function POST(req: Request) {
try {
const { phone } = await req.json();
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 });
}
}
Step 3. 인증번호 검증 API (/api/verify)
app/api/verify/route.ts 파일을 생성합니다. 사용자가 입력한 인증번호(OTP)가 맞는지 확인합니다.
import { NextResponse } from 'next/server';
export async function POST(req: Request) {
try {
const { phone, code } = await req.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 })
});
if (!response.ok) throw new Error('인증 실패');
return NextResponse.json({ success: true, message: '인증이 완료되었습니다.' });
} catch (error) {
return NextResponse.json({ success: false, error: '잘못된 인증번호입니다.' }, { status: 400 });
}
}
💻 Complete Code: 프론트엔드 연동
이제 위에서 만든 API를 호출하는 실제 클라이언트 컴포넌트를 만들어보겠습니다. app/signup/page.tsx에 아래 코드를 작성합니다.
'use client';
import { useState } from 'react';
export default function SignupPage() {
const [phone, setPhone] = useState('');
const [code, setCode] = useState('');
const [step, setStep] = useState<'IDLE' | 'SENT' | 'VERIFIED'>('IDLE');
const handleSendSMS = async () => {
const res = await fetch('/api/send', {
method: 'POST',
body: JSON.stringify({ phone })
});
if (res.ok) {
setStep('SENT');
alert('인증번호 6자리가 발송되었습니다.');
}
};
const handleVerifyCode = async () => {
const res = await fetch('/api/verify', {
method: 'POST',
body: JSON.stringify({ phone, code })
});
if (res.ok) {
setStep('VERIFIED');
alert('인증에 성공했습니다! 🎉');
} else {
alert('인증번호가 올바르지 않습니다.');
}
};
return (
<div>
<h2>휴대폰 본인인증</h2>
<div>
setPhone(e.target.value)}
disabled={step === 'VERIFIED'}
className="border p-2 flex-1 rounded"
/>
{step === 'SENT' ? '재전송' : '인증번호 받기'}
</div>
{step !== 'IDLE' && (
<div>
setCode(e.target.value)}
disabled={step === 'VERIFIED'}
className="border p-2 flex-1 rounded"
/>
확인
</div>
)}
</div>
);
}
🛡️ 실무를 위한 보안 팁 & Best Practices
- 3분 타이머 적용 (Timeout): 인증번호는 보통 3분의 유효기간을 갖습니다. 클라이언트에서
setInterval을 이용해 남은 시간을 보여주면 UX가 크게 향상됩니다. - Rate Limiting (요청 제한): 악의적인 사용자가 인증번호 발송 API를 무단으로 호출하여 비용 폭탄을 맞지 않도록, Next.js Middleware나 Upstash Redis를 사용하여 동일 IP당 1분 내 3회 이하로 발송을 제한하세요.
- 자동 발신번호의 이점: 이지어스(EasyAuth)를 사용하면 복잡한 발신번호 사전등록 없이 플랫폼 전용 자동 발신번호로 즉각 전송이 가능합니다.
🎉 결론: 가장 빠르게 MVP를 검증하는 방법
지금까지 Next.js에서 SMS 인증을 구현하는 방법을 살펴보았습니다. 기존 방식이라면 며칠씩 걸렸을 서류 준비와 심사 과정을 완전히 건너뛰고 단 5분 만에 코드를 완성했습니다.
빠른 실행력이 생명인 스타트업 MVP나 1인 개발자에게 **이지어스(EasyAuth)**는 최고의 선택지입니다.
- 서류 불필요 / 자동 발신번호 지원
- 기존 30
50원 대비 **저렴한 1525원의 단가** - 가입 즉시 10건 무료 테스트 제공
인증 API 구현에 시간을 낭비하지 마세요. 핵심 비즈니스 로직 개발에 집중하고, 본인인증은 이지어스로 오늘 당장 끝내보세요!