on
Dynamic Library를 embed하지 않았을 때 생기는 문제
Dynamic Library를 embed하지 않았을 때 생기는 문제
이 글에서는 Dynamic Framework를 embed하지 않았을 때 발생하는 문제와 그 원리를 정리해보려고 해요.
Static Framework vs Dynamic Framework
먼저 두 프레임워크의 차이를 간단히 볼게요.
-
Static Framework
빌드 시 실행 파일 안에 코드가 포함돼요.
앱 실행 시 별도의 로딩 과정이 필요 없고, 사용되지 않는 코드를 제거하는 Dead Code Stripping 최적화도 받을 수 있어요. -
Dynamic Framework
실행 파일에는 포함되지 않고, 앱 번들의Frameworks/폴더에 복사돼요.
런타임 시 Dynamic Loader(dyld) 가 이 폴더의 프레임워크를 찾아 메모리에 올려요.
그래서 이 복사 과정(Embed)이 빠지면 런타임에 프레임워크를 찾지 못해 크래시가 발생해요.
💥 문제 상황
Dynamic Framework를 “Do Not Embed”로 설정하면,
앱 번들의 Frameworks/ 폴더에 프레임워크가 복사되지 않아요.
그럼 이런 현상이 생겨요.
| 환경 | 실행 결과 |
|---|---|
| Xcode에서 Run (⌘ + R) | 정상 실행 |
| 시뮬레이터에서 앱 아이콘 클릭 실행 | 크래시 발생 |
| 실기기에서 실행 | 크래시 발생 |
🧩 왜 Xcode에서 Run하면 괜찮을까?
Xcode는 앱을 Run할 때 다음 환경 변수를 자동으로 추가해줘요.
DYLD_FRAMEWORK_PATH = /Users/<사용자>/Library/Developer/Xcode/DerivedData/<Project>/Build/Products/Debug-iphonesimulator
즉, 앱을 실행할 때 DerivedData 빌드 결과물 안의 프레임워크 경로를 동적 로더에게 알려주는 거예요.
그래서 앱 번들에 프레임워크가 없어도
dyld가 DerivedData 안에서 프레임워크를 찾아 실행할 수 있는 거예요.
하지만,
- 시뮬레이터 홈 화면에서 앱을 직접 실행하거나
- 실기기에서 실행하면
이 환경 변수가 사라져요.
결국 런타임 로더가 프레임워크를 찾지 못하고 “Library not loaded” 크래시가 나요.
🧠 정리하자면
| 항목 | Static Framework | Dynamic Framework |
|---|---|---|
| 코드 포함 위치 | 실행 파일 내부 | 앱 번들의 Frameworks/ 폴더 |
| Dead Code Stripping | 가능 | 불가능 |
| 리소스 번들 처리 | 별도 번들 필요 | 프레임워크에 포함 가능 |
| Embed 필요 여부 | ❌ 필요 없음 | ✅ 반드시 필요 |
| 런타임 로드 방식 | 빌드 타임 포함 | dyld가 런타임에 로드 |
💡 Framework 선택 기준
-
기본적으로 Static Framework를 사용하는 게 좋아요.
앱 크기를 줄이고 Dead Code Stripping 최적화 효과를 받을 수 있어요. -
다만 Design System이나 리소스를 포함해야 하는 모듈(이미지, font 등)은 리소스 복사 처리가 간단한 Dynamic Framework로 구성하는 게 좋아요.
🔍 사견 — “왜 Xcode는 이런 짓을 할까?”
Xcode가 DYLD_FRAMEWORK_PATH를 DerivedData로 지정하는 이유는 간단해요.
Embed 없이도 빌드 결과물을 직접 로드해서 실행 속도를 높이기 위해서예요.
즉, 매번 앱 번들을 다시 구성하지 않고 빠르게 디버깅할 수 있도록 도와주는 기능이에요.
✅ 결론
Dynamic Framework를 “Do Not Embed”로 설정하면
시뮬레이터에서는 잘 동작하지만,
환경 변수가 사라지는 실기기나 직접 실행 환경에서는 반드시 크래시가 발생해요.
따라서 Dynamic Framework를 사용할 때는
“Embed & Sign” 또는 “Embed Without Signing” 으로 설정해야 해요.