이 글은 SDK 개발기 2편이다. 1편: SDK 개발 1편 — Framework, Static Library, XCFramework — 포장과 배포 이야기. 이번 편은 그 안에 담을 공개 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)
}
encKey: String?
public init 을 직접 선언
baseURL 은 extension BrandGiftConfig에 internal로 뒀다. 같은 public struct에 붙어 있어도 internal 멤버는 .swiftinterface에 안나온다.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)
}
파트너가 호출하는건 이게 전부