なぜパッケージマネージャが生まれたのか
한국어 원문으로 표시합니다.
한 줄 요약
패키지 관리자는 파일을 푸는 도구가 아니라 "무엇이 무엇을 필요로 하는가"라는 그래프를 푸는 도구다.
왜 이게 필요했나
소프트웨어를 tarball 로 배포하던 시절의 설치는 이랬다. 압축을 풀고, ./configure 를 돌리고, 없다는 라이브러리를 하나씩 찾아 설치하고, 그 라이브러리가 또 다른 것을 요구하면 다시 찾아 나선다. 이걸 "의존성 지옥" 이라고 불렀다.
문제의 본질은 파일을 옮기는 일이 어려운 게 아니라, 무엇을 먼저 옮겨야 하는지 아무도 모른다는 것이었다. 그래서 패키지 형식은 파일 묶음에 메타데이터를 붙였다. 이 패키지는 무엇을 제공하는가(Provides), 무엇을 요구하는가(Depends), 무엇과 충돌하는가(Conflicts). 이제 설치는 파일 복사 문제가 아니라 그래프 문제가 됐고, 그래프 문제는 컴퓨터가 사람보다 잘 푼다.
어떻게 동작하나
deb 와 rpm 의 세부는 다르지만 뼈대는 같다.
| 개념 | 무엇인가 | 데비안 표기 | RPM 표기 |
|---|---|---|---|
| 이름·버전 | 패키지를 식별 | Package, Version |
Name, Version, Release |
| 필수 의존 | 없으면 못 씀 | Depends |
Requires |
| 약한 의존 | 있으면 좋음 | Recommends, Suggests |
Recommends, Suggests |
| 제공 | 가상 이름을 만족 | Provides |
Provides |
| 충돌 | 같이 못 있음 | Conflicts, Breaks |
Conflicts |
| 아키텍처 | 어느 CPU 용인가 | amd64 / all |
x86_64 / noarch |
여기서 가장 자주 발목을 잡는 것이 세 가지다.
첫째, 의존성의 단위가 패키지 이름이 아닐 수 있다. RPM 쪽이 특히 그렇다. Requires: libnl-3.so.200()(64bit) 처럼 공유 라이브러리의 소네임이 그대로 의존 대상이 된다. 그래서 "패키지 하나만 받아 오면 되지 않느냐"는 요청이 폐쇄망에서 반나절짜리 작업이 된다.
둘째, 가상 패키지(Provides)가 있다. mail-transport-agent 를 요구하면 postfix 도 exim4 도 그 요구를 만족시킨다. 그래서 "이 이름의 패키지가 저장소에 없는데 왜 설치가 되지?" 같은 상황이 생긴다.
셋째, 버전 비교 규칙이 직관과 다르다. 데비안은 1.0~rc1 이 1.0 보다 작다(틸데는 어떤 문자보다도 작다). RPM 은 epoch 가 있어서 1:1.0 이 2.0 보다 크다. 그리고 epoch 는 파일 이름에 나타나지 않는다. 조용하고 치명적인 차이다.
현장에서 만나는 모습
폐쇄망 반입 요청이 "rpm 파일 하나만 받아다 주세요" 로 들어오는 일이 잦다. 받아서 넣으면 nothing provides libnl-3.so.200()(64bit) needed by htop 같은 에러가 난다. 다시 나가서 그걸 받아 오면 또 다른 게 없다고 한다. USB 를 서너 번 왕복하면 반나절이 지나 있고, 반입 심의는 하루에 한 번뿐이다.
그래서 숙련자는 처음부터 그래프를 통째로 푼 결과를 들고 간다. 그 계산을 어디서 하느냐가 이 코스 후반부의 주제다.
패키지 관리자가 하지 않는 일
패키지 관리자는 파일을 놓고 의존성을 풀지만, 그 뒤의 일은 대부분 하지 않는다. 이 경계를 모르면 "설치했는데 왜 안 되지" 가 반복된다.
설정 파일은 덮어쓰지 않는다. 패키지 갱신 시 우리가 고친 설정 파일이 있으면, 관리자는 덮어쓰는 대신 물어보거나 새 파일을 옆에 .dpkg-dist·.rpmnew 같은 이름으로 놓아둔다. 그래서 갱신 뒤에 이런 파일이 쌓여 있는지 확인하는 절차가 필요하다. 새 버전이 요구하는 설정 항목이 있어도 우리 파일에는 없기 때문에, 조용히 기본값으로 동작하다가 나중에 문제가 된다.
서비스를 재시작해 줄지는 배포판마다 다르다. 어떤 배포판은 갱신 후 자동으로 재시작하고, 어떤 배포판은 하지 않는다. 자동으로 하는 쪽은 예기치 않은 순간에 서비스가 끊길 수 있고, 하지 않는 쪽은 옛 코드가 계속 도는 채로 남는다. 어느 쪽인지 알고 그에 맞는 절차를 두는 것이지, 기본 동작을 믿고 넘어갈 일이 아니다.
설치하지 않은 것은 지워 주지 않는다. 패키지를 지워도 그것이 만들어 낸 로그, 데이터 디렉터리, 사용자 계정은 대개 남는다. 데비안 계열에서 remove 와 purge 가 나뉘어 있는 것이 이 차이다. 남는 것이 있다는 사실 자체는 안전장치이지만, 지웠다고 믿고 있으면 나중에 같은 패키지를 다시 깔았을 때 옛 설정이 되살아나 혼란을 일으킨다.
언어별 패키지 관리자와는 서로를 모른다. 시스템 패키지로 깐 파이썬 라이브러리와 pip 로 깐 것이 섞이면 어느 쪽이 쓰이는지 예측하기 어려워지고, 시스템 갱신이 애플리케이션을 깨뜨린다. 그래서 애플리케이션 의존성은 가상 환경이나 컨테이너로 분리하고, 시스템 패키지 관리자는 시스템의 것만 다루게 두는 것이 원칙이다.
다음에서 할 것
apt 의 실전 조작으로 넘어간다. 검색·설치·제거는 시작일 뿐이고, hold 와 pin 으로 버전을 붙잡는 법까지 손에 익힌다.