라이브러리 (컴퓨팅)
"오늘의AI위키"의 AI를 통해 더욱 풍부하고 폭넓은 지식 경험을 누리세요.
1. 개요
라이브러리 (컴퓨팅)는 여러 프로그램에서 공유하고 사용할 수 있는 재사용 가능한 코드와 데이터의 모음이다. 라이브러리는 코드 재사용과 모듈 프로그래밍을 장려하며, 정적 라이브러리와 동적 라이브러리 두 가지 주요 유형이 있다. 정적 라이브러리는 컴파일 시에 프로그램에 포함되고, 동적 라이브러리는 프로그램 실행 중에 필요에 따라 로드된다. 라이브러리는 링크, 스마트 링크, 재배치, 객체 라이브러리, 원격 라이브러리, 코드 생성 라이브러리 등 다양한 형태로 발전해 왔으며, 운영체제와 프로그래밍 언어에 따라 파일 이름 명명 규칙이 다르다. 동적 로딩은 실행 중인 프로그램이 명시적으로 라이브러리를 로드하는 기술로, 플러그인 시스템 구현에 활용된다.
더 읽어볼만한 페이지
- 라이브러리 - 바이너리 재컴파일러
- 라이브러리 - 동적 링크 라이브러리
동적 링크 라이브러리(DLL)는 윈도우 운영체제에서 프로그램 실행 시 필요한 코드와 데이터를 제공하며, 여러 프로그램에서 공유되어 메모리 효율성을 높이고 모듈성을 향상시키는 라이브러리 형식이다. - 운영체제 기술 - 프로세스
프로세스는 컴퓨터에서 실행되는 프로그램의 인스턴스로, 운영 체제가 시스템 자원을 효율적으로 관리하며 멀티태스킹 환경에서 독립적인 실행 흐름을 유지한다. - 운영체제 기술 - 커널 (컴퓨팅)
커널은 운영 체제의 핵심으로, 하드웨어와 소프트웨어 간 상호 작용을 관리하며 시스템 보안, 자원 관리, 하드웨어 추상화, 프로세스 스케줄링, 프로세스 간 통신, 다중 작업 환경 지원 등의 기능을 제공하고, 모놀리식, 마이크로, 혼합형 커널 등으로 구현되며 가상화 및 클라우드 컴퓨팅 환경에서 중요성이 커지고 있다. - 컴퓨터에 관한 - 고속 패킷 접속
고속 패킷 접속(HSPA)은 3세대 이동통신(3G)의 데이터 전송 속도를 높이는 기술 집합체로, 고속 하향/상향 패킷 접속(HSDPA/HSUPA)을 통해 속도를 개선하고 다중 안테나, 고차 변조, 다중 주파수 대역 활용 등의 기술로 진화했으나, LTE 및 5G 기술 발전으로 현재는 상용 서비스가 중단되었다. - 컴퓨터에 관한 - 데이터베이스
데이터베이스는 여러 사용자가 공유하고 사용하는 정보의 집합으로, 데이터베이스 관리 시스템을 통해 접근하며, 검색 및 갱신 효율을 높이기 위해 고도로 구조화되어 있고, 관계형, NoSQL, NewSQL 등 다양한 모델로 발전해왔다.
라이브러리 (컴퓨팅) |
---|
2. 역사
라이브러리의 개념은 초기 프로그래밍 시대부터 데이터와 구현체를 분리하기 위한 목적으로 존재해왔다.
찰스 배비지는 1888년 해석 기관에 대한 논문에서 컴퓨터 연산을 별도의 카드에 펀칭하여 재사용할 수 있도록 저장하면 "점차 기관은 자체 라이브러리를 갖게 될 것"이라고 제안했다.[3]
1947년 허먼 골드스타인과 존 폰 노이만은 IAS 머신에서 작업하기 위해 서브루틴의 "라이브러리"를 만드는 것이 유용할 것이라고 추측하며, 재사용 가능한 컴퓨터 코드를 저장하는 자기 와이어 녹음의 물리적 라이브러리를 구상했다.[4][5]
모리스 윌크스와 그의 팀은 폰 노이만의 영감을 받아 EDSAC를 구축했다. EDSAC의 서브루틴 라이브러리는 펀치 테이프 보관 캐비닛에 보관되었다.[6] 1951년, 윌크스 팀은 프로그래밍에 관한 최초의 교과서 ''전자 디지털 컴퓨터를 위한 프로그램 준비(The Preparation of Programs for an Electronic Digital Computer)''를 출판하여 라이브러리의 생성과 목적을 상세히 설명했다.[8]
1960년대 중반까지 어셈블러용 복사 및 매크로 라이브러리가 일반화되었다. IBM System/360의 인기를 시작으로 시스템 매개변수와 같은 다른 유형의 텍스트 요소가 포함된 라이브러리도 일반화되었으며, OS/360 및 후속 제품에서는 이를 분할 데이터 세트라고 불렀다.
2. 1. 초기 개념
라이브러리와 유사한 초기 프로그래밍 개념은 프로그램 구현체로부터 데이터를 분리하려는 의도에서 비롯되었다. 1959년, JOVIAL 언어는 "COMPOOL"(Communication Pool)이라는 개념을 통해 주목을 받았는데, 이는 대형 시스템 SAGE 소프트웨어에서 가져온 것이다. 관심사 분리와 정보 감춤이라는 컴퓨터 과학 원칙에 따라, Comm Pool은 중앙 집중식 데이터 기술을 제공하여 여러 프로그램 간에 시스템 데이터 공유를 허용했다.[26]코볼은 1959년에 라이브러리 시스템을 위한 기본적인 기능을 포함했지만,[9] 진 E. 새밋(Jean E. Sammet)은 회고하면서 이를 "부적절한 라이브러리 시설"이라고 평가했다.[10]
2. 2. 현대적 발전
FORTRAN의 서브프로그램은 서로 독립적으로 컴파일할 수 있었지만, 링커가 없어 자료형 검사가 불가능했다.[30] 객체 지향 프로그래밍 언어인 시뮬라 67은 클래스 개념을 도입하여 현대 라이브러리 개념에 큰 영향을 미쳤다.[31] 시뮬라의 클래스는 자바, C++, C 샤프 등에서 사용되는 현대적 개념과 매우 유사했으며, 에이다의 패키지, 모듈라-2 모듈의 조상이기도 하다.[31] 시뮬라 클래스는 1965년에 개발되었음에도 불구하고 라이브러리 파일에 포함되어 컴파일 시점에 추가될 수 있었다.[32]3. 라이브러리 링크
라이브러리는 링크 또는 바인드 작업을 통해 프로그램과 연결되며, 이 과정은 링커나 바인더 프로그램에 의해 자동으로 수행된다. 링커는 주어진 순서대로 라이브러리 및 다른 모듈 집합을 검색하여 라이브러리 모듈에 대한 참조(심볼)를 해결한다.[1] 링크 대상이 여러 번 발견되어도 오류로 간주되지 않는 것이 일반적이다. 링크는 실행 파일 생성 시(정적 링크) 또는 프로그램이 런타임에 사용될 때(동적 링크) 수행될 수 있다.[1]
해결되는 참조는 점프 및 기타 루틴 호출에 대한 주소일 수 있으며, 메인 프로그램 또는 다른 모듈에 있을 수 있다. 이러한 참조는 각 참조 모듈의 메모리 세그먼트에 대한 런타임 메모리를 할당하여 고정 또는 재배치 가능한 주소로 해결된다.
일부 프로그래밍 언어는 '스마트 링크' 기능을 사용한다. 이를 통해 컴파일러와 링커가 통합되어 외부 참조 사용 방식을 파악하고, 사용되지 않는 라이브러리 코드를 제거하여 응용 프로그램 파일 크기와 메모리 사용량을 줄일 수 있다.
3. 1. 정적 라이브러리
정적 라이브러리는 컴파일러가 소스 파일을 컴파일할 때 참조되는 프로그램 모듈이다. 정적 라이브러리는 루틴, 외부 함수, 변수들의 집합으로, 컴파일러, 링커, 바인더 등에 의해 목표된 애플리케이션으로 복사되어 오브젝트 파일과 독립적으로 실행 가능한 파일을 생성하는 데 사용된다. 윈도우의 .LIB 파일과 같이 .a 확장자를 갖는다.[1]프로그램에 필요한 모든 모듈은 정적으로 링크되어 실행 파일에 복사된다. 이 프로세스와 결과로 생성된 독립 실행 파일은 프로그램의 정적 빌드라고 한다. 정적 빌드는 가상 메모리가 사용되고 주소 공간 배치 난수화가 원치 않는 경우 더 이상의 재배치가 필요하지 않을 수 있다.[16]
실행 파일 또는 다른 객체 파일의 생성 중에 링크가 수행되는 경우 이를 '정적 링크' 또는 '초기 바인딩'이라고 한다. 이 경우 링크는 일반적으로 링커에 의해 수행되지만, 컴파일러에 의해 수행될 수도 있다.[15] 정적 라이브러리는 '아카이브'라고도 하며, 정적으로 링크되도록 설계되었다. 원래는 정적 라이브러리만 존재했다. 모든 모듈을 다시 컴파일할 때 정적 링크를 수행해야 한다.
3. 2. 동적 라이브러리
윈도우에서는 주로 DLL 확장자를 가지며, 리눅스에서는 주로 SO 확장자를 가진다.[1] 동적 라이브러리는 프로그램 수행 도중 해당 모듈이 필요할 때 불러쓰는 프로그램 모듈이다.실행 가능한 코드 라이브러리는 기능을 호출하는 잘 정의된 인터페이스 (컴퓨팅)를 가지고 있다. 예를 들어, C (프로그래밍 언어)에서 라이브러리 함수는 C의 일반적인 함수 호출 기능을 통해 호출된다. 링커는 프로그램 자체에서가 아닌 라이브러리에서 함수를 사용할 수 있는 경우, 라이브러리 메커니즘을 통해 함수를 호출하는 코드를 생성한다.[1]
라이브러리 함수는 호출하는 프로그램의 다양한 프로그램 수명 주기 단계에서 연결될 수 있다. 라이브러리 코드가 호출하는 프로그램의 빌드 중에 액세스되는 경우, 해당 라이브러리를 정적 라이브러리라고 한다.[2] 프로그램 실행 파일을 라이브러리 파일과 분리하여 빌드하는 경우, 라이브러리 함수는 실행 파일이 시작된 후, 로드 시 또는 런타임에 연결된다. 이러한 라이브러리를 동적 라이브러리라고 한다.
대부분의 컴파일 언어는 표준 라이브러리를 가지고 있으며, 프로그래머는 자체 사용자 지정 라이브러리를 만들 수도 있다. 대부분의 최신 소프트웨어 시스템은 시스템 서비스의 대부분을 구현하는 라이브러리를 제공하며, 이는 최신 애플리케이션에 필요한 서비스를 구성한다. 따라서 최신 애플리케이션에서 사용되는 대부분의 코드는 이러한 시스템 라이브러리에서 제공된다.
'''동적 링크'''()는 라이브러리 내의 데이터 (코드를 포함)를 새로운 실행 파일의 빌드 시 복사하지 않고 디스크 상에 별도의 파일로 두는 것이다. 빌드 시 링커 (링키지 에디터)가 하는 일은 해당 실행 파일이 필요로 하는 라이브러리의 어느 부분인지 (함수명이나 인덱스)를 기록하는 것뿐이다. 링크 작업의 대부분은 해당 애플리케이션이 메인 메모리에 로드될 때 또는 실행 시에 이루어진다. 링크를 수행하는 프로그램 코드는 로더 ()라고 불리며, 실제로는 OS의 일부로 간주된다. 적절한 시점에 로더는 필요한 라이브러리를 디스크에서 찾아 프로세스의 메모리 공간에 (추가 데이터 공간과 함께) 매핑한다. OS에 따라서는 프로세스가 실행되기 전까지 라이브러리를 링크할 수 없는 경우도 있지만, 많은 OS에서는 프로세스 실행 시 실제로 라이브러리를 참조할 때 링크할 수 있다. 후자를 "지연 로딩"이라고 부른다. 어느 경우든 라이브러리는 '''동적 링크 라이브러리''' ('''다이나믹 링크 라이브러리''')라고 불린다. Windows 환경에서는 동적 링크 라이브러리의 약칭인 "DLL"이라는 호출이 일반적이며, 동적 라이브러리의 파일 확장자는 통상 ''.dll''이다[20] . 동적 링크 라이브러리 중, 시스템 상의 여러 실행 프로그램에 의해 공유 및 재사용될 수 있는 것을 '''공유 라이브러리'''라고 한다. Windows API의 대부분은 시스템 DLL에 C 언어 형식의 함수 또는 COM 컴포넌트 형태로 구현 및 공개되어 있으며, 모든 Windows 애플리케이션에서 사용할 수 있는 공유 라이브러리이기도 하다.
로더의 처리는 메모리 상의 각 라이브러리의 위치가 실제로 로드될 때까지 확정되지 않으므로 약간의 트릭이 필요하다. 디스크 상의 파일 내에 절대 주소를 기록해두는 것은 DLL 내에서도 불가능하다. 이론적으로는 메모리에 로드될 때 라이브러리를 참조하는 부분을 모두 수정하여 올바른 메모리 상의 위치를 참조하도록 할 수 있지만, 이에 소모되는 시간과 메모리는 무시할 수 없다. 대신 많은 동적 링크 시스템에서는 주소란이 비어 있는 심볼 테이블을 컴파일 시에 준비한다. 라이브러리에 대한 참조는 모두 이 심볼 테이블을 경유하여 이루어진다. (컴파일러는 심볼 테이블에서 주소를 가져와 사용하는 코드를 생성한다) 메모리에 로드되면, 로더가 이 테이블을 수정한다.
라이브러리도 모든 메서드 (함수, 서브루틴)의 테이블을 가지고 있다. 라이브러리에 들어올 때는 이 테이블을 경유하여 각 루틴으로 점프한다. 이것은 라이브러리의 루틴 콜에 오버헤드를 발생시키지만, 일반적으로는 무시할 수 있을 정도로 작다.
동적 링커/로더는 기능면에서 다양한 형태를 가진다. 어떤 경우에는 실행 파일에 저장된 명시적인 라이브러리 경로에 의존하여 라이브러리 이름이나 디스크 상의 배치를 변경하면 시스템이 작동하지 않게 된다. 보다 일반적인 방법으로는 라이브러리 이름만 실행 파일에 저장하고, OS가 어떤 알고리즘으로 디스크 상의 라이브러리를 검색한다. 유닉스 계열 시스템에서는 라이브러리를 찾는 장소 (디렉터리)를 구성 파일에 리스트로 작성해둔다. 라이브러리 개발자는 그곳에 쓰여 있는 디렉터리에 라이브러리를 배치하는 것을 권장한다. 그러나 이 방법은 새로운 라이브러리를 설치할 때 문제를 발생시키기 쉽고, 공통 디렉토리에 너무 많은 라이브러리가 놓이게 되어 관리가 어려워진다. Windows에서는 레지스트리를 사용하여 COM 컴포넌트 및 ActiveX DLL의 위치를 결정하지만, 표준 DLL의 경우 다음 순서로 디렉터리를 찾는다.[21]
# 애플리케이션의 실행 파일이 존재하는 디렉터리
#
SetDllDirectory()
로 지정되는 디렉터리 (Windows XP SP1 이후 지원)# 시스템 디렉터리 (NT 계열에서는 System32)
# 16비트 시스템 디렉터리 (System)
# Windows 디렉터리
# 현재 디렉터리
# PATH 환경 변수
OPENSTEP은 더욱 유연한 시스템을 사용하며, 라이브러리 검색 리스트를 가지고 있다. 그러나 부정한 DLL이 검색 상위에 위치해 있으면 실행 파일이 부정한 동작을 할 수 있다. Windows에서는 이것이 "DLL 지옥" ()이라고 불리며, 잘 알려진 문제이다.
Windows XP부터 Side-by-Side 어셈블리 (DLL 서명, WinSxS)라는 메커니즘이 추가되었다. 이는 동적 링크 시 라이브러리의 파일 이름이 아닌 라이브러리에 부여된 서명에 의해 링크해야 할 라이브러리를 결정하는 것이다. 이로 인해 동일한 파일 이름을 가지지만 다른 구현을 가진 라이브러리를 동시에 사용할 수 있다. 흔히 사용되는 패턴으로, 소스 코드에서 개조 및 빌드된 런타임 라이브러리를 시스템에 설치하는 경우 이 메커니즘이 효과적으로 작동한다. 시스템에 설치된 라이브러리는 라이브러리 검색 리스트에서 비교적 상위에 존재하지만, 서명이 일치하는 프로그램에만 로드되므로 DLL 지옥은 앞으로 해소될 것으로 예상된다. 그러나 이 기구에는 한 가지 약점이 있다. 그것은 시스템 라이브러리를 오버라이드하여 독자적인 기능을 구현할 때 이 기구가 쓸모없는 방향으로 작동한다. 그러한 구현을 할 때에는, 고의적으로 매니페스트 기능을 무효화하고 라이브러리를 만들어야 한다. 더구나, 그러한 접근 방식은, 시스템 파일 보호 기능이 탑재된 Windows 2000의 릴리스 시점에서 시대에 뒤떨어졌으며, Windows Vista에 이르러서는 관리자라고 해도 시스템 라이브러리를 수정하는 것은 불가능해졌다.
동적 라이브러리의 기원은 불분명하지만, 적어도 1960년대 후반의 MTS (Michigan Terminal System)까지 거슬러 올라갈 수 있다 ("A History of MTS", ''Information Technology Digest'', Vol. 5, No. 5). 동적 로딩(dynamic loading)은 동적 링크의 하위 범주이며, 빌드 시에 링크된(암묵적 링크, implicit linking) 것 이외의 동적 링크 라이브러리를 실행 중인 프로그램이 명시적으로 로드하는 것이다. 명시적 링크(explicit linking)라고도 한다.[22] 이 경우, 라이브러리는 플러그인 모듈로 사용되는 것이 일반적이며, 스프레드시트 프로그램의 애드인(add-in) 등이 전형적이다.
동적 라이브러리를 지원하는 시스템은 모듈의 동적 로딩 API도 지원하는 것이 일반적이다. 예를 들어 Windows에서는 `LoadLibrary()`와 `GetProcAddress()`가 제공되며, Unix 계열 시스템에서는 `dlopen()`과 `dlsym()`이 제공된다. 몇몇 개발 환경에서는 이 처리를 자동화하고 있다. 반대로, 불필요해진 모듈을 해제(언로드)하는 API(`FreeLibrary()`나 `dlclose()`)도 제공된다. 이러한 API는 특히 사용자에 의한 기능 확장을 가능하게 하는 플러그인 시스템을 애플리케이션 내에 구현하는 데에도 유용하다.
.NET Framework에서는 라이브러리의 어셈블리는 필요해진 시점에 동적이고 자동으로 로드되는 지연 로딩이 기본이지만, 어셈블리의 명시적인 언로드는 불가능하다. P/Invoke도 마찬가지이다. .NET 4 이후에는 플러그인 시스템의 구현을 용이하게 하는 기능이 지원되게 되었다.
스크립트 언어(동적 프로그래밍 언어)의 처리계(인터프리터 등)를 애플리케이션에 통합하여, 정형 처리를 자동화하거나 기능 확장을 위해 사용자가 작성한 프로그램을 실행할 수 있도록 하는 경우도 있다. Microsoft Office의 Visual Basic for Applications가 대표적인 예이지만, Maya 8.5 이후[23]나 LightWave 11 이후[24]와 같이, 독자적인 스크립트 언어 이외에 범용 프로그래밍 언어 Python에 의한 스크립팅 기능을 탑재하는 경우도 늘고 있다. 이들은 외부의 사용자 코드를 광의의 동적 라이브러리로 활용하는 플러그인 기능이라고 할 수 있다.
3. 3. 공유 라이브러리
'''공유 라이브러리''' 또는 '''공유 오브젝트'''는 실행 파일, 더 나아가 공유 오브젝트 파일에 의해 공유될 목적으로 만들어진 파일이다.[1] 실행 가능한 코드 라이브러리는 기능을 호출하는 잘 정의된 인터페이스 (컴퓨팅)를 가지고 있다.라이브러리의 함수는 호출하는 프로그램의 다양한 프로그램 수명 주기 단계에서 연결될 수 있다. 라이브러리 코드가 호출하는 프로그램의 빌드 중에 액세스되는 경우, 해당 라이브러리를 정적 라이브러리라고 한다.[2] 또 다른 방법은 프로그램 실행 파일을 라이브러리 파일과 분리하여 빌드하는 것이다. 라이브러리 함수는 실행 파일이 시작된 후, 로드 시 또는 런타임에 연결된다. 이 경우, 라이브러리를 동적 라이브러리라고 한다.
대부분의 컴파일 언어는 표준 라이브러리를 가지고 있으며, 프로그래머는 자체 사용자 지정 라이브러리를 만들 수도 있다. 대부분의 최신 소프트웨어 시스템은 시스템 서비스의 대부분을 구현하는 라이브러리를 제공한다. 이러한 라이브러리는 최신 애플리케이션에 필요한 서비스를 구성했다. 따라서 최신 애플리케이션에서 사용되는 대부분의 코드는 이러한 시스템 라이브러리에서 제공된다.
'''동적 링크'''()는 라이브러리 내의 데이터 (코드를 포함)를 새로운 실행 파일의 빌드 시 복사하지 않고 디스크 상에 별도의 파일로 존재하는 것이다. 빌드 시 링커 (링키지 에디터)가 하는 일은 해당 실행 파일이 필요로 하는 라이브러리의 어느 부분인지 (함수명이나 인덱스)를 기록하는 것뿐이다. 링크 작업의 대부분은 해당 애플리케이션이 메인 메모리에 로드될 때 또는 실행 시에 이루어진다. 링크를 수행하는 프로그램 코드는 로더라고 불리며, 실제로는 OS의 일부로 간주된다. 적절한 시점에 로더는 필요한 라이브러리를 디스크에서 찾아 프로세스의 메모리 공간에 (추가 데이터 공간과 함께) 매핑한다.
동적 링크 라이브러리 중, 시스템 상의 여러 실행 프로그램에 의해 공유 및 재사용될 수 있는 것을 '''공유 라이브러리'''라고 부른다. Windows API의 대부분은 시스템 DLL에 C 언어 형식의 함수 또는 COM 컴포넌트 형태로 구현 및 공개되어 있으며, 모든 Windows 애플리케이션에서 사용할 수 있는 공유 라이브러리이기도 하다.
'''공유 라이브러리'''()는 다소 모호한 용어로, 두 가지 개념을 포함한다. 첫 번째는 디스크상의 코드를 여러 관련 없는 프로그램이 공유하는 것을 의미한다. 두 번째 개념은 메모리상의 코드 공유로, 라이브러리의 로드된 물리적 메모리 페이지가 여러 프로세스의 주소 공간에 매핑되어 동시에 접근되는 것을 의미한다.
메모리상의 공유 라이브러리는 UNIX에서는 위치 독립 코드(PIC)를 사용하여 구현된다. 이는 유연한 아키텍처이지만 복잡하며, Windows 등에서는 사용되지 않는다. Windows 등은 DLL마다 매핑해야 할 주소를 미리 결정하는 등 메모리상에서 공유 가능하게 한다. Windows의 DLL은 UNIX에서 보면 공유 라이브러리가 아니다[25]。
최근의 OS에서는 공유 라이브러리가 일반 실행 파일과 같은 형식이 된다. 여기에는 두 가지 이점이 있다. 첫 번째는 하나의 로더로 둘 다 로드할 수 있다는 점과 두 번째는 심볼 테이블만 있으면 실행 파일을 공유 라이브러리로 사용할 수 있다는 점이다. 이러한 파일 형식으로, ELF(UNIX)와 PE(Windows)가 있다.
4. 특징
라이브러리는 여러 독립적인 소비자(프로그램 및 기타 라이브러리)가 사용할 수 있다. 이는 프로그램 내에서만 사용할 수 있는 리소스와는 다르다.
라이브러리 리소스를 사용하면, 자체적으로 구현할 필요 없이 라이브러리의 기능을 활용할 수 있다. 라이브러리는 코드 재사용을 모듈식 방식으로 장려한다.
라이브러리를 사용하는 코드를 작성할 때 프로그래머는 라이브러리의 내부 세부 사항이 아닌, 무엇을 포함하고 어떻게 사용하는지와 같은 상위 수준의 정보만 알면 된다.
라이브러리는 다른 라이브러리를 사용할 수 있으며, 이로 인해 프로그램 내에 라이브러리의 계층 구조가 생길 수 있다.
4. 1. 실행 가능한 라이브러리
라이브러리는 기능을 호출하는 잘 정의된 인터페이스 (컴퓨팅)를 가지고 있다. 예를 들어, C (프로그래밍 언어)에서 라이브러리 함수는 C의 일반적인 함수 호출 기능을 통해 호출된다. 링커는 프로그램 자체가 아닌 라이브러리에서 함수를 사용할 수 있는 경우, 라이브러리 메커니즘을 통해 함수를 호출하는 코드를 생성한다.[1]라이브러리의 함수는 호출하는 프로그램의 다양한 프로그램 수명 주기 단계에서 연결될 수 있다. 라이브러리 코드가 호출하는 프로그램의 빌드 중에 액세스되는 경우, 해당 라이브러리를 정적 라이브러리라고 한다.[2] 프로그램 실행 파일을 라이브러리 파일과 분리하여 빌드하는 방법도 있다. 이 경우 라이브러리 함수는 실행 파일이 시작된 후, 로드 시 또는 런타임에 연결된다. 이러한 라이브러리를 동적 라이브러리라고 한다.
대부분의 컴파일 언어는 표준 라이브러리를 가지고 있으며, 프로그래머는 자체 사용자 지정 라이브러리를 만들 수도 있다. 대부분의 최신 소프트웨어 시스템은 시스템 서비스의 대부분을 구현하는 라이브러리를 제공한다. 이러한 라이브러리는 최신 애플리케이션에 필요한 서비스를 구성했다. 따라서 최신 애플리케이션에서 사용되는 대부분의 코드는 이러한 시스템 라이브러리에서 제공된다.
5. 고급 개념
일부 프로그래밍 언어는 '스마트 링크' 기능을 사용하여 링커가 컴파일러와 통합되어 사용되지 않는 라이브러리 코드를 제거한다. 이를 통해 파일 크기와 메모리 사용량을 줄일 수 있다.
프로그램이나 라이브러리 모듈의 참조는 상대적 형태로 저장되는데, ''재배치''는 이러한 참조를 조정하는 과정이다. 링커나 로더가 수행하며, 위치 독립 코드는 재배치가 필요 없다.
'''객체 라이브러리'''는 객체 지향 프로그래밍(OOP)에서 사용되며, 원격 접근을 지원하는 경우 '''분산 객체'''라고도 불린다. IBM의 시스템 객체 모델(SOM/DSOM), 선 마이크로시스템즈의 어디에나 분산 객체(DOE) 등이 그 예시이다.[1] '''클래스 라이브러리'''는 OOP에서 클래스를 포함하며, 클래스는 객체의 특성과 동작(메서드)을 정의한다. 자바 같은 일부 OOP 언어에서는 클래스가 JAR 파일 형식에 포함된다.[2] 오늘날 대부분의 클래스 라이브러리는 패키지 저장소에 저장된다. (예: 자바의 Maven Central)[3]
Java에서는 객체 라이브러리로 주로 JAR이 사용되며, JAR 파일 안에는 클래스의 바이트코드 형식이 저장되어 있다.[4]
'''원격 라이브러리'''는 원격 프로시저 호출(RPC)을 통해 다른 컴퓨터의 네트워크를 통해 호출하는 기술이다. 이는 운영 체제 재사용을 극대화할 수 있지만, 모든 라이브러리 호출에 상당한 오버헤드가 발생한다.
'''코드 생성 라이브러리'''는 자바 바이트코드를 생성하거나 변환할 수 있는 고급 응용 프로그래밍 인터페이스(API)이다. 관점 지향 프로그래밍 등에서 동적 프록시 객체를 생성하는 데 사용된다.[17]
5. 1. 스마트 링크
일부 프로그래밍 언어는 ''스마트 링크''라는 기능을 사용한다. 여기서 링커는 컴파일러를 인식하거나 컴파일러와 통합되어, 링커가 외부 참조가 어떻게 사용되는지 알 수 있으며, 내부적으로 참조되더라도 실제로 ''사용되지 않는'' 라이브러리의 코드는 컴파일된 응용 프로그램에서 제거할 수 있다. 예를 들어, 산술 연산에 정수만 사용하거나 산술 연산을 전혀 수행하지 않는 프로그램은 부동 소수점 라이브러리 루틴을 제외할 수 있다. 이 스마트 링크 기능을 통해 응용 프로그램 파일 크기를 줄이고 메모리 사용량을 줄일 수 있다.5. 2. 재배치
프로그램 또는 라이브러리 모듈의 일부 참조는 모든 코드와 라이브러리에 최종 고정 주소가 할당될 때까지 해결할 수 없는 상대적 또는 기호적 형태로 저장된다. ''재배치''는 이러한 참조를 조정하는 과정이며, 링커 또는 로더에 의해 수행된다. 일반적으로 재배치는 개별 라이브러리 자체에 대해 수행될 수 없는데, 메모리의 주소가 해당 라이브러리를 사용하는 프로그램 및 함께 결합되는 다른 라이브러리에 따라 달라질 수 있기 때문이다. 위치 독립 코드는 절대 주소에 대한 참조를 피하므로 재배치가 필요하지 않다.5. 3. 객체 라이브러리
객체 지향 프로그래밍(OOP)에서 사용되는 '''객체 라이브러리'''는 원격 접근을 지원하는 경우 '''분산 객체'''라고도 불린다. 마이크로소프트의 COM은 로컬 사용을 위한 객체 라이브러리의 예시이며, COM의 수정 버전인 DCOM은 원격 접근을 지원한다.[1] 한때 객체 라이브러리는 프로그래밍 세계에서 "다음 빅 씽"으로 여겨졌으며, 여러 플랫폼에서 실행될 시스템을 만들기 위한 노력이 있었다. 기업들은 개발자들을 자사 시스템에 묶어두기 위해 경쟁했다. IBM의 시스템 객체 모델(SOM/DSOM), 선 마이크로시스템즈의 어디에나 분산 객체(DOE), NeXT의 이식 가능한 분산 객체(PDO), 디지털 이큅먼트 코퍼레이션(Digital)의 ObjectBroker, 마이크로소프트의 컴포넌트 객체 모델(COM/DCOM), 그리고 수많은 CORBA 기반 시스템이 그 예시이다.[1]'''클래스 라이브러리'''는 객체 지향 프로그래밍(OOP)에서 이전 유형의 코드 라이브러리와 유사한 개념이다.[2] 클래스 라이브러리는 클래스를 포함하며, 클래스는 객체의 특성을 설명하고 동작(메서드)을 정의한다. 클래스 라이브러리는 인스턴스를 생성하는 데 사용된다.[2] 자바와 같은 일부 OOP 언어에서는 클래스가 라이브러리 파일(JAR 파일 형식)에 포함되고, 인스턴스화된 객체는 메모리에만 존재한다.[2] 스몰토크와 같은 다른 언어에서는 클래스 라이브러리가 환경의 전체 상태를 포함하는 시스템 이미지의 시작점이다.[2]
오늘날 대부분의 클래스 라이브러리는 패키지 저장소에 저장된다. 예를 들어 자바의 Maven Central이 있다. 클라이언트 코드는 빌드 구성 파일(예: 자바의 Maven Pom)에서 외부 라이브러리에 대한 종속성을 명시적으로 선언한다.[3]
Java에서는 객체 라이브러리로 주로 JAR이 사용된다. JAR 파일 안에는 (압축된) 클래스의 바이트코드 형식이 저장되어 있으며, Java 가상 머신이나 특수한 클래스 로더가 그것을 로드한다.[4]
5. 4. 원격 라이브러리
원격 라이브러리는 완전히 별개의 실행 파일(종종 가벼운 형태)을 사용하여, 다른 컴퓨터의 네트워크를 통해 원격 프로시저 호출(RPC)을 통해 호출하는 기술이다. 이렇게 하면 운영 체제 재사용을 극대화할 수 있다. 즉, 라이브러리를 지원하는 데 필요한 코드는 다른 모든 프로그램에 대한 애플리케이션 지원 및 보안을 제공하는 데 사용되는 코드와 동일하다. 또한 이러한 시스템은 라이브러리가 동일한 머신에 존재할 필요가 없으며, 네트워크를 통해 요청을 전달할 수 있다.그러나 이러한 접근 방식은 모든 라이브러리 호출에 상당한 오버헤드가 필요하다는 것을 의미한다. RPC 호출은 동일한 머신에 이미 로드된 공유 라이브러리를 호출하는 것보다 훨씬 더 많은 비용이 든다. 이 접근 방식은 특히 클라이언트-서버 시스템 및 애플리케이션 서버 (예: Enterprise JavaBeans)와 같이 이러한 원격 호출을 많이 사용하는 분산 컴퓨팅 아키텍처에서 일반적으로 사용된다.
5. 5. 코드 생성 라이브러리
자바 바이트코드를 생성하거나 변환할 수 있는 고급 API이다. 관점 지향 프로그래밍, 일부 데이터 액세스 프레임워크 및 테스트에서 동적 프록시 객체를 생성하는 데 사용된다. 또한 필드 접근을 가로채는 데 사용된다.[17]6. 파일 이름 명명 규칙
운영체제마다 라이브러리 파일 이름에 대한 다른 명명 규칙을 사용한다.
- 유닉스 계열 시스템: `libfoo.a` (정적 라이브러리) 또는 `libfoo.so` (동적 링크 라이브러리) 형태를 사용하며, `libfoo.so.2`와 같이 인터페이스 번호를 덧붙이기도 한다.[1] GNU/Linux, Solaris, BSD 계열 운영체제는 `lib` 접두사와 `.a` (정적) 또는 `.so` (동적) 확장자를 사용한다.[2] macOS는 BSD 규칙을 따르지만, 동적 라이브러리에 `.dylib` 확장자를 사용하기도 한다.[2]
- macOS: BSD의 정적 라이브러리 규칙을 상속받아 `.a` 파일을 사용하며, `.so` 스타일의 동적 연결 라이브러리도 사용 가능하고 `.dylib` 접미사를 사용한다.[2] 대부분 "프레임워크" 형태로 구성되며, 이는 "번들" 디렉터리에 라이브러리와 메타데이터를 포함한다.
- Microsoft Windows: 동적 링크 라이브러리는 주로 `.DLL` 확장자를 사용하고, OLE 라이브러리는 `.OCX` 확장자를 사용하기도 한다.[18] `.LIB` 파일은 정적 라이브러리 또는 "임포트 라이브러리"일 수 있다.[20] 윈도우에서는 `.LIB` 파일이 어떤 종류인지 확인해야 하며, 임포트 라이브러리의 경우 런타임에 `.DLL` 파일이 필요하다. 동적 링커/로더는 다양한 기능을 하며, 실행 파일에 라이브러리 경로를 저장하거나, OS가 라이브러리를 검색하는 방식을 사용한다. Windows는 레지스트리를 사용하여 COM 컴포넌트 및 ActiveX DLL 위치를 결정하고, 표준 DLL은 특정 디렉터리들을 검색한다.[21] Windows XP부터 Side-by-Side 어셈블리 메커니즘이 추가되어, 라이브러리 서명을 기반으로 링크할 라이브러리를 결정한다.
6. 1. 유닉스 계열 시스템
대부분의 최신 유닉스 계열 시스템은 `libfoo.a` 및 `libfoo.so` 파일을 `/lib`, `/usr/lib` 또는 `/usr/local/lib`와 같은 디렉토리에 저장한다. 파일 이름은 항상 `lib`로 시작하고 `.a` (아카이브, 정적 라이브러리) 또는 `.so` (공유 객체, 동적 링크 라이브러리)의 접미사로 끝난다.[1] 일부 시스템은 동적 링크 라이브러리에 대해 여러 이름을 가질 수 있는데, 이러한 이름은 일반적으로 동일한 접두사를 공유하며 버전 번호를 나타내는 다른 접미사를 갖는다. 대부분의 이름은 최신 버전의 심볼릭 링크에 대한 이름이다.[1] 예를 들어, 일부 시스템에서 `libfoo.so.2`는 동적 링크 라이브러리 `libfoo`의 두 번째 주요 인터페이스 개정판의 파일 이름이 될 것이다.[1]GNU/Linux, Solaris, BSD 파생 운영체제에서 라이브러리 파일 이름은 항상 접두사 `lib`로 시작하며, 확장자로 `.a` (정적 라이브러리) 또는 `.so` (동적 링크 라이브러리)가 사용된다.[2] 옵션으로 다중 확장자를 사용한 인터페이스 번호가 부여되는 경우가 있다. 예를 들어, `libfoo.so.2`는 `libfoo` 라이브러리의 두 번째 메이저 인터페이스 번호가 붙은 동적 링크 라이브러리이다.[2] 공유 라이브러리는 `/lib`, `/usr/lib`, `/usr/local/lib` 등의 디렉토리에 위치한다.[2]
macOS에서 라이브러리 명명 규칙은 BSD를 따르고 있으며, 동적 라이브러리의 확장자에는 `.dylib`이 사용되지만, 대신 `.so`를 사용할 수도 있다.[2]
6. 2. macOS
macOS 시스템은 BSD에서 정적 라이브러리 규칙을 상속받아 라이브러리를.a
파일에 저장하며, .so
스타일의 동적 연결 라이브러리(.dylib
접미사 사용)를 사용할 수 있다. 그러나 macOS의 대부분의 라이브러리는 라이브러리에 필요한 파일과 메타데이터를 묶는 "번들"이라는 특수 디렉터리에 위치하는 "프레임워크"로 구성된다. 예를 들어, MyFramework
라는 프레임워크는 MyFramework.framework
라는 번들로 구현되며, MyFramework.framework/MyFramework
는 동적으로 연결된 라이브러리 파일이거나 MyFramework.framework/Versions/Current/MyFramework
의 동적으로 연결된 라이브러리 파일에 대한 심볼릭 링크이다.6. 3. Microsoft Windows
동적 링크 라이브러리는 일반적으로 `*.DLL` 확장자를 사용한다.[18] 예를 들어, OLE 라이브러리의 경우 `*.OCX` 확장자를 사용한다. 컴파일 방식에 따라 `*.LIB` 파일은 정적 라이브러리이거나 컴파일 중에만 필요한 동적으로 연결 가능한 라이브러리의 표현인 "임포트 라이브러리"일 수 있다. 유닉스와 달리, 윈도우에서 `.LIB` 파일에 링크할 때는 먼저 일반 정적 라이브러리인지 또는 임포트 라이브러리인지 알아야 한다. 임포트 라이브러리의 경우, 런타임에 `.DLL` 파일이 존재해야 한다.[20]동적 링크(dynamic linking)는 라이브러리 내의 데이터(코드를 포함)를 새로운 실행 파일의 빌드 시 복사하지 않고 디스크 상에 별도의 파일로 존재하게 하는 것이다. 링커(링키지 에디터)는 실행 파일이 필요로 하는 라이브러리의 부분(함수명이나 인덱스)을 기록만 하고, 실제 링크 작업은 애플리케이션이 메인 메모리에 로드될 때 또는 실행 시에 이루어진다. 이 링크를 수행하는 프로그램 코드는 로더(loader)라고 불리며, OS의 일부로 간주된다. 로더는 필요한 라이브러리를 디스크에서 찾아 프로세스의 메모리 공간에 매핑한다. 많은 OS에서는 프로세스 실행 시 실제로 라이브러리를 참조할 때 링크하는 "지연 로딩"을 지원하며, 이러한 라이브러리를 '''동적 링크 라이브러리''' ('''다이나믹 링크 라이브러리''')라고 부른다. Windows 환경에서는 "DLL"이라는 호출이 일반적이며, 파일 확장자는 통상 ''.dll''이다.[20]
시스템 상의 여러 실행 프로그램에 의해 공유 및 재사용될 수 있는 동적 링크 라이브러리를 '''공유 라이브러리'''라고 한다. Windows API의 대부분은 시스템 DLL에 C 언어 형식의 함수 또는 COM 컴포넌트 형태로 구현 및 공개되어 있으며, 모든 Windows 애플리케이션에서 사용할 수 있는 공유 라이브러리이기도 하다.
로더는 메모리 상의 각 라이브러리의 위치가 로드될 때까지 확정되지 않으므로, DLL 내에서 절대 주소를 기록하는 것은 불가능하다. 따라서 많은 동적 링크 시스템에서는 주소란이 비어 있는 심볼 테이블을 컴파일 시에 준비하고, 라이브러리에 대한 참조는 모두 이 심볼 테이블을 통해 이루어지도록 한다. 메모리에 로드되면 로더가 이 테이블을 수정한다. 라이브러리는 모든 메서드(함수, 서브루틴)의 테이블을 가지며, 라이브러리에 들어올 때는 이 테이블을 경유하여 각 루틴으로 점프한다. 이는 오버헤드를 발생시키지만, 일반적으로는 무시할 수 있을 정도로 작다.
동적 링커/로더는 기능면에서 다양한 형태를 가진다. 실행 파일에 저장된 명시적인 라이브러리 경로에 의존하는 경우, 라이브러리 이름이나 배치를 변경하면 시스템이 작동하지 않게 된다. 일반적인 방법으로는 라이브러리 이름만 실행 파일에 저장하고, OS가 알고리즘으로 디스크 상의 라이브러리를 검색한다. Windows에서는 레지스트리를 사용하여 COM 컴포넌트 및 ActiveX DLL의 위치를 결정하지만, 표준 DLL의 경우, 다음 디렉터리를 찾는다[21]:
# 애플리케이션 실행 파일이 존재하는 디렉터리
# `SetDllDirectory()`로 지정되는 디렉터리 (Windows XP SP1 이후 지원)
# 시스템 디렉터리 (NT 계열에서는 System32)
# 16비트 시스템 디렉터리 (System)
# Windows 디렉터리
# 현재 디렉터리
# PATH 환경 변수
부정한 DLL이 검색 상위에 있으면 실행 파일이 부정한 동작을 할 수 있는데, Windows에서는 이를 "DLL 지옥(DLL hell)"이라고 부른다.
Windows XP부터 Side-by-Side 어셈블리(DLL 서명, WinSxS) 메커니즘이 추가되어, 동적 링크 시 라이브러리 파일 이름이 아닌 서명으로 링크할 라이브러리를 결정한다. 이로 인해 동일한 파일 이름을 가지지만 다른 구현을 가진 라이브러리를 동시에 사용할 수 있다. 그러나 이 기구는 시스템 라이브러리를 오버라이드하여 독자적인 기능을 구현할 때 쓸모없게 작동하는 약점이 있다. Windows Vista에서는 관리자도 시스템 라이브러리를 수정하는 것이 불가능해졌다.
7. 동적 로딩
동적 로딩(dynamic loading)은 동적 링크의 하위 범주로, 실행 중인 프로그램이 명시적으로 동적 링크 라이브러리를 로드하는 것을 말한다. 이를 명시적 링크(explicit linking)라고도 부른다.[22] 이 방식은 주로 플러그인 모듈로 사용되며, 스프레드시트 프로그램의 애드인(add-in) 등이 대표적인 예이다.
동적 라이브러리를 지원하는 시스템은 일반적으로 모듈의 동적 로딩을 위한 API를 제공한다. 예를 들어, Windows에서는 `LoadLibrary()`와 `GetProcAddress()` API를 사용하고, 유닉스 계열 시스템에서는 `dlopen()`과 `dlsym()` API를 사용한다. 일부 개발 환경에서는 이러한 처리를 자동화하기도 한다. 또한, 필요 없어진 모듈을 해제(언로드)하는 API(`FreeLibrary()`나 `dlclose()`)도 제공되는데, 이러한 API는 사용자가 기능 확장을 할 수 있도록 플러그인 시스템을 애플리케이션에 구현하는 데 유용하다.
.NET Framework에서는 라이브러리의 어셈블리가 필요할 때 자동으로 로드되는 지연 로딩이 기본이지만, 어셈블리를 명시적으로 언로드하는 것은 불가능하다. P/Invoke도 마찬가지이다. .NET 4 이후에는 플러그인 시스템 구현을 쉽게 해주는 기능이 지원된다.
스크립트 언어(동적 프로그래밍 언어) 처리계(인터프리터 등)를 애플리케이션에 통합하여 정형 처리를 자동화하거나 기능 확장을 위해 사용자가 작성한 프로그램을 실행할 수 있게 하는 경우도 있다. Microsoft Office의 Visual Basic for Applications가 대표적인 예이며, Maya 8.5 이후[23]나 LightWave 11 이후[24]와 같이, 자체 스크립트 언어 외에 범용 프로그래밍 언어 Python을 이용한 스크립팅 기능을 탑재하는 경우도 늘고 있다. 이러한 기능들은 외부 사용자 코드를 넓은 의미의 동적 라이브러리로 활용하는 플러그인 기능이라고 할 수 있다.
참조
[1]
학위논문
Metamorphic Detection Using Function Call Graph Analysis
San Jose State University Library
[2]
웹사이트
Static Libraries
http://tldp.org/HOWT[...]
TLDP
2013-10-03
[3]
학술저널
The Analytical Engine
https://www.fourmila[...]
1888-09-12
[4]
서적
The Computer from Pascal to von Neumann
http://dx.doi.org/10[...]
Princeton University Press
2008-12-31
[5]
보고서
Planning and coding of problems for an electronic computing instrument
Institute for Advanced Study
1947
[6]
학회자료
1951 International Workshop on Managing Requirements Knowledge
IEEE
1951
[7]
학술저널
In Praise of 'Wilkes, Wheeler, and Gill'
https://cacm.acm.org[...]
2011-09
[8]
서적
The Preparation of Programs for an Electronic Digital Computer
https://archive.org/[...]
Addison-Wesley
1951
[9]
서적
History of Programming Languages
https://archive.org/[...]
Academic Press (A subsidiary of [[Harcourt Brace]])
[10]
문서
[11]
문서
[12]
서적
Comparative Programming Languages
Addison-Wesley
[13]
문서
[14]
문서
[15]
서적
Reverse Engineering Code with IDA Pro
Elsevier
2021-05-27
[16]
학회자료
SLINKY: Static Linking Reloaded
http://usenix.org/le[...]
Department of Computer Science, [[University of Arizona]]
2016-03-17
[17]
웹사이트
Code Generation Library
https://sourceforge.[...]
[[Source Forge]]
2010-03-03
[18]
서적
LPIC-1 Linux Professional Institute Certification Study Guide: Exam 101-400 and Exam 102-400
https://books.google[...]
John Wiley & Sons
2015-09-03
[19]
웹사이트
API, SDK, Libraryの違い | DAFTCRAFT ENGINEER BLOG | ダフトクラフト株式会社
https://daftcraft.co[...]
[20]
문서
[21]
웹사이트
Dynamic-Link Library Search Order
http://msdn.microsof[...]
2008-11-11
[22]
웹사이트
Link an executable to a DLL | Microsoft Docs
https://docs.microso[...]
[23]
웹사이트
ASCII.jp:「無償体験版も提供する予定」──オートデスクが語る『Maya 8.5』
https://ascii.jp/ele[...]
[24]
웹사이트
Python Scripting For LightWave | 2024
https://docs.lightwa[...]
[25]
문서
[26]
서적
History of Programming Languages
https://archive.org/[...]
Academic Press (A subsidiary of [[Harcourt Brace]])
[27]
문서
[28]
문서
[29]
문서
[30]
서적
Comparative Programming Languages
https://archive.org/[...]
Addison-Wesley
[31]
문서
[32]
문서
본 사이트는 AI가 위키백과와 뉴스 기사,정부 간행물,학술 논문등을 바탕으로 정보를 가공하여 제공하는 백과사전형 서비스입니다.
모든 문서는 AI에 의해 자동 생성되며, CC BY-SA 4.0 라이선스에 따라 이용할 수 있습니다.
하지만, 위키백과나 뉴스 기사 자체에 오류, 부정확한 정보, 또는 가짜 뉴스가 포함될 수 있으며, AI는 이러한 내용을 완벽하게 걸러내지 못할 수 있습니다.
따라서 제공되는 정보에 일부 오류나 편향이 있을 수 있으므로, 중요한 정보는 반드시 다른 출처를 통해 교차 검증하시기 바랍니다.
문의하기 : help@durumis.com