Skip to content
ioob.dev
Go back

Linux 기초 7편 — 패키지 관리

· 8분 읽기
Linux 시리즈 (7/8)
  1. Linux 기초 1편 — 셸과 파일시스템 구조
  2. Linux 기초 2편 — 파일 권한과 사용자/그룹
  3. Linux 기초 3편 — 프로세스와 시그널
  4. Linux 기초 4편 — 텍스트 처리와 파이프
  5. Linux 기초 5편 — 네트워크 도구
  6. Linux 기초 6편 — Systemd와 서비스 관리
  7. Linux 기초 7편 — 패키지 관리
  8. Linux 기초 8편 — Bash 스크립팅 기초
Table of contents

Table of contents

왜 “패키지 관리”라는 별도 개념이 있나

처음 리눅스에 입문하면 윈도우의 exe 설치와는 다르게, 대부분의 소프트웨어를 apt install 한 줄로 까는 모습에 약간 놀란다. 실제로 리눅스 패키지 관리 시스템은 “앱 스토어”와 닮았다. 다만 GUI가 아니라 CLI로, 중앙 저장소에서 의존성을 자동 해결해 설치한다.

왜 별도 개념이 필요한지부터 짚어보자. 리눅스 앱은 대체로 공유 라이브러리에 의존한다. 예를 들어 curl은 OpenSSL을 쓰고, Python은 libffi·readline·libsqlite3를 쓴다. 이런 의존 그래프가 수백 개의 노드로 펼쳐진다. 사람이 하나씩 따라 설치하면 금세 버전이 꼬이고 충돌이 난다. 패키지 매니저는 의존성 그래프를 풀어 한꺼번에 설치해주는 도구다.

전체 그림은 이렇다.

flowchart LR
    USER["사용자<br/>(apt install nginx)"] --> MGR["패키지 매니저<br/>(apt / dnf)"]
    MGR --> CACHE["로컬 메타데이터 캐시"]
    MGR -->|"HTTPS"| REPO["저장소<br/>(archive.ubuntu.com 등)"]
    REPO --> PKGS["패키지 인덱스<br/>& .deb / .rpm 파일"]
    MGR --> DB[("설치 상태 DB<br/>/var/lib/dpkg/ 또는 /var/lib/rpm/")]
    MGR --> FS["파일시스템에 설치<br/>/usr/bin, /etc, /lib"]

사용자가 명령을 치면 패키지 매니저가 저장소에서 메타데이터를 받아 의존 그래프를 계산하고, 필요한 .deb/.rpm 파일을 내려받아 압축 해제하고, 설치 상태 DB에 기록한다. 이 흐름이 배포판마다 세부가 다르지만 골격은 같다.

Debian/Ubuntu 계열 — apt

Debian과 그 파생 배포판(Ubuntu, Mint, Pop!_OS 등)은 .deb 포맷과 apt 도구를 쓴다. 가장 자주 쓰는 명령을 먼저 훑어보자.

# 저장소 메타데이터 갱신 (설치 전 거의 항상 선행)
sudo apt update

# 업그레이드 가능한 패키지 확인
apt list --upgradable

# 모든 패키지 업그레이드
sudo apt upgrade

# 패키지 설치
sudo apt install nginx

# 특정 버전 설치
sudo apt install nginx=1.24.0-1ubuntu1

# 제거 (설정은 남김)
sudo apt remove nginx

# 제거 + 설정 파일까지 삭제
sudo apt purge nginx

# 더 이상 필요 없는 자동 설치 의존성 정리
sudo apt autoremove

# 이름·설명으로 검색
apt search nginx

# 설치된 패키지의 상세 정보
apt show nginx

# 이 파일이 어느 패키지에서 나왔나?
dpkg -S /usr/sbin/nginx

# 특정 패키지가 설치한 파일 목록
dpkg -L nginx

apt updateapt upgrade의 차이가 헷갈리는데, 짝으로 외워두면 편하다. update는 “목록 갱신”, upgrade는 “실제 설치”다. “목록만 새로고침하고 설치는 안 한다”가 update라는 점이 처음에는 직관적이지 않다.

apt-get vs apt — 왜 두 개가 있나

현장 문서에서는 apt-get installapt install이 섞여 있다. 같은 일을 하지만, 역사와 쓰임새가 다르다.

스크립트에는 apt-get, 대화형 사용에는 apt가 관례다. Dockerfile에 apt install을 쓰면 “CLI가 사람용이라 포맷이 안정적이지 않다”는 경고가 뜨는 이유가 그래서다.

