본문 바로가기

iOS

(iOS) Library vs Framework(3)

이전 글에서는 정적, 동적 라이브러리의 차이 및 장단점에 대해서 알아보았고, 이번 글에서는 iOS에서 프레임워크가 어떻게 구성되고 사용되는지에 대해서 정리하려고 한다.

 

Framework 사용 목적

프로젝트 규모가 커지고 복잡해질수록 프레임워크를 사용할 때 이점이 많아질 수 있다. 라이브러리와 마찬가지로 프레임워크는 코드 구성이 쉬워지고, 재사용성이 증가하며, 목적에 따라 사용하는 코드의 분리가 가능하다. 

프로젝트가 커지며 새로운 기능이 추가될 수록 당연히 코드도 복잡해지고 관리하기가 어려워진다. 따라서 프레임워크를 사용하면 다음과 같은 이점을 얻을 수 있다.

1. 모듈화

각 프레임워크는 특정 기능을 캡슐화하여 코드를 더 쉽게 이해하고 유지 관리할 수 있도록 한다. 앱의 한 영역에서 버그나 성능 문제가 발생하면 다른 영역에 영향을 미치지 않고 해당 프레임워크에 집중할 수 있다.

2. 재사용

프레임워크는 여러 프로젝트에서 재사용하거나 다른 개발자와 공유할 수 있다. 예를 들어 사용자 인증이 필요한 다른 앱에서 인증 프레임워크를 사용하거나 특정 유틸리니 코드를 프레임워크화 하여 단일, 다수의 앱에서 공유하여 사용할 수 있다.

3. 책임 분

앱을 별개의 프레임워크로 분할하여 각 구성 요소의 책임을 분리할 수 있으므로, 의존성을 보다 쉽게 관리하고 각 프레임워크가 하나의 목적을 갖도록 보장할 수 있다.

4. 테스트 및 디버깅

프레임워크를 좀더 작게 구성할수록 유닛 테스트를 작성하고 유지 관리하기가 쉬워져 앱의 각 부분이 잘 테스트되고 신뢰할 수 있다. 코드 추상화가 쉬워지고 Mock 생성이 쉬워짐에 따라 테스트코드를 작성하는 것도 쉬워진다.

5. 빌드 속도 감소

코드를 별도의 프레임워크로 구성하여 변경된 프레임워크만 다시 빌드하면 되는 증분 빌드를 활용할 수 있다. 이를 통해 특히 대규모 프로젝트의 경우 빌드 시간이 단축될 수 있다.

 

프레임워크 구성

Bundle

프레임워크를 설명하기 전 번들에 대해 먼저 이야기해보면 좋을 것 같다. 번들(Bundle)이란 번들은 앱의 실행 파일과 관련 리소스를 함께 묶어 놓은 디렉토리라고 생각하면 된다. 여기서 말하는 리소스란 이미지, 사운드, 스토리보드, nib파일 등을 의미한다.

라이브러리와 달리 프레임워크는 기본적으로 번들 형태로 존재하기 때문에 같은 디렉토리에서 프레임워크와 리소스를 모두 가지고 관리할 수 있다. 

프레임워크 생성

Xcode에서 프레임워크 생성 ⌘⇧N

Xcode에서 프레임워크를 생성하면 기본적으로 Mach-O Type이 Dynamic Library으로 선택되어 있다.

Mach-O Type

언제든 Dynamic Library를 Static Library로 변경하여 Static Framework로 빌드할 수도 있다.

프로젝트 구성

프레임워크 프로젝트 파일 구성

프레임워크는 라이브러리와 달리 헤더, 리소스, 소스파일을 모두 포함하는 모듈 형태로 존재한다. 

header file

헤더 파일을 살펴보면, 타 언어(ObjC, C, C++ 등)에 대한 public header file을 추가할 수 있도록 하며, 버전 정보를 export하여 프레임워크 사용 시 참조할 수 있도록 한다. 라이브러리와 달리 프레임워크는 여러 버전을 두어 관리할 수 있도록 한다.

 

문서화

Swift 또는 Xcode에서 프로젝트 개발을 하다 보면 개발자 문서를 한 번이라도 본 적이 있을 것이다. 사용자가 프레임워크에 정의된 기능들을 좀 더 쉽게 사용할 수 있도록 MarkDown형태로 문서를 작성할 수 있는 docc 파일을 제공한다.

쉬운 사용

라이브러리를 사용할 때는 스위프트 모듈과 라이브러리 검색 경로 등을 Build Settings에서 직접 지정해주었어야 했다. 프레임워크의 경우 빌드된 프레임워크(확장자. framework) 파일을 프로젝트에 추가해주기만 하면 별도 세팅 없이 import 하여 사용할 수 있다.

Embed & Sign, Embed Without Signing, Do Not Embed

 

