안녕하세요, dvHuni입니다!!
2022년의 첫 포스트는.. 가볍게 시작해보려해요 ㅎㅎㅎ
모듈화 스터디를 진행하면서 느낀점이 하나 있는데,
Static Framework와 Dynamic Framework에 대한 이해가 없으면
공부하고 있는 자료의 내용을 이해하는데 어려움이 있었다는점 입니다...
Framework / Library는 알겠는데... Static? Dynamic? Framework .. 😖 뭐냐구... 대체..
그!래!서
이번에는 Framework에 대해 조금 더 자세히 정리해 보았습니다. 함께 보시죠 👀
Framework는 Library보다 다양한 리소스를 단일 패키지로 캡슐화 하는 계층 구조 파일 디렉토리입니다.
시스템은 필요에 따라 해당 리소스를 메모리에 로드하고 가능한 경우 모든 애플리케이션 간에 리소스 복사본 하나를 공유합니다.
Framework는 Static 및 Daynamic share Library와 같은 기능을 제공합니다.
즉, 애플리케이션이 특정 작업을 수행하기 위해 호출할 수 있는 루틴을 제공한다는 것 입니다.
Dynamic Framework는 동시에 여러 프레임워크 혹은 프로그램에서 공유하여 사용하기 때문에 메모리를 효율적으로 사용합니다.
동적으로 연결되어 있으므로, 전체 빌드를 다시 하지 않아도 새로운 프레임워크 사용이 가능합니다.
Static Linker를 통해 Dynamic Library Reference
가 어플리케이션 코드에 들어가고 모듈 호출시 Stack에 있는 Library에 접근하여 사용합니다.
💡 Xcode에서 Framework를 생성하면 기본적으로 Dynamic Framework로 생성됩니다.
Static Framework는 Static Linker를 통해 Static Library 코드가 어플리케이션 코드 내로 들어가 Heap 메모리에 상주합니다.
따라서 Static Library가 복사되므로, Static Framework를 여러 Framework에서 사용하게 되면 코드 중복이 발생하게 됩니다.
Library는 Framework가 아니라 Static Library가 복사된 곳 위치하므로, Bundle의 위치는 Static Framework가 아닌 Static Library가 위치해 있는 곳이 됩니다.
때문에 번들을 접근할 때는 스스로가 접근하는 것 보단 외부에서 Bundle의 위치를 주입받는 것이 좋습니다.
따라서
소스코드가 복사되는 Static Framework 보다는Dynamic Framework를 사용하는것이 좋아보입니다.
하지만, Dynamic Framework의 무분별한 사용은 App Launch Time을 증가시킵니다.
💡 Library와 Framework 단어가 혼용되어서 헷갈릴 수 있어서 잠시 짚고 넘어가겠습니다.
Library는 단지 실행 가능한 코드 이지만,
Framework는 공유 라이브러리와 헤더 및 다른 리소스의 하위 디렉토리를 포함하는 번들(디렉토리 구조)입니다.
Apple’s Reducing Your App’s Launch Time article 에서는 정확한 숫자는 언급하지 않았지만,
Dynamic Module이 Total App Launch Time을 어떻게 증가시키는지 설명하고 있습니다.
App Launch Time은 Apple’s Logging Dynamic Loader Events 의 옵션들을 사용하여 체크할 수 있고,
혹은 instrument를 사용하여 체크 할 수 있습니다.
(직접해봤는데.. 잘 안되더라구요.. 헤헤.. 이것도 더 시도해보고 따로 포스팅하겠습니다 🥲)
Total pre-main time: 95.07 milliseconds (100.0%)
dylib loading time: 25.00 milliseconds (26.3%)
rebase/binding time: 19.75 milliseconds (20.7%)
ObjC setup time: 6.85 milliseconds (7.2%)
initializer time: 43.45 milliseconds (45.7%)
slowest intializers :
libSystem.B.dylib : 8.43 milliseconds (8.8%)
libBacktraceRecording.dylib : 9.00 milliseconds (9.4%)
libMainThreadChecker.dylib : 22.05 milliseconds (23.1%)
즉, LanuchTime을 줄이기 위해서는 Dynamic Framework의 숫자는 제한하고, StaticFramework의 사용을 권고하는 것으로 보입니다.
그렇다면 이쯤에서 드는 의문은 많은 프로젝트들이 CocoaPods을 의존하고 있는데,
과연 CocoaPods은 어떻게 이루어져있는가 입니다.
기본적으로 CocoaPods은 모든 dependency를 Static Library로 link하고 build합니다.
만약 use_frameworks!
키워드를 Pdofile에 추가하게 되면 Dynamic Framework로 link하고 build합니다.
또한 use_frameworks! :linkage => :static
키워드는 Static Framework 처럼 link하고 build하게 됩니다.
자세한 내용은 문서를 참고해주시기 바랍니다.
알아본 김에 Swift Package Manager도 슬쩍 보고갑시다.
SPM은 link와 build 방법을 설정 할 수 없도록 되어있습니다.
SPM은 모두 Static Library죠.
Package.swift 파일에서 설정 할 수 있다고 하는데, 이는 package의 owner만 설정할 수 있으니 사용자가 설정한다 하여도 무용지물입니다.
Building a dynamic modular iOS architecture
👆위 글을 참조하면서 모듈화에 대해 스터디를 진행하고 있는데.. framework에 대한 설명을 하는데..
잘 이해하지 못하고 넘어가다보니.. 내용을 따라가기 힘들었습니다.
그래도 이제는 조금 알것 같긴 해요.. 헤헤 :)
오늘은 간단하게 포스트가 마무리 된것 같네요!! (날먹)
그래도 앱 실행 속도에 영향을 주게 되는 요소를 하나 더 알게 되었네요!!
우리 앱은 Launch Time이 얼마나 되려나 ~~~ 보러가야징 🏃♂️
이번 포스트도 읽어주셔서 감사합니다!! 🙇
다음 포스트에서 만나요 👋
질문이나 지적은 언제든지 환영합니다 😉
참조 :
https://minsone.github.io/ios/mac/ios-framework-part-1-static-framework-dynamic-framework
https://developer.apple.com/library/archive/documentation/MacOSX/Conceptual/BPFrameworks/Frameworks.html#//apple_ref/doc/uid/10000183-SW1
https://bpoplauschi.github.io/2021/10/25/Advanced-static-vs-dynamic-libraries-and-frameworks.html