--- title: "iOS SDK" slug: "appsafer-ios" updated: 2026-09-17T09:08:11Z published: 2026-09-17T09:08:11Z canonical: "guide.ncloud-docs.com/appsafer-ios" stale: true --- > ## Documentation Index > Fetch the complete documentation index at: https://guide.ncloud-docs.com/llms.txt > Use this file to discover all available pages before exploring further. # iOS SDK Classic/VPC 환경에서 이용 가능합니다. iOS 앱의 보안을 위한 App Safer iOS SDK 사용 방법에 대해 설명합니다. SDK를 설치하고 환경을 구성함으로써 App Safer를 연동할 수 있습니다. 참고 App Safer를 적용하는 전반적인 샘플 코드는 샘플 코드에서 확인해 주십시오. ## SDK 설치 및 환경 구성 App Safer에서 제공하는 기능을 이용하려면 먼저 iOS SDK를 설치한 후 환경을 구성해 주십시오. iOS 앱용 App Safer의 라이브러리는 하나의 프레임워크로 구성되어 있으며, Bitcode Enable/Disable 환경을 모두 지원합니다. 구성하는 방법은 다음과 같습니다. 참고 Xcode 8.0 이상의 환경에서 빌드하는 것을 권장합니다. 1. 다운로드한 SDK를 임의의 디렉터리에서 압축 해제해 주십시오. 2. 프로젝트의 Bitcode 설정을 확인해 주십시오. - 경로: **Build Settings > Build Options > Enable Bitcode** 3. App Safer 프레임워크를 프로젝트에 추가해 주십시오. - 경로: **File** > **Add Files to "Your Project"...** > **Options** > **Copy items if needed** 선택 > **AppSaferFramework.framework** 선택 > **Add** 클릭 4. Swift를 사용하는 경우 Objective-C와의 호환을 위해 Bridging Header를 생성해 주십시오. - 헤더 파일 생성: **File** > **New File...** > **Header File** 선택 > 프로젝트 루트 위치에 파일명 'AppSaferFramework-Bridging-Header.h'으로 설정 - 헤더 파일을 빌드 설정에 추가: **Build Settings** > **Swift Compiler - General** > **Objective-C Bridging Header** > **AppSaferFramework-Bridging-Header.h**에서 다음 코드 입력 ``` #ifndef AppSaferFramework_Bridging_Header_h #define AppSaferFramework_Bridging_Header_h #import #endif /* AppSaferFramework_Bridging_Header_h */ ``` ### 디버깅 방지 기능 적용 디버깅 방지 기능은 SDK를 설치하면 자동으로 적용됩니다. 만약 디버깅이 필요한 경우 App Safer SDK를 일시적으로 적용 해제한 상태에서 사용해 주십시오. ### 캡처 차단 및 탐지 기능 적용 App Safer SDK에서 제공하는 앱 미리 보기 화면 보호, 스크린샷 탐지, 녹화 및 미러링 시 화면 보호 기능을 적용하려면 API를 호출해야 합니다. - iOS 13.0 미만: AppDelegate에서 앱 생명 주기에 맞춰 App Safer API 호출 - iOS 13.0 이상: SceneDelegate에서 앱 생명 주기에 맞춰 App Safer API 호출 API를 호출하는 예제는 다음과 같습니다. `selector`를 등록하면 캡처 이벤트 탐지 시 callback을 받고 원하는 동작을 수행할 수 있습니다. **AppDelegate (Swift)** ``` import UIKit @main class AppDelegate: UIResponder, UIApplicationDelegate { var window: UIWindow? @objc func didDetectCapture() -> Void { print("[DETECT] Detected Screenshot in AppDelegate"); } func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool { AppSafer.registerScreenProtectionObserver(window, observer: self, selector: #selector(didDetectCapture)) return true } func applicationWillResignActive(_ application: UIApplication) { AppSafer.preventScreenshot(window, isInvisible: 0) } func applicationDidEnterBackground(_ application: UIApplication) { AppSafer.preventScreenshot(window, isInvisible: 1) } func applicationWillEnterForeground(_ application: UIApplication) { AppSafer.preventScreenshot(window, isInvisible: 0) } func applicationDidBecomeActive(_ application: UIApplication) { AppSafer.preventScreenshot(window, isInvisible: 1) } } ``` **AppDelegate (Objective-C)** ``` #import "AppDelegate.h" #import @interface AppDelegate () @end @implementation AppDelegate - (void)didDetectCapture { NSLog(@"[DETECT] Detected Screenshot in AppDelegate"); } - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { [AppSafer registerScreenProtectionObserver:_window observer:self selector:@selector(didDetectCapture)]; return YES; } - (void)applicationWillEnterForeground:(UIApplication *)application { [AppSafer preventScreenshot:_window isInvisible:false]; } - (void)applicationDidBecomeActive:(UIApplication *)application { [AppSafer preventScreenshot:_window isInvisible:false]; } - (void)applicationWillResignActive:(UIApplication *)application { [AppSafer preventScreenshot:_window isInvisible:true]; } - (void)applicationDidEnterBackground:(UIApplication *)application { [AppSafer preventScreenshot:_window isInvisible:true]; } @end ``` **SceneDelegate (Swift)** ``` import UIKit import SwiftUI class SceneDelegate: UIResponder, UIWindowSceneDelegate { var window: UIWindow? @objc func didDetectCapture() -> Void { print("[DETECT] Detected Screenshot in AppDelegate"); } func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) { let contentView = ContentView() if let windowScene = scene as? UIWindowScene { let window = UIWindow(windowScene: windowScene) window.rootViewController = UIHostingController(rootView: contentView) self.window = window window.makeKeyAndVisible() AppSafer.registerScreenProtectionObserver(window, observer: self, selector: #selector(didDetectCapture)) } } func sceneDidBecomeActive(_ scene: UIScene) { AppSafer.preventScreenshot(window, isInvisible: 0) } func sceneWillResignActive(_ scene: UIScene) { AppSafer.preventScreenshot(window, isInvisible: 1) } func sceneWillEnterForeground(_ scene: UIScene) { AppSafer.preventScreenshot(window, isInvisible: 0) } func sceneDidEnterBackground(_ scene: UIScene) { AppSafer.preventScreenshot(window, isInvisible: 1) } } ``` **SceneDelegate (Objective-C)** ``` #import "SceneDelegate.h" #import @interface SceneDelegate () @end @implementation SceneDelegate - (void)didDetectCapture { NSLog(@"[DETECT] Detected Screenshot in SceneDelegate"); } - (void)scene:(UIScene *)scene willConnectToSession:(UISceneSession *)session options:(UISceneConnectionOptions *)connectionOptions API_AVAILABLE(ios(13.0)) { [AppSafer registerScreenProtectionObserver:_window observer:self selector:@selector(didDetectCapture)]; } - (void)sceneWillEnterForeground:(UIScene *)scene API_AVAILABLE(ios(13.0)) { [AppSafer preventScreenshot:_window isInvisible:false]; } - (void)sceneDidBecomeActive:(UIScene *)scene API_AVAILABLE(ios(13.0)) { [AppSafer preventScreenshot:_window isInvisible:false]; } - (void)sceneWillResignActive:(UIScene *)scene API_AVAILABLE(ios(13.0)) { [AppSafer preventScreenshot:_window isInvisible:true]; } - (void)sceneDidEnterBackground:(UIScene *)scene API_AVAILABLE(ios(13.0)) { [AppSafer preventScreenshot:_window isInvisible:true]; } @end ``` ## 제공 API App Safer API는 2개의 패키지를 통해 제공되며, 각 패키지에서 호출 가능한 API는 다음과 같습니다. - **AppSafer** | 이름 | 설명 | | --- | --- | | [initAppSafer](/docs/appsafer-ios#initAppSafer) | AppSafer을 사용하기 위해 초기화 | | [checkTampering](/docs/appsafer-ios#checkTampering) | 실시간 보안 탐지 - Jailbreak 탐지 - Simulator 탐지 - Debugging 탐지 - Memory Tampered 탐지 - Unauthorized Signature 탐지 | | [setUserId](/docs/appsafer-ios#setUserId) | 사용자 식별자 설정 | - **AppSaferDelegate** - 비동기로 동작하는 Callback 함수입니다. - 결과 처리는 AppSaferDelegate를 통해 위임됩니다. - 검사 결과를 받으려면 AppSaferDelegate를 구현한 후 initAppSafer 함수를 이용해 등록해야 합니다. - Swift를 사용할 경우 `struct`가 아닌 `class`에 구현해야 하며 AppSaferDelegate와 NSObject를 모두 추가해야 합니다. | 이름 | 필수 여부 | 설명 | | --- | --- | --- | | [appSaferDidInitFinish](/docs/appsafer-ios#appSaferDidInitFinish) | 필수 | App Safer의 초기화 결과 확인 | | [appSaferDidCheckTamperingFinish](/docs/appsafer-ios#appSaferDidCheckTamperingFinish) | 필수 | checkTampering 함수 수행 결과 확인 | | [appSaferDetectedJailbreak](/docs/appsafer-ios#appSaferDetectedJailbreak) | 선택 | 기기의 탈옥 행위 탐지 시 호출 | | [appSaferDetectedSimulator](/docs/appsafer-ios#appSaferDetectedSimulator) | 선택 | 기기가 가상 머신에서 실행 중임을 탐지 시 호출 | | [appSaferDetectedDebugging](/docs/appsafer-ios#appSaferDetectedDebugging) | 선택 | 디버깅 행위 탐지 시 호출 | | [appSaferDetectedMemoryTampered](/docs/appsafer-ios#appSaferDetectedMemoryTampered) | 선택 | 앱의 메모리 변조 탐지 시 호출 | ### initAppSafer App Safer는 초기화를 성공해야만 사용할 수 있습니다. App Safer를 초기화하려면 아래 코드를 사용해 주십시오. 로그를 전송하는 데 필요한 정보 및 전역으로 사용되는 변수가 초기화됩니다. - 초기화 성공 여부를 전달받으려면 AppSaferDelegate를 구현해야 합니다. ``` func initAppSafer(_ delegate: AppSaferDelegate!, serviceCode: String!, key appsaferKey: String!) -> Int32 ``` ``` - (int) initAppSafer:(id)delegate serviceCode:(NSString *)serviceCode key:(NSString *)appsaferKey ``` - 매개변수 | 매개변수 | 설명 | | --- | --- | | delegate | AppSaferDelegate가 구현된 인스턴스 | | serviceCode | App Safer를 이용하기 위한 코드 네이버 클라우드 플랫폼 사용자는 반드시 'ncloud'를 전달 | | appsaferKey | 콘솔에서 앱 등록 시 생성된 App Safer Key 값 | - 반환 값 | 반환 값 | 설명 | | --- | --- | | SUCCESS(0) | 성공 | | FAIL(-1) | 실패 | - 예제 ``` struct ContentView: View { func initAppSaferExample() { // APP_SAFER_KEY generated when registering an app to the Console let result = AppSafer().initAppSafer(AppSaferDelegator.delegator, serviceCode: "ncloud", key: "") NSLog("initAppSafer() result: %d", result); if(result == SUCCESS) { // init success } else if(result == FAIL) { // init fail } } var body: some View { Button("initAppSafer") { initAppSaferExample() } } } ``` ``` #import @implementation ViewController - (IBAction)initAppSaferExample:(id)sender { AppSafer *appSafer = [[AppSafer alloc] init]; int res = FAIL; if(appSafer != nil) { // APP_SAFER_KEY generated when registering an app to the Console res = [appSafer initAppSafer:self serviceCode:@"ncloud" key:@""]; NSLog(@"initAppSafer() result: %d", res); if(res == SUCCESS) { // init success } } } ``` ### checkTampering 실시간 보안 탐지 기능을 실행하려면 아래 코드를 사용해 주십시오. ``` func checkTampering() ``` ``` - (int)checkTampering ``` - 반환 값 | 반환 값 | 설명 | | --- | --- | | SUCCESS(0) | 검사 시작 성공 | | FAIL(-1) | 검사 시작 실패 | | BLOCK(2) | 보안 정책을 위반하여 차단 | | BEFOREINIT(3) | App Safer가 초기화되지 않음 | - 예제 ``` struct ContentView: View { func checkTamperingExample() { let result = AppSafer().checkTampering() switch(result) { case FAIL: print("Failed to check tampering") break case SUCCESS: print("Check Tampering Success") break case BLOCK: print("Device is blocked") break case BEFOREINIT: print("AppSafer is not initialized") break default: break } } var body: some View { Button("checkTampering") { checkTamperingExample() } } } ``` ``` #import @implementation ViewController - (IBAction)checkAppSafer:(id)sender { AppSafer *appSafer = [[AppSafer alloc] init]; if(appSafer != nil) { int res = [appSafer checkTampering]; switch(res) { case FAIL: NSLog(@"Failed to check tampering"); break; case SUCCESS: NSLog(@"Check Tampering Success"); break; case BLOCK: NSLog(@"Device is blocked"); break; case BEFOREINIT: NSLog(@"AppSafer is not initialized"); break; } } else { NSLog(@"AppSafer is nil"); } } @end ``` ### setUserId 초기화 및 탐지 이벤트 발생 시 App Safer 서버로 전송되는 로그에 사용자 식별자를 포함하려면 아래 코드를 사용해 주십시오. ``` func setUserId(_ userId: String!) -> Int32 ``` ``` - (int)setUserId:(NSString *)userId ``` - 매개변수 | 매개변수 | 설명 | | --- | --- | | userId | 사용자 식별자 | - 반환 값 | 반환 값 | 설명 | | --- | --- | | SUCCESS(0) | 설정 성공 | | FAIL(-1) | 설정 실패 | - 예제 ``` struct ContentView: View { func setUserIdExample(_ userId: String) { print("setUserId(\(userId))") let result = AppSafer().setUserId(userId) switch(result) { case FAIL: print("Failed to set userId: \(userId)") break case SUCCESS: print("setUserId() Success: \(userId)") break default: break } } var body: some View { Button("setUserId") { setUserIdExample("ExampleUserId") } } } ``` ``` #import @implementation ViewController - (IBAction)setUserId:(id)sender { AppSafer *appSafer = [[AppSafer alloc] init]; if(appSafer != nil) { NSLog(@"setUserId(%@)", [self.useridText text]); int res = [appSafer setUserId:[self.useridText text]]; switch(res) { case FAIL: NSLog(@"Failed to set userId"); break; case SUCCESS: NSLog(@"setUserId Success"); break; } } else { NSLog(@"AppSafer is nil"); } } ``` ### appSaferDidInitFinish initAppSafer 함수 호출 후 초기화 결과를 전달하기 위해 아래 함수가 호출됩니다. ``` func appSaferDidInitFinish(_ result: Int32) ``` ``` - (void)appSaferDidInitFinish:(int)result ``` - 매개변수 | 매개변수 | 설명 | | --- | --- | | SUCCESS(0) | 초기화 성공 | | FAIL(-1) | 초기화 실패 | | BLOCK(2) | 보안 정책 위반으로 차단됨 | - 예제 ``` func appSaferDidInitFinish(_ result: Int32) { print("appSaferDidInitFinish result: \(result)"); if(result == BLOCK) { print("Device is blocked!"); // add to exit application logic } } ``` ``` #import @implementation ViewController - (void)appSaferDidInitFinish:(NSUInteger)result msg:(NSString *)message { NSLog(@"appSaferDidInitFinish result: %d", result); if(result == BLOCK) { NSLog(@"Device is blocked!"); // add to exit application logic } } ``` ### appSaferDidCheckTamperingFinish checkTampering 함수의 수행 결과를 전달하기 위해 아래 함수가 호출됩니다. ``` func appSaferDidCheckTamperingFinish(_ result: Int32) ``` ``` - (void)appSaferDidCheckTamperingFinish:(int)result ``` - 매개변수 | 매개변수 | 설명 | | --- | --- | | FAIL(-1) | 검사 실패 | | SAFE(0) | 이벤트가 탐지되지 않음 | | DETECT(1) | 이벤트 탐지 | | BLOCK(2) | 차단됨 | - 예제 ``` func appSaferDidCheckTamperingFinish(_ result: Int32) { print("appSaferDidCheckTamperingFinish result: " + ( result == FAIL ? "FAIL" : result == SAFE ? "SAFE" : result == DETECT ? "DETECT" : result == BLOCK ? "BLOCK": "UNKNOWN")) if(result == BLOCK) { print("Device is blocked!") // add to exit application logic } } ``` ``` #import @implementation ViewController - (void)appSaferDidCheckTamperingFinish:(int)result { NSLog(@"appSaferDidCheckTamperingFinish result: %@", result == FAIL ? @"FAIL" : result == SAFE ? @"SAFE" : result == DETECT ? @"DETECT" : result == BLOCK ? @"BLOCK": @"UNKNOWN"); if(result == BLOCK) { NSLog(@"Device is blocked!"); // add to exit application logic } } ``` ### appSaferDetectedJailbreak 기기의 탈옥이 탐지될 때 아래 함수가 호출됩니다. checkTampering 함수 동작이 완료되지 않았더라도 결과를 받고 싶을 때 사용할 수 있습니다. ``` func appSaferDetectedJailbreak() ``` ``` - (void)appSaferDetectedJailbreak ``` - 예제 ``` func appSaferDetectedJailbreak() { print("[DETECT] appSaferDetectedJailbreak"); } ``` ``` #import @implementation ViewController - (void)appSaferDetectedJailbreak { NSLog(@"[DETECT] appSaferDetectedJailbreak"); } ``` ### appSaferDetectedSimulator 앱이 가상 머신에서 실행 중임이 탐지될 때 아래 함수가 호출됩니다. checkTampering 함수 동작이 완료되지 않았더라도 결과를 받고 싶을 때 사용할 수 있습니다. ``` func appSaferDetectedSimulator() ``` ``` - (void)appSaferDetectedSimulator ``` - 예제 ``` func appSaferDetectedSimulator() { print("[DETECT] appSaferDetectedSimulator"); } ``` ``` #import @implementation ViewController - (void)appSaferDetectedSimulator { NSLog(@"[DETECT] appSaferDetectedSimulator"); } ``` ### appSaferDetectedDebugging 기기에서 디버깅이 탐지될 때 아래 함수가 호출됩니다. checkTampering 함수 동작이 완료되지 않았더라도 결과를 받고 싶을 때 사용할 수 있습니다. ``` func appSaferDetectedDebugging() ``` ``` - (void)appSaferDetectedDebugging ``` - 예제 ``` func appSaferDetectedDebugging() { print("[DETECT] appSaferDetectedDebugging"); } ``` ``` #import @implementation ViewController - (void)appSaferDetectedDebugging { NSLog(@"[DETECT] appSaferDetectedDebugging"); } ``` ### appSaferDetectedMemoryTampered 메모리 변조가 탐지될 때 아래 함수가 호출됩니다. checkTampering 함수 동작이 완료되지 않았더라도 결과를 받고 싶을 때 사용할 수 있습니다. ``` func appSaferDetectedMemoryTampered() ``` ``` - (void)appSaferDetectedMemoryTampered ``` - 예제 ``` func appSaferDetectedMemoryTampered() { print("[DETECT] appSaferDetectedMemoryTampered"); } ``` ``` #import @implementation ViewController - (void)appSaferDetectedMemoryTampered { NSLog(@"[DETECT] appSaferDetectedMemoryTampered"); } ```