# Dockerfile에서 권장
RUN apt-get update && apt-get install -y --no-install-recommends nginx

저장소는 어디에 적혀 있나

apt가 “저장소에서 받는다”고 했는데, 그 저장소 목록은 /etc/apt/sources.list/etc/apt/sources.list.d/*.list에 적혀 있다.

cat /etc/apt/sources.list
# deb http://archive.ubuntu.com/ubuntu jammy main restricted universe multiverse
# deb http://archive.ubuntu.com/ubuntu jammy-updates main restricted universe multiverse
# deb http://security.ubuntu.com/ubuntu jammy-security main restricted universe multiverse

한 줄의 의미를 풀어보면 이렇다.

외부 저장소(예: Docker 공식 리포)를 추가할 때는 별도 .list 파일을 만들고, GPG 키를 키링에 등록한다. 이게 현대 데비안의 권장 패턴이다.

# 예시: Docker 공식 리포 추가
sudo install -m 0755 -d /etc/apt/keyrings
curl -fsSL https://download.docker.com/linux/ubuntu/gpg \
  | sudo gpg --dearmor -o /etc/apt/keyrings/docker.gpg

echo "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.gpg] \
https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable" \
  | sudo tee /etc/apt/sources.list.d/docker.list

sudo apt update
sudo apt install docker-ce docker-ce-cli containerd.io

signed-by=...가 핵심이다. “이 저장소의 패키지는 반드시 이 공개키로 서명된 것만 신뢰한다”는 의미다. 예전엔 apt-key add로 전역 키링에 넣었는데, 보안상 문제가 있어 키링을 저장소별로 분리하는 방향으로 바뀌었다.

의존성 해결이 꼬일 때 — Held broken packages

패키지 설치가 실패하면서 “The following packages have unmet dependencies”가 뜨는 일이 종종 있다. 이때 쓰는 구조 명령을 몇 개 기억해두면 구난 속도가 달라진다.

# 문제의 패키지 재설치로 강제 정비
sudo apt --fix-broken install

# 설치 상태 DB 일관성 복구
sudo dpkg --configure -a

# 캐시 초기화 후 재시도
sudo rm -rf /var/lib/apt/lists/*
sudo apt update

--fix-broken은 “알아서 풀어봐라”에 가깝고, dpkg --configure -a는 중단된 설치 단계가 있다면 마저 끝내게 한다. 순서대로 시도한다.

RHEL 계열 — dnf / yum

RHEL(Red Hat Enterprise Linux)과 파생 배포판(CentOS, Rocky Linux, AlmaLinux, Fedora)은 .rpm 포맷을 쓰고, 도구는 dnf(또는 과거의 yum)를 쓴다.

배포판권장 도구
RHEL 8+ / Rocky / Alma / Fedoradnf
CentOS 7 / RHEL 7 (EOL 근접)yum

yum은 Python 2 기반의 구형, dnf는 이를 리팩토링한 후속 도구다. 인터페이스는 거의 같아서, 대부분의 커맨드를 yum에서 dnf로 바꿔도 돌아간다. 최신 RHEL 계열에서는 yum이 사실상 dnf의 심볼릭 링크다.

자주 쓰는 명령을 apt와 대조해서 정리하면 이렇다.

작업aptdnf
메타데이터 갱신apt update(자동, 또는 dnf check-update)
업그레이드apt upgradednf upgrade
설치apt install pkgdnf install pkg
제거apt remove pkgdnf remove pkg
검색apt search pkgdnf search pkg
정보apt show pkgdnf info pkg
파일→패키지dpkg -S filednf provides file
파일 목록dpkg -L pkgrpm -ql pkg

dnf 특유의 기능 중 유용한 게 트랜잭션 히스토리다. 이 기능 덕에 “며칠 전 설치한 패키지 때문에 뭔가 꼬였다”를 정확히 되돌릴 수 있다.

sudo dnf history
# ID | Command line            | Date and time    | Action(s)  | Altered
# ---+-------------------------+------------------+------------+--------
# 42 | install nginx           | 2026-04-18 10:00 | Install    |  3
# 41 | upgrade                 | 2026-04-17 03:00 | E, I, U    | 42

# 42번 트랜잭션 상세
sudo dnf history info 42

# 42번 트랜잭션 되돌리기
sudo dnf history undo 42

apt에도 /var/log/apt/history.log가 있긴 하지만, “undo”처럼 한 번에 되돌리는 도구는 dnf가 더 단정하다. RHEL 계열에서 롤백 가능성이 더 잘 갖춰져 있다고 보면 된다.

저장소 정의 파일

dnf의 저장소는 /etc/yum.repos.d/*.repo 아래에 하나씩 파일로 있다.

# /etc/yum.repos.d/docker-ce.repo
[docker-ce-stable]
name=Docker CE Stable - $basearch
baseurl=https://download.docker.com/linux/centos/$releasever/$basearch/stable
enabled=1
gpgcheck=1
gpgkey=https://download.docker.com/linux/centos/gpg

$basearch, $releasever 같은 변수는 dnf가 자동으로 채워준다. apt와 다르게 저장소 블록이 한 파일 안에 INI 섹션으로 들어가는 게 인상 깊다.

활성·비활성 저장소 목록은 아래 명령으로 본다.

dnf repolist --all

비활성 저장소를 한 번만 켜서 설치하고 싶을 땐 --enablerepo를 쓴다.

sudo dnf --enablerepo=epel install htop

공통 개념 — 버전 핀, 보관, 롤백

배포판이 달라도 “의존성 있는 시스템”이라는 공통 과제를 다룬다. 실무에서 자주 쓰는 공통 패턴 몇 가지다.

버전 핀 — 특정 버전에 고정

CI/배포 환경에서 “항상 같은 버전”이 중요한 경우가 있다.

# apt
sudo apt install nginx=1.24.0-1ubuntu1
sudo apt-mark hold nginx          # 업그레이드 대상에서 제외
sudo apt-mark unhold nginx

# dnf
sudo dnf install nginx-1.24.0
sudo dnf versionlock add nginx    # 플러그인 필요: dnf-plugin-versionlock

설치 없이 내려받기만

네트워크가 제한된 환경에 옮겨 설치할 때 쓴다.

# apt — /var/cache/apt/archives 로
sudo apt install --download-only nginx

# dnf — 현재 디렉토리에
sudo dnf download nginx

보안 업데이트만 적용

프로덕션 서버에서 일반 업그레이드는 주저되지만 보안 패치는 반드시 넣어야 할 때가 있다.

# Ubuntu (unattended-upgrades의 수동 대안)
sudo apt install unattended-upgrades
sudo unattended-upgrade --dry-run -d

# RHEL
sudo dnf upgrade --security
sudo dnf upgrade-minimal --security

대안 — 시스템 패키지가 부족할 때

배포판 저장소에 원하는 도구가 없거나, 최신 버전이 필요할 때 흔히 쓰는 대안 세 가지도 간단히 짚고 간다.

실무에서는 일단 시스템 패키지 매니저(apt/dnf), 없으면 언어 매니저, 최후에 수동 설치 순서로 고르는 게 무난하다. 시스템 패키지가 관리가 쉽고, 자동 보안 패치도 받기 쉽다.

실전 체크리스트

서버에 올라가서 새 도구를 깔 때 내가 실제로 밟는 순서를 정리해두면 대체로 이렇다.

flowchart TB
    A["1. 배포판 확인<br/>cat /etc/os-release"] --> B{"apt? dnf?"}
    B --> C["2. 저장소 인덱스 갱신<br/>apt update 또는 dnf check-update"]
    C --> D["3. 검색·정보 확인<br/>apt search / dnf search"]
    D --> E["4. 버전 결정 후 설치"]
    E --> F["5. 파일 경로 확인<br/>dpkg -L / rpm -ql"]
    F --> G["6. systemctl enable --now 서비스"]
    G --> H["7. journalctl 로 기동 로그 확인"]

이 순서가 몸에 붙으면 새 서버에 올라갔을 때 “뭐부터 해야 하지?”에서 막히지 않는다. 6편의 systemd 체계와 8편의 쉘 스크립트를 합치면, 서버 하나를 운영 가능한 상태로 세팅하는 기본기가 완성된다.


다음 편에서는 Bash 스크립트를 다룬다. 이제까지 쳐온 명령들을 하나의 파일로 묶어 자동화하는 방법, 조건문·반복문·함수·exit code, set -e·set -u 같은 안전 옵션, 그리고 실전에 자주 쓰는 백업·모니터링 스크립트 예제까지 살펴본다.

8편: Bash 스크립팅 기초


Related Posts

Share this post on:

Comments

Loading comments...


Previous Post
Linux 기초 6편 — Systemd와 서비스 관리
Next Post
Linux 기초 8편 — Bash 스크립팅 기초