iOS 통합 가이드
1. 에이전트 소개
NetFUNNEL 에이전트는 NetFUNNEL 서버와 통신하기 위한 일종의 NetFUNNEL 전용 클라이언트 입니다. 사용자는 적용하고자 하는 클라이언트 어플리케이션 코드에 에이전트에서 제공하는 다양한 함수들을 적용, 구현하여 가상 대기실을 적용할 수 있습니다.
1.1 에이전트 요구사항
- iOS 12.0 이상
- Storyboard(Objective-C 및 Swift), SwiftUI
2. 에이전트 설치
NetFUNNEL iOS 에이전트는 .framework 형식으로 제공됩니다. iOS 프로젝트에 .framework 파일을 추가하고, Xcode에 등록합니다.
2.1 에이전트 다운로드
에이전트 파일을 다운로드 합니다.
프로젝트의 포맷에 맞는 에이전트를 설치하기 위한 과정으로 .xcframework를 사용하는 것을 권장합니다.

2.2 Framework 적용
2.2.1 Frameworks 폴더 생성
프로젝트의 루트 경로에 Frameworks 폴더를 생성합니다.

2.2.2 Framework 파일 이동
NetFUNNEL iOS 에이전트를 프로젝트 내 Frameworks 폴더에 추가합니다.

2.2.3 Framework 등록
NetFUNNEL iOS 에이전트를 프로젝트에 Framework 로 포함시킵니다.
[프로젝트 > General > Frameworks, Libraries, and Embedded Content > + 버튼]을 클릭하여 이전 과정에서 위치시킨 경로의 에이전트를 추가합니다.Add Files…버튼을 클릭합니다.

Frameworks에 위치시킨 에이전트를 클릭 후 Open 버튼을 클릭합니다.

아래와 같이 Framework가 표시되면, 프로젝트에 정상적으로 포함된 것입니다.

