비트베이크

서류 없이 5분 만에 끝내는 Flutter + Riverpod SMS 본인인증 구현하기

2026-06-01T01:02:17.258Z

FLUTTER-RIVERPOD-SMS

서류 없이 5분 만에 끝내는 Flutter + Riverpod SMS 본인인증 구현하기

Flutter로 토이 프로젝트나 MVP를 개발 중이신가요? 서비스 런칭을 위해 회원가입을 만들다 보면 반드시 마주치는 장벽이 있습니다. 바로 **SMS 본인인증(OTP)**입니다.

기존의 문자 발송 API(포트원, 쿨에스엠에스 등)를 사용해 보셨다면 아실 겁니다.

  • 사업자등록증 제출
  • 발신번호 사전등록을 위한 통신사 가입증명원
  • 며칠이 걸리는 심사 기간

개인 개발자나 사업자가 없는 초기 스타트업에게는 시작조차 할 수 없는 조건이죠. 이 글에서는 **서류 없이 가입 후 5분 만에 연동 가능한 초간단 API, EasyAuth(이지어스)**를 활용해 Flutter와 Riverpod로 완벽한 인증 플로우를 만드는 방법을 소개합니다.


왜 EasyAuth인가요?

EasyAuth는 개발자를 위한 가장 실용적인 SMS API입니다.

  • 서류 불필요: 사업자등록증 없이 이메일 가입만으로 즉시 시작
  • 자동 발신번호: 복잡한 발신번호 등록 없이 기본 번호 제공
  • 합리적 가격: 건당 15~25원으로 기존(30~50원) 대비 절반 가격
  • 단순한 구조: /send/verify 단 두 개의 엔드포인트

1. Riverpod 인증 상태 정의하기

인증 과정은 크게 '입력 전', '발송 완료(타이머 동작)', '인증 성공', '에러' 상태로 나뉩니다. Riverpod의 Notifier를 활용해 상태 관리를 해보겠습니다.

import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:http/http.dart' as http;
import 'dart:convert';

enum AuthStatus { initial, sending, codeSent, verifying, success, error }

class AuthState {
  final AuthStatus status;
  final String? errorMessage;
  AuthState({required this.status, this.errorMessage});
}

class AuthNotifier extends Notifier {
  @override
  AuthState build() => AuthState(status: AuthStatus.initial);

  // 1. 인증번호 발송 (POST /send)
  Future sendSms(String phone) async {
    state = AuthState(status: AuthStatus.sending);
    try {
      final response = await http.post(
        Uri.parse('https://api.easyauth.kr/send'),
        headers: {'Authorization': 'Bearer YOUR_API_KEY'},
        body: jsonEncode({'phone': phone}),
      );

      if (response.statusCode == 200) {
        state = AuthState(status: AuthStatus.codeSent);
      } else {
        state = AuthState(status: AuthStatus.error, errorMessage: '발송 실패');
      }
    } catch (e) {
      state = AuthState(status: AuthStatus.error, errorMessage: '네트워크 오류');
    }
  }

  // 2. 인증번호 검증 (POST /verify)
  Future verifyCode(String phone, String code) async {
    state = AuthState(status: AuthStatus.verifying);
    try {
      final response = await http.post(
        Uri.parse('https://api.easyauth.kr/verify'),
        headers: {'Authorization': 'Bearer YOUR_API_KEY'},
        body: jsonEncode({'phone': phone, 'code': code}),
      );

      if (response.statusCode == 200) {
        state = AuthState(status: AuthStatus.success);
      } else {
        state = AuthState(status: AuthStatus.error, errorMessage: '인증번호 불일치');
      }
    } catch (e) {
      state = AuthState(status: AuthStatus.error, errorMessage: '네트워크 오류');
    }
  }
}

final authProvider = NotifierProvider(() => AuthNotifier());

2. 완벽한 UI/UX 구현하기

