Skip to content

[모듈화 2편] Dynamic Library vs Static Library

박효준 edited this page Nov 9, 2024 · 3 revisions

반갑습니다 ! Memorial House의 집주인 효준 & 영현 입니다.

지난 편에서 Library와 Framework의 차이를 보았고,

본 편에서는 Dynamic Library vs Static Library에 대해 알아보겠습니다 !!

총 3편의 시리즈로 구성되어 있습니다..!

그럼 레쯔고 〰️

문제 상황

  • 모듈화를 하면서 Library & Framework, Static & Dynamic에 대해 혼동이 왔음
  • 용어에 대한 개념 차이
  • Target - General - Frameworks, Libraries, and Embedded Content에서의 Embed 역할이 무엇인가 ?
  • Dynamic Library는 도대체 언제 쓰이는 걸까 ?

문제 해결

이전 포스팅에 이어 본 포스팅에서는 Dynamic과 Static에 대한 Library(Framework)를 보겠다.

이전 포스팅 핵심: Framework는 Library를 포함하고 있고, Resource를 비롯한 추가적인 것을 가질 수 있다는 점이다.

이 개념을 알아야 본 포스팅을 이해할 수 있다 !

그럼 레쭈고~~

Dynamic Framework vs Static Framework

지난 포스팅에서 “Static Framework와 Dynamic Framework도 선택할 수 있다.”고 말을 하며 넘어갔었다.

본 포스팅에서 제일 헷갈릴 수 있는 이 내용부터 설명하며 글을 시작하겠다.

아래는 Tuist로 Package를 설정하는 예제이다.

스크린샷 2024-11-10 오전 3 07 44

사진과 같이 타겟을 Dynamic Framework로 할 지, Static Framework로 할 지 정할 수 있다.

둘은 뭐가 다른 걸까 ?

정확히 말하면 Framework 내부에 포함된 Library를 Dynamic으로 할 것인지, Static으로 할 것인지에 대한 차이이다.

스크린샷 2024-11-10 오전 3 07 50

무엇으로 설정했느냐에 따라 Mach-O Type이 달리지게 된다.

  • Dynamic Framework는 Dynamic Library로 설정
  • Static Framework는 Static Library로 설정

여기서 말하는 Mach-O Type는 링킹될 때 어떻게 될 것인지를 말하는 타입이다.

TMI) Mach는 커널 종류중 하나로, 애플의 macOS와 iOS에서 사용되는 Darwin을 구성하는 XNU 커널의 기반이다.

즉, Framework의 Dynamic과 Static 설정은 내부 Library를 어떻게 링킹할지 결정하는 것이다.


Dynamic Library vs Static Library

우리는 위에서 Static Framework와 Dynamic Framework의 차이를 알았다.

그러면 Library 관점에서는 어떻게 다른 걸까 ?

스크린샷 2024-11-10 오전 3 08 32

우리가 빌드를 하면 컴파일이 동작하고, 컴파일 된 코드와 외부 Library에 대한 정보들이 연결(= 링킹)된다.

이때, Dynamic Library vs Static Library 에 따라 어떻게 연결되는지 살펴보자

  • Static Library는 링킹이 될 때 Library의 코드들이 포함된 Executable 파일을 만들고 Heap에 적재시킨다.
  • Dynamic Library는 링킹이 될 때 Library 파일에 대한 참조값만 포함된 Executable 파일을 Heap에 적재하고, 실제 Library 코드는 Stack 영역에 적재된다. 그리고 런타임 시점에 필요할 때마다 Stack영역에서 실행에 필요한 코드들을 불러다 사용한다.

Static Library

  • .a 확장자이다.
  • 실행 파일을 만들때 라이브러리 내용을 복사해서 넣어둠
    • 메모리 용량을 많이 차지하게 된다.
    • 빌드가 오래 걸린다.
  • 런타임 시점에서는 Dynamic보다 상대적으로 빠름 !
  • Static Library가 업데이트되면, 새로 빌드를 해줘야 함 그렇지 않으면 executable 파일에 업데이트 이전의 내용이 계속 복제되어 적재됨
스크린샷 2024-11-10 오전 3 08 39

Dynamic Library

  • .dylib 확장자이다.
  • 실행 파일을 만들때 Heap에 내용 전체를 로드하지 않고 참조값만 넣기 때문에 빌드 속도가 빠름!
  • 그러나, 런타임 시점에 참조값을 찾아야하므로 런치 타임이 김
  • 메모리를 효율적으로 사용할 수 있다.
    • 앱 실행파일에 라이브러리를 복사해서 저장하지 않음
    • 여러 곳에서 사용되는 경우, 참조만 하면 되기 때문에 여러 곳에 복제를 할 필요가 없다.
  • 모든 iOS 시스템 라이브러리는 Dynamic라이브러리를 차용한다. → 시스템 라이브러리가 업데이트 될 때마다 시스템 라이브러리를 빌드하지 않아도 업데이트된 라이브러리를 사용할 수 있는 이유이다.
스크린샷 2024-11-10 오전 3 08 42

링크할 때, Library 파일들을 복사해서 적재하는가, 참조만 적재하는가의 차이이다.


Embed & Sign

Target - General - Frameworks, Libraries, and Embedded Content에서의 Embed 역할이 무엇인가 ?

스크린샷 2024-11-10 오전 3 09 42

