Skip to content

iOS용 바인딩 추가 #238

@bab2min

Description

@bab2min

Kiwi Swift 바인딩 구현 계획

개요

Kiwi 한국어 형태소 분석기에 Swift 바인딩을 추가하여 iOS/macOS에서 사용 가능하게 합니다.

핵심 결정사항:

  • 배포 방식: XCFramework (바이너리)
  • 최소 iOS: 12.0 / macOS: 10.14
  • Async/await: 미지원 (동기 API만 제공)

접근 방식: C API 직접 연동

Swift의 C interop 기능을 활용하여 기존 C API(capi.h)를 직접 import합니다.

┌─────────────────┐
│  Swift API      │  ← 사용자 친화적 Swift 인터페이스
│  (Kiwi.swift)   │
└────────┬────────┘
         │
┌────────┴────────┐
│  CKiwi Module   │  ← module.modulemap으로 C API import
└────────┬────────┘
         │
┌────────┴────────┐
│  libkiwi_static │  ← XCFramework로 배포
└─────────────────┘

디렉토리 구조

bindings/swift/
├── Package.swift
├── README.md
├── Sources/
│   ├── CKiwi/
│   │   ├── module.modulemap
│   │   └── include/           # capi.h 심볼릭 링크
│   └── Kiwi/
│       ├── Kiwi.swift         # 메인 클래스
│       ├── KiwiBuilder.swift  # 빌더 패턴
│       ├── Token.swift        # 토큰 구조체
│       ├── POSTag.swift       # 품사 태그 enum
│       ├── MatchOptions.swift # 분석 옵션 (OptionSet)
│       ├── Dialect.swift      # 방언 플래그
│       ├── Joiner.swift       # 형태소 결합
│       ├── MorphemeSet.swift  # 블랙리스트
│       ├── TypoTransformer.swift
│       ├── Errors.swift       # KiwiError
│       └── Internal/
│           └── HandleWrapper.swift  # C 핸들 RAII 래퍼
├── Tests/
│   └── KiwiTests/
├── CMakeLists.txt             # iOS/macOS 빌드 설정
└── scripts/
    └── build-xcframework.sh   # XCFramework 빌드 스크립트

핵심 타입 매핑

C API Swift
kiwi_h Kiwi (class)
kiwi_builder_h KiwiBuilder (class)
kiwi_res_h 내부 처리 후 [TokenResult]로 변환
kiwi_joiner_h Joiner (class)
kiwi_token_info_t Token (struct)
KIWI_MATCH_* MatchOptions (OptionSet)
KIWI_TAG_* POSTag (enum)

주요 API 설계

// KiwiBuilder
public final class KiwiBuilder {
    public init(modelPath: String, numThreads: Int = -1, options: BuildOptions = .default) throws
    public init(bundle: Bundle, modelDirectory: String = "KiwiModels") throws

    public func addWord(_ word: String, tag: POSTag, score: Float = 0) throws -> Bool
    public func build(typoTransformer: TypoTransformer? = nil) throws -> Kiwi
}

// Kiwi
public final class Kiwi {
    public static var version: String { get }

    public func analyze(_ text: String, topN: Int = 1, options: MatchOptions = .all) throws -> [TokenResult]
    public func tokenize(_ text: String, options: MatchOptions = .all) throws -> [Token]
    public func splitIntoSentences(_ text: String) throws -> [Sentence]
    public func createJoiner(useLMSearch: Bool = true) -> Joiner
}

// Token
public struct Token {
    public let form: String
    public let tag: POSTag
    public let position: Int
    public let length: Int
    public let score: Float
}

메모리 관리

모든 C 핸들을 Swift class로 래핑하고 deinit에서 정리:

internal final class HandleWrapper<H> {
    let handle: H
    private let cleanup: (H) -> Void

    init(_ handle: H, cleanup: @escaping (H) -> Void) {
        self.handle = handle
        self.cleanup = cleanup
    }

    deinit { cleanup(handle) }
}

빌드 시스템

CMakeLists.txt 주요 설정

# iOS Device (arm64)
set(CMAKE_SYSTEM_NAME iOS)
set(CMAKE_OSX_DEPLOYMENT_TARGET "12.0")
set(CMAKE_OSX_ARCHITECTURES "arm64")

# iOS Simulator (arm64 + x86_64)
set(CMAKE_OSX_SYSROOT iphonesimulator)
set(CMAKE_OSX_ARCHITECTURES "arm64;x86_64")

# macOS (Universal)
set(CMAKE_OSX_DEPLOYMENT_TARGET "10.14")
set(CMAKE_OSX_ARCHITECTURES "arm64;x86_64")

XCFramework 빌드

scripts/build-xcframework.sh:

  1. iOS device용 arm64 빌드
  2. iOS simulator용 arm64+x86_64 빌드
  3. macOS용 arm64+x86_64 빌드
  4. xcodebuild -create-xcframework로 통합

구현 단계

1단계: 기반 구조

  • bindings/swift/ 디렉토리 생성
  • Package.swift 작성
  • Sources/CKiwi/module.modulemap 작성
  • HandleWrapper.swift 구현

2단계: 핵심 타입

  • POSTag.swift - 61개 품사 태그
  • MatchOptions.swift - 분석 옵션 플래그
  • Dialect.swift - 방언 플래그
  • Token.swift - 토큰 구조체
  • Errors.swift - KiwiError enum

3단계: 메인 API

  • KiwiBuilder.swift - 빌더 클래스
  • Kiwi.swift - 메인 분석 클래스
  • Joiner.swift - 형태소 결합

4단계: 고급 기능

  • MorphemeSet.swift - 블랙리스트
  • TypoTransformer.swift - 오타 교정
  • Bundle에서 모델 로딩 지원

5단계: 빌드 및 배포

  • CMakeLists.txt 작성
  • build-xcframework.sh 작성
  • GitHub Actions 워크플로우 추가
  • README.md 문서화

6단계: 테스트

  • 단위 테스트 작성
  • 예제 iOS 앱 (선택)

수정할 파일

새로 생성:

  • bindings/swift/ 전체 디렉토리

수정:

  • CMakeLists.txt - iOS 타겟 추가 (선택적)
  • .github/workflows/ - iOS 빌드 워크플로우 추가

검증 방법

  1. XCFramework 빌드 성공 확인
  2. 새 iOS 프로젝트에서 SPM으로 추가
  3. 기본 분석 테스트:
    let kiwi = try KiwiBuilder(modelPath: path).build()
    let tokens = try kiwi.tokenize("안녕하세요")
    assert(!tokens.isEmpty)
  4. 메모리 누수 테스트 (Instruments)

참고 파일

  • include/kiwi/capi.h - C API 전체 정의
  • bindings/java/src/kr/pe/bab2min/Kiwi.java - Java API 참고
  • bindings/java/csrc/kiwi_java.cpp - 바인딩 구현 참고

Metadata

Metadata

Labels

No labels
No labels

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions