Tuist Framework vs Static Framework 비교 가이드

Ios_Roy·2025년 9월 5일

TUIST뿌시기

목록 보기
6/6
post-thumbnail

Tuist Framework vs Static Framework 비교 가이드

개요

Tuist에서 모듈을 구성할 때 Framework와 Static Framework 중 어떤 것을 선택할지는 프로젝트의 성능, 빌드 시간, 배포 방식에 큰 영향을 미칩니다. 이 문서에서는 두 방식의 차이점과 각각의 장단점을 상세히 비교합니다.

Framework (Dynamic Framework)

정의

Dynamic Framework는 런타임에 동적으로 링크되는 프레임워크입니다. 앱 실행 시 필요한 시점에 메모리로 로드됩니다.

특징

  • 런타임 링크: 앱 실행 시 동적으로 로드
  • 별도 바이너리: 각 프레임워크가 독립된 바이너리 파일
  • 메모리 공유: 여러 앱에서 동일한 프레임워크 공유 가능
  • 지연 로딩: 필요할 때만 메모리에 로드

Project.swift 설정 예시

let project = Project(
    name: "MyProject",
    targets: [
        .target(
            name: "MyFramework",
            destinations: .iOS,
            product: .framework, // Dynamic Framework
            bundleId: "com.example.myframework",
            sources: ["Sources/**"],
            dependencies: []
        )
    ]
)

Static Framework

정의

Static Framework는 컴파일 타임에 앱 바이너리에 직접 포함되는 프레임워크입니다. 앱 빌드 시 모든 코드가 하나의 실행 파일에 병합됩니다.

특징

  • 컴파일 타임 링크: 빌드 시점에 앱 바이너리에 포함
  • 단일 바이너리: 모든 코드가 하나의 실행 파일에 병합
  • 독립 실행: 외부 의존성 없이 실행 가능
  • 즉시 사용: 런타임 로딩 과정 불필요

Project.swift 설정 예시

let project = Project(
    name: "MyProject",
    targets: [
        .target(
            name: "MyStaticFramework",
            destinations: .iOS,
            product: .staticFramework, // Static Framework
            bundleId: "com.example.mystaticframework",
            sources: ["Sources/**"],
            dependencies: []
        )
    ]
)

상세 비교

1. 빌드 시간

Dynamic Framework

  • 장점:
    • 증분 빌드 시 변경된 프레임워크만 다시 빌드
    • 큰 프로젝트에서 빌드 시간 단축 효과
  • 단점:
    • 초기 설정 복잡성
    • 프레임워크 간 의존성 관리 필요

Static Framework

  • 장점:
    • 간단한 빌드 프로세스
    • 의존성 해결이 명확함
  • 단점:
    • 전체 앱 재빌드 필요
    • 큰 프로젝트에서 빌드 시간 증가

2. 앱 크기

Dynamic Framework

앱 구조:
MyApp.app/
├── MyApp (실행 파일)
├── Frameworks/
│   ├── FrameworkA.framework
│   ├── FrameworkB.framework
│   └── FrameworkC.framework
└── Info.plist
  • 장점: 코드 중복 제거로 전체 앱 크기 감소 가능
  • 단점: 프레임워크 메타데이터로 인한 오버헤드

Static Framework

앱 구조:
MyApp.app/
├── MyApp (모든 코드 포함된 단일 실행 파일)
└── Info.plist
  • 장점: 메타데이터 오버헤드 없음
  • 단점: 코드 중복 시 앱 크기 증가

3. 런타임 성능

Dynamic Framework

  • 시작 시간: dyld가 프레임워크를 로드하는 시간 필요
  • 메모리 사용: 프레임워크별 개별 메모리 공간
  • 캐시 효율성: 시스템 레벨에서 프레임워크 캐싱 가능

Static Framework

  • 시작 시간: 모든 코드가 이미 로드되어 빠른 실행
  • 메모리 사용: 단일 메모리 공간에서 효율적 관리
  • 캐시 효율성: CPU 캐시 최적화 가능

4. 배포 및 업데이트

Dynamic Framework

  • 모듈별 업데이트: 개별 프레임워크만 교체 가능 (이론상)
  • 앱스토어: iOS에서는 앱 번들 내 프레임워크만 가능
  • 테스트: 프레임워크별 독립 테스트 용이

Static Framework

  • 전체 업데이트: 앱 전체 재배포 필요
  • 단순성: 배포 프로세스가 단순함
  • 테스트: 통합 테스트에 유리

