DLL 은 Dynamic Link Library 의 약자
라이브러리
소프트웨어 개발에서 자주 쓰고 기초적인 함수들을 중복 개발하는 것을 피하기 위해
표준화된 함수 및 데이터 타입을 만들어서 모아 놓은 것을 말합니다.
이런 라이브러리는 언제 메인 프로그램에 연결하느냐에 따라서 Static Link 와 Dynamic Link 로 나뉘며,
우리가 배우게 될 DDL 은 후자를 뜻합니다.
Static Link
정적 링크라고 하며 컴파일 시점에 라이브러리가 링커에 의해 연결되어 실행 파일의 일부분이 됩니다.
DLL ( Dynamic Link Library )
동적 링크라고 하며 실행 파일에서 해당 라이브러리의 기능을 사용 시에만, 라이브러리 파일을 참조하여 기능을 호출합니다. 정적 링크와는 다르게 컴파일 시점에 실행 파일에 함수를 복사하지 않고, 함수의 위치정보만 갖고 그 함수를 호출할 수 있게 해줍니다.
여러 프로그램에서 특정 기능이 필요한 경우, 각 프로그램에 그 기능을 개별로 포함하는 대신 하나의 DLL 파일을 만들어 공유하면, 모든 프로그램이 그 DLL 을 사용해 동일한 기능을 쓸 수 있게 해줍니다.
간단한 DLL 파일 만들기
MyLibrary.cpp 파일에 다음과 같은 코드를 작성합니다.
// MyLibrary.cpp
#include "MyLibrary.h"
// 함수 정의
extern "C" __declspec(dllexport) int Add(int a, int b) {
return a + b;
}
똑같은 경로에 MyLibrary.h 라는 헤더 파일을 추가합니다.
// MyLibrary.h
#pragma once
extern "C" __declspec(dllexport) int Add(int a, int b);
작성이 완료되었다면 솔루션 탐색기에서 프로젝트를 우클릭하고, 빌드를 선택하여 DLL 을 컴파일합니다.
빌드가 완료되면 프로젝트 폴더 내 Debug or Release 폴더에서 MyLibrary.dll 파일이 생성된 것을 보실 수 있습니다.
DLL 을 사용하려면, 이 DLL 을 호출하는 별도의 프로그램에서 LoadLibrary , GetProcAddress 와 같은 함수를 통해 DLL 에 접근할 수 잇습니다. 아래는 예시 코드 입니다.
// Main.cpp
#include <iostream>
#include <windows.h>
#include "MyLibrary.h" // 헤더 파일 포함
typedef int (*AddFunc)(int, int); // Add 함수 포인터 선언
int main() {
HINSTANCE hinstLib = LoadLibrary(TEXT("MyLibrary.dll")); // DLL 로드
if (hinstLib == NULL) {
std::cout << "DLL 로드를 실패했습니다." << std::endl;
return 1;
}
AddFunc Add = (AddFunc)GetProcAddress(hinstLib, "Add"); // 함수 주소 가져오기
if (Add == NULL) {
std::cout << "Add 함수 찾기를 실패했습니다." << std::endl;
FreeLibrary(hinstLib);
return 1;
}
int result = Add(10, 20); // 함수 호출
std::cout << "Add 함수 결과: " << result << std::endl;
FreeLibrary(hinstLib); // DLL 언로드
return 0;
}
DLL 의 장점
1. 컴파일 시간이 줄어든다.
프로그램에서 DLL 을 사용하면 DLL 파일을 별도로 컴파일해서 그 기능을 필요한 곳에서 호출하기만 하면 됩니다.
이렇게 하면 DLL 이 제공하는 기능이 바뀌지 않는 한, DLL 을 새로 컴파일 할 필요가 없으니 전체 프로그램의 컴파일 시간을 크게 줄일 수 있습니다.
예를 들어, 게임 프로그램에서 물리 연산이나 그래픽 효과와 같은 공통 기능을 DLL 로 만들어두면,
메인 프로그램을 수정할 때마다 물리 연산 코드까지 컴파일할 필요가 없습니다.
2. 외주 개발 시 기능을 소스 코드 없이 제공할 수 있습니다.
DLL 파일은 실행 가능한 형태의 기능 모듈이기 때문에 프로그램에 포함해 기능을 사용할 수 있지만, 그 구체적인 소스 코드 내용은 숨겨져 있습니다. 따라서 핵심 코드나 알고리즘을 보호하면서도 기능을 제공합니다.
3. 모듈 별로 버전관리가 가능해집니다.
한쪽의 내부 코드가 변경되더라도 인터페이스가 같다면 다른 쪽의 코드 변경 없이 그대로 사용 가능합니다.
즉, 아예 새로 컴파일도 필요없이 파일교체만으로도 업그레이드가 가능해 집니다.
조금 더 쉽게 설명하자면, DLL 은 외부 프로그램과 정해진 인터페이스 ( 입출력 구조 ) 로 소통합니다.
이 인터페이스란 함수 이름, 매개변수의 종류와 개수, 반환값 등이 정해진 구조 입니다. DLl 내부의 코드가 바뀌어도, 인터페이스가 바뀌지 않으면 프로그램 입장에서는 DLL 의 사용법이 똑같이 유지되기 때문에 아무 문제 없이 작동할 수 있는 것이죠.
예를 들어, 계산 기능을 제공하는 Math.dll 파일이 있다고 가졍해 봅시다. 이 DLl 파일에는 Add(int a, int b) 라는 덧셈 함수가 포함되어 있습니다. 원래 Math.adll 의 Add 함수가 아주 간단하게 return a + b; 를 실행하는 함수이지만, 이후 개발자가
이 덧셈 기능을 더 최적화 해서 성능을 높이려고 내부 코드를 바꿧다고 해도 함수 이름(Add)과 매개변수(a,b), 반환값 같은 인터페이스가 그대로 유지하게 된다면, DLL 을 사용하는 프로그램 입장에서는 Add 함수를 똑같이 사용하게 됩니다.
즉, DLL 파일을 바꾸기만 하면 프로그램의 재컴파일도 필요하지 않습니다.
4. DLL 을 사용하는 경우 메모리 절약이 가능합니다.
프로그램이 같은 기능을 중복해서 사용한다면,
DLL 을 이용해 해당 기능을 공유함으로써 메모리 사용량을 줄일 수 있습니다.
만약 A 프로그램과 B 프로그램이 같은 기능을 포함하는 DLL 을 사용하도록 만들어 졌다고 가정해 봅시다.
운영체제는 DLL 파일을 메모리에 한 번만 로드하고, 이 DLL 을 필요로 하는 모든 프로그램이 그 로드된 DLL 을 공유하게 됩니다. 따라서 하나의 DLL 을 여러 프로그램이 참조하여 메모리를 절약할 수 있습니다.
DLL 단점
버전 관리를 잘못하면 프로그램 수정 시 엇나가는 경우가 생깁니다.
혼자서 관리하는 경우 모듈별 디버깅이 귀찮아 집니다.
'CS' 카테고리의 다른 글
Base64, Blob (0) | 2024.11.29 |
---|---|
XML (1) | 2024.11.19 |
Docker 실습 (0) | 2024.10.28 |
Docker (1) | 2024.10.26 |
DNS 의 기초 상식 (0) | 2024.08.19 |