본문으로 건너뛰기
버전: 4.6.1-saas

iOS 에이전트

개요

NetFUNNEL 에이전트는 NetFUNNEL 서버와 통신하기 위한 일종의 NetFUNNEL 전용 클라이언트 입니다. 사용자는 적용하고자 하는 클라이언트 어플리케이션 코드에 에이전트에서 제공하는 다양한 함수들을 적용, 구현하여 가상 대기실을 적용할 수 있습니다.

최소 요구 사항

  • iOS 15.6 이상
  • Storyboard(Objective-C, Swift), SwiftUI

에이전트 동작 흐름

대기 전

  • 대기 전, 설정 정보를 초기화합니다. 이 과정은 NetFUNNEL 서버로부터 설정 정보를 Fetch하고 해당 정보들을 기반으로 객체들을 초기화하는 과정입니다.
  • “초기화 함수”를 사용하여 NetFUNNEL의 설정 정보를 초기화하세요.

대기 중

  • 가상 대기실을 노출하여 트래픽 대기를 적용하고 싶은 화면(View)에서 대기시키는 과정입니다.
  • “대기 시작 함수”를 사용하여 가상 대기실을 적용하세요.

대기 후

  • 대기가 종료된 이후 상황에 대한 처리 과정입니다. end-user의 대기가 종료되는 상황은 다음과 같습니다.
    • 대기 마친 후, 진입 성공
    • 대기 도중, 서버 에러 혹은 네트워크 에러 상황으로 인해 진입 실패
    • 대기 도중, end-user의 대기 취소
  • “콜백 함수”와 “대기 종료 함수”를 사용하여 대기 종료 후 로직을 구현하세요.

에이전트 설치

에이전트 다운로드

NetFUNNEL 콘솔의 에이전트 탭에서 NetFUNNEL iOS 에이전트를 다운로드합니다. 프로젝트의 포맷에 맞는 에이전트를 설치하기 위한 과정으로 .xcframework를 사용하는 것을 권장합니다.

에이전트 적용

Frameworks 폴더 생성

프로젝트의 루트 경로에 Frameworks 폴더를 생성합니다.

Frameworks 파일 이동

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

Frameworks 등록

NetFUNNEL iOS 에이전트를 프로젝트에 Framework로 포함시킵니다.

  1. [프로젝트 > General > Frameworks, Libraries, and Embedded Content > + 버튼]을 클릭하여 이전 과정에서 위치시킨 경로의 에이전트를 추가합니다.

  2. [Add Files…] 버튼을 클릭합니다.

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

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

위험

Xcode에서 프레임워크 파일에 물음표(?)가 표시되는 경우, 해당 프레임워크가 로컬 파일 경로와 연결이 끊겼거나, Git으로 관리되고 있는 외부 파일이 아직 프로젝트에 추가되지 않았을 때 발생합니다.

이러한 경우에는 아래와 같은 방법으로 수동 등록을 통해 문제를 해결할 수 있습니다:

[프레임워크 우클릭 > Source Control > Add netfunnel_ios.xcframework]

정상적으로 등록되면 물음표 아이콘이 사라지고, 빌드 시 프레임워크가 정상적으로 인식됩니다.

에이전트 초기화

NetFUNNEL iOS 에이전트는 앱 실행과 동시에 초기화되어야 합니다.

정보

AppDelegate의 application(_:didFinishLaunchingWithOptions:) 메서드에서 앱 시작 시 한 번만 실행될 수 있도록 초기화 작업을 수행합니다.

Swift

let agent = Netfunnel.shared
agent.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
)

Objective-c

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];
파라미터타입설명필수 여부조건
clientIdString사용자 고유 아이디O
delegateNetfunnelDelegateNetfunnelDelegate를 상속한 View Controller (혹은 클래스)O프로토콜을 구현한 객체
serverUrlString넷퍼넬 서버 주소X빈 문자열 불가
errorUrlString넷퍼넬 에러페이지 주소X빈 문자열 불가
networkTimeoutNSNumber (Long)넷퍼넬 동작의 네트워크 타임아웃X기본 (ms): 3,000
최대 (ms): 10,000
최소 (ms): 100
retryCountNSNumber (Int)넷퍼넬 동작의 재시도 횟수X기본 (time): 0
최대 (time): 10
최소 (time): 0
printLogNSNumber (Bool)넷퍼넬 디버그를 위한 로그 출력 유무X기본: false
errorBypassNSNumber (Bool)에러 발생 시 바이패스 유무X기본: false
useNetfunnelTemplateNSNumber (Bool)넷퍼넬 콘솔에서 설정한 대기실 템플릿 사용 유무X기본: true
userIdString넷퍼넬 White/Black List 구분을 위한 데이터XN/A
useNetworkRecoveryModeNSNumber (Bool)넷퍼넬 대기중 네트워크 문제가 발생하더라도 네트워크 회복 시까지 대기실을 종료하지 않고 유지X기본: false

에이전트 적용

NetFUNNEL iOS 에이전트에서 제공하는 함수를 통해 특정 화면에 대기실을 적용할 수 있습니다.

정보

시작 함수와 종료 함수에 사용하는 프로젝트 키와 세그먼트 키는 콘솔의 프로젝트 탭에서 확인 가능합니다.

델리게이트

NetFUNNEL iOS 에이전트를 사용하기 위해서는 시작 함수와 종료 함수에 델리게이트를 반드시 주입해야 합니다.

대기실은 다양한 상황(대기 성공, 취소, 차단, 에러, 네트워크 오류 등)에 따라 종료될 수 있으며, 각 상황에 대한 처리 시나리오는 델리게이트를 통해 구현할 수 있습니다.

델리게이트필수 구현 여부
nfSuccess필수
nfError필수
nfNetworkError필수
nfBlock선택
nfClose선택
nfContinue선택
nfComplete선택

시작 델리게이트

델리게이트상태 코드시나리오
nfSuccess200대기열을 정상 통과하여 서비스 이용이 허용
nfSuccess300구독이나 라이센스 만료
콘솔의 프로젝트/세그먼트 비활성화
에이전트의 errorBypass=true 설정 및 에러 발생 시
nfSuccess303콘솔의 화이트리스트에 등록된 IP 혹은 ID로 요청한 경우 (관리자 전용 바이패스)
nfError500에이전트의 초기화 함수 없이 시작 함수 호출
에이전트의 시작 함수에 존재하지 않는 프로젝트/세그먼트 키 사용
콘솔의 세그먼트 삭제
서버 에러로 인해 응답이 일부 누락된 경우
nfNetworkError1001네트워크 연결 차단 (와이파이, 셀룰러 데이터 차단)
nfNetworkError1002네트워크 타임아웃
서버 에러로 인해 유효하지 않은 HTML URL 받은 경우
서버 다운으로 인해 응답받지 못할 경우 (502 등)
nfBlock301콘솔의 세그먼트 차단 (선의적 진입 차단)
nfBlock302콘솔의 블랙리스트에 등록된 IP 혹은 ID로 요청한 경우 (관리자 전용 차단)
콘솔의 BotManager Basic 활성화 (악의적 진입 차단)
nfClose495사후 대기실의 닫기 버튼 클릭
nfClose496사전 대기실의 닫기 버튼 클릭
nfClose497매크로 차단실의 닫기 버튼 클릭
nfClose498차단실의 닫기 버튼 클릭
nfClose499기본 대기실의 취소 버튼 클릭
nfContinue201에이전트의 useNetfunnelTemplate=false 설정 및 기본 대기 시

종료 델리게이트

콜백 함수상태 코드시나리오
nfComplete200대기 완료 후 서버에 진입 키 반납을 성공한 경우
nfComplete500대기 완료 후 서버에 진입 키 반납을 실패한 경우

Swift

import Foundation
import 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)")
/**
* 대기열 통과 시 처리할 로직
* ex - 서비스 화면 진입 처리
*/
onSuccess?(projectKey, segmentKey, statusCode, message)
}

func nfError(projectKey: String, segmentKey: String, statusCode: Int, message: String) {
NSLog("nfError \(statusCode) \(message)")
/**
* 에러 발생 시 처리할 로직
* ex - 사용자에게 오류 메시지 표시 또는 바이패스
*/
onError?(projectKey, segmentKey, statusCode, message)
}

func nfNetworkError(projectKey: String, segmentKey: String, statusCode: Int, message: String) {
NSLog("nfNetworkError \(statusCode) \(message)")
/**
* 네트워크 에러 발생 시 처리할 로직
* ex - 네트워크 재연결 안내 또는 재시도 화면으로 이동
*/
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 업데이트 로직 (넷퍼넬 대기실 미사용 시에만 해당)
* ex - 실시간 대기 정보를 커스텀 대기 화면에 업데이트
*/
onContinue?(projectKey, segmentKey, statusCode, message, aheadWait, behindWait, waitTime, progressRate)
}

func nfBlock(projectKey: String, segmentKey: String, statusCode: Int, message: String) {
NSLog("nfBlock \(statusCode) \(message)")
/**
* 사용자 진입 차단 시 처리할 로직
* ex - 접근 제한 메시지 표시
*/
onBlock?(projectKey, segmentKey, statusCode, message)
}

func nfClose(projectKey: String, segmentKey: String, statusCode: Int, message: String) {
NSLog("nfClose \(statusCode) \(message)")
/**
* 사용자가 대기를 취소한 경우 처리할 로직
* ex - 종료 안내 Toast 표시 (웹뷰 자동 복귀)
*/
onClose?(projectKey, segmentKey, statusCode, message)
}

func nfComplete(projectKey: String, segmentKey: String, statusCode: Int, message: String) {
NSLog("nfComplete \(statusCode) \(message)")
/**
* 최종 완료 시 처리할 로직
* ex - 대기 완료 후 후속 처리
*/
onComplete?(projectKey, segmentKey, statusCode, message)
}
}

Objective-c

