퀵가이드
이 퀵가이드는 NetFUNNEL Flutter 에이전트를 처음 적용하는 개발자가 빠르게 시작할 수 있도록 필수 구현 사항을 간략히 안내합니다.
1. 디렉터리 구조
섹션 제목: “1. 디렉터리 구조”아래는 예제의 기본 디렉터리 구조입니다. 각 파일은 에이전트 초기화, 진입 요청, 진입 완료 처리를 담당합니다.
├── pubspec.yaml // netfunnel_flutter 경로 의존성├── android/app/src/main/│ └── AndroidManifest.xml // 인터넷 권한└── lib/ ├── main.dart // initialize 호출 - 에이전트 초기화 ├── main_screen.dart // nfStart 호출 - 진입 요청 └── event_screen.dart // nfStop 호출 - 진입 완료 처리2. 에이전트 초기화
섹션 제목: “2. 에이전트 초기화”Flutter 에이전트는 안정적인 동작을 위해 앱 실행 시 가장 먼저 초기화되어야 합니다. 따라서 main()에서 runApp() 전에 초기화 함수를 호출합니다. (패키지 추가와 자세한 초기화 설정은 통합 가이드를 참고하세요.)
import 'package:netfunnel_flutter/netfunnel_flutter.dart';
void main() async { await Netfunnel.instance.initialize( clientId: '{{CLIENT_ID}}', );
runApp(const MyApp());}
class MyApp extends StatelessWidget { const MyApp({super.key});
@override Widget build(BuildContext context) { return MaterialApp( title: 'NetFUNNEL Sample App', theme: ThemeData(primarySwatch: Colors.blue), home: const HomeScreen(), ); }}Android에서 NetFUNNEL 서버와 통신할 수 있도록 인터넷 권한을 추가합니다.
<manifest xmlns:android="http://schemas.android.com/apk/res/android"> <!-- 인터넷 접속 권한 허용 --> <uses-permission android:name="android.permission.INTERNET" /></manifest>3. 콜백 함수
섹션 제목: “3. 콜백 함수”시작 함수(nfStart, nfStartSection)에 전달한 NetfunnelCallback으로 넷퍼넬 서버의 응답을 받습니다. 응답은 콜백 메서드와 상태 코드(statusCode), 메시지(message)로 전달되며, 콜백에 따라 분기 처리합니다.
onSuccess: 진입 또는 우회 응답. 화면 이동·함수 실행 등 기존 서비스 로직을 실행합니다.onError: 시스템 에러. 원활한 이용을 위해 onSuccess와 동일하게 기존 로직을 실행합니다.onNetworkError: 네트워크 장애. 기존 로직을 실행하거나, 악용 방지를 위해 다시 대기하도록 처리할 수 있습니다.
import 'package:netfunnel_flutter/netfunnel_flutter.dart';
class NetfunnelHandler extends NetfunnelCallback { final BuildContext context;
NetfunnelHandler({required this.context});
static const String _tag = "[APP]";
@override void onSuccess(int statusCode, String message) { /// 대기열 통과 시 처리할 로직 /// ex - 서비스 화면 진입 처리 print('$_tag onSuccess: $statusCode $message'); navigateToEventScreen(); }
@override void onError(int statusCode, String message) { /// 에러 발생 시 처리할 로직 /// ex - 사용자에게 오류 메시지 표시 또는 바이패스 print('$_tag onError: $statusCode $message'); navigateToEventScreen(); }
@override void onNetworkError(int statusCode, String message) { /// 네트워크 에러 발생 시 처리할 로직 /// ex - 네트워크 재연결 안내 또는 재시도 화면으로 이동 print('$_tag onNetworkError: $statusCode $message');
if (statusCode == 1001) { showSnackBar("네트워크 연결에 실패했습니다. 네트워크 설정을 확인해 주세요."); } else if (statusCode == 1002) { navigateToEventScreen(); } }
@override void onBlock(int statusCode, String message) { /// 사용자 진입 차단 시 처리할 로직 /// ex - 접근 제한 메시지 표시 print('$_tag onBlock: $statusCode $message'); }
@override void onClose(int statusCode, String message) { /// 사용자가 대기를 취소한 경우 처리할 로직 /// ex - 종료 안내 메시지 표시 print('$_tag onClose: $statusCode $message'); }
@override void onContinue(int statusCode, String message, int aheadWait, int behindWait, String waitTime, int progressRate) { /// 대기 진행 중 UI 업데이트 로직 (자체 커스텀 대기실 사용 시에만 해당) /// ex - 실시간 대기 정보를 커스텀 대기 화면에 업데이트 print('$_tag onContinue: $statusCode $message'); }
void navigateToEventScreen() { Navigator.push( context, MaterialPageRoute( builder: (_) => EventScreen(), ), ); }
void showSnackBar(String message) { ScaffoldMessenger.of(context).showSnackBar( SnackBar( content: Text(message), ), ); }}4. 시작 함수
섹션 제목: “4. 시작 함수”nfStart(기본 제어), nfStartSection(구간 제어)는 대기 상태를 감지하고 필요 시 대기실을 띄우는 함수입니다. 대기실을 띄울 화면의 context를 함께 전달합니다.
import 'package:netfunnel_flutter/netfunnel_flutter.dart';
class HomeScreen extends StatefulWidget { const HomeScreen({super.key});
@override State<HomeScreen> createState() => _HomeScreenState();}
class _HomeScreenState extends State<HomeScreen> { @override void initState() { super.initState(); Netfunnel.instance.nfStart( projectKey: '{{PROJECT_KEY}}', segmentKey: '{{SEGMENT_KEY}}', callback: NetfunnelHandler(context: context), context: context, ); }
@override Widget build(BuildContext context) { return Scaffold( appBar: AppBar(title: const Text("Home Screen")), body: const Center( child: Text("Home Screen"), ), ); }}5. 종료 함수
섹션 제목: “5. 종료 함수”nfStop(기본 제어), nfStopSection(구간 제어)은 대기 완료 후 서버에 진입 키를 반납하는 함수입니다. 키를 반납해 다음 사용자가 진입할 수 있게 하며, 일반적으로 서비스 진입 직후 실행합니다.
import 'package:flutter/material.dart';import 'package:flutter_sample/utils/constants.dart';import 'package:netfunnel_flutter/netfunnel_flutter.dart';
class EventScreen extends StatefulWidget { const EventScreen({super.key});
@override State<EventScreen> createState() => _EventScreenState();}
class _EventScreenState extends State<EventScreen> { @override void initState() { super.initState(); Netfunnel.instance.nfStop( projectKey: '{{PROJECT_KEY}}', segmentKey: '{{SEGMENT_KEY}}', ); }
@override Widget build(BuildContext context) { return Scaffold( appBar: AppBar(title: const Text("Event Screen")), body: const Center( child: Text("Event Screen"), ), ); }}6. 코드 기반 적용 예시
섹션 제목: “6. 코드 기반 적용 예시”6.1 MainScreen에서 EventScreen으로 이동
섹션 제목: “6.1 MainScreen에서 EventScreen으로 이동”MainScreen의 버튼에서 시작 함수를 호출해 대기열을 적용하고, onSuccess 응답을 받으면 EventScreen으로 이동합니다. EventScreen이 표시되면 종료 함수를 호출해 키를 반납합니다. (기본 제어와 구간 제어의 적용 방식은 동일합니다.)
import 'package:flutter/material.dart';import 'package:netfunnel_flutter/netfunnel_flutter.dart';import 'event_screen.dart';
class MainScreen extends StatelessWidget { const MainScreen({super.key});
@override Widget build(BuildContext context) { return Scaffold( body: Center( child: ElevatedButton( onPressed: () => Netfunnel.instance.nfStart( projectKey: '{PROJECT_KEY}', segmentKey: '{SEGMENT_KEY}', callback: _EnterCallback(context), context: context, ), child: const Text('Go to Event'), ), ), ); }}
class _EnterCallback extends NetfunnelCallback { _EnterCallback(this.context); final BuildContext context;
void _goToEvent() { Navigator.of(context).push(MaterialPageRoute(builder: (_) => const EventScreen())); }
@override void onSuccess(int statusCode, String message) => _goToEvent();
// 시스템 에러 시에도 서비스 이용을 위해 이동 @override void onError(int statusCode, String message) => _goToEvent();
@override void onNetworkError(int statusCode, String message) => _goToEvent();}import 'package:flutter/material.dart';import 'package:netfunnel_flutter/netfunnel_flutter.dart';
class EventScreen extends StatefulWidget { const EventScreen({super.key});
@override State<EventScreen> createState() => _EventScreenState();}
class _EventScreenState extends State<EventScreen> { @override void initState() { super.initState(); // 화면 진입 후 진입 키 반납 Netfunnel.instance.nfStop(projectKey: '{PROJECT_KEY}', segmentKey: '{SEGMENT_KEY}'); }
@override Widget build(BuildContext context) { return const Scaffold(body: Center(child: Text('Event'))); }}6.2 하나의 화면 안에서 함수를 실행
섹션 제목: “6.2 하나의 화면 안에서 함수를 실행”한 화면 안에서 시작 함수 호출 후, onSuccess에서 서비스 로직(예: 주문 요청)을 처리한 뒤 적절한 위치에서 종료 함수를 실행합니다.
class _OrderCallback extends NetfunnelCallback { @override void onSuccess(int statusCode, String message) async { await requestOrder(); // 주문 처리가 끝나면 진입 키 반납 await Netfunnel.instance.nfStop(projectKey: '{PROJECT_KEY}', segmentKey: '{SEGMENT_KEY}'); }
@override void onError(int statusCode, String message) => requestOrder();
@override void onNetworkError(int statusCode, String message) => requestOrder();}
void onOrderPressed(BuildContext context) { Netfunnel.instance.nfStart( projectKey: '{PROJECT_KEY}', segmentKey: '{SEGMENT_KEY}', callback: _OrderCallback(), context: context, );}