선택 가이드

Dynamic Framework를 선택해야 하는 경우

  1. 대규모 프로젝트

    • 10개 이상의 모듈
    • 팀 단위별 독립 개발
  2. 빠른 개발 사이클

    • 빈번한 빌드가 필요한 환경
    • 핫스왑 기능 활용
  3. 모듈 재사용

    • 여러 앱에서 동일한 프레임워크 사용
    • 라이브러리 형태의 모듈
// 예시: 대규모 프로젝트 구성
let targets: [Target] = [
    // 메인 앱
    .app(name: "MainApp", dependencies: [
        .target(name: "FeatureLogin"),
        .target(name: "FeatureHome"),
        .target(name: "FeatureSettings")
    ]),
    
    // 각 기능별 Dynamic Framework
    .framework(name: "FeatureLogin"),
    .framework(name: "FeatureHome"),
    .framework(name: "FeatureSettings"),
    
    // 공통 모듈
    .framework(name: "DesignSystem"),
    .framework(name: "NetworkLayer")
]

Static Framework를 선택해야 하는 경우

  1. 중소규모 프로젝트

    • 5개 이하의 모듈
    • 단순한 구조
  2. 성능 최우선

    • 앱 시작 시간이 중요한 경우
    • 메모리 사용량 최적화 필요
  3. 단순한 배포

    • 복잡한 의존성 관리 피하고 싶은 경우
    • 앱스토어 배포만 고려
// 예시: 중소규모 프로젝트 구성
let targets: [Target] = [
    // 메인 앱
    .app(name: "SimpleApp", dependencies: [
        .target(name: "CoreLogic"),
        .target(name: "UIComponents")
    ]),
    
    // Static Framework로 구성
    .staticFramework(name: "CoreLogic"),
    .staticFramework(name: "UIComponents")
]

성능 벤치마크 예시

앱 시작 시간 비교

소규모 앱 (3개 모듈):
- Static Framework: 0.8초
- Dynamic Framework: 1.2초

대규모 앱 (15개 모듈):
- Static Framework: 2.1초  
- Dynamic Framework: 1.9초

빌드 시간 비교

전체 빌드:
- Static Framework: 45초
- Dynamic Framework: 52초

증분 빌드 (1개 모듈 수정):
- Static Framework: 35초
- Dynamic Framework: 12초

하이브리드 접근법

실제 프로젝트에서는 두 방식을 혼합하여 사용하는 것이 효과적입니다.

let project = Project(
    name: "HybridProject",
    targets: [
        .app(name: "MainApp", dependencies: [
            // 자주 변경되는 기능 모듈 - Dynamic
            .target(name: "FeatureModules"),
            
            // 안정적인 유틸리티 - Static  
            .target(name: "CoreUtilities"),
            .target(name: "NetworkLayer")
        ]),
        
        .framework(name: "FeatureModules"), // Dynamic
        .staticFramework(name: "CoreUtilities"), // Static
        .staticFramework(name: "NetworkLayer") // Static
    ]
)

마이그레이션 가이드

Dynamic에서 Static으로

  1. 설정 변경
// Before
.target(product: .framework)

// After  
.target(product: .staticFramework)
  1. 의존성 점검: Static linking으로 인한 중복 심볼 확인
  2. 빌드 스크립트 업데이트: 프레임워크 복사 단계 제거

Static에서 Dynamic으로

  1. 설정 변경
// Before
.target(product: .staticFramework)

// After
.target(product: .framework)  
  1. 번들 설정: 각 프레임워크의 Bundle ID 설정
  2. 런타임 의존성: 프레임워크 로딩 순서 고려

결론

기준Dynamic FrameworkStatic Framework
빌드 속도 (증분)⭐⭐⭐⭐⭐⭐⭐
앱 시작 속도⭐⭐⭐⭐⭐⭐⭐⭐
메모리 효율성⭐⭐⭐⭐⭐⭐⭐
구현 복잡도⭐⭐⭐⭐⭐⭐⭐
디버깅 용이성⭐⭐⭐⭐⭐⭐⭐

프로젝트의 규모, 팀 구성, 성능 요구사항을 종합적으로 고려하여 적절한 방식을 선택하거나 하이브리드 접근법을 사용하는 것이 권장됩니다.


이 문서는 Tuist 4.x 버전을 기준으로 작성되었습니다. 최신 버전에서는 일부 설정이 달라질 수 있습니다.

profile
iOS 개발자 공부하는 Roy

0개의 댓글