모듈
모듈이란 소프트웨어의 논리적 그룹화 단위로, 시스템을 기능 단위로 묶은 요소입니다. 또한 모듈은 컴파일 단위이자 배포 단위로, 여러 가지 형태를 가지고 있습니다.
System Module
import Foundation // Foundation 모듈
import UIKit // UIKit 모듈
import CoreData // CoreData 모듈
App Module
앱 자체도 하나의 모듈입니다. 기본적으론느 앱의 Bundle Identifier가 모듈명으로, 별도의 import 없이 앱 내에서 사용 가능합니다.
Framework Module
import Alamofire // 외부 프레임워크 모듈
import MyFramework // 커스텀 프레임워크 모듈
Package Module
import MySwiftPackage // Swift Package 모듈
모듈 시스템의 장점
- 네임스페이스 제공
- 접근 제어
- 컴파일 최적화
- 모듈 단위로 독립적 컴파일 가능
- 변경된 모듈만 재컴파일
패키지
패키지는 관련된 모듈들을 디렉토리 형태로 묶어놓은 것을 의미합니다. Swift Package Manager 등을 통해 iOS에선 패키지를 생성하고 배포할 수 있습니다.
라이브러리
라이브러리는 컴파일된 바이너리 코드를 .a, .dylib 파일로 묶어둔 것을 의미합니다. 패키지의 집합으로 다른 부수적인 패키지가 없는 것에 대해 걱정할 필요 없이 바로 사용할 수 있는 기능들의 집합을 제공합니다.
프레임워크
프레임워크는 라이브러리가 발전된 형태로, 바이너리뿐만 아니라 헤더 파일, 리소스, 메타 데이터를 하나의 .framework 번들로 묶어는 것입니다. UIKit, Foundation이 프레임워크의 예시입니다.
정리하자면 모듈은 기능에 따라 묶는 논리적 단위를 의미하는 것이고, 여러 모듈을 합쳐서 패키지로 생성할 수 있고, 여러 패키지를 기반으로 라이브러리를 생성할 수 있고, 여러 라이브러리를 통해 프레임워크가 탄생할 수 있는 느낌으로 이해할 수 있을 것 같습니다. 그렇다고 해서 패키지나 프레임워크가 모듈이 아니라고는 할 수 없습니다. 이들 또한 기능의 논리적 묶음 단위이기 때문입니다.
라이브러리 vs 프레임워크
제어의 역전(IoC)
라이브러리와 프레임워크의 가장 큰 차이점은 '누가 프로그램의 흐름을 제어하는가'에 있습니다. 쉽게 말해, 라이브러리는 내가 가져다 쓰는 도구이고 프레임워크는 내가 그 안으로 들어가서 작업하는 틀입니다.
예를 들어 수학 라이브러리를 통해 Math.sqrt(16)을 호출하면 4가 반환되고 끝이 나는데, 이는 개발자가 언제, 어떻게 사용할 지 가져다가 사용하는 것이기 때문에 라이브러리입니다. 하지만 UIKit 프레임워크에서 viewDidLoad()가 호출될 때 개발자가 viewDidLoad()를 임의로 제어하여 호출하는 것이 아니라, viewDidLoad()가 호출된 상황 안에서 로직을 작성하는 것이기 때문에 프레임워크입니다. 개발자가 viewDidLoad() 자체가 언제 어떻게 호출되는지는 정의하는 것이 아니라 viewDidLoad() 안에 있는 로직을 정의하면, UIKit 프레임워크가 해당 코드들을 보고 viewDidLoad() 시기에 알아서 로직을 호출해줍니다.
형식
라이브러리는 프로그램이 연결할 수 있는 패키징된 Object 파일들의 모음으로, 순수한 코드의 집합체라고 할 수 있습니다. 반면, 프레임워크(Framework)는 이러한 라이브러리에서 한 걸음 더 나아간 개념입니다. 단순한 코드 덩어리인 라이브러리와 달리, 프레임워크는 라이브러리를 포함하면서 헤더 파일, 이미지나 오디오 같은 리소스, 지역화 파일 등 코드 외적인 요소들까지 하나의 번들(Bundle)이라는 패키지 형태로 묶어놓은 것입니다. iOS 개발에서 .framework 확장자를 가진 것들이 바로 이것입니다. 이처럼 프레임워크는 개발에 필요한 모든 것을 담고 있는 '종합 선물 세트'와 같다고 볼 수 있습니다.
이 코드 덩어리인 라이브러리를 애플리케이션에 연결(linking)하는 방식에 따라 크게 두 가지로 나뉩니다.
라이브러리의 종류
정적 라이브러리 (Static Library, .a)
하나는 정적 라이브러리(Static Library)입니다. 이는 컴파일 시점에 라이브러리의 코드가 앱의 실행 파일(Executable file)에 그대로 복사되어 하나로 합쳐지는 방식입니다. 앱이 모든 코드를 자체적으로 포함하게 되므로 실행 파일의 크기는 커지지만, 런타임에 외부 파일을 참조할 필요가 없어 실행이 빠르다는 장점이 있습니다.
공유 라이브러리 (Shared/Dynamic Library, .dylib)
다른 하나는 공유 라이브러리(Shared Library) 또는 동적 라이브러리(Dynamic Library)입니다. 이 방식에서는 컴파일 시점에 코드 전체가 복사되는 대신, 해당 라이브러리를 어디서 찾아야 하는지에 대한 참조(reference) 정보만 실행 파일에 기록됩니다. 그리고 앱이 실제로 실행될 때 운영체제(OS)가 이 정보를 바탕으로 필요한 라이브러리 코드를 메모리에 불러와 연결해줍니다. 덕분에 실행 파일의 크기를 작게 유지할 수 있고, 여러 프로그램이 하나의 라이브러리를 공유하여 메모리를 효율적으로 사용할 수 있습니다. 하지만 참조에 대한 연결을 진행해야 하기 때문에 실행 속도는 상대적으로 느립니다.
프레임워크의 종류
그리고 프레임워크 역시 그 안에 담고 있는 라이브러리의 성격에 따라 정적 프레임워크(Static Framework)와 동적 프레임워크(Dynamic Framework)로 나뉩니다.
정적 프레임워크 (static framework)
정적 프레임워크는 내부에 정적 라이브러리(.a)를 가지고 있습니다. 따라서 이 프레임워크를 사용하면, 프레임워크 내의 코드 전체가 컴파일 시점에 앱의 실행 파일에 복사됩니다. 여러 프레임워크가 동일한 정적 라이브러리를 참조할 경우, 코드 중복이 발생하여 앱의 용량이 불필요하게 커질 수 있습니다.
동적 프레임워크 (dynamic framework)
동적 프레임워크는 내부에 동적 라이브러리(.dylib)를 가지고 있습니다. 앱 실행 파일에는 프레임워크를 가리키는 참조만 저장되고, 앱이 실행될 때 필요에 따라 시스템이 프레임워크 코드를 메모리에 로드합니다. 이는 앱의 초기 실행 파일 크기를 줄여주고, 메모리 관리를 더 효율적으로 만들어줍니다.
패키지 vs 프레임워크
'패키지'는 코드의 소스 관리 및 빌드 방법을 정의하는 설계도이고, '프레임워크'는 그 설계도를 바탕으로 만들어진 실제 결과물(제품)입니다.
설계도(Package) vs. 결과물(Framework)
패키지 (Package): 레고 박스와 설명서
- 스위프트 패키지(Swift Package)는 소스 코드 파일들과 Package.swift라는 설명서(매니페스트)로 구성된 하나의 묶음(보통 Git 저장소)입니다.
- 역할: Package.swift 설명서는 이 레고 조각들(소스 코드)로 무엇을 만들 수 있고(Products), 어떤 다른 레고 부품들(Dependencies)이 필요한지를 정의합니다.
- 단계: 빌드 이전의 소스 코드 상태입니다.
프레임워크 (Framework): 완성된 레고 자동차
프레임워크는 스위프트 패키지라는 설계도를 Xcode 빌드 시스템이 읽어서 조립을 완료한 최종 산출물입니다.
- 역할: 컴파일된 코드와 리소스가 담겨 있어, 다른 앱에서 즉시 가져다 쓸 수 있는 완성된 부품입니다.
- 단계: 빌드 이후의 결과물입니다.
전체 흐름
Swift Package (Git 저장소 + Package.swift) ➡️ SPM / Xcode 빌드 시스템 ➡️ MyFramework.framework
한눈에 보는 차이점
구분 | 패키지 (Package) | 프레임워크 (Framework) |
핵심 | 빌드 방법을 정의하는 설계도 | 빌드 후 생성되는 결과물 |
형태 | 소스 파일 + Package.swift 파일 | 컴파일된 코드 + 리소스를 담은 .framework 번들 |
단계 | 빌드 이전 (Before Build) | 빌드 이후 (After Build) |
비유 | 레고 박스 + 설명서 | 완성된 레고 자동차 |
'iOS' 카테고리의 다른 글
[iOS] Optimistic UI의 정의 및 적용 사례 (SwiftUI) (2) | 2025.06.08 |
---|---|
[iOS] Decimal을 사용해야 하는 이유 (0) | 2025.04.02 |
[iOS] Xcode의 빌드 과정 (0) | 2025.01.16 |
[UIKit] UILabel.text와 문자열 보간법의 옵셔널 표현의 차이 (0) | 2025.01.03 |
[iOS] SwiftLint 설치 및 적용하기 (0) | 2023.12.23 |