이번 포스팅에서는 정적(Static), 동적(Dynamic)라이브러리의 장단점, 사용하는 플랫폼에 따라 어떤 차이가 있는지 살펴본 후 프레임워크에 대해서 다뤄보려고 한다.
Static Library의 장점.
1. 휴대성(Portability)
정적 라이브러리는 플랫폼에 독립적이므로 라이브러리가 컴파일된 것과 동일한 아키텍처 및 운영 체제를 지원하는 모든 시스템에서 사용할 수 있다. 여기에서 같은 아키텍처를 지원한다는 말이 조금 어려운데, 우리가 소프트웨어 개발 관점에서 아키텍쳐를 설명할 때는 시스템에서 사용중인 프로세서 또는 CPU를 의미한다. 많이 사용되고있는 x86아키텍쳐와 ARM 아키텍쳐는 사용하고 있는 명령어 셋이 다르기떄문에, 한 아키텍쳐를 목적으로 컴파일한 코드가 다른 아키텍쳐에서 실행되기는 어렵다.
따라서 정적 라이브러리도 마찬가지로 같은 운영체제 및 아키텍쳐를 지원하는 모든 시스템에서 사용 가능하다.
2. 성능(Performance)
정적 라이브러리는 동적 라이브러리에 비해 속도가 빠르다. 그 이유는 실행 파일에 정적 라이브러리가 다이렉트로 링킹 되어있기 때문이다. 따라서 로드 및 실행시간이 빠르다.
3. 신뢰성(Reliability)
동적라이브러리의 경우 런타임에 로드가 되지 않을 경우 프로그램이 비정상적으로 종료될 수 있다는 위험성을 가지고 있다. 정적 라이브러리는 이미 실행파일에 코드가 포함되어 있으므로 런타임에 위와 같은 문제가 발생할 것을 걱정할 필요가 없다. 또한, 프로그램이 의도한 대로 정확한 코드를 사용하도록 하여 동적 라이브러리에서 발생할 수 있는 보안 취약성의 위험을 줄일 수 있다. 동적 라이브러리를 사용하면 공격자가 라이브러리를 악의적인 버전으로 바꾸거나 런타임에 라이브러리에 코드를 주입할 수 있는 위험이 있다.
Static Library의 단점.
1. 코드 중복(Code duplication)
정적라이브러리는 실행 파일에 직접적으로 포함되므로 여러 프로그램이 같은 정적 라이브러리를 사용한다면 코드 중복이 발생할 수 있다. 이렇게 중복 사용하는 프로그램이 많을수록 같은 리소스를 사용하면서도 더 많은 메모리를 사용해야한다는 단점이 있다.
2. 실행 파일 크기 증가(Larger executable size)
실행파일에서 사용하는 정적 라이브러리가 많을 수록 그만큼의 코드를 모두 포함해야 하기 때문에, 실행 파일의 크기가 커지게 된다.
3. 업데이트(Update)
정적 라이브러리가 링킹 된 실행파일은 업데이트된 정적 라이브러리를 사용하기 위해 무조건 재컴파일 및 재배포가 필요하다. 따라서 업데이트 때마다 많은 시간이 들고 귀찮은 작업을 수행해야 한다.
Dynamic Library의 장점.
1. 코드 공유(Shared Code)
동적 라이브러리는 정적 라이브러리처럼 코드 중복을 발생시키지 않으면서 여러 실행파일에서 코드를 공유하여 사용할 수 있다. 이를 위해서 OS에서는 애플리케이션에서 동적 라이브러리가 로드할 경우 해당 라이브러리를 위한 메모리 공간을 할당 후 애플리케이션과 매핑시킨다. 여러 애플리케이션에서 사용할 수 있도록 하기 위해 이미 해당 라이브러리가 로드되어있는지를 체크한 후 참조 카운트를 늘리는 방식으로 관리한다.
2. 동적 로딩(Dynamic Loading)
동적 라이브러리는 런타임에 로드된다. 그 말은 필요할 때 로드되었다가 필요 없어지면 메모리에서 해제된다는 뜻이다. 앞서 설명했던 것과 같이 참조 카운트를 늘리는 것으로 동적 라이브러리가 사용되었다는 것을 나타내는데, 모든 애플리케이션에서 사용이 완료될 경우 참조 카운트가 0이 될 테고, 메모리에서 해제된다. 따라서 메모리를 조금 더 효율적으로 사용할 수 있다.
3. 업데이트(Update)
애플리케이션을 다시 컴파일하고 재배포하지 않아도 업데이트된 동적 라이브러리를 적용할 수 있다. 대표적으로 iOS에서 UIKit 또는 Foundation의 경우 거의 모든 애플리케이션에서 사용되고 있지만 OS업데이트를 통해 업데이트된 동적 라이브러리를 적용할 수 있다.
Dynamic Library의 단점.
1. 호환성(Compatibility)
동적 라이브러리가 자동으로 업데이트되면서 생기는 문제들이 있을 수 있다. 오래된 API가 Deprecated 되었을 수도 있고, 정의되어있던 기능이 다르게 동작할 수도 있다. 따라서 릴리즈노트 등을 잘 참고하거나 API 문서를 잘 확인하여 앱이 오작동하거나 크래시가 나지 않도록 신경을 써주어야 한다.
2. 성능(Performance)
동적 라이브러리는 런타임에 라이브러리를 로드하고 연결해야 하므로 추가적인 성능 오버헤드가 발생할 수 있다. 여러 응용프로그램이 동일한 동적 라이브러리를 사용하는 경우 라이브러리 로드 및 언로드와 관련된 추가 오버헤드가 여러 번 발생할 수 있다.
3. 보안(Security)
동적 라이브러리는 라이브러리를 주의 깊게 검사하지 않거나 공격자가 이용할 수 있는 취약성을 포함하는 경우 보안 문제를 일으킬 수 있다. 동적 라이브러리는 응용 프로그램과 독립적으로 업데이트될 수 있으므로 공격자가 라이브러리를 악의적인 버전으로 바꾸거나 런타임에 코드를 주입하는 방법으로 공격을 시도할 수 있다.
그럼 어떤 상황에서 어떤 라이브러리를 사용해야할까...?
위에서 정적 라이브러리와 동적 라이브러리의 장단점에 대해서 설명했으나... 확실히 어떤 상황에서 써야 할지는 잘 감이 오지 않는다. 따라서 각각의 라이브러리가 어떤 상황일 때 좋을지 한번 정리해 보자.
정적 라이브러리
1. 라이브러리의 크기가 작을 경우
적은 양의 클래스 또는 함수를 포함하는 라이브러리와 같이 크기가 작은 라이브러리는 링킹 후 애플리케이션 사이즈가 작아지며 시작 속도가 빨라져 사용자가 앱이 로드될 때까지 오래 기다릴 필요가 없으므로 사용자 환경이 개선될 수 있다.
2. 애플리케이션이 높은 성능을 내길 원할 경우
정적 라이브러리는 실행 파일에 직접 링킹 되므로, 특히 고성능 또는 낮은 오버헤드가 필요한 애플리케이션의 경우 동적 라이브러리보다 더 나은 성능을 제공할 수 있다.
3. 애플리케이션에 높은 안정성 또는 보안이 필요한 경우
정적 연결을 사용하면 응용프로그램이 의도한 대로 정확한 코드를 사용하도록 하여 동적 라이브러리에서 발생할 수 있는 런타임 오류 또는 보안 취약성의 위험을 줄일 수 있다.
동적 라이브러리
1. 메모리 공간을 절약하고 싶을 경우
동적 라이브러리는 런타임에 로드되고 다수의 애플리케이션에서 공유하여 사용가능하다. 이럴 경우 Memory Footprint를 줄일 수 있다. 여기서 Footprint란 어플리캐이션 또는 또는 프로세스가 사용 중인 메모리의 양을 의미한다. 필요할 때 로드되고 필요 없을 경우 메모리에서 해제되므로 메모리를 효율적으로 사용할 수 있다. 다만 이러한 로드 및 해제가 자주 일어나면 오히려 성능에 좋지 않을 수 있다.
2. 규모가 있는 프로젝트를 진행할 경우
프로젝트가 커지면 커질수록 빌드 시간이 길어지므로 모듈화 또는 컴포넌트를 나누는 작업을 통해 빌드 시간을 줄이고자 할 것이다. 코드를 더 작게 나누어 개발 및 테스트한 후 다이나믹 라이브러리로 만들어 동적으로 링킹 시켜 사용하면 된다. 이럴 경우 수정 사항이 발생한 부분에 대해서만 다시 빌드하여 사용하면 되므로 개발 시간을 많이 줄여줄 수 있다.
각각의 장단점이 존재하므로 상황에 맞게 사용하면 좋을 것 같다.
Framework에 대하여..
지금까지 라이브러리에 대해서 다뤄보았는데, 이번에는 프레임워크에 대해서 알아보도록 하자.
라이브러리가 특정 동작을 하는 코드를 빌드해 놓은 결과물이라고 한다면, 프레임워크는 특정 목적을 위해 이러한 라이브러리들과 다양한 리소스(음성, 이미지 등의 데이터)를 조합한 것이라고 보면 쉽다. 또한 버전 관리, 개발 문서 등을 포함하여 사용자가 프레임워크를 더 나은 버전으로 개선할 수 있도록 하기도 한다.(실제로 오픈소스 프레임워크들은 이런 식으로 기여를 받아 업데이트하는 경우가 많음).
네트워킹 프레임워크를 예로 들어보면 우리가 네트워크로부터 어떤 데이터를 받아서 사용하기 위해서는 다음과 같은 작업이 필요하다고 해보자.
1. HTTP Request & Response 처리
2. Response로부터 받은 데이터 처리
3. 데이터를 화면에 표시하기 위하 렌더링
4. 데이터 재사용을 위한 저장(데이터베이스 등)
위와 같은 작업이 필요하다고 할 때 각각의 작업을 수행하는 라이브러리가 4개가 필요하게 된다. 프레임워크를 사용하게 된다면 이러한 4개의 라이브러리를 조합하여 특정 작업을 위해 사용할 수 있도록 해준다.
프레임워크의 특징
프레임워크의 기본 개념은 플랫폼마다 유사하지만, 다른 플랫폼과 비교하여 프레임워크가 iOS 개발에 사용되는 방식에는 약간의 차이가 있다. 몇 가지 예를 들어 보자.
1. 패키징
Java에서는 프레임워크가 일반적으로 jar파일로 패키징 되며, 자바 클래스 파일 또는 다른 리소스들을 포함한다. .NET에서는 DLL 또는 NuGet파일로 관리하며 파이썬에서는 Egg와 Wheel파일이 있다.
iOS에서는 프레임워크를 번들로 관리하는데, 디렉토리 형태로 패키징 되어 사용된다. 이 패키지에 라이브러리 바이너리, 헤더 및 리소스 등을 가지고 있다.
2. 리소스 관리
iOS 프레임워크에서는 이미지, 음성 및 로컬라이즈 스트링과 같은 리소스를 프레임워크 번들 내에서 관리한다. 반면 웹과 같은 플랫폼에서는 백앤드에 코드를 두고 CDN(Content Delivery Network)과 같은 저장소에 리소스를 저장하여 많이 사용한다. 이러한 웹 환경에서의 프레임워크는 이러한 리소스를 쉽게 불러와 HTML로 랜더링 할 수 있도록 API 및 헬퍼 함수들을 제공한다.
3. 특정 플랫폼에 특화됨.
다른 플랫폼과 유사하게 iOS 프레임워크도 UI, 네트워킹 및 데이터 스토리지와 같은 기능에 대한 API를 제공할 때 iOS개발을 위해 특화된 개발 환경을 제공한다.
4. 패키지 매니징 시스템
node.js에서는 NPM, PHP에서는 Composer 또는 Laravel 등으로 패키지를 설치 제거 및 업데이트할 수 있도록 제공한다. iOS에서도 CocoaPods, Carthage와 같은 패키지 매니징 시스템을 제공하며, Xcode에서는 First Party 패키지 매니징 시스템인 SPM을 제공하여 별도의 설치 없이 IDE 내에서 패키지를 설치하고 관리할 수 있다.
이번 포스팅에서는 정적라이브러리와 동적 라이브러리에 대한 장단점, 사용 예시에 대해 알아보고 프레임워크에 대한 개념을 간단하게 살펴보았다. 다음 글에서는 iOS에서 프레임워크가 어떻게 구성되고 관리되는지, 그리고 어떻게 사용되는지에 대해서 정리해 보도록 하자.
'iOS' 카테고리의 다른 글
(iOS) 유니플로거 리팩토링(2) 튜토리얼 (0) | 2023.06.07 |
---|---|
(iOS) 유니플로거 리팩토링(1) XCFramework (4) | 2023.05.07 |
(iOS) Library vs Framework(3) (0) | 2023.04.06 |
(iOS) Library vs Framework(1) (1) | 2023.02.18 |
Swift import 알아보기 (0) | 2023.01.30 |