상태에 따라 전화번호 입력창과 인증번호 입력창이 전환되는 UI를 구성합니다.

import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';

class SmsAuthScreen extends ConsumerWidget {
  final phoneController = TextEditingController();
  final codeController = TextEditingController();

  @override
  Widget build(BuildContext context, WidgetRef ref) {
    final authState = ref.watch(authProvider);
    final authNotifier = ref.read(authProvider.notifier);

    return Scaffold(
      appBar: AppBar(title: Text('SMS 본인인증')),
      body: Padding(
        padding: const EdgeInsets.all(20.0),
        child: Column(
          crossAxisAlignment: CrossAxisAlignment.stretch,
          children: [
            TextField(
              controller: phoneController,
              keyboardType: TextInputType.phone,
              decoration: InputDecoration(labelText: '휴대폰 번호 (- 없이 입력)'),
              enabled: authState.status == AuthStatus.initial || authState.status == AuthStatus.error,
            ),
            SizedBox(height: 16),
            if (authState.status == AuthStatus.initial || authState.status == AuthStatus.error)
              ElevatedButton(
                onPressed: () => authNotifier.sendSms(phoneController.text),
                child: Text('인증번호 받기'),
              ),

            if (authState.status == AuthStatus.codeSent || authState.status == AuthStatus.verifying) ...[
              TextField(
                controller: codeController,
                keyboardType: TextInputType.number,
                decoration: InputDecoration(labelText: '인증번호 6자리'),
              ),
              SizedBox(height: 16),
              ElevatedButton(
                onPressed: () => authNotifier.verifyCode(phoneController.text, codeController.text),
                child: authState.status == AuthStatus.verifying
                    ? CircularProgressIndicator()
                    : Text('인증하기'),
              ),
            ],

            if (authState.status == AuthStatus.success)
              Padding(
                padding: const EdgeInsets.only(top: 20),
                child: Text('✅ 인증이 완료되었습니다!', style: TextStyle(color: Colors.green, fontSize: 18)),
              ),

            if (authState.errorMessage != null)
              Padding(
                padding: const EdgeInsets.only(top: 20),
                child: Text(authState.errorMessage!, style: TextStyle(color: Colors.red)),
              ),
          ],
        ),
      ),
    );
  }
}

3. 실무 적용 꿀팁 (Best Practices)

  1. Autofill 자동 완성: TextFieldautofillHints 속성에 [AutofillHints.oneTimeCode]를 추가하면 iOS/Android에서 문자로 온 인증번호를 키보드 상단에 자동으로 띄워줍니다.
  2. 타이머 추가: SMS 발송 후 3분(180초) 타이머를 추가하여 보안을 강화하세요. Timer.periodic을 사용해 상태에 남은 시간을 업데이트하면 됩니다.
  3. 버튼 비활성화 중복 클릭 방지: API 통신 중(sending, verifying 상태)일 때는 버튼을 비활성화하여 중복 요청을 막아주세요.

마무리

지금까지 Flutter와 Riverpod, 그리고 EasyAuth를 활용하여 빠르고 깔끔한 SMS 인증 플로우를 구현해 보았습니다.

사이드 프로젝트나 스타트업 MVP 개발 시 문자 인증 때문에 막막하셨다면, 더 이상 통신사 서류와 씨름하지 마세요. 가입 즉시 10건의 무료 테스트 크레딧을 제공하는 EasyAuth로 지금 바로 인증 기능을 완성해 보세요!

Start advertising on Bitbake

Contact Us

More Articles

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 생존법: 리워드 기반 퀴즈 마케팅으로 제로파티 데이터 구축하기

Services

HomeFeedFAQCustomer Service

Inquiry

Bitbake

LAEM Studio | Business Registration No.: 542-40-01042

4th Floor, 402-J270, 16 Su-ro 116beon-gil, Wabu-eup, Namyangju-si, Gyeonggi-do

TwitterInstagramNaver Blog