▫️

Static Library와 Bundle의 이해 - 개요


최근 Tuist에서 Tuist CommunityStatic frameworks now always host resources (no extra bundle)라는 업데이트 내역을 확인하게 되었다.
우리는 CLI 4.122.2에서 정적 프레임워크(static framework)의 리소스 처리 방식을 변경했습니다. 이제 Tuist는 정적 프레임워크에 대해 별도의 .bundle 타깃을 생성하지 않습니다. 대신, 리소스는 항상 정적 프레임워크 내부에 포함되어야 합니다. 이는 Xcode 15 이상에서 리소스를 포함한 정적 프레임워크를 지원하는 방식과 일치하며, Apple의 “Creating a static framework” 문서에서 안내하는 내용과도 부합합니다. 변경 이유 • 추가적인 리소스 번들 타깃과 그에 따른 번들 조회 로직을 제거할 수 있습니다. • 리소스를 포함한 정적 프레임워크에 대한 Apple의 가이드라인과 Tuist의 동작을 일치시킵니다. • 플랫폼 전반에서 정적 프레임워크의 런타임 번들 탐색(bundle discovery)을 단순화합니다. 이번 변경은 정적 프레임워크의 리소스 처리 방식을 개선하려는 이전 시도들을 기반으로 합니다. 관심이 있다면 이전 논의도 참고해 보세요. 이 변경 사항을 직접 사용해 보시고, 특히 macOS나 혼합 플랫폼 워크스페이스에서 발견되는 문제를 공유해 주시면 감사하겠습니다. 문제가 발생한다면, 최소 재현 예제, Xcode 버전, 그리고 **타깃 유형(정적 프레임워크인지 XCFramework인지)**을 함께 알려주시면 큰 도움이 됩니다. 감사합니다! 여러분의 피드백은 다양한 환경에서 이 변경 사항을 검증하는 데 큰 도움이 될 것입니다.
 
Creating a static framework..?
 
ChatGPT 말로는..
네! Apple 공식 “Creating a static framework” 문서가 무엇인지, 그리고 핵심 개념과 절차를 명확하게 요약해서 설명해 드리겠습니다. ⸻ 📌 Static Framework (정적 프레임워크)란? 정적 프레임워크는 코드와 리소스를 동시에 포함할 수 있는 프레임워크 형태입니다. • 정적 라이브러리(.a)를 중심으로 • 헤더 파일, 리소스 (이미지/스토리보드/자원) 및 메타데이터도 함께 묶습니다. 이 구조는 Xcode 15 이상에서 공식적으로 지원됩니다.  ⸻ 🧱 Static Framework의 핵심 동작 방식 ✅ 1) 빌드 시점에 코드가 앱에 포함됨 정적 프레임워크의 정적 라이브러리 부분은 앱이 빌드될 때 앱의 실행 파일에 정적으로 링크(link) 됩니다. 즉, 프레임워크의 코드는 최종 앱 바이너리 안에 들어갑니다.  ✅ 2) 리소스를 프레임워크 내부에 포함 전통적으로 정적 라이브러리는 리소스를 포함할 수 없었는데, Xcode 15부터는 .framework 내부에 리소스를 넣을 수 있도록 공식적으로 지원합니다. (그래서 Tuist의 변경도 이 지원을 기반으로 하고 있습니다.)  ✅ 3) 앱에 임베드할 때 처리 클라이언트 앱으로 프레임워크를 삽입할 때 Xcode 15 이상은: • 정적 코드는 이미 앱 실행 파일에 포함되므로, • 실제 프레임워크 번들 안에서는 코드가 제거되거나 스텁(binary stub)처럼 처리됩니다.  ⸻ 🛠️ 정적 프레임워크 만들기 — 절차 요약 ① 새 프레임워크 타깃 생성 Xcode에서 새로운 프레임워크 타깃을 생성합니다.  ② 프레임워크를 정적으로 설정 생성된 프레임워크 타깃의 Mach-O Type을 Static Library로 설정하면 정적 프레임워크가 됩니다.  ③ 코드 & 리소스 추가 • Swift/Obj-C 소스 파일 → Compile Sources • 이미지, 스토리보드 같은 리소스 → Copy Bundle Resources에 추가  ④ 빌드/테스트/디스트리뷰션 준비 빌드, 테스트 완료 후 배포용으로 아카이브하고, 필요 시 여러 플랫폼을 지원하려면 XCFramework로 패키징합니다.  ⸻ 🧠 왜 Static Framework를 쓰나요? 장점 설명 빠른 로딩 프레임워크 코드가 실행 파일에 포함되어 별도 로딩 과정 필요 없음 리소스 포함 이제 정적 프레임워크 내부에 리소스를 깔끔하게 넣을 수 있음  명확한 배포 구조 하나의 .framework 단위로 라이브러리 + 리소스를 묶어서 배포 가능 ⸻ 🆚 Static Framework vs Static Library 항목 Static Framework Static Library 코드 정적 링크됨 정적 링크됨 리소스 포함 가능(Xcode15+)  포함 불가 배포 프레임워크 번들로 배포 라이브러리 + 별도 리소스 패키징 필요 ⸻ 📌 요약 • Static Framework: 정적 라이브러리를 프레임워크 형식으로 묶은 것. • Xcode 15부터는 정적 프레임워크 내부에 리소스를 넣을 수 있음.  • 생성 → 코드 & 리소스 추가 → 테스트 → (필요 시) XCFramework로 패키징이 일반적인 작업 흐름입니다.  ⸻ 원하면 예시 Xcode 설정 스크린샷이나 Tuist 관점에서 리소스 설정 예시도 설명해 드릴까요?
 
