[Auth.js v5] Next.js에서 서류 없이 5분 만에 SMS 인증(OTP) 구현하기
2026-04-28T01:02:47.867Z
SMS 인증, 꼭 이렇게 복잡해야 할까요?
사이드 프로젝트나 스타트업 MVP를 개발하다 보면 전화번호 인증이 필요한 순간이 반드시 옵니다. 하지만 막상 기존 API를 연동하려고 하면 개발보다 행정 업무가 더 많습니다. 사업자등록증 제출, 발신번호 사전등록, 복잡한 심사 과정까지... 개발자의 흐름이 완전히 끊기게 되죠.
이 글에서는 Next.js App Router와 Auth.js v5(구 NextAuth), 그리고 서류 제출 없이 즉시 사용할 수 있는 EasyAuth(이지어스) API를 조합해 단 5분 만에 SMS 인증을 구현하는 방법을 단계별로 소개합니다.
왜 Auth.js v5 + EasyAuth인가요?
- Auth.js v5: 최신 Next.js App Router와 완벽하게 호환됩니다.
Credentials프로바이더를 사용해 커스텀 OTP 로그인 로직을 매우 쉽게 연동할 수 있습니다. - EasyAuth(이지어스):
- 서류 0장: 사업자등록증, 이용증명원 제출 불필요
- 즉시 시작: 가입 후 5분 내 연동 완료 (가입 시 테스트용 무료 10건 제공)
- 자동 발신번호: 대표번호 사전등록 없이 즉시 발송 가능
- 간편한 API:
/send,/verify두 개의 엔드포인트로 끝!
1단계: Auth.js v5 환경 설정
먼저 Next.js 프로젝트에 Auth.js 최신 버전을 설치합니다.
npm install next-auth@beta
프로젝트의 루트(또는 src 폴더)에 auth.ts 파일을 생성하고, EasyAuth의 검증 API(/verify)를 authorize 콜백에 연동합니다.
import NextAuth from "next-auth";
import Credentials from "next-auth/providers/credentials";
export const { handlers, signIn, signOut, auth } = NextAuth({
providers: [
Credentials({
name: "SMS OTP",
credentials: {
phone: { label: "Phone Number", type: "text" },
code: { label: "OTP Code", type: "text" },
},
async authorize(credentials) {
if (!credentials?.phone || !credentials?.code) return null;
// EasyAuth API로 인증번호 검증
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: credentials.phone,
code: credentials.code
})
});
const data = await response.json();
// 검증 성공 시 세션에 저장될 사용자 객체 반환
if (response.ok && data.success) {
return { id: credentials.phone as string, name: credentials.phone as string };
}
return null; // 인증 실패 시
}
})
],
pages: {
signIn: "/login", // 커스텀 로그인 페이지 경로
}
});
2단계: 인증번호 발송 API (Route Handler) 작성
클라이언트 사이드에서 직접 API 키를 노출하는 것은 보안상 매우 위험합니다. Next.js Route Handler를 생성해 서버에서 EasyAuth의 /send 엔드포인트를 호출하도록 구성합니다.
app/api/send-otp/route.ts 파일을 생성합니다.
import { NextResponse } from "next/server";
export async function POST(req: Request) {
try {
const { phone } = await req.json();
// EasyAuth API로 인증번호 발송
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: "OTP sent" });
} catch (error) {
return NextResponse.json(
{ success: false, error: "서버 에러가 발생했습니다." },
{ status: 500 }
);
}
}
3단계: 클라이언트 로그인 폼 (전체 완성 코드)
마지막으로 사용자가 전화번호를 입력하고, 수신한 인증번호를 제출하여 로그인할 수 있는 UI를 구성합니다.
app/login/page.tsx
"use client";
import { useState } from "react";
import { signIn } from "next-auth/react";
export default function LoginPage() {
const [phone, setPhone] = useState("");
const [code, setCode] = useState("");
const [step, setStep] = useState<1 | 2>(1);
// 1. 인증번호 발송 요청
const handleSendCode = async () => {
const res = await fetch("/api/send-otp", {
method: "POST",
body: JSON.stringify({ phone }),
});
if (res.ok) {
alert("인증번호가 발송되었습니다!");
setStep(2);
} else {
alert("발송에 실패했습니다. 다시 시도해주세요.");
}
};
// 2. 인증번호 검증 및 NextAuth 로그인 처리
const handleVerifyCode = async () => {
const result = await signIn("credentials", {
phone,
code,
redirect: true,
redirectTo: "/dashboard", // 로그인 성공 후 이동할 경로
});
};
return (
<div>
<h1>SMS 본인인증</h1>
{step === 1 ? (
<div>
setPhone(e.target.value)}
placeholder="전화번호 (예: 01012345678)"
className="border p-3 rounded"
/>
인증번호 받기
</div>
) : (
<div>
setCode(e.target.value)}
placeholder="인증번호 6자리"
className="border p-3 rounded"
/>
인증 완료 및 로그인
</div>
)}
</div>
);
}
💡 Tips & Best Practices
- 보안 철저 (환경 변수 보호):
EASYAUTH_API_KEY는 반드시.env.local파일에 서버사이드 전용으로만 보관하세요.NEXT_PUBLIC_접두사를 붙이면 클라이언트에 노출되므로 절대 주의해야 합니다. - 예외 처리 최적화: 실제 상용 서비스에 적용할 때는 유효하지 않은 전화번호 정규식 검사나 검증 실패 시의 명확한 에러 피드백을 추가하는 것이 좋습니다.
마무리: 서류 없는 가장 쉬운 SMS 인증
지금까지 최신 Auth.js v5와 Next.js App Router를 사용하여 깔끔하고 안전하게 SMS OTP 인증을 구현하는 방법을 살펴보았습니다.
기존 방식대로라면 사업자 인증 심사만 며칠을 기다려야 했겠지만, **EasyAuth(이지어스)**를 활용하면 이 모든 과정을 생략하고 단 5분 만에 핵심 비즈니스 로직 연동을 완료할 수 있습니다. 복잡한 절차 없이 오늘 당장 구현을 마쳐야 하는 프리랜서나 1인 개발자, 스타트업 개발자라면 가입 즉시 무료로 제공되는 10건의 크레딧으로 이 코드들을 테스트해 보세요!
비트베이크에서 광고를 시작해보세요
광고 문의하기