[SDK 개발] 브랜드상품권 SDK 설계

이 글은 SDK 개발기 2편이다. 1편: SDK 개발 1편 — Framework, Static Library, XCFramework — 포장과 배포 이야기. 이번 편은 그 안에 담을 공개 API 설계다.

1. 공개 API 설계 - 세 타입이 전부

설계 기준은 하나였다 → 파트너 개발자가 가이드 문서 없이 자동완성만으로 연동을 끝낼 수 있을까?

공개 (3개)                          내부 (4개)
 ├── BrandGiftConfig                 ├── APIClient        토큰 → 인가코드 통신
 │   └── Environment (enum)          ├── FieldCrypto      AES-128 GCM 필드 암호화
 ├── BrandGiftError (enum)           ├── BrandGiftWebViewController  웹뷰 + 브리지
 └── BrandGiftWebView                └── DeviceInfo       NMA_* 단말정보

BrandGiftConfig - 키는 전부 주입 받는다.

public struct BrandGiftConfig {
    public enum Environment { case development, production }

    public let environment: Environment
    public let orgCode: String          // 문서상 org_id → API에선 ORG_CD
    public let clientID: String
    public let clientSecret: String
    public let encKey: String?          // nil이면 필드 암호화 미사용
    public let messageHandlerName: String
    public let enableLogging: Bool      // SDK 내부 로그 on/off (기본 false)

    public init(..., encKey: String? = nil,
                messageHandlerName: String = "partnerBridge",
                enableLogging: Bool = false)
}

BrandGiftError

 public enum BrandGiftError: Error {
    case network(Error)
    case server(code: String, message: String)
    case encryptionFailed
    case invalidResponse
}

BUILD_LIBRARY_FOR_DISTRIBUTION=YES (library evolution 모드)에서 public enum은 기본이 non-frozen 이다.

파트너는 @unknown default 로 미래의 case에 대비하도록 컴파일러가 안내하고, 우리는 나중에 case를 추가해도 바이너리 호환이 유지된다. 배포용 SDK 설정이 API 설계의 제약 하나를 풀어주는 셈

📄 Library Evolution in Swift | Swift.org Blog

BrandGiftWebView - 진입점은 메서드 하나

public final class BrandGiftWebView {
		public init(config: BrandGiftConfig)
		public func present(from viewController: UIViewController,
												ci: String,
												completion: ((Result<Void, BrandGiftError>) -> Void)? = nil)
}

파트너가 호출하는건 이게 전부