이쪽 파트는 잘 알지 못해서 공부해 보려고 한다. GPT의 로드맵을 따라서!
좋은 판단이에요. 이 영역은 Xcode 빌드 시스템 + 링킹 모델 + 프레임워크 패키징이 얽혀 있어서, 순서 없이 보면 굉장히 혼란스럽습니다. 아래처럼 학습 순서를 계층적으로 잡는 걸 추천합니다. ⸻ 1️⃣ 1단계: “정적 vs 동적” 링킹 모델부터 확실히 잡기 (가장 중요) 이걸 모르면 이후 내용이 전부 추상적으로 느껴집니다. 핵심 질문 • 정적 라이브러리와 동적 라이브러리는 언제 앱에 포함되는가? • 런타임에 어떤 바이너리가 로딩되는가? • 왜 “정적 프레임워크인데 프레임워크 번들이 남아있나?” 같은 말이 나오는가? 공부 포인트 • Static Library (.a) → 링크 시점에 앱 바이너리에 포함됨 • Dynamic Library / Framework (.dylib / .framework) → 런타임에 dyld가 로드 🔑 여기서 반드시 이해해야 할 개념: • Link time vs Runtime • Symbol resolution • dyld의 역할 👉 추천 자료 • Apple 문서: Linking / Dynamic Libraries • WWDC: “Behind the Scenes of the Xcode Build Process” ⸻ 2️⃣ 2단계: “Framework는 포맷이지, 링킹 방식이 아니다” 이해하기 많이 헷갈리는 지점입니다. 정리 • .framework = 번들 포맷 • 내부에 들어가는 바이너리가 • static이면 Static Framework • dynamic이면 Dynamic Framework 여기서 봐야 할 것 • .framework 디렉토리 구조 • Info.plist, Modules, Resources의 역할 • 왜 static framework는 실행 시 로드되지 않는데도 번들이 존재하는지 👉 실습 추천 lipo -info MyFramework.framework/MyFramework otool -L MyApp.app/MyApp 이걸로 “어디에 실제 코드가 있는지” 눈으로 확인하면 이해가 급격히 올라갑니다. ⸻ 3️⃣ 3단계: Xcode 15 이전 vs 이후 리소스 모델 변화 Tuist 변경의 핵심 배경입니다. 과거 (Xcode 14 이하) • Static library / static framework → 리소스 직접 포함 ❌ • 별도 .bundle 타깃 생성 • Bundle.module, Bundle(for:) 등 복잡한 탐색 로직 필요 현재 (Xcode 15+) • Static framework 내부에 리소스 포함 가능 ✅ • Apple 공식 지원 • 번들 탐색 로직 단순화 👉 반드시 읽어볼 것 • Creating a static framework (지금 보고 계신 문서) • SwiftPM의 Bundle.module 동작 방식과 비교 ⸻ 4️⃣ 4단계: 리소스 접근 방식 정리 (실무 핵심) 리소스 접근의 세 가지 패턴 1. Bundle.main 2. Bundle(for: SomeClass.self) 3. Bundle.module (SwiftPM) Static Framework에서 중요한 점 • 코드 위치 ≠ 리소스 위치 (정적 링크이기 때문) • “이 번들은 실행되지 않는다”는 개념 이해 필요 👉 추천 실험 • 동일한 리소스를 • static framework • dynamic framework • SwiftPM 에서 각각 로드해 보기 ⸻ 5️⃣ 5단계: Tuist / SwiftPM / XCFramework 관점으로 재정리 이제 도구들이 왜 그렇게 설계됐는지 보이기 시작합니다. 질문에 답할 수 있으면 성공 • Tuist가 왜 예전엔 resource bundle 타깃을 만들었나? • Xcode 15 이후 그게 왜 불필요해졌나? • Static framework + XCFramework 조합에서 리소스는 어디에 존재하나? ⸻ 📚 추천 학습 로드맵 (압축 버전) 1. 정적 vs 동적 링킹 개념 2. Framework = 포맷이라는 관점 3. Xcode 15 리소스 정책 변화 4. Bundle 탐색 로직 5. Tuist/SwiftPM 설계 이유 ⸻ 🎯 현실적인 조언 이 도메인은: • “한 번에 이해” ❌ • “실험 → 확인 → 문서 재독” ⭕ 특히 otool, lipo, nm 같은 툴을 직접 써보는 순간 이해도가 급상승합니다. ⸻ 원하시면 다음 중 하나로 바로 들어갈 수 있어요: • 🔍 최소 예제로 static vs dynamic framework 구조 비교 • 🧪 Xcode 15에서 static framework 리소스 로딩 실험 가이드 • 🧰 Tuist 설정을 기준으로 한 실무 설명 어느 쪽부터 가볼까요?
 

References


awdiojawd