프레임워크를 추가해 본 경험이 있다면 한 번쯤 본 적이 있는 문구일 것이다. 뜻만 봤을 때는 당연히 앱에서 사용할 프레임워크니까 Embed시켜줘야지 하고 생각할 수도 있다. Sign의 경우 개발자 인증서로 서명하는 거겠거니 하고 넘어갔던 기억이 있다. 각각의 세팅이 뭐가 다를까?

일단 Embed만 놓고 이야기해 보자면 앱 빌드 시 프레임워크가 앱 번들 내에 포함되어야 할지 말지를 결정하는 거라고 보면 된다.

Static Framework의 경우 컴파일 시 이미 앱에 복사가 될 텐데 굳이 있어야 할까 하는 의문이 생길 수도 있다. 답만 놓고 보자면 Do Not Embed해도 된다.

반대로 Dynamic Framework의 경우 런타임에 동적으로 링킹이 일어나므로 이때 별도의 위치에 존재해야 한다. 이런 경우 앱 번들에 포함시켜서 앱에서 언제든 참조할 수 있도록 Embed & Sign 또는 Embed Without Signing을 선택하면 된다. 만약 Do Not Embed를 선택 후 빌드할 경우 런타임에서 다음과 같은 에러를 출력하게 된다.

동적 링킹 중 경로에서 프레임워크를 찾지 못함.

빌드가 완료된 앱의 패키지 내용을 보면 프레임워크가 번들에 포함되지 않은 것을 확인할 수 있다.

App Bundle에 Framework 없음

선택값을 Embed & Sign으로 변경 후 다시 빌드해 보면 아래와 같이 앱 번들에 Frameworks 디렉토리와 프레임워크가 포함된 것을 확인할 수 있고, 링킹 에러도 출력되지 않는 것을 확인할 수 있다.

App Bundle에 Framework 포함됨.

위처럼 사용하는 프레임워크에 따라 필요시 embed해서 사용하도록 하자.

증분 빌드 관점

프레임워크를 사용하는 큰 이유 중 하나는 증분 빌드 때문이지 않을까 싶다. 
증분 빌드는 전체 프로젝트를 다시 빌드하는 것이 아니라 마지막 빌드 이후 변경된 프로젝트의 일부만 다시 컴파일하여 컴파일 시간을 줄이는 것을 목표로 하는 빌드 시스템의 기능이다. 이 방식은 특히 대규모 프로젝트나 종속성이 많은 프로젝트의 경우 빌드 프로세스 속도를 크게 높일 수 있다. 
이러한 장점을 살리기 위해서 어떤 타입(Static or Dynamic)의 프레임워크를 사용하느냐도 많은 영향을 준다. 

 

1. 정적 프레임워크
정적 프레임워크가 수정되면 프레임워크 내의 object 파일을 다시 컴파일하고 앱 바이너리로 다시 링크해야 한다. 즉, 정적 프레임워크를 수정하면 전체 앱을 다시 빌드해야 할 수 있다.
그러나 앱 코드가 수정되었지만 정적 프레임워크가 변경되지 않은 경우 빌드 시스템은 정적 프레임워크를 링크하지 않고 수정된 앱 코드만 다시 컴파일하여 증분 빌드를 활용할 수 있다.

2. 동적 프레임워크
동적 프레임워크를 수정하면 프레임워크의 변경된 부분만 다시 컴파일하면 되며 앱의 바이너리를 생성할 필요가 없다. 이는 동적 프레임워크가 별도의 바이너리이며 런타임에 연결되기 때문이다.
앱 코드가 수정되었지만 동적 프레임워크가 변경되지 않은 경우 빌드 시스템은 수정된 앱 코드만 다시 컴파일하여 증분 빌드를 다시 사용할 수 있다.

 

이러한 관점에서 동적 프레임워크가 장점이 더 많아 보이긴 하지만, 앱 코드만 수정했을 경우에는 증분 빌드에 대한 장점을 활용할 수 있으므로 필요에 따라 적절한 프로젝트를 선택하여 사용하면 된다. 


지금까지 라이브러리, 프레임워크에 대해 간단하게 정리해 보았다. 간단한 앱을 개발할 때는 이런 라이브러리 또는 프레임워크를 굳이 사용해야 하나 싶지만, 우리가 일반적으로 CocoaPods, SPM, Carthage를 통해 사용하는 코드들도 누군가 재사용 및 다른 장점들을 살리기 위해 배포한 것을 우리가 활용하여 사용하고 있다. 

개인 또는 회사에서 개발하는 프로젝트의 규모에 따라 적절하게 선택해서 개발 및 활용해 보면 좋을 것 같다.

'iOS' 카테고리의 다른 글

(iOS) 유니플로거 리팩토링(2) 튜토리얼  (0) 2023.06.07
(iOS) 유니플로거 리팩토링(1) XCFramework  (4) 2023.05.07
(iOS) Library vs Framework(2)  (0) 2023.03.07
(iOS) Library vs Framework(1)  (1) 2023.02.18
Swift import 알아보기  (0) 2023.01.30