iOS Library, Framework, Swift Package,,, 알아보자 차이점

Joon Won Lee
DelightRoom
Published in
11 min readJan 15, 2023
freepik.com

멀티 모듈 코드베이스의 시대

알라미는 원하는 시간에 잘 일어나게 해주는 “알람 시계”에서 성공적인 아침을 만들어주는 “모닝 웰니스” 서비스로 확장하면서 점점 많은 기능들이 추가 하고 있다.

서비스의 규모가 커지면서, 동시에 프로젝트 코드베이스도 점점 커지기 시작했고, 그러면서 몇가지 문제가 발생했었다.

  • 첫째, 프로젝트 빌드를 하는데 시간이 엄청 오래 걸리기 시작했다.
  • 둘째, 현재 프로젝트에서 어떤 모듈에 어떤 책임이 주어졌고, 그것으로 어떤 기능이 포함되어 있는지 파악하기가 점점 어려워 졌다.
  • 마지막으로 여러 작업자가 특정 모듈을 자주 변경하면서, 여러 충돌이 발생했다.

따라서, iOS 팀내에서 위의 문제를 해결하기 위해, 멀티 모듈 기반의 코드베이스 전환을 진행하기로 했다.

이 글에서는 멀티 모듈 코드베이스를 만들기전에, iOS 에서 모듈라 코드베이스를 만들수 있는 방법에 대해서 알아보고자 한다.

  • Library
  • Framework (애플에서 새로 제공한 XCFramework도 포함)
  • Swift Package

사전에 알아두면 좋은 지식들

주로 코드 구조화 및 접근 제어를 얘기할때 모듈이란 단어를 사용해서 얘기를 한다.

모듈은 하나의 코드 배포단위라고 생각하면 된다. 프레임웍, 라이브러리, 스위프트 패키지, 빌드 타겟 모두 Xcode 에서 하나의 독립된 모듈로 판단하고 있다. 각 모듈은 각자의 네임스페이스 및 액세스 컨트롤 가지고 있다.

보통 각 모듈은 해결하려는 특정 문제의 도메인을 가지고 있다. 예를 들면, AVFoundation 은 오디오, 미디어 관련 객체들을 제공해줌으로써 개발자가 오디오, 미디어 제품을 만들수 있도록 도와주고 있다.

따라서, 각 모듈은 사용하려는 개발자가 풀려는 문제에 따라, 반복적으로 재사용 가능하다.

Bundle

  • 번들은 내부에 있는 파일 디렉토리이다. 특히, iOS 에서 번들은 앱에 관련된 파일을 하나의 패키지로 제공하는 역할을 한다. 따라서, 시스템에서는 이를 하나의 파일로 취급해서, 내부 구조를 몰라도 편하게 접근할수 있도록 해준다.

Source file

  • 모듈에 있는 스위프트 파일이라고 생각하면 된다.

Executable file

  • 앱 실행을 위한 바이너리

Object code

  • object code 는 보통, 컴파일러를 통해 생산된 결과물이라고 볼수 있다. 보통 기계어의 나열이라고 생각해볼수 있다.

Object file

  • object code 를 포함하고 있는 파일이다.

Library

Library는 타겟(앱)에서 사용될 코드와 데이터들의 모임이다. 이후에 컴파일 시점 또는 런타임 시점에 타겟(앱)에 연결(링킹)되어 사용된다. 단, 이미지와 같은 리소스들은 포함할수가 없다.

Library 은 타겟에 어떻게 링킹하는가에 따라 2 타입으로 나누어 볼수 있다.

  • Static Library (.a)
  • Dynamic Library (.dylib)

Static Library

Static Library 은 object file 의 묶음이다. .a 파일 익스텐션을 가지고 있고, archiver tool 을 이용해서 생성된다.

마치 zip 아카이빙 같은 느낌인데, 비슷한 개념이다. 즉, 여러개의 object file 을 아카이빙 한 녀석이 Static Library 이다.

💡 .a 는 UNIX 에서 ar tool 에서 사용되던 포맷임.

💡 오브젝트 파일은 Mach-O 라는 iOS, macOS 에서 사용하는 포맷을 가지고 있다.
기본적으로는 바이너리 스트림인데, 아래의 내용을 포함하고 있다.

- Header: 파일의 타켓 아키텍쳐를 명시함. Mach-O 는 하나의 타겟 아키텍쳐에 대한 코드와 데이터를 갖기 때문에, x86-64 용 코드는 arm64 에서 동작하지 않음
- Load commands: 심볼 테이블의 위치 같은, 파일의 논리적 구조를 명시화하고 있음
- Raw segment data: 로우 코드 및 데이터를 포함함

앱에서 사용하는 코드는 컴파일 시점에 static linker 를 통해서 executable file 로 복사가 된다. 그리고, 앱 런타임 전체 시간동안 메모리 Heap 영역에 로드되어서 사용된다.

Linking static library and memory usage

Static Library 의 한계점도 있다.

  • 사용될 타겟의 프로세서 아키텍쳐와 같게 빌드를 해야함 (x86-64, arm64 등)
  • 리소스 파일들(image, assets, nibs, strings file)을 포함할수가 없음

Dynamic Library

Dynamic Library의 코드는 Static Library 처럼 컴파일 시점에 executable file 에 복사되지 않는다. 대신, 필요한 시점에 동적으로 로드되서 사용한다. 따라서 매번 컴파일(새로운 빌드) 할 필요 없이 쓸수 있다는 장점이 있다.

