퀵가이드
이 퀵가이드는 NetFUNNEL iOS 에이전트를 처음 적용하는 개발자가 빠르게 시작할 수 있도록 필수 구현 사항을 간략히 안내합니다.
1. 디렉터리 구조
섹션 제목: “1. 디렉터리 구조”아래는 예제의 기본 디렉터리 구조입니다. 각 파일은 에이전트 초기화, 응답 처리, 진입 요청, 진입 완료 처리를 담당합니다.
{PROJECT_NAME}/├── AppDelegate.swift // initialize 호출 - 에이전트 초기화├── NetfunnelHandler.swift // NetfunnelDelegate 구현 - 응답 처리├── MainViewController.swift // nfStart 호출 - 진입 요청└── EventViewController.swift // nfStop 호출 - 진입 완료 처리2. 에이전트 초기화
섹션 제목: “2. 에이전트 초기화”iOS 에이전트는 안정적인 동작을 위해 앱 실행 시 가장 먼저 초기화되어야 합니다. 따라서 AppDelegate의 application(_:didFinishLaunchingWithOptions:)에서 초기화 함수를 호출하고, 응답을 받을 델리게이트를 함께 등록합니다. (에이전트 설치와 자세한 초기화 설정은 통합 가이드를 참고하세요.)
import Netfunnel_iOS
func application( _ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool { Netfunnel.shared.initialize(clientId: "{CLIENT_ID}", delegate: NetfunnelHandler.shared) return true}@import Netfunnel_iOS;
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { // Objective-C에서는 옵셔널 파라미터도 모두 명시적으로 전달합니다. // (각 파라미터는 통합 가이드의 초기화 항목 참고) [[Netfunnel shared] initializeWithClientId:@"{CLIENT_ID}" serverUrl:@"{SERVER_URL}" errorUrl:@"{ERROR_URL}" delegate:[NetfunnelHandler sharedInstance] networkTimeout:@3000 retryCount:@0 printLog:@NO useNetfunnelTemplate:@YES errorBypass:@NO userId:@"{USER_ID}" useNetworkRecoveryMode:@NO]; return YES;}3. 델리게이트
섹션 제목: “3. 델리게이트”시작 함수(nfStart, nfStartSection)를 호출하면 넷퍼넬 서버의 응답이 초기화 때 등록한 델리게이트로 전달됩니다. 응답은 델리게이트 메서드와 상태 코드(statusCode), 메시지(message)로 전달되며, 메서드에 따라 분기 처리합니다.
nfSuccess: 진입 또는 우회 응답. 화면 이동·함수 실행 등 기존 서비스 로직을 실행합니다.nfError: 시스템 에러. 원활한 이용을 위해 nfSuccess와 동일하게 기존 로직을 실행합니다.nfNetworkError: 네트워크 장애. 기존 로직을 실행하거나, 악용 방지를 위해 다시 대기하도록 처리할 수 있습니다.
아래 예시는 델리게이트를 별도 객체(NetfunnelHandler)로 두고, 진입 후 실행할 동작을 화면에서 넘겨받아 실행합니다.
import Foundationimport Netfunnel_iOS
class NetfunnelHandler: NSObject, NetfunnelDelegate {
static let shared = NetfunnelHandler()
// MARK: - 필수 콜백 클로져 (반드시 정의 필요) var onSuccess: ((String, String, Int, String) -> Void)? var onError: ((String, String, Int, String) -> Void)? var onNetworkError: ((String, String, Int, String) -> Void)?
// MARK: - 선택 콜백 클로져 (필요 시 정의) var onContinue: ((String, String, Int, String, Int, Int, String, Int) -> Void)? var onBlock: ((String, String, Int, String) -> Void)? var onClose: ((String, String, Int, String) -> Void)? var onComplete: ((String, String, Int, String) -> Void)?
private override init() {}
// MARK: - NetfunnelDelegate Methods
func nfSuccess(projectKey: String, segmentKey: String, statusCode: Int, message: String) { NSLog("nfSuccess \(statusCode) \(message)") onSuccess?(projectKey, segmentKey, statusCode, message) }
func nfError(projectKey: String, segmentKey: String, statusCode: Int, message: String) { NSLog("nfError \(statusCode) \(message)") onError?(projectKey, segmentKey, statusCode, message) }
func nfNetworkError(projectKey: String, segmentKey: String, statusCode: Int, message: String) { NSLog("nfNetworkError \(statusCode) \(message)") onNetworkError?(projectKey, segmentKey, statusCode, message) }
func nfContinue(projectKey: String, segmentKey: String, statusCode: Int, message: String, aheadWait: Int, behindWait: Int, waitTime: String, progressRate: Int) { NSLog("nfContinue \(statusCode) \(message)") onContinue?(projectKey, segmentKey, statusCode, message, aheadWait, behindWait, waitTime, progressRate) }
func nfBlock(projectKey: String, segmentKey: String, statusCode: Int, message: String) { NSLog("nfBlock \(statusCode) \(message)") onBlock?(projectKey, segmentKey, statusCode, message) }
func nfClose(projectKey: String, segmentKey: String, statusCode: Int, message: String) { NSLog("nfClose \(statusCode) \(message)") onClose?(projectKey, segmentKey, statusCode, message) }
func nfComplete(projectKey: String, segmentKey: String, statusCode: Int, message: String) { NSLog("nfComplete \(statusCode) \(message)") onComplete?(projectKey, segmentKey, statusCode, message) }}#import <Foundation/Foundation.h>#import <Netfunnel_iOS/NetfunnelDelegate.h>
NS_ASSUME_NONNULL_BEGIN
@interface NetfunnelHandler : NSObject <NetfunnelDelegate>
+ (instancetype)sharedInstance;
// 필수 콜백@property (nonatomic, copy, nullable) void (^onSuccess)(NSString *projectKey, NSString *segmentKey, NSInteger statusCode, NSString *message);@property (nonatomic, copy, nullable) void (^onError)(NSString *projectKey, NSString *segmentKey, NSInteger statusCode, NSString *message);@property (nonatomic, copy, nullable) void (^onNetworkError)(NSString *projectKey, NSString *segmentKey, NSInteger statusCode, NSString *message);
// 선택 콜백@property (nonatomic, copy, nullable) void (^onContinue)(NSString *projectKey, NSString *segmentKey, NSInteger statusCode, NSString *message, NSInteger aheadWait, NSInteger behindWait, NSString *waitTime, NSInteger progressRate);@property (nonatomic, copy, nullable) void (^onBlock)(NSString *projectKey, NSString *segmentKey, NSInteger statusCode, NSString *message);@property (nonatomic, copy, nullable) void (^onClose)(NSString *projectKey, NSString *segmentKey, NSInteger statusCode, NSString *message);@property (nonatomic, copy, nullable) void (^onComplete)(NSString *projectKey, NSString *segmentKey, NSInteger statusCode, NSString *message);
@end
NS_ASSUME_NONNULL_END#import "NetfunnelHandler.h"
@implementation NetfunnelHandler
+ (instancetype)sharedInstance { static NetfunnelHandler *sharedInstance = nil; static dispatch_once_t onceToken; dispatch_once(&onceToken, ^{ sharedInstance = [[NetfunnelHandler alloc] init]; }); return sharedInstance;}
#pragma mark - NetfunnelDelegate Methods
- (void)nfSuccessWithProjectKey:(NSString *)projectKey segmentKey:(NSString *)segmentKey statusCode:(NSInteger)statusCode message:(NSString *)message { NSLog(@"nfSuccess %ld %@", (long)statusCode, message); if (self.onSuccess) { self.onSuccess(projectKey, segmentKey, statusCode, message); }}
- (void)nfErrorWithProjectKey:(NSString *)projectKey segmentKey:(NSString *)segmentKey statusCode:(NSInteger)statusCode message:(NSString *)message { NSLog(@"nfError %ld %@", (long)statusCode, message); if (self.onError) { self.onError(projectKey, segmentKey, statusCode, message); }}
- (void)nfNetworkErrorWithProjectKey:(NSString *)projectKey segmentKey:(NSString *)segmentKey statusCode:(NSInteger)statusCode message:(NSString *)message { NSLog(@"nfNetworkError %ld %@", (long)statusCode, message); if (self.onNetworkError) { self.onNetworkError(projectKey, segmentKey, statusCode, message); }}
- (void)nfContinueWithProjectKey:(NSString *)projectKey segmentKey:(NSString *)segmentKey statusCode:(NSInteger)statusCode message:(NSString *)message aheadWait:(NSInteger)aheadWait behindWait:(NSInteger)behindWait waitTime:(NSString *)waitTime progressRate:(NSInteger)progressRate { NSLog(@"nfContinue %ld %@", (long)statusCode, message); if (self.onContinue) { self.onContinue(projectKey, segmentKey, statusCode, message, aheadWait, behindWait, waitTime, progressRate); }}
- (void)nfBlockWithProjectKey:(NSString *)projectKey segmentKey:(NSString *)segmentKey statusCode:(NSInteger)statusCode message:(NSString *)message { NSLog(@"nfBlock %ld %@", (long)statusCode, message); if (self.onBlock) { self.onBlock(projectKey, segmentKey, statusCode, message); }}
- (void)nfCloseWithProjectKey:(NSString *)projectKey segmentKey:(NSString *)segmentKey statusCode:(NSInteger)statusCode message:(NSString *)message { NSLog(@"nfClose %ld %@", (long)statusCode, message); if (self.onClose) { self.onClose(projectKey, segmentKey, statusCode, message); }}
- (void)nfCompleteWithProjectKey:(NSString *)projectKey segmentKey:(NSString *)segmentKey statusCode:(NSInteger)statusCode message:(NSString *)message { NSLog(@"nfComplete %ld %@", (long)statusCode, message); if (self.onComplete) { self.onComplete(projectKey, segmentKey, statusCode, message); }}
@end4. 시작 함수
섹션 제목: “4. 시작 함수”nfStart(기본 제어), nfStartSection(구간 제어)는 대기 상태를 감지하고 필요 시 대기실을 띄우는 함수입니다.
Netfunnel.shared.nfStart(projectKey: "{PROJECT_KEY}", segmentKey: "{SEGMENT_KEY}")[[Netfunnel shared] nfStartWithProjectKey:@"{PROJECT_KEY}" segmentKey:@"{SEGMENT_KEY}"];5. 종료 함수
섹션 제목: “5. 종료 함수”nfStop(기본 제어), nfStopSection(구간 제어)은 대기 완료 후 서버에 진입 키를 반납하는 함수입니다. 키를 반납해 다음 사용자가 진입할 수 있게 하며, 일반적으로 서비스 진입 직후 실행합니다.
Netfunnel.shared.nfStop(projectKey: "{PROJECT_KEY}", segmentKey: "{SEGMENT_KEY}")[[Netfunnel shared] nfStopWithProjectKey:@"{PROJECT_KEY}" segmentKey:@"{SEGMENT_KEY}"];6. 코드 기반 적용 예시
섹션 제목: “6. 코드 기반 적용 예시”6.1 MainViewController에서 EventViewController로 이동
섹션 제목: “6.1 MainViewController에서 EventViewController로 이동”MainViewController의 버튼에서 시작 함수를 호출해 대기열을 적용하고, nfSuccess 응답을 받으면 EventViewController로 이동합니다. EventViewController가 표시되면 종료 함수를 호출해 키를 반납합니다. (기본 제어와 구간 제어의 적용 방식은 동일합니다.)
import UIKitimport Netfunnel_iOS
class MainViewController: UIViewController {
@IBAction func didTapEventButton(_ sender: UIButton) { // 진입(또는 에러) 응답을 받으면 EventViewController로 이동 let goToEvent: (String, String, Int, String) -> Void = { [weak self] _, _, _, _ in DispatchQueue.main.async { self?.performSegue(withIdentifier: "showEvent", sender: nil) } } NetfunnelHandler.shared.onSuccess = goToEvent NetfunnelHandler.shared.onError = goToEvent Netfunnel.shared.nfStart(projectKey: "{PROJECT_KEY}", segmentKey: "{SEGMENT_KEY}") }}#import "MainViewController.h"#import "NetfunnelHandler.h"@import Netfunnel_iOS;
@implementation MainViewController
- (IBAction)didTapEventButton:(UIButton *)sender { // 진입(또는 에러) 응답을 받으면 EventViewController로 이동 __weak typeof(self) weakSelf = self; void (^goToEvent)(NSString *, NSString *, NSInteger, NSString *) = ^(NSString *projectKey, NSString *segmentKey, NSInteger statusCode, NSString *message) { dispatch_async(dispatch_get_main_queue(), ^{ [weakSelf performSegueWithIdentifier:@"showEvent" sender:nil]; }); }; [NetfunnelHandler sharedInstance].onSuccess = goToEvent; [NetfunnelHandler sharedInstance].onError = goToEvent; [[Netfunnel shared] nfStartWithProjectKey:@"{PROJECT_KEY}" segmentKey:@"{SEGMENT_KEY}"];}
@endimport UIKitimport Netfunnel_iOS
class EventViewController: UIViewController { override func viewDidLoad() { super.viewDidLoad() // 화면 진입 후 진입 키 반납 Netfunnel.shared.nfStop(projectKey: "{PROJECT_KEY}", segmentKey: "{SEGMENT_KEY}") }}#import "EventViewController.h"@import Netfunnel_iOS;
@implementation EventViewController
- (void)viewDidLoad { [super viewDidLoad]; // 화면 진입 후 진입 키 반납 [[Netfunnel shared] nfStopWithProjectKey:@"{PROJECT_KEY}" segmentKey:@"{SEGMENT_KEY}"];}
@end6.2 하나의 화면 안에서 함수를 실행
섹션 제목: “6.2 하나의 화면 안에서 함수를 실행”한 화면 안에서 시작 함수 호출 후, nfSuccess에서 서비스 로직(예: 주문 요청)을 처리한 뒤 적절한 위치에서 종료 함수를 실행합니다.
@IBAction func didTapOrderButton(_ sender: UIButton) { NetfunnelHandler.shared.onSuccess = { [weak self] _, _, _, _ in self?.requestOrder { // 주문 처리가 끝나면 진입 키 반납 Netfunnel.shared.nfStop(projectKey: "{PROJECT_KEY}", segmentKey: "{SEGMENT_KEY}") } } Netfunnel.shared.nfStart(projectKey: "{PROJECT_KEY}", segmentKey: "{SEGMENT_KEY}")}- (IBAction)didTapOrderButton:(UIButton *)sender { __weak typeof(self) weakSelf = self; [NetfunnelHandler sharedInstance].onSuccess = ^(NSString *projectKey, NSString *segmentKey, NSInteger statusCode, NSString *message) { [weakSelf requestOrderWithCompletion:^{ // 주문 처리가 끝나면 진입 키 반납 [[Netfunnel shared] nfStopWithProjectKey:@"{PROJECT_KEY}" segmentKey:@"{SEGMENT_KEY}"]; }]; }; [[Netfunnel shared] nfStartWithProjectKey:@"{PROJECT_KEY}" segmentKey:@"{SEGMENT_KEY}"];}