From ncp-sms-auth
네이버 클라우드 플랫폼(Naver Cloud Platform, NCP) SENS를 이용한 SMS 문자 인증 시스템. Next.js 웹 애플리케이션에 휴대폰 번호 인증, OTP 코드 검증 기능 통합. 회원가입, 로그인, 본인확인, 2단계 인증(2FA)에 사용. NCP SENS API를 통한 SMS 발송, Supabase를 통한 인증번호 저장(3분 만료), Supabase MCP 자동 배포 지원, React 컴포넌트 포함. 키워드: 네이버클라우드, 문자인증, 휴대폰인증, 본인인증, SMS verification, phone authentication, OTP, SENS.
How this skill is triggered — by the user, by Claude, or both
Slash command
/ncp-sms-auth:ncp-sms-authThe summary Claude sees in its skill listing — used to decide when to auto-load this skill
네이버 클라우드 플랫폼(NCP) SMS 기반 OTP 인증을 Next.js 애플리케이션에 통합합니다. 이 스킬은 SMS를 통해 인증코드를 전송하고, Supabase에 안전하게 저장하며, 사용자 입력을 검증하고, 자동 만료 기능을 포함한 완전한 엔드-투-엔드 워크플로우를 제공합니다.
네이버 클라우드 플랫폼(NCP) SMS 기반 OTP 인증을 Next.js 애플리케이션에 통합합니다. 이 스킬은 SMS를 통해 인증코드를 전송하고, Supabase에 안전하게 저장하며, 사용자 입력을 검증하고, 자동 만료 기능을 포함한 완전한 엔드-투-엔드 워크플로우를 제공합니다.
이 스킬이 호출되면 다음 단계를 자동으로 수행해야 합니다:
.env.local 파일을 Read 도구로 읽어서 다음 변수가 있는지 확인:
NEXT_PUBLIC_NCP_ACCESS_KEYNEXT_PUBLIC_NCP_SECRET_KEYNEXT_PUBLIC_NCP_SERVICE_IDNEXT_PUBLIC_SUPABASE_URLNEXT_PUBLIC_SUPABASE_ANON_KEYmcp__supabase__list_tables로 sms 테이블 존재 확인mcp__supabase__apply_migration으로 테이블 생성:CREATE TABLE IF NOT EXISTS sms (
id BIGSERIAL PRIMARY KEY,
code VARCHAR(6) NOT NULL,
phone_number VARCHAR(20) NOT NULL,
expiry_at TIMESTAMPTZ NOT NULL,
verified BOOLEAN DEFAULT false,
created_at TIMESTAMPTZ DEFAULT NOW(),
verified_at TIMESTAMPTZ
);
CREATE INDEX IF NOT EXISTS idx_sms_phone ON sms(phone_number);
CREATE INDEX IF NOT EXISTS idx_sms_code ON sms(code);
CREATE INDEX IF NOT EXISTS idx_sms_expiry ON sms(expiry_at);
ALTER TABLE sms ENABLE ROW LEVEL SECURITY;
CREATE POLICY "Allow insert for all users" ON sms FOR INSERT WITH CHECK (true);
CREATE POLICY "Allow select for own phone number" ON sms FOR SELECT USING (true);
CREATE POLICY "Allow update for all users" ON sms FOR UPDATE USING (true) WITH CHECK (true);
mcp__supabase__list_tables로 생성된 테이블의 컬럼 타입 확인expiry_at: timestamp with time zone (timestamptz) 여야 함created_at: timestamp with time zone (timestamptz) 여야 함verified_at: timestamp with time zone (timestamptz) 여야 함timestamp without time zone으로 생성되었다면 다음 migration 실행:ALTER TABLE sms
ALTER COLUMN expiry_at TYPE TIMESTAMPTZ USING expiry_at AT TIME ZONE 'UTC',
ALTER COLUMN created_at TYPE TIMESTAMPTZ USING created_at AT TIME ZONE 'UTC',
ALTER COLUMN created_at SET DEFAULT NOW(),
ALTER COLUMN verified_at TYPE TIMESTAMPTZ USING verified_at AT TIME ZONE 'UTC';
scripts/send-sms-edge-function.ts 파일을 Read 도구로 읽기mcp__supabase__deploy_edge_function으로 배포:
send-sms-ncpfalseindex.tsindex.ts로 설정app/api/auth/send-sms/route.ts 파일 생성 (Write 도구 사용)app/api/auth/verify-sms/route.ts 파일 생성 (Write 도구 사용)phone_number 파라미터를 사용하는 경우 API도 동일하게 맞춤message 필드 포함package.json 읽어서 @supabase/supabase-js 확인npm install @supabase/supabase-js 실행app/page.tsx 파일이 이미 있는지 확인scripts/SmsAuthForm.tsx를 components/SmsAuthForm.tsx로 복사사용자에게 다음 정보 제공:
sms 테이블 생성 완료send-sms-ncp 배포 완료/api/auth/send-sms, /api/auth/verify-sms)npm run dev로 테스트 가능SMS 인증 흐름은 3단계로 구성됩니다:
이 스킬은 Supabase MCP를 사용하여 테이블 생성과 Edge Function 배포를 자동으로 수행합니다.
NCP Console에서 다음을 준비하세요:
상세 가이드: references/setup-guide.md
.env.local 파일을 생성하고 NCP 및 Supabase 정보를 입력하세요:
NEXT_PUBLIC_NCP_ACCESS_KEY=ncp_iam_...
NEXT_PUBLIC_NCP_SECRET_KEY=ncp_iam_BPKMKRFvAVuAWbH8vmU9tLKroyehML3LFP
NEXT_PUBLIC_NCP_SERVICE_ID=ncp:sms:kr:362312123301:binibot
NEXT_PUBLIC_SUPABASE_URL=https://your-project.supabase.co
NEXT_PUBLIC_SUPABASE_ANON_KEY=eyJhbGc...
이 스킬을 실행하면 Claude Code가 Supabase MCP를 통해 자동으로:
✅ Supabase 테이블 생성
CREATE TABLE sms (
id BIGSERIAL PRIMARY KEY,
code VARCHAR(6) NOT NULL,
phone_number VARCHAR(20) NOT NULL,
expiry_at TIMESTAMP NOT NULL,
verified BOOLEAN DEFAULT false,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
verified_at TIMESTAMP
);
CREATE INDEX idx_sms_phone ON sms(phone_number);
CREATE INDEX idx_sms_code ON sms(code);
CREATE INDEX idx_sms_expiry ON sms(expiry_at);
✅ Edge Function 생성 및 배포
send-sms-ncp✅ API 라우트 생성
app/api/auth/send-sms/route.ts - SMS 전송app/api/auth/verify-sms/route.ts - 코드 검증✅ React 컴포넌트 생성
components/SmsAuthForm.tsx - 완성된 UI 컴포넌트모든 설정이 자동으로 완료되었습니다. 개발 서버를 실행하세요:
npm run dev
MCP 없이 Supabase CLI로 수동 설정하는 방법:
references/setup-guide.md)npm install -g supabasesupabase login
supabase link --project-ref your-project-id
Supabase Dashboard > SQL Editor에서 실행:
CREATE TABLE sms (...); -- 전체 스키마는 위 참조
# 함수 생성
supabase functions new send-sms-ncp
# scripts/send-sms-edge-function.ts 내용을
# supabase/functions/send-sms-ncp/index.ts에 복사
# Secrets 설정
supabase secrets set NEXT_PUBLIC_NCP_ACCESS_KEY=ncp_iam_...
supabase secrets set NEXT_PUBLIC_NCP_SECRET_KEY=ncp_iam_...
supabase secrets set NEXT_PUBLIC_NCP_SERVICE_ID=ncp:sms:kr:...
# 배포
supabase functions deploy send-sms-ncp
references/api-implementation.md 참조하여 수동 생성
import { SmsAuthForm } from "@/components/SmsAuthForm";
<SmsAuthForm
onVerifySuccess={(phoneNumber) => {
// Handle successful verification
}}
/>;
이 스킬이 실행되면 다음 작업이 자동으로 수행됩니다:
MCP를 통해 sms 테이블을 자동으로 생성합니다:
code: 6자리 인증코드phone_number: 사용자 전화번호expiry_at: 만료 시간 (3분)verified: 인증 완료 여부MCP를 통해 send-sms-ncp Edge Function을 생성하고 배포합니다:
scripts/send-sms-edge-function.tsNEXT_PUBLIC_NCP_ACCESS_KEYNEXT_PUBLIC_NCP_SECRET_KEYNEXT_PUBLIC_NCP_SERVICE_IDNCP_SENDER_PHONE (선택사항)프로젝트에 다음 API 라우트를 생성합니다:
app/api/auth/send-sms/route.ts
app/api/auth/verify-sms/route.ts
app/page.tsx (기존 UI 활용)
필요한 작업:
handleSendCode() 함수: /api/auth/send-sms 호출 (기존 코드 수정)handleVerifyCode() 함수: /api/auth/verify-sms 호출 (기존 코드 수정)phone_number 필드명 일치 확인중요: Supabase MCP를 사용하려면 Organization이 필요합니다.
Supabase Organization 생성
Claude Code에서 MCP 연결
MCP가 연결되면 이 스킬 실행
회원가입/로그인을 위한 가장 간단한 구현:
// Page.tsx
import { SmsAuthForm } from "@/components/auth/SmsAuthForm";
export default function LoginPage() {
return (
<SmsAuthForm
onVerifySuccess={(phoneNumber) => {
// Create session, redirect, etc.
}}
/>
);
}
더 큰 인증 흐름 내에서 사용:
// SignupForm.tsx
const [verifiedPhone, setVerifiedPhone] = useState<string | null>(null);
if (!verifiedPhone) {
return <SmsAuthForm onVerifySuccess={setVerifiedPhone} />;
}
return <AdditionalDetailsForm phoneNumber={verifiedPhone} />;
휴대폰/IP당 SMS 요청을 제한하여 남용 방지. Redis 기반 구현 패턴은 references/rate-limiting.md를 참조하세요.
sms 테이블 구조:
CREATE TABLE sms (
id BIGSERIAL PRIMARY KEY,
code VARCHAR(6) NOT NULL,
phone_number VARCHAR(20) NOT NULL,
expiry_at TIMESTAMP NOT NULL,
verified BOOLEAN DEFAULT false,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
verified_at TIMESTAMP
);
CREATE INDEX idx_sms_phone ON sms(phone_number);
CREATE INDEX idx_sms_code ON sms(code);
| 설정 | 기본값 | 목적 |
|---|---|---|
| OTP 길이 | 6자리 | 인증코드 길이 |
| 만료 시간 | 3분 | 코드 유효 기간 |
| 메시지 템플릿 | "[App] Code: {code}" | SMS 내용 |
| 발신자 번호 | NCP 등록 번호 | NCP 콘솔에서 검증 |
send-sms 라우트에서 조정:
const expiryAt = new Date();
expiryAt.setMinutes(expiryAt.getMinutes() + 5); // 5분
Edge Function 본문 수정:
const templates = {
signup: `[AppName] 회원가입 코드: ${cert_code}`,
recovery: `[AppName] 비밀번호 재설정: ${cert_code}`,
};
SMS 전송 실패 시 이메일로 코드 전송. 구현 방법은 참고 자료를 참조하세요.
supabase startsupabase secrets set NCP_SECRET_KEY=...supabase functions deploy send-smsnpm run devreferences/testing.md의 cURL 명령으로 테스트references/test-cases.md에서 제공되는 테스트 시나리오 사용:
완전한 오류 코드 매핑 및 복구 전략은 references/error-handling.md를 참조하세요:
| 오류 | 원인 | 해결 방법 |
|---|---|---|
| SMS_SEND_FAILED | NCP API 도달 불가 | 지수 백오프로 재시도 |
| INVALID_CODE | 코드 불일치 | 사용자 입력 오류 |
| CODE_EXPIRED | 3분 이상 경과 | 새 코드 요청 |
| DB_ERROR | 데이터베이스 사용 불가 | Supabase 상태 확인 |
프로덕션 배포 체크리스트는 references/security-checklist.md를 참조하세요.
일반적인 문제 및 해결 방법:
"API 키 인증 실패"
.env.local에 있고 하드코딩되지 않았는지 확인"SMS 전송 실패"
"검증 시간 초과"
"코드 불일치 또는 만료"
자세한 디버깅은 references/debugging.md를 참조하세요.
Provides CDSS development patterns for drug interaction checking, dose validation, clinical scoring (NEWS2, qSOFA), and alert classification integrated into EMR workflows.
npx claudepluginhub auraworks/my-marketplace --plugin ncp-sms-auth