모든 iOS 및 macOS 시스템 라이브러리는 Dynamic Library이다. 따라서, iOS 및 macOS 에 배포한 앱들은 향후 새로운 빌드를 배포하지 않아도, 시스템 라이브러리의 혜택을 받을수가 있다.

앱 컴파일 시점에 메모리에 로드해 놓지 않았기 때문에, 상대적으로 Static Library 보다는 코드 접근 속도가 느리다.

(대신에 앱의 스타트업 속도를 빠르게 하는데 유리하다.)

Linking dynamic library and memory usage

Framework

Framework 이라고 하면 계층 구조를 갖는 디렉터리를 의미한다. dynamic library, header file, resource (storyboards, image files, localized string) 등을 하나의 패키지에 감싸서 가지고 있다.

Framework 을 사용할때는 앱 번들안에 포함 시켜야 한다.

Framework 은 Library 처럼 목적(같은 도메인)이 같은 코드의 모음이라고 보면된다.

다만, Framework 은 Library 와 아래와 같은 다른점이 있다.

  • 리소스를 포함할수 있다. (예를 들어 image, asset, documentations, strings)
  • 오직 하나의 Framework 코드 및 리소스를 메모리에 올릴수 있음.
  • 그래서 메모리 풋프린트를 줄이고, 시스템 성능을 향상 시킬수 있음
  • 또한 여러 앱이 해당 Framework이 필요한 경우, 공유되어 사용됨

XCFrameworks

XCFrameworks 은 Xcode11 부터 가능해진 새로운 Framework 배포 방법이다.

XCFrameworks 장점은 아래와 같다.

  • XCFrameworks 여러변형들(디바이스, 시뮬레이터, Xcode 가 지원하는 모든 플랫폼)을 포함해서 배포할수 있음
  • Swift 와 C 기반 코드 바이너리 지원함
  • Static Library 와 헤더들을 묶을수 있음
swift package

Swift Package

Swift 는 크로스 플랫폼 언어이며, 여러 플랫폼에서 빌드할수 있는 툴을 필요로한다. SPM(Swift Package Manager)의 목표중 하나는 swift 로된 코드를 간단하게 배포할수 있게 만드는 것이다.

Swift Package 는 소스 파일매니페스트 파일을 포함하고 있다. 매니페스트 파일에는 이 놈의 Swift Package 가 어떻게 구성되어 있는지 설명되어 있다. Swift Package 는 소스 형식으로 배포가 된다. 그래서 바이너리 호환성에 대해서 신경 안써도 되고, SPM 알아서 Swift Package를 정의하고, 실제 앱에서 링킹해서 사용한다.

그래서 소스코드로 배포를 할예정이라면, Swift Package 는 아주 좋은 툴이다. Xcode11 부터는 아주 쉽게 생성 및 배포를 할수 있게 되었다.

Swift Package 는 크게 3가지 파트로 구성되어 있다.

  • Dependencies
  • Targets
  • Products

Dependencies:

현재 패키지에서 사용하고 있는 다른 Swift Package 들을 명시한다.

(실제 소스 위치와 버젼들을 명시함)

Targets:

애플에서 설명으로는 Target 은 “The basic building block of a Swift package.” 으로 설명한다.

기본 빌드 단위라고 생각하면 되겠음.

Xcode12 이후 부터는 Swift, Obj-C, C++, C 외에도, image, storyboard, JSON file 과 같은 리소스도 포함할수 있게 되었다.

Products

Library 또는 Executable 과 같은 Package 의 산출물이며, 외부 패키지에서도 바라볼수 있는 녀석들이다.

Swift Package 는 Binary 호환성 걱정 안해도 되고, Xcode에 의해서 Dependencies, Versioning 등을 관리도 해주고, 여러리소스를 포함할수 있는 장점을 가지고 있어서 최고의 선택지로 보이기도 한다. 다만, framework 을 배포해야하는 B2B 회사의 경우에는, 소스 코드 공유가 꺼려질수 있기 때문에 선택하기 어려울수 있다.

결론

멀티 모듈 코드베이스를 만들기전에, 각 모듈라 방법에 대한 알아보았다. 실제 프로젝트 적용간에는 각 방법에 따른 한계점을 충분히 알고, 적용해야 한다.

너무 많은 Static Library 을 적용하는 경우에는 앱 바이너리가 매우 커질 수 있고, 앱 런치 시간도 오래걸리고, 메모리도 많이 사용할수 있다. Framework 의 경우에는 Static Library 보다 유연하게 시스템 리소스도 활용하고, 추가로 이미지와 같은 리소스도 포함시킬수 있다. 그리고 만약 소스 코드를 배포 할수 있다면, 그럴때는 Swift Package 가 아주 적절한 방법이 될것이다. 왜냐하면, Xcode 가 dependencies, versioning, platform 등을 모두 알아서 관리해줄 것이기 때문이다.

내부 코드베이스를 모듈화 한다고 했을때는 Swift Package 를 이용한 방법이 효과적이라고 판단된다.

참조

Bundle

Libraries

Frameworks

Swift Package

⏰ 딜라이트룸에서 알라미와 함께 아침을 바꿀 분들을 모십니다 🙌

--

--