위 Embed는 앱 패키지 내부에 Framework를 포함 시킨다는 것을 의미한다.

이 위의 내용들을 제대로 이해했다면, Static, Dynamic에 따라 앱이 빌드가 될 때, 앱의 실행파일(executable file) 내부에 Framework 소스코드가 포함되어있을 수도 아닐 수도 있다는 사실을 알 것이다.

이를 실험해보기 위해 DynamicLibraryPractice라는 프로그램을 하나 생성했다, 그리고 해당 프로그램에는 MyFramework라는 Framework와 MyStaticLibrary라는 StaticLibrary가 있다.

스크린샷 2024-11-10 오전 3 09 45

메인 프로그램(DynamicLibraryPractice)이 MyFramework와 MyStaticLibrary를 아래와 같이 불러와 사용하고 있다.

스크린샷 2024-11-10 오전 3 09 48

이 상태로, 해당 프로그램을 빌드시키고 앱 패키지를 뜯어보자.

스크린샷 2024-11-10 오전 3 09 52

그럼 위 사진과 같이 앱 패키지 내부에 MyFramework가 포함되어있는 것을 확인할 수 있다.

그럼 Do Not Embed로 설정을 바꾸면 어떻게 될까?

스크린샷 2024-11-10 오전 3 10 35 스크린샷 2024-11-10 오전 3 10 39

당연하게도 Frameworks라는 폴더도 사라지고 MyFramework는 앱 패키지 내부에 포함되지 않음을 확인할 수 있다.

그럼 이 Embed는 언제해줘야할까?

다들 예상할 수 있겠지만, Dynamic Library를 사용할 때 Embed를 해줘야한다.

여기서 설명을 더 해보자면, Dynamic Library를 사용하면 앱의 실행파일에는 해당 Frameworks에 대한 참조값만 들어가있다고 했는데, 앱 실행파일이 실행되고 참조값이 있는 곳에 도달하면 dyld라는 친구가 앱 패키지에 있는 진짜 소스코드를 찾으러간다. (dyld은 Dynamic Loader라는 친구임.. 말그대로 동적으로 코드를 로드해주는 친구 ~)

이때, 앱 패키지에 Frameworks가 존재하지 않으면? 실제 실행시켜야하는 소스코드가 없으니 에러를 내뱉으면서 앱이 멈추게 되는 것이다. (펑 ~ 💥)

따라서 Dynamic Library를 사용하면서 Do Not Embed를 하면 런타임에 대강 아래와 같은 에러를 맞이할 수 있을 것이다 ^0^

dyld[57618]: library not loaded: @rpath/xctest.framework/versions/a/xctest referenced from: <71cbdd91-4800-3ac3-9c10-50b0e51fd259>

그럼 Static Library일 때에는?? Embed 해줘도 앱이 터지지는 않는다.

하지만 실행시켜야 할 소스코드가 이미 실행 파일에 들어가 있는데, 앱 패키지에 한 번 더 추가해주는 것이므로 용량만 더 차지하게 되는 꼴이 된다. 따라서 Static Library를 사용할 때에는 Do Not Embed 해주는 것이 좋다 !

(근데 또 Static Library에서 뭐 이미지 같은 걸 사용할 때와 같이 예외적인 상황에는 Embed 해줘야한다는데.. 자료를 못찾아서 일단 그러려니..하고 넘어간다…누군가 이에 대한 좋은 자료를 찾으신다면.. 알려주세요..)


Tuist 혹은 Xcode에서 Dynamic Library는 언제 쓰이는 걸까 ?

스크린샷 2024-11-10 오전 3 10 59

Tuist에서 Dynamic Library로 설정할 수 있는데,

Library는 Embed 설정이 안 된다..! 그러면 Embed 없이 Library를 동적으로 쓰는게 불가능해서 다음과 같은 에러가 뜬다.

Dynamic loader라 불리는 Dynamic Library를 로드하는 관리자가 라이브러리을 파일을 적재에 실패했다는 뜻이다.

이 부분은 해결하지 못 했지만, 이론적으로는 문제없고 안 쓰면 되니까 패스하겠습니다.

아시는 분 계시면 답글 부탁드립니다 !


배운 점

Static Library

스크린샷 2024-11-10 오전 3 11 28
  • 컴파일 시점에 Executable 파일에 다 복사해서 적재해버림
  • 컴파일이 오래 걸림
  • 런타임이 빠름
  • 런치 타임을 줄일 수 있음

Dynamic Library

스크린샷 2024-11-10 오전 3 11 31
  • Executable 파일에 참조값만 저장
  • 필요할 때 참조 값을 통해 필요한 소스코드를 읽어서 사용
  • 컴파일이 빠름
  • 런타임이 느림
  • 메모리를 효율적으로 씀

참조 링크

[[iOS] 빌드 결과로 보는 Static Framework 와 Dynamic Framework](https://sujinnaljin.medium.com/ios-%EB%B9%8C%EB%93%9C-%EA%B2%B0%EA%B3%BC%EB%A1%9C-%EB%B3%B4%EB%8A%94-static-framework-%EC%99%80-dynamic-framework-8568c5840e59)

[(Static/Dynamic) Library](https://zeddios.tistory.com/1308)

[Swift. Static and Dynamic Libraries. Frameworks](https://maxim-kryloff.medium.com/swift-static-and-dynamic-libraries-frameworks-343952d3011e)

Clone this wiki locally