Framework에 물음표(?)가 표시되는 경우
Xcode에서 프레임워크 파일에 물음표(?)가 표시되는 경우, 해당 프레임워크가 로컬 파일 경로와 연결이 끊겼거나, Git으로 관리되고 있는 외부 파일이 아직 프로젝트에 추가되지 않았을 때 발생합니다.
이러한 경우에는 아래와 같은 방법으로 수동 등록을 통해 문제를 해결할 수 있습니다:
[프레임워크 우클릭 > Source Control > Add netfunnel_ios.xcframework]
정상적으로 등록되면 물음표 아이콘이 사라지고, 빌드 시 프레임워크가 정상적으로 인식됩니다.
3. 에이전트 초기화
NetFUNNEL iOS 에이전트를 초기화하려면, 먼저 초기화 함수에 전달할 델리게이트를 구현해야 합니다.
3.1 델리게이트 정의
NetFUNNEL iOS 에이전트 사용을 위해 델리게이트를 반드시 구현하고, 초기화 함수에 전달합니다.
| 델리게이트 | 필수 | 호출 조건 | 설명 |
|---|---|---|---|
nfSuccess | O | 진입 성공 | • 진입 성공 후 실행될 로직 구현• 대기실 닫힘 |
nfError | O | 넷퍼넬 서버 오류 | • 넷퍼넬 서버 오류 발생 시 로직• 대기 중단 및 대기실 닫힘 |
nfNetworkError | O | 네트워크 오류 | • 네트워크 오류 발생 시 로직• 대기 중단 및 대기실 닫힘 |
nfBlock | X | 진입 차단 | • 차단실이 표시됐을 때 실행될 로직 구현 |
nfClose | X | 종료 함수 호출 후 | • 대기실 종료 후 실행할 로직 |
nfComplete | X | 종료 함수 호출 후 | • 종료 함수 호출 후 실행할 로직 |
nfContinue | X | 넷퍼넬 템플릿 미사용 및 대기 중 | • 커스텀 대기실 UI에 상태 업데이트 로직 구현 |
3.1.1 시작 델리게이트
| 델리게이트 | 상태 코드 | 시나리오 |
|---|---|---|
| nfSuccess | 200 |
|
| 300 |
| |
| 303 |
| |
| nfError | 500 |
|
| nfNetworkError | 1001 |
|
| 1002 |
| |
| nfBlock | 301 |
|
| 302 |
| |
| nfClose | 495 |
|
| 496 |
| |
| 497 |
| |
| 498 |
| |
| 499 |
| |
| nfContinue | 201 |
|
3.1.2 종료 델리게이트
| 콜백 함수 | 상태 코드 | 시나리오 |
|---|---|---|
| nfComplete | 200 |
|
| 500 |
|
- Swift
- Objective-C
import Foundation
import Netfunnel_iOS
class NetfunnelHandler: NSObject, NetfunnelDelegate {
static let shared = NetfunnelHandler()
// MARK: - Required callback closures (must be defined)
var onSuccess: ((String, String, Int, String) -> Void)?
var onError: ((String, String, Int, String) -> Void)?
var onNetworkError: ((String, String, Int, String) -> Void)?
// MARK: - Optional callback closures (define if needed)
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)")
/**
* Logic to handle when queue is successfully passed
* ex - Handle service screen entry
*/
onSuccess?(projectKey, segmentKey, statusCode, message)
}
func nfError(projectKey: String, segmentKey: String, statusCode: Int, message: String) {
NSLog("nfError \(statusCode) \(message)")
/**
* Logic to handle when error occurs
* ex - Display error message to user or bypass
*/
onError?(projectKey, segmentKey, statusCode, message)
}
func nfNetworkError(projectKey: String, segmentKey: String, statusCode: Int, message: String) {
NSLog("nfNetworkError \(statusCode) \(message)")
/**
* Logic to handle when network error occurs
* ex - Guide network reconnection or move to retry screen
*/
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)")
/**
* UI update logic during waiting (only when not using NetFunnel waiting room)
* ex - Update real-time waiting information to custom waiting screen
*/
onContinue?(projectKey, segmentKey, statusCode, message, aheadWait, behindWait, waitTime, progressRate)
}
func nfBlock(projectKey: String, segmentKey: String, statusCode: Int, message: String) {
NSLog("nfBlock \(statusCode) \(message)")
/**
* Logic to handle when user entry is blocked
* ex - Display access restriction message
*/
onBlock?(projectKey, segmentKey, statusCode, message)
}
func nfClose(projectKey: String, segmentKey: String, statusCode: Int, message: String) {
NSLog("nfClose \(statusCode) \(message)")
/**
* Logic to handle when user cancels waiting
* ex - Display termination notice Toast (webview auto return)
*/
onClose?(projectKey, segmentKey, statusCode, message)
}
func nfComplete(projectKey: String, segmentKey: String, statusCode: Int, message: String) {
NSLog("nfComplete \(statusCode) \(message)")
/**
* Logic to handle final completion
* ex - Follow-up processing after waiting completion
*/
onComplete?(projectKey, segmentKey, statusCode, message)
}
}
#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);
/**
* Logic to handle when queue is successfully passed
* ex - Handle service screen entry
*/
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);
/**
* Logic to handle when error occurs
* ex - Display error message to user or bypass
*/
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);
/**
* Logic to handle when network error occurs
* ex - Guide network reconnection or move to retry screen
*/
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);
/**
* UI update logic during waiting (only when not using NetFunnel waiting room)
* ex - Update real-time waiting information to custom waiting screen
*/
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);
/**
* Logic to handle when user entry is blocked
* ex - Display access restriction 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);
/**
* Logic to handle when user cancels waiting
* ex - Display termination notice Toast (webview auto return)
*/
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);
/**
* Logic to handle final completion
* ex - Follow-up processing after waiting completion
*/
if (self.onComplete) {
self.onComplete(projectKey, segmentKey, statusCode, message);
}
}
@end
3.2 초기화 함수 호출
NetFUNNEL iOS 에이전트는 앱 실행과 동시에 초기화되어야 합니다.
AppDelegate의 application(_:didFinishLaunchingWithOptions:)에서 초기화 함수를 호출합니다.
- Swift
- Objective-C
import Netfunnel_iOS
Netfunnel.shared.initialize(
clientId: "{CLIENT_ID}",
serverUrl: "{SERVER_URL}",
errorUrl: "{ERROR_URL}",
delegate: self, // Set the delegate to a specified delegate object or 'self'.
networkTimeout: 3000,
retryCount: 0,
printLog: false,
useNetfunnelTemplate: true,
errorBypass: false,
userId: "{USER_ID}",
useNetworkRecoveryMode: false
)
#import "Netfunnel_iOS/Netfunnel_iOS.h"
Netfunnel *agent = [Netfunnel shared];
[agent initializeWithClientId:@"{CLIENT_ID}"
serverUrl:@"{SERVER_URL}"
errorUrl:@"{ERROR_URL}"
delegate:self // Set the delegate to a specified delegate object or 'self'.
networkTimeout:3000
retryCount:0
printLog:NO
useNetfunnelTemplate:YES
errorBypass:NO
userId:@"{USER_ID}"
useNetworkRecoveryMode:NO];
| 파라미터 | 필수 | 설명 | 조건 | 필수 |
|---|---|---|---|---|
| clientId | String | 사용자를 식별하기 위한 고유 ID | - | O |
| delegate | Object | NetfunnelDelegate를 상속한 View Controller (혹은 클래스) | 프로토콜을 구현한 객체 | O |
| serverUrl | String | 넷퍼넬 서버 주소 | 빈 문자열 불가 | X |
| errorUrl | String | 넷퍼넬 에러페이지 주소 | 빈 문자열 불가 | X |
| networkTimeout | Long | 넷퍼넬 동작의 네트워크 타임아웃 |
| X |
| retryCount | Int | 넷퍼넬 동작의 재시도 횟수 |
| X |
| printLog | Boolean | 넷퍼넬 디버그를 위한 로그 출력 유무 | 기본: false | X |
| errorBypass | Boolean | 에러 발생 시 바이패스 유무 | 기본: false | X |
| useNetfunnelTemplate | Boolean | 넷퍼넬 콘솔에서 설정한 대기실 템플릿 사용 유무 | 기본: true | X |
| userId | String | 넷퍼넬 White/Black List 구분을 위한 데이터 | N/A | X |
| useNetworkRecoveryMode | Boolean | 넷퍼넬 대기중 네트워크 문제가 발생하더라도, 네트워크 회복이 될 때까지 대기실을 종료하지 않고 유지합니다. | 기본: false | X |
4. 에이전트 적용
NetFUNNEL iOS 에이전트에서 제공하는 함수를 통해 특정 화면에 대기실을 적용할 수 있습니다.
시작 함수와 종료 함수에 사용하는 프로젝트 키와 세그먼트 키는 콘솔의 프로젝트 탭에서 확인 가능합니다.
넷퍼넬 적용 함수를 호출할 때는 다음 두 개의 필수 파라미터가 사용됩니다. 이 파라미터들은 넷퍼넬 콘솔에서 생성한 프로젝트와 세그먼트 정보를 식별하는 데 사용됩니다.
| 파라미터 | 타입 | 설명 | 필수 |
|---|---|---|---|
| projectKey | String | 넷퍼넬 콘솔의 구간 제어 프로젝트 키 | O |
| segmentKey | String | 넷퍼넬 콘솔의 구간 제어 세그먼트 키 | O |
4.1 기본제어
4.1.1 시작 함수
특정 화면(View)에서 대기실을 적용시키기 위해서는 에이전트에서 제공하는 대기 시작 함수를 사용하여 가상 대기실을 노출시킬 수 있습니다. 기본 제어는 end-user가 특정 화면에 진입할 때 대기를 적용하여 서버 부하를 조절하고, end-user 경험을 관리하는 데 유용합니다.
- Swift
- Objective-C
import Netfunnel_iOS
var agent = Netfunnel.shared
agent.nfStart(projectKey: "{PROJECT_KEY}", segmentKey: "{SEGMENT_KEY}")
#import "Netfunnel_iOS/Netfunnel_iOS.h" // @import Netfunnel_iOS;
Netfunnel *agent = [Netfunnel shared];
[agent nfStartWithProjectKey: @"{PROJECT_KEY}" segmentKey: @"{SEGMENT_KEY}"];
| 함수명 | 호출 조건 | 설명 |
|---|---|---|
nfStart | 기본 제어 시작 | 이벤트 구간에 대한 시작 시점에 호출합니다. |
4.1.2 종료 함수
기본 제어의 대기를 성공적으로 마치는 경우, 아래와 같은 2가지 상황을 구현해야 합니다.
대기를 마치고 서비스로 진입하는 코드 (타겟 페이지로 진입하는 코드)
비즈니스 로직을 마치고 "대기 종료 함수"를 호출하여 서비스 진입 키를 NetFUNNEL 서버에 반납하는 코드
- Swift
- Objective-C
import Netfunnel_iOS
var agent = Netfunnel.shared
agent.nfStop(projectKey: "{PROJECT_KEY}", segmentKey: "{SEGMENT_KEY}")
#import "Netfunnel_iOS/Netfunnel_iOS.h" // @import Netfunnel_iOS;
Netfunnel *agent = [Netfunnel shared];
[agent nfStopWithProjectKey: @"{PROJECT_KEY}" segmentKey: @"{SEGMENT_KEY}"];
| 함수명 | 호출 조건 | 설명 |
|---|---|---|
nfStop | 기본 제어 종료 | 진입이 완료된 후 서버에 키를 반납하여 다음대기자가 진입할 수 있도록 합니다. |
4.2 구간 제어
4.2.1 시작 함수
구간 제어는 특정 페이지의 진입과 종료 사이에 대기 상태를 적용하는 방법입니다. 구간 제어를 통해 사용자는 페이지의 특정 구간에서 원활한 흐름을 유지할 수 있습니다.
이벤트 페이지에 진입한 후 상품을 구매하고, 결제 완료 버튼을 클릭한 경우
end-user의 로그인 이후 로그아웃할 때까지의 주기
구간 제어를 시작하기 위해서는, "구간 시작 함수"를 사용하여 특정 제어 구간의 시작을 정의해야 합니다. 이에 따라 특정 구간의 흐름에서 대기 상태를 유지하도록 설정할 수 있습니다.
| 함수명 | 호출 조건 | 설명 |
|---|---|---|
nfStartSection | 구간 제어 시작 | 이벤트 구간에 대한 시작 시점에 호출합니다. |
- Swift
- Objective-C
var agent = Netfunnel.shared
agent.nfStartSection(projectKey: "{PROJECT_KEY}", segmentKey: "{SEGMENT_KEY}")
Netfunnel *agent = [Netfunnel shared];
[agent nfStartSectionWithProjectKey: @"{PROJECT_KEY}" segmentKey: @"{SEGMENT_KEY}"];
4.2.2 종료 함수
구간 제어의 대기를 성공적으로 마치는 경우, 아래와 같은 상황을 구현할 수 있습니다.
대기를 마치고 서비스로 진입하는 코드 (타켓 페이지로 진입하는 코드)
구간 제어를 종료하기 위해서는, "구간 종료 함수"를 사용하여 특정 구간의 끝을 정의해야 합니다. 이에 따라 end-user의 구간 제어를 종료하고 다음 end-user가 진입할 수 있도록 설정할 수 있습니다.
| 함수명 | 호출 조건 | 설명 |
|---|---|---|
nfStopSection | 구간 제어 종료 | 진입 성공 이후 구간 종료 시점에 호출합니다. |
- Swift
- Objective-C
import Netfunnel_iOS
var agent = Netfunnel.shared
agent.nfStopSection(projectKey: "{PROJECT_KEY}", segmentKey: "{SEGMENT_KEY}")
#import "Netfunnel_iOS/Netfunnel_iOS.h" // @import Netfunnel_iOS;
Netfunnel *agent = [Netfunnel shared];
[agent nfStopSectionWithProjectKey: @"{PROJECT_KEY}" segmentKey: @"{SEGMENT_KEY}"];