정적 라이브러리, 동적 라이브러리, 그리고 macOS Framework의 차이
.a, .dylib, .framework를 링크 시점·배포 방식·메모리 사용·패키징 구조 관점에서 비교합니다.
C/C++이나 macOS 개발을 하다 보면 .a, .dylib, .framework 같은 파일을 자주 만나게 됩니다.
겉으로 보면 모두 “다른 프로그램의 기능을 가져다 쓰기 위한 라이브러리”처럼 보이지만, 실제로는 링크되는 시점과 배포 방식, 메모리 사용 방식, 패키징 구조가 서로 다릅니다.
정적 라이브러리
빌드 시 필요한 라이브러리 코드가 실행 파일 내부에 포함됩니다.
동적 라이브러리
실행 시 동적 로더가 별도 라이브러리를 찾아 메모리에 로드합니다.
macOS Framework
바이너리, 헤더, 리소스, 메타데이터 등을 하나의 Bundle로 묶습니다.
| 구분 | 정적 라이브러리 | 동적 라이브러리 | Framework |
|---|---|---|---|
| 대표 확장자 | .a | .dylib | .framework |
| 실제 코드가 앱에 포함되는가 | O | X | 내부 바이너리에 따라 다름 |
| 링크 시점 | 빌드 시 | 빌드 + 실행 시 | 내부 바이너리에 따라 다름 |
| 별도 배포 필요 | 보통 X | O | 보통 O |
| 여러 프로세스 간 코드 공유 | X | 가능 | 동적 Framework라면 가능 |
| 헤더/리소스 포함 | X | X | O |
| 버전 관리 구조 | 별도 구현 | dylib 자체 지원 | Bundle 구조로 지원 |
| macOS 친화성 | 일반적 | 일반적 | 매우 높음 |
1. 먼저 라이브러리란 무엇인가?
프로그램을 작성하다 보면 모든 기능을 직접 구현하지는 않습니다.
예를 들어 다음과 같은 함수를 여러 프로그램에서 사용한다고 해보겠습니다.
int add(int a, int b);
int subtract(int a, int b);
이 코드들을 하나의 라이브러리로 만들어 두면 여러 프로그램이 공통으로 사용할 수 있습니다.
math library
├─ add()
├─ subtract()
└─ multiply()
↓ 사용
Application A
Application B
Application C
문제는 이 라이브러리 코드를 최종 실행 파일에 어떻게 연결할 것인가입니다.
여기서 정적 링크와 동적 링크가 나뉩니다.
2. 정적 라이브러리란?
정적 라이브러리(Static Library)는 빌드할 때 필요한 라이브러리 코드를 실행 파일 안에 포함시키는 방식입니다.
Unix/macOS에서는 일반적으로 다음 확장자를 사용합니다.
libcrypto.a
libmath.a
libfoo.a
.a는 archive를 의미합니다.
정적 라이브러리는 여러 개의 object file을 묶어 놓은 파일이라고 이해하면 쉽습니다.
foo.c
↓ compile
foo.o
bar.c
↓ compile
bar.o
foo.o + bar.o
↓
libtest.a
그리고 프로그램을 빌드할 때 linker가 필요한 코드를 가져옵니다.
main.o
+
libtest.a
↓
Linker
↓
my_app
최종적으로 필요한 라이브러리 코드가 my_app 내부에 들어갑니다.
실제로는 라이브러리 전체가 복사되는가?
“정적 라이브러리를 링크하면 .a 전체가 실행 파일에 복사된다.”
라고 설명하지만 엄밀하게는 약간 다릅니다.
일반적으로 linker는 .a 안에 들어 있는 object file 중에서 필요한 심볼을 제공하는 object를 선택해 링크합니다.
libmath.a
add.o
subtract.o
matrix.o
fft.o
프로그램이 add()만 사용한다면 모든 코드가 반드시 포함되는 것은 아닙니다.
3. 정적 라이브러리의 장점
가장 큰 장점은 배포가 단순하다는 것입니다.
my_app
안에 필요한 라이브러리 코드가 이미 포함되어 있다면 실행할 때 별도로 libfoo.dylib를 찾아야 할 필요가 없습니다.
따라서 실행 환경에서 다음과 같은 문제가 줄어듭니다.
Library not loaded
또한 특정 버전의 라이브러리가 실행 파일 안에 고정되므로, 개발 당시 사용한 버전의 영향을 비교적 안정적으로 유지할 수 있습니다.
4. 정적 라이브러리의 단점
반대로 실행 파일이 커질 수 있습니다.
App A
└─ Library Code
App B
└─ Library Code
App C
└─ Library Code
각 실행 파일에 라이브러리 코드가 들어갑니다.
또 하나의 중요한 단점은 라이브러리를 수정하면 애플리케이션을 다시 링크해야 한다는 것입니다.
libfoo.a 수정
↓
Application 재빌드/재링크 필요
5. 동적 라이브러리란?
동적 라이브러리(Dynamic Library)는 라이브러리 코드를 실행 파일 내부에 넣지 않고 별도의 라이브러리 파일로 유지하는 방식입니다.
macOS → libfoo.dylib
Linux → libfoo.so
Windows → foo.dll
Application
│
│ 참조
▼
libfoo.dylib
“이 프로그램은 실행할 때 libfoo가 필요하다”
라는 의존 관계가 실행 파일에 기록됩니다.
6. 동적 라이브러리는 언제 연결되는가?
동적 라이브러리라고 해서 컴파일/링크 단계에서 아무것도 하지 않는 것은 아닙니다.
소스 코드
↓
Compiler
↓
Object File
↓
Linker
↓
Executable
linker는 “이 함수는 libfoo.dylib에서 제공된다”라는 정보를 실행 파일에 기록합니다.
그리고 프로그램 실행 시 macOS의 동적 로더인 dyld가 실제 라이브러리를 찾아 메모리에 로드합니다.
Application 실행
↓
dyld
↓
필요한 dylib 검색
↓
라이브러리 로드
↓
Symbol 연결
↓
프로그램 실행
7. 동적 라이브러리의 장점
App A ─┐
App B ─┼──→ libfoo.dylib
App C ─┘
여러 프로그램이 하나의 라이브러리를 사용할 수 있습니다.
그래서 디스크 공간을 절약할 수 있고, 조건이 맞으면 라이브러리의 코드 페이지를 여러 프로세스가 메모리에서 공유할 수도 있습니다.
또한 라이브러리를 앱과 분리하여 관리할 수 있습니다.
8. 동적 라이브러리의 단점
가장 대표적인 문제는 런타임 의존성입니다.
dyld: Library not loaded: ...
프로그램을 실행했는데 dylib가 없거나 버전·ABI가 호환되지 않으면 실행 자체가 실패할 수 있습니다.
9. macOS의 @rpath는 왜 자주 등장할까?
@rpath/libfoo.dylib
@loader_path
@executable_path
이것들은 dyld가 동적 라이브러리의 실제 위치를 찾는 데 사용합니다.
MyApp.app
├── Contents
│ ├── MacOS
│ │ └── MyApp
│ └── Frameworks
│ └── libfoo.dylib
실행 파일에는 라이브러리 경로가 @rpath/libfoo.dylib처럼 기록될 수 있습니다.
10. 그렇다면 macOS Framework란?
.framework는 동적 라이브러리의 다른 이름일까?
그렇지 않습니다.
Framework는 본질적으로 Bundle, 즉 정해진 디렉터리 구조를 가진 패키지입니다.
라이브러리 바이너리 + 헤더 + 리소스 + 메타데이터 등을 하나의 디렉터리에 패키징한 형태
MyFramework.framework/
├── MyFramework
├── Headers/
│ ├── MyFramework.h
│ └── Crypto.h
├── Modules/
│ └── module.modulemap
├── Resources/
│ └── Info.plist
└── Versions/
11. Framework 안의 MyFramework는 무엇인가?
Framework 디렉터리 안의 MyFramework가 실제 실행 코드가 들어 있는 Mach-O 바이너리입니다.
Framework
│
├─ Dynamic Framework
│
└─ Static Framework
그래서 .framework = dynamic library라고 이해하면 정확하지 않습니다.
Framework는 패키징 형식, Static/Dynamic은 링크 방식에 대한 개념입니다.
12. .dylib와 Framework의 차이
동적 Framework를 예로 들면 실제 코드의 동작 방식은 .dylib와 상당히 비슷합니다.
하지만 Framework는 관련된 파일까지 함께 묶을 수 있다는 차이가 있습니다.
/usr/local/lib/libcrypto.dylib
/usr/local/include/crypto.h
/usr/local/share/crypto/...
Crypto.framework/
├── Crypto
├── Headers/
├── Modules/
├── Resources/
└── Info.plist
13. Framework가 제공하는 가장 큰 장점
Framework의 가장 큰 장점은 라이브러리에 필요한 구성요소를 하나의 논리적인 단위로 묶을 수 있다는 것입니다.
┌───────────────────────┐
│ MyFramework.framework │
│ │
│ Binary │
│ Headers │
│ Resources │
│ Modules │
│ Metadata │
└───────────────────────┘
14. 세 가지를 구조로 비교하면
정적 라이브러리
libfoo.a
│
│ Build
▼
┌─────────────────┐
│ Application │
│ │
│ App Code │
│ + │
│ Library Code │
└─────────────────┘
동적 라이브러리
┌─────────────────┐
│ Application │
└────────┬────────┘
│ Runtime
▼
┌─────────────────┐
│ libfoo.dylib │
└─────────────────┘
Dynamic Framework
Application
│ Runtime
▼
Foo.framework
│
├── Foo ← Dynamic Mach-O binary
├── Headers
├── Modules
├── Resources
└── Info.plist
15. Static Framework는 어떻게 동작할까?
Foo.framework
│ Build
▼
Application Binary
├─ App Code
└─ Foo Code
.framework는 포장 방식이고, Static / Dynamic은 링크 방식입니다.
16. 핵심 개념을 두 축으로 생각하면 쉽다
질문 1. 코드를 어떻게 링크하는가?
Static
vs
Dynamic
질문 2. 라이브러리를 어떻게 패키징하는가?
.a
.dylib
.framework
Packaging
│
┌────────────────┴───────────────┐
│ │
Library Framework
│ │
┌────┴────┐ ┌────┴────┐
Static Dynamic Static Dynamic
.a .dylib Framework Framework
17. 각각 언제 사용하는 것이 좋을까?
정적 라이브러리는 다음 상황에서 유리합니다.
- 외부 파일 의존성을 최소화하고 싶을 때
- 배포 구조를 단순하게 만들고 싶을 때
- 라이브러리 버전을 애플리케이션과 완전히 고정하고 싶을 때
- 작은 라이브러리이고 여러 프로세스에서 공유할 필요가 없을 때
동적 라이브러리는 다음과 같은 경우에 적합합니다.
- 여러 프로그램이 동일한 라이브러리를 공유할 때
- 실행 파일 크기를 줄이고 싶을 때
- 라이브러리를 독립적으로 관리할 필요가 있을 때
- 플러그인이나 런타임 로딩 구조가 필요한 경우
Framework는 특히 Apple 플랫폼에서 다음과 같은 경우 유용합니다.
- 라이브러리 코드와 헤더를 함께 배포해야 할 때
- 이미지, 설정 파일 등 리소스가 필요한 라이브러리일 때
- Swift/Objective-C 모듈 형태로 제공할 때
- Apple 플랫폼의 Bundle 및 코드 서명 체계와 통합해야 할 때
18. 장단점을 한 번에 비교하면
| 항목 | Static Library | Dynamic Library | Framework |
|---|---|---|---|
| 대표 형태 | .a | .dylib | .framework |
| 본질 | 정적 코드 묶음 | 동적 공유 라이브러리 | Apple Bundle |
| 코드 포함 시점 | 빌드 시 | 실행 시 로드 | Static/Dynamic에 따라 다름 |
| 실행 파일 크기 | 커질 수 있음 | 상대적으로 작음 | 타입에 따라 다름 |
| 별도 파일 의존성 | 적음 | 있음 | Dynamic이면 있음 |
| 메모리 코드 공유 | 어려움 | 가능 | Dynamic이면 가능 |
| 라이브러리 단독 업데이트 | 어려움 | 가능 | Dynamic이면 가능 |
| 배포 편의성 | 높음 | 경로 관리 필요 | Apple 환경에서 높음 |
| Header 포함 | 일반적으로 별도 | 일반적으로 별도 | 가능 |
| Resource 포함 | 일반적으로 별도 | 일반적으로 별도 | 가능 |
| macOS Bundle 지원 | X | X | O |
19. macOS에서 실제 파일을 확인하는 방법
어떤 파일이 정적인지 동적인지 헷갈린다면 macOS의 file 명령어를 사용할 수 있습니다.
file MyFramework.framework/MyFramework
또 실행 파일이 어떤 동적 라이브러리에 의존하는지 보고 싶다면:
otool -L MyApp
MyApp:
@rpath/MyFramework.framework/Versions/A/MyFramework
/usr/lib/libSystem.B.dylib
처럼 나온다면 MyApp이 해당 Framework를 동적으로 참조하고 있다는 것을 알 수 있습니다.
20. 마지막으로 가장 중요한 구분
Static Library
Dynamic Library
Framework
사실은 세 가지가 같은 레벨의 개념이 아닙니다.
Static과 Dynamic은 “코드를 어떻게 링크할 것인가”의 차이입니다.
Static
→ Build Time에 코드 포함
Dynamic
→ Runtime에 별도 Binary 로드
반면 Framework는 “코드와 관련 자료를 어떻게 묶어서 배포할 것인가”에 대한 Apple의 Bundle 형식입니다.
Library / Module
┌────────────┴────────────┐
│ │
Link 방식 Packaging 방식
│ │
┌─────┴─────┐ ┌──────┴──────┐
│ │ │ │
Static Dynamic .a/.dylib Framework
정적 라이브러리는 코드를 애플리케이션 안에 넣고, 동적 라이브러리는 실행 시 외부 코드를 불러오며, macOS Framework는 라이브러리 바이너리와 헤더·리소스·메타데이터 등을 하나의 Bundle로 묶기 위한 패키징 구조입니다.
'공부' 카테고리의 다른 글
| git: 공유 repository 서브트리(subtree) (0) | 2026.07.15 |
|---|---|
| Gemini 3.1 Flash TTS와 VoxCPM2 (0) | 2026.04.16 |
