> For the complete documentation index, see [llms.txt](https://help-partner.mallpie.kr/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://help-partner.mallpie.kr/api/sdk/ios-sdk.md).

# iOS SDK 연동 가이드

본 문서는 iOS 애플리케이션에 Mallpie SDK를 연동하기 위한 가이드입니다. SDK는 간편한 설정으로 Mallpie 서비스를 앱 내에 포함시킬 수 있는 환경을 제공합니다.

## 1. 연동 준비 및 요구 사항

* **최소 지원 iOS 버전**: iOS 13.0 이상
* **언어**: Swift

## 2. 프로젝트 설정 (설치)

&#x20;\[[`MallpieSDK.xcframework`](https://next-sellerd-stg.s3.ap-northeast-2.amazonaws.com/cps/prd/sdk/MallpieSDK.xcframework.zip)`]` 파일을 Xcode 프로젝트에 추가해야 합니다.<br>

{% stepper %}
{% step %}

### Xcode 프로젝트 네비게이터 열기

Xcode 프로젝트 네비게이터(Project Navigator)를 엽니다.
{% endstep %}

{% step %}

### General 탭으로 이동

타겟(Target) 설정의 **General** 탭으로 이동합니다.
{% endstep %}

{% step %}

### Frameworks, Libraries, and Embedded Content에 추가

**Frameworks, Libraries, and Embedded Content** 섹션에 `MallpieSDK.xcframework`를 끌어다 놓습니다.
{% endstep %}

{% step %}

### Embed 옵션 확인

추가된 프레임워크의 Embed 옵션이 **Embed & Sign** 으로 설정되어 있는지 확인합니다.
{% endstep %}
{% endstepper %}

## 3. 권한 설정 (Info.plist)

추적 권한(App Tracking Transparency)을 획득하기 위해 애플리케이션의 `Info.plist` 파일에 다음 항목을 반드시 추가해야 합니다. 이 권한은 SDK 내부적으로 ADID 식별자를 수집하여 사용자 식별을 돕는 데 사용됩니다. (이 권한 팝업은 iOS 14.0 이상 기기에서 동작하며, SDK가 이를 적절히 처리합니다.)

```xml
<key>NSUserTrackingUsageDescription</key>
<string>고객님에게 맞춤형 서비스 혜택을 제공하기 위해 추적 권한이 필요합니다.</string>
```

### 3.1 외부 앱(결제 등) 딥링크 호출 설정 (Info.plist)

Mallpie 서비스 내에서 **토스페이먼츠(Toss Payments) 및 기타 카드사 앱을 통해 결제를 진행**하려면 해당 앱들의 스키마(Scheme)가 SDK 호스트 앱의 `Info.plist` 내 권한 목록에 선언되어 있어야 합니다. 애플 정책상 이를 누락하면 외부 결제 수단으로 넘어갈 수 없습니다. 자세한 내용은 [토스페이먼츠 웹뷰 가이드](https://docs.tosspayments.com/guides/v2/webview)를 참고하시거나, 본 SDK의 샘플 프로젝트(`MallpieIOSSample`) 설정을 확인해 주시기 바랍니다.

```xml
<key>LSApplicationQueriesSchemes</key>
<array>
    <string>supertoss</string>
    <string>kb-acp</string>
    <string>liivbank</string>
    <string>newliiv</string>
    <string>kbbank</string>
    <string>nhappcardansimclick</string>
    <string>nhallonepayansimclick</string>
    <string>nonghyupcardansimclick</string>
    <string>lottesmartpay</string>
    <string>lotteappcard</string>
    <string>mpocket.online.ansimclick</string>
    <string>ansimclickscard</string>
    <string>tswansimclick</string>
    <string>ansimclickipcollect</string>
    <string>vguardstart</string>
    <string>samsungpay</string>
    <string>scardcertiapp</string>
    <string>shinhan-sr-ansimclick</string>
    <string>smshinhanansimclick</string>
    <string>com.wooricard.wcard</string>
    <string>newsmartpib</string>
    <string>citispay</string>
    <string>citicardappkr</string>
    <string>citimobileapp</string>
    <string>cloudpay</string>
    <string>hanawalletmembers</string>
    <string>hdcardappcardansimclick</string>
    <string>smhyundaiansimclick</string>
    <string>shinsegaeeasypayment</string>
    <string>payco</string>
    <string>lpayapp</string>
    <string>ispmobile</string>
    <string>tauthlink</string>
    <string>ktauthexternalcall</string>
    <string>upluscorporation</string>
    <string>kftc-bankpay</string>
    <string>kakaotalk</string>
    <string>wooripay</string>
    <string>lmslpay</string>
    <string>naversearchthirdlogin</string>
    <string>hanaskcardmobileportal</string>
    <string>kb-bankpay</string>
    <string>kakaobank</string>
    <string>monimopay</string>
    <string>monimopayauth</string>
</array>
```

## 4. SDK 초기화 (Initialization)

앱이 시작되는 시점(예: `AppDelegate`의 `didFinishLaunchingWithOptions` 내부)에 `MallpieSDK.shared.initialize()` 메서드를 한 번 호출하여 SDK를 초기화합니다.

### 4.1 초기화 파라미터 설명

* `userKey`: (필수) 암호화된 사용자 고유 식별자 키 (복호화 필요 없음.)
* `apiKey`: (필수) 발급받은 Mallpie API 키
* `isTrackingEnabled`: (선택) ADID 수집 활성화 여부 (기본값: `true`)
* `isDev`: (선택) 개발 환경 여부 설정 (기본값: `false`)
* `allowsSwipeBack`: (선택) 스와이프 백 제스처 (왼쪽 엣지 스와이프) 활성화 여부 (기본값: `false`)
* `headerViewProvider`: (선택) SDK 상단에 표시할 커스텀 헤더 뷰를 제공하는 클로저
* `footerViewProvider`: (선택) SDK 하단에 표시할 커스텀 푸터 뷰를 제공하는 클로저
* `delegate`: (선택) 뒤로가기 및 화면 닫힘 이벤트를 제어할 델리게이트 객체
* `completion_handler`: (선택) 초기화 완료 혹은 실패 결과를 전달받는 클로저 (`nil` 이면 결과 상관없이 패스)

### 4.2 초기화 예시 코드

```swift
import UIKit
import MallpieIOS

@main
class AppDelegate: UIResponder, UIApplicationDelegate {
    var window: UIWindow?

    func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
        
        // 1. SDK 초기화
        MallpieSDK.shared.initialize(
            userKey: "사용자_고유_키",
            apiKey: "발급받은_API_KEY",
            isDev: false,
            allowsSwipeBack: true,
            completion_handler: { error in
                if error == nil {
                    print("SDK 초기화 성공")
                } else {
                    print("SDK 초기화 실패: \(String(describing: error))")
                }
            }
        )
        
        // 2. 윈도우 구성 
        let window = UIWindow(frame: UIScreen.main.bounds)
        window.rootViewController = MyRootViewController() // 여러분의 루트 뷰컨트롤러
        self.window = window
        window.makeKeyAndVisible()
        
        return true
    }
}

// 닫기 버튼의 Action을 처리할 헬퍼 클래스 예시
class CloseActionTarget {
    weak var viewController: UIViewController?
    
    init(viewController: UIViewController) {
        self.viewController = viewController
    }
    
    @objc func close() {
        guard let vc = viewController else { return }
        if let nav = vc.navigationController ?? vc.presentedViewController?.navigationController {
            nav.popViewController(animated: true)
        } else {
            vc.dismiss(animated: true)
        }
    }
}
```

## 5. SDK 화면 호출 및 사용

앱의 특정 화면(버튼 클릭 이벤트 등)에서 SDK 진입을 실행할 때는 `start()` 메서드를 호출합니다.

```swift
import MallpieIOS

// SDK를 띄울 ViewController를 명시적으로 파라미터로 전달합니다. (내부적으로 Push 또는 Present 처리됨)
let result = MallpieSDK.shared.start(from: self)

switch result {
case .success:
    print("SDK 화면 호출 성공")
case .failure(let error):
    print("SDK 화면 호출 실패: \(error)")
}
```

> **참고**: `start()`를 호출한 시점에 아직 `initialize()` 과정이 끝나지 않았다면, SDK는 초기화가 끝날 때까지 백그라운드 모드로 대기한 뒤 완료 즉시 자동으로 화면을 띄워줍니다.

## 6. 하이브리드 앱 또는 커스텀 UI 내 웹뷰 생성

기본 화면 호출 방식 외에도, 직접 네이티브 뷰(`UIView`) 계층에 Mallpie 전용 웹뷰를 삽입하고 싶을 때는 `createWebView()`를 사용합니다.

```swift
if let mallpieWebView = MallpieSDK.shared.createWebView() {
    // 반환된 mallpieWebView 객체를 뷰 계층에 추가해주면 됩니다.
    mallpieWebView.translatesAutoresizingMaskIntoConstraints = false
    view.addSubview(mallpieWebView)
    
    // 오토 레이아웃 설정
    NSLayoutConstraint.activate([
        mallpieWebView.topAnchor.constraint(equalTo: view.safeAreaLayoutGuide.topAnchor),
        mallpieWebView.leadingAnchor.constraint(equalTo: view.leadingAnchor),
        mallpieWebView.trailingAnchor.constraint(equalTo: view.trailingAnchor),
        mallpieWebView.bottomAnchor.constraint(equalTo: view.bottomAnchor)
    ])
} else {
    print("SDK 초기화가 완료되지 않아 뷰를 생성할 수 없습니다.")
}
```

## 7. 고급 설정 및 이벤트 제어

### 7.1 커스텀 헤더 뷰 생성 (HeaderViewProvider)

기본으로 열리는 `MallpieIOSViewController` 최상단에, 서비스 고유의 네이티브 뒤로 가기 버튼이나 로고 등을 직접 그리고 싶을 경우 사용할 수 있습니다.

```swift
MallpieSDK.shared.initialize(
    // ... 기본 파라미터 생략 ...
    headerViewProvider: { viewController in
        // 상단에 표시될 커스텀 헤더 UI 생성 (예: 높이 50)
        let header = UIView(frame: CGRect(x: 0, y: 0, width: UIScreen.main.bounds.width, height: 50))
        header.backgroundColor = .systemBlue
        
        // 닫기 버튼 생성
        let closeButton = UIButton(type: .system)
        closeButton.setTitle("닫기", for: .normal)
        closeButton.setTitleColor(.white, for: .normal)
        closeButton.translatesAutoresizingMaskIntoConstraints = false
        
        // 닫기 버튼 액션 연결 (#selector 방식)
        let target = CloseActionTarget(viewController: viewController)
        // 액션 타겟을 메모리에 유지하기 위해 associated object 등으로 참조를 잡아두는 것을 권장합니다.
        objc_setAssociatedObject(closeButton, "closeAction", target, .OBJC_ASSOCIATION_RETAIN_NONATOMIC)
        closeButton.addTarget(target, action: #selector(CloseActionTarget.close), for: .touchUpInside)
        
        header.addSubview(closeButton)
        
        // ... 제약 조건 설정 로직 등 (예제 생략)
        return header
    }
)
```

### 7.2 커스텀 푸터 뷰 생성 (FooterViewProvider)

기본으로 열리는 `MallpieIOSViewController` 최하단에, 앱 고유의 커스텀 내비게이션 바나 안내 문구 등을 포함하고 싶을 경우 사용할 수 있습니다.

```swift
MallpieSDK.shared.initialize(
    // ... 기본 파라미터 생략 ...
    footerViewProvider: { viewController in
        // 하단에 표시될 커스텀 푸터 UI 생성 (예: 높이 60)
        let footer = UIView(frame: CGRect(x: 0, y: 0, width: UIScreen.main.bounds.width, height: 60))
        footer.backgroundColor = .systemGroupedBackground
        
        let label = UILabel()
        label.text = "커스텀 푸터 영역"
        label.sizeToFit()
        footer.addSubview(label)
        
        return footer
    }
)
```

### 7.3 SDK 델리게이트 이벤트 수신 (MallpieSDKDelegate)

`MallpieSDK.shared.initialize()` 선언부 영역에서 등록할 수 있는 `MallpieSDKDelegate` 델리게이트는 사용자가 뒤로가기 동작을 했거나 화면이 사라지는 시점을 후킹하여 동작을 제어할 수 있도록 도와줍니다.

```swift
class MySDKDelegate: MallpieSDK.MallpieSDKDelegate {
    static let shared = MySDKDelegate()
    
    func mallpieSDKShouldHandleBackAction(_ webView: MallpieWebView) -> Bool {
        // 뒤로가기 액션(왼쪽 스와이프 등)이 발생했을 때 호출됩니다.
        // webView.canGoBack 을 파악하여 현재 웹뷰의 히스토리 등을 판별할 수 있습니다.
        
        // true를 반환하면 SDK의 내부 기본 동작(웹 히스토리 백 -> 없으면 화면 종료)을 따릅니다.
        // false를 반환하면 SDK가 자체적으로 아무 행동도 하지 않아 연동 측에서 직접 제어가 가능합니다.
        return true 
    }
    
    func mallpieSDKWillDismiss() {
        // SDK 화면 자체가 닫히기 직전에 최종적으로 호출됩니다.
        print("SDK 뷰가 닫힙니다.")
    }
}
```

### 7.4 자바스크립트 커스텀 네이티브 동작 추가 (addCustomAction)

Mallpie 웹뷰 내에서 호출할 수 있는 커스텀 네이티브 동작을 등록할 수 있습니다. 자바스크립트에서 특정 함수명으로 네이티브 이벤트를 호출할 수 있도록 연결합니다.

```swift
MallpieSDK.shared.addCustomAction(functionName: "myCustomFunction") { payload in
    print("웹에서 전달받은 데이터: \(payload ?? "없음")")
    // 원하는 네이티브 동작 수행
}
```

### 7.5 푸터(Footer) 노출 설정 (setFooterVisible)

SDK 내부 하단 영역에 노출되는 푸터의 가시성을 동적으로 제어할 수 있습니다.

```swift
// 푸터 숨기기
MallpieSDK.shared.setFooterVisible(false)

// 푸터 다시 보이기
MallpieSDK.shared.setFooterVisible(true)
```

### 7.6 현재 웹뷰 URL 가져오기 (getCurrentUrl)

현재 실행 중인 Mallpie 웹뷰의 URL을 프로그래밍 방식으로 확인할 수 있습니다.

```swift
let currentUrl = MallpieSDK.shared.getCurrentUrl()
if let url = currentUrl {
    print("현재 로드된 URL: \(url)")
}
```

### 7.7 웹뷰 페이지 이동 이벤트 수신 (onPageNavigation)

웹뷰 내에서 새로운 페이지로 이동(Navigation)이 시작될 때마다 호출되는 콜백을 등록하여, 현재 진입하는 URL을 실시간으로 확인할 수 있습니다.

```swift
MallpieSDK.shared.onPageNavigation = { url in
    print("웹뷰 페이지 이동 감지: \(url)")
    // 필요한 애널리틱스 트래킹이나 조건부 네이티브 로직 수행
}
```

## 8. 에러 핸들링 가이드 (`MallpieSDKError`)

SDK 초기화 및 구동 중 예외 상황이 발생하면 `completion_handler` 콜백을 통해 `MallpieSDKError` 열거형(Enum) 객체가 반환됩니다. 에러 객체는 고유의 케이스를 가지고 있어 서비스 측에서 상황에 맞는 적절한 UI 처리 및 예방 로직을 작성할 수 있습니다.

### 8.1 에러 확인 방법 예시

```swift
MallpieSDK.shared.initialize(
    // ... 파라미터 생략 ...
    completion_handler: { error in
        if let error = error {
            switch error {
            case .shopIdNotInitialized:
                print("[E001] Shop ID 획득 실패. 통신 상태를 확인해주세요.")
            case .networkError(let message):
                print("[E100] 네트워크 에러 발생: \(message)")
            default:
                print("SDK 초기화 실패: \(error)")
            }
        } else {
            print("SDK 초기화 성공")
        }
    }
)
```

### 8.2 SDK 에러 명세 (`MallpieSDKError` Enum)

#### 인증 및 초기화 관련 (E0xx)

| 에러 케이스                       | 대응 에러 코드 | 설명                                                  |
| ---------------------------- | -------- | --------------------------------------------------- |
| **`shopIdNotInitialized`**   | E001     | Shop ID가 초기화되지 않았습니다. API 연결 상태를 확인해주세요.            |
| **`mediaKeyNotInitialized`** | E002     | API Key(Media Key)가 누락되거나 유효하지 않습니다.                |
| **`userKeyNotInitialized`**  | E003     | User Key가 누락되었습니다. SDK 초기화 시점에 올바른 사용자 키를 입력해야 합니다. |
| **`initializing`**           | E004     | SDK가 이미 초기화 중입니다. 이전 호출의 응답을 기다려주세요.                |

#### 네트워크 및 시스템 연동 (E1xx \~ E3xx)

| 에러 케이스                           | 대응 에러 코드 | 설명                                 |
| -------------------------------- | -------- | ---------------------------------- |
| **`networkError(message:)`**     | E100     | 네트워크 연결 오류 혹은 서버 상태 이상 시 발생합니다.    |
| **`internalApiError(message:)`** | E200     | Mallpie 서버 간의 내부 통신 에러 발생 시 반환됩니다. |
| **`otherError(message:)`**       | E300     | SDK 구동 중 알 수 없는 예외 상황 발생 시 반환됩니다.  |

#### 주의 (경고성 메시지)

| 에러 케이스                   | 대응 에러 코드 | 설명                                                                           |
| ------------------------ | -------- | ---------------------------------------------------------------------------- |
| **`adIdNotInitialized`** | W001     | 광고 식별자(ADID) 수집 실패. (SDK 기능 자체는 정상 작동하나, 추천상품 등 개인화된 서비스 제공에 제한이 있을 수 있습니다.) |
