글을 읽기 전 라이브러리에 대해 알기 위해선 컴파일, 링크에 대해 알아야 합니다.
관련 글은 아래 링크를 참고해 주세요.
https://gamedeveloper-programming.tistory.com/3
빌드 과정 [Build Process]
Bulid 란 ? 빌드(Build)란 여러 소스코드 파일들을 기계어로 변환 후 실행 파일 혹은 라이브러리로 만드는 과정을 의미합니다. 컴퓨터는 0 과 1밖에 모르기 떄문에 우리가 작성하는 코드들을 바로 컴
gamedeveloper-programming.tistory.com
라이브러리(Libarary) 란?
프로그래밍에 사용할 수 있게 미리 만들어져 있는 함수나 변수들의 묶음입니다.
미리 컴파일된 여러 개의 오브젝트 파일을 하나의 큰 오브젝트 파일로 만든 것을 의미합니다.
오브젝트 파일 이기 때문에 빌드할 때, 라이브러리도 같이 링크하며 기능을 사용할 수 있게 합니다.
즉, 개발 시 사용되는 프로그램의 구성 요소로, 공통으로 사용될 수 있는 특정한 기능을 모듈화 한 것입니다.
라이브러리의 장점
- 코드를 재사용하기 쉽다.
- 코드의 정의를 숨겨 보안성이 좋다.
- 이미 구현된 기능들을 가져다 쓸 수 있어 시간 단축을 할 수 있다.
- 컴파일 시간을 단축할 수 있다.
라이브러리에 헤더 파일이 있는 이유
소스 코드를 컴파일 시에 만들었던 구멍은 여전에 만들어야 하기 때문에 헤더 파일을 인클루드(#include) 함으로써 링크작업을 할 때 구멍을 메꿔야 합니다.
그러기에 라이브러리를 사용할 때 인클루드를 함으로써 라이브러리의 헤더 파일을 사용을 해야 하는 것입니다.
구멍 이란?
컴파일러는 함수 구현부를 만나면 그 이름과 똑같은 레이블을 정의합니다.
함수를 호출하는 코드를 레이블이 정의된 곳으로 점프하는 코드로 변환하는 것을 '구멍 생성'이라고 합니다.
(아직 정의된 위치를 모르는 상황입니다.)
다음 링크 작업에서 파일들을 합칠 때 이 레이블이 정의된 곳이 어디인지 알아내어 그 주소로 점프하도록 해주는걸
'구멍 메꾸기' 라고 합니다.
그러기에 '구멍 매꾸기' 작업까지 끝낸다면 헤더파일에 있는 함수 선언 부분에서 어떤 함수가 있는지 알고 호출을 하기만 해도 정의를 몰라도 알아서 정의 부분을 찾아 함수를 실행시켜주는 것입니다.
때문에 라이브러리를 배포하거나 stdio.h 와 같은 라이브러리를 사용할 때 헤더파일만 선언해도 그 정의까지 사용할 수 있는 것입니다.
라이브러리 종류
라이브러리에는 링크되는 타이밍에 따라 2종류로 나눌 수 있습니다.
- 정적 라이브러리
- 동적 라이브러리
그러기에 이 각 라이브러리의 장점이 링크 방식의 정의 및 장담점이 같다고 볼 수도 있습니다.
정적, 동적 라이브러리는 여러 가지 상반되는 장단점이 있습니다.
일반적으로 정적 라이브러리를 쓰되, 필요하면 아래 차이점을 참고해서 상황에 맞는 라이브러리를 사용하는 것이 좋습니다.
정적 라이브러리(Static Library)
정적 라이브러리는 빌드 시에 정적 라이브러리 파일도 같이 링크해서 ( 정적 링킹 [ Static Linking ] ) 하나의 실행 파일을 빌드하는 방식입니다.
정적 라이브러리의 확장자는 윈도우에서는 *.lib, 리눅스에서는 *.a 입니다.
정적 라이브러리의 장점
실행 파일이 라이브러리를 가지고 있으므로, 실행 파일을 배포할 때 라이브러리를 따로 배포할 필요가 없습니다.
그만큼 안정적이고 이식성이 좋습니다.
빌드 시에 같이 링크되기 때문에 컴파일러나 링크가 최적화 작업도 해주므로 일반적으로 성능은 동적 라이브러리보다 좋습니다.
정적 라이브러리의 단점
- 빌드한 실행 파일이 정적 라이브러리의 기계어가 다 포함되므로 동적 라이브러리에 비해 용량이 큽니다.
- 정적 라이브러리에는 실행 파일마다 붙어있기 때문에 라이브러리 또는 실행 파일 둘 중에 하나라도 수정을 한다면 둘 다 다시 빌드해야 합니다.
동적 라이브러리(Dynamic Library)
동적 라이브러리는 빌드할 때 링크 작업에 포함시키지 않습니다.
실행 파일에 동적 라이브러리를 포함되지 않는다는 뜻.
프로그램을 실행하는 순간, 운영체제가 실행 파일과 동적 파이브러리를 링크시킵니다.(동적 링킹 [Dynamic Linking] )
동적 라이브러리의 확장자는 윈도우에서는 *.dll, 리눅스에서는 *.so 입니다.
동적 라이브러리의 장점
정적 라이브러리처럼 실행 파일마다 라이브러리가 있는 게 아닌 하나의 라이브러리를 쓰는 것이기 때문에 정적 라이브러리보다 용량이 적습니다.
정적 라이브러리에서는 실행 파일, 라이브러리 둘 중 하나라도 수정을 하였으면 둘 다 다시 빌드를 했어야 했는데동적 라이브러리에서는 수정된 것만 다시 빌드를 할 수 있습니다.
동적 라이브러리의 단점
- 실행 파일뿐만이 아니라 라이브러리 파일도 가지고 있어야 합니다, 그러기에 외부 의존도가 생기며 이식성이 낮습니다. 또한 버전 충돌로 인한 'DDL Hell'이 발생할 수도 있습니다.
DDL Hell 이란?
만약 은행 A의 프로그램에서 보안 라이브러리 버전 1.0을 요구하고
은행 B의 프로그램에서 보안 라이브러리 버전 2.0 버전을 요구하는 경우
은행 A의 프로그램 인스톨러에서 통해 설치를 하여 보안 라이브러리 1.0을 설치하여 사용하다가
은행 B의 프로그램 인스톨러에서 통해 설치를 하게 되면 보안 라이브러리는 이름이 같으므로 2.0으로 덮어 씌워지게 됩니다.
이때 은행 B의 프로그램은 잘 실행되지만 은행 A의 프로그램은 보안 라이브러리 버전 충돌로 실행이 안됩니다.
그러면 은행 A의 프로그램을 삭제하고 다시 설치하면 보안 라이브러리가 또다시 1.0으로 덮어 씌워지게 되면서
A는 잘되지만 이번에는 B가 버전 충돌로 안되고 이것을 반복하는 상태를 뜻합니다.
(정적 라이브러리는 실행 파일마다 라이브러리가 포함되어 있으므로 버전문제로 인한 'DDL Hell' 문제가 일어날 리가 없다.)
- *.dll 파일에 있는 함수들을, 프로그램 실행 시에 운영체제가 링크하기 때문에 만약 *.dll 파일에 있는 특정 함수의 헤더를 알고 있다면 그것과 똑같은 헤더를 만들고 구현부를 다르게 하여 원래 있던 *.dll 파일과 똑같은 이름으로 만들어 덮어쓰기를 한다면, 내가 수정한 *.dll 로 실행되기 때문에 해킹이 가능함 ( ex : 크랙 프로그램 )
- 운영체제에 의존적이다.
마무리
빌드 과정을 이해했다면 라이브러리의 동작 방식도 이해하기 어렵진 않았을 것이라고 생각합니다.
또한, 라이브러리를 이해했다면 본인이 직접 라이브러리를 만들 수 있어 파일 분할을 좀 더 세분화해가지고 나눌 수 있을 것 같습니다.
한 가지 개념을 배우면 다른 개념과 연쇄적으로 터지면서 활용할 수 있는 점이 무궁무진하게 많아지는 것 같아요.
최근에 배운 것 중 라이브러리가 제일 재밌던 것 같습니다.
'프로그래밍 > ETC' 카테고리의 다른 글
컴파일러 종류 [ Compiler ] (0) | 2022.12.31 |
---|---|
파일 분할 (0) | 2022.12.28 |
빌드 과정 [Build Process] (0) | 2022.12.28 |