#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);
/**
* 대기열 통과 시 처리할 로직
* ex - 서비스 화면 진입 처리
*/
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);
/**
* 에러 발생 시 처리할 로직
* ex - 사용자에게 오류 메시지 표시 또는 바이패스
*/
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);
/**
* 네트워크 에러 발생 시 처리할 로직
* ex - 네트워크 재연결 안내 또는 재시도 화면으로 이동
*/
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 업데이트 로직 (넷퍼넬 대기실 미사용 시에만 해당)
* ex - 실시간 대기 정보를 커스텀 대기 화면에 업데이트
*/
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);
/**
* 사용자 진입 차단 시 처리할 로직
* ex - 접근 제한 메시지 표시
*/
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);
/**
* 사용자가 대기를 취소한 경우 처리할 로직
* ex - 종료 안내 Toast 표시 (웹뷰 자동 복귀)
*/
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);
/**
* 최종 완료 시 처리할 로직
* ex - 대기 완료 후 후속 처리
*/
if (self.onComplete) {
self.onComplete(projectKey, segmentKey, statusCode, message);
}
}

@end

기본 제어

시작 함수

특정 화면(View)에서 대기실을 적용시키기 위해서는 에이전트에서 제공하는 대기 시작 함수를 사용하여 가상 대기실을 노출시킬 수 있습니다. 기본 제어는 end-user가 특정 화면에 진입할 때 대기를 적용하여 서버 부하를 조절하고, end-user 경험을 관리하는 데 유용합니다.

Swift

var agent = Netfunnel.shared
agent.nfStart(projectKey: "{{PROJECT_KEY}}", segmentKey: "{{SEGMENT_KEY}}")

Objective-c

Netfunnel *agent = [Netfunnel shared];
[agent nfStartWithProjectKey: @"{{PROJECT_KEY}}" segmentKey:@"{{SEGMENT_KEY}}"];
파라미터타입설명필수 여부
projectKeyString콘솔의 기본 제어 프로젝트 키O
segmentKeyString콘솔의 기본 제어 세그먼트 키O

종료 함수

기본 제어의 대기를 성공적으로 마치는 경우, 아래와 같은 2가지 상황을 구현해야 합니다.

  • 대기를 마치고 서비스로 진입하는 코드 (타겟 페이지로 진입하는 코드)
  • 비즈니스 로직을 마치고 “대기 종료 함수”를 호출하여 서비스 진입 키를 NetFUNNEL 서버에 반납하는 코드

Swift

var agent = Netfunnel.shared
agent.nfStop(projectKey: "{{PROJECT_KEY}}", segmentKey: "{{SEGMENT_KEY}}")

Objective-c

Netfunnel *agent = [Netfunnel shared];
[agent nfStopWithProjectKey: @"{{projectKey}}" segmentKey:@"{{segmentKey}}"];
파라미터타입설명필수 여부
projectKeyString넷퍼넬 콘솔의 기본 제어 프로젝트 키O
segmentKeyString넷퍼넬 콘솔의 기본 제어 세그먼트 키O

구간 제어

시작 함수

구간 제어는 특정 페이지의 진입과 종료 사이에 대기 상태를 적용하는 방법입니다. 구간 제어를 통해 사용자는 페이지의 특정 구간에서 원활한 흐름을 유지할 수 있습니다.

  • 이벤트 페이지에 진입한 후 상품을 구매하고, 결제 완료 버튼을 클릭한 경우
  • end-user의 로그인 이후 로그아웃할 때까지의 주기

구간 제어를 시작하기 위해서는, “구간 시작 함수”를 사용하여 특정 제어 구간의 시작을 정의해야 합니다. 이에 따라 특정 구간의 흐름에서 대기 상태를 유지하도록 설정할 수 있습니다.

Swift

var agent = Netfunnel.shared
agent.nfStartSection(projectKey: "{{projectKey}}", segmentKey: "{{segmentKey}}")

Objective-c

Netfunnel *agent = [Netfunnel shared];
[agent nfStartSectionWithProjectKey: @"{{projectKey}}" segmentKey:@"{{segmentKey}}"];
파라미터타입설명필수 여부
projectKeyString콘솔의 구간 제어 프로젝트 키O
segmentKeyString콘솔의 구간 제어 세그먼트 키O

종료 함수

구간 제어의 대기를 성공적으로 마치는 경우, 아래와 같은 상황을 구현할 수 있습니다.

  • 대기를 마치고 서비스로 진입하는 코드 (타켓 페이지로 진입하는 코드)

구간 제어를 종료하기 위해서는, “구간 종료 함수”를 사용하여 특정 구간의 끝을 정의해야 합니다. 이에 따라 end-user의 구간 제어를 종료하고 다음 end-user가 진입할 수 있도록 설정할 수 있습니다.

Swift

var agent = Netfunnel.shared
agent.nfStopSection(projectKey: "{{projectKey}}", segmentKey: "{{segmentKey}}")

Objective-c

Netfunnel *agent = [Netfunnel shared];
[agent nfStopSectionWithProjectKey: @"{{projectKey}}" segmentKey:@"{{segmentKey}}"];
파라미터타입설명필수 여부
projectKeyString넷퍼넬 콘솔의 구간 제어 프로젝트 키O
segmentKeyString넷퍼넬 콘솔의 구간 제어 세그먼트 키O