RHEL 기초 #3 dnf와 패키지 관리 — repo, modules, AppStream
#2에서 RHEL 머신을 띄우고 등록까지 마쳤습니다. 이제 이 위에 무언가를 깔고 지우는 일을 다룰 차례입니다. RHEL의 패키지 관리는 dnf 한 명령으로 통합니다. 우분투의 apt와 같은 역할입니다.
RHEL 기초 시리즈에서 이번 글의 위치:
- #1 RHEL이란 — Fedora에서 RHEL까지, 그리고 AlmaLinux와 Rocky Linux
- #2 셋업 — RHEL 9 설치, Subscription Manager, 첫 로그인
- #3 dnf와 패키지 관리 — repo, modules, AppStream ← 이번 글
- #4 systemd 입문 — 서비스, target, journalctl
- #5 사용자/그룹/권한 — UID/GID, sudo, ACL
- #6 파일 시스템 기본 — XFS, mount, /etc/fstab
- #7 기본 보안 — firewalld, SSH 하드닝
rpm / yum / dnf — 한 줄 정리 #
먼저 헷갈리는 세 단어부터 정리해 둡니다.
| 도구 | 다루는 것 | 설명 |
|---|---|---|
| rpm | .rpm 파일 한 장 | 의존성 자동 해결 안 됨. 직접 받은 .rpm을 설치할 때만 가끔 씀. |
| yum | 저장소 + 의존성 | RHEL 5~7의 표준. RHEL 8부터는 사실상 dnf의 별명. |
| dnf | 저장소 + 의존성 + modules | RHEL 8부터 표준. 파이썬으로 다시 쓴 yum. |
RHEL 9에서는 yum 명령어를 쳐도 동작하긴 합니다. 그냥 dnf로 심볼릭 링크돼 있습니다. 새 자료를 검색하거나 새 명령(dnf module)을 쓰려면 dnf로 통일하는 편이 좋습니다.
$ which yum
/usr/bin/yum
$ ls -l /usr/bin/yum
lrwxrwxrwx. 1 root root 5 ... /usr/bin/yum -> dnf-3dnf의 일상 명령군 #
가장 자주 만나는 명령부터.
검색 — search / info / list
#
$ dnf search nginx
=================== Name & Summary Matched: nginx ===================
nginx.aarch64 : A high performance web server and reverse proxy server
nginx-mod-http-image-filter.aarch64 : Nginx HTTP image filter module
...
$ dnf info nginx
Name : nginx
Version : 1.20.1
Release : 20.el9
Architecture : aarch64
Size : 593 k
Source : nginx-1.20.1-20.el9.src.rpm
Repository : rhel-9-for-aarch64-appstream-rpms
Summary : A high performance web server and reverse proxy server
URL : https://nginx.org
License : BSD
Description : ...info가 검색보다 정보가 많아 더 자주 봅니다. Repository 항목으로 어느 저장소에서 오는지 알 수 있습니다 — 위에서는 AppStream 저장소.
$ dnf list installed | head # 설치된 패키지
$ dnf list available nginx* # 설치 가능한 패키지
$ dnf list updates # 업데이트 가능한 패키지설치 — install
#
$ sudo dnf install nginx
Dependencies resolved.
============================================================
Package Arch Version Repository Size
============================================================
Installing:
nginx aarch64 1:1.20.1-20.el9 appstream 593 k
Installing dependencies:
nginx-filesystem noarch 1:1.20.1-20.el9 appstream 11 k
...
Transaction Summary
============================================================
Install 6 Packages
Total download size: 1.3 M
Installed size: 4.2 M
Is this ok [y/N]:여러 개를 한 번에 설치할 수 있고 (dnf install nginx git vim), 의존성도 자동으로 끌고 옵니다. 자동 yes가 필요하면 -y를 붙여요. 자동화 스크립트에서는 자주 쓰지만, 수동 작업에서는 의존성 목록을 한 번 보고 결정하는 습관이 좋습니다.
$ sudo dnf install ./some-package.rpm다운로드한 단일 .rpm 파일도 dnf install로 설치하면 의존성을 자동으로 해결합니다. rpm -i보다 거의 항상 이쪽이 정답입니다.
제거 — remove
#
$ sudo dnf remove nginx
Dependencies resolved.
=========================================================
Removing:
nginx ...
Removing unused dependencies:
nginx-filesystem ...설치할 때 같이 끌려온 의존성도 다른 곳에서 안 쓰면 자동 정리됩니다 (autoremove 동작 내장). 우분투에서 apt remove + apt autoremove 두 번 쳐야 하는 걸 한 번에 정리합니다.
함정 —
dnf remove가 핵심 패키지 (예:systemd,kernel) 를 같이 지우려 들면 즉시 멈추고 입력 확인을 다시 보세요. 의존성이 사방으로 얽힌 곳에선 패키지 하나 지우다 시스템이 부팅 불가가 되기도 합니다. 모르는 의존성 목록은 항상 멈춰 읽습니다.
업데이트 — update / upgrade
#
$ sudo dnf check-update # 업데이트 가능한 것만 보기 (변경 없음)
$ sudo dnf update # 모든 패키지 최신으로
$ sudo dnf update nginx # 한 패키지만update와 upgrade는 RHEL/dnf에서 사실상 같은 동작입니다 (다른 배포판에선 다를 수 있음). 보통 update를 더 많이 써요.
의존성 추적 — repoquery
#
깊이 들어갈 때 자주 쓰는 명령입니다.
$ dnf repoquery --requires nginx # nginx가 의존하는 것
$ dnf repoquery --whatrequires nginx # nginx를 의존하는 것
$ dnf repoquery -l nginx # 패키지가 설치하는 파일 목록
$ dnf repoquery --provides nginx # 패키지가 제공하는 가상 이름특히 dnf repoquery -l <패키지> — 어떤 패키지가 무슨 파일을 깔았는지 추적할 때 손이 자주 갑니다.
dnf history — 시간을 되돌리는 명령 #
가장 RHEL 다운 기능. 모든 dnf 트랜잭션이 이력으로 남고, 트랜잭션 단위로 되돌릴 수 있습니다.
$ sudo dnf history
ID | Command line | Date and time | Action(s) | Altered
----------------------------------------------------------------------
12 | install nginx | 2026-04-11 14:23 | Install | 6
11 | update -y | 2026-04-11 09:01 | I, U | 42
10 | install git vim | 2026-04-10 17:45 | Install | 8
9 | system upgrade ... | 2026-04-10 16:02 | Install | 362$ sudo dnf history info 12
Transaction ID : 12
Begin time : 2026-04-11 14:23:08
Command Line : install nginx
Packages Altered:
Install nginx-1:1.20.1-20.el9.aarch64 @appstream
Install nginx-filesystem-1:1.20.1-20.el9.noarch @appstream
...$ sudo dnf history undo 12 # 12번 트랜잭션 되돌리기
$ sudo dnf history redo 12 # 다시 적용운영에서 가장 손이 자주 가는 명령은 **장애 직후의 dnf history**입니다. “방금 뭘 바꿨더라?“라는 질문의 답이 거기 있습니다. apt에는 없는 기능입니다.
BaseOS와 AppStream — 두 저장소가 갈린 이유 #
#2에서 dnf repolist를 쳐 보면 두 줄이 나왔습니다.
$ dnf repolist
repo id repo name
rhel-9-for-aarch64-appstream-rpms Red Hat Enterprise Linux 9 - AppStream
rhel-9-for-aarch64-baseos-rpms Red Hat Enterprise Linux 9 - BaseOS두 저장소가 따로 있는 데는 의도가 있습니다.
BaseOS — 변하지 않는 OS 코어 #
커널 / glibc / systemd / coreutils / openssl / NetworkManager
↑ OS가 OS답게 동작하는 데 꼭 필요한 부품RHEL 9의 라이프사이클(10년) 동안 메이저 버전이 거의 바뀌지 않습니다. 보안 패치만 받습니다. “운영 중인 시스템의 안정성"이 BaseOS의 약속입니다.
AppStream — 빠르게 변할 수 있는 응용 패키지 #
PostgreSQL / Python / Node.js / nginx / Apache / Redis / Ruby / PHP / ...
↑ 사람이 골라 까는 응용 / 언어 / DB / 서버여기서는 같은 RHEL 9 안에서도 다른 메이저 버전들을 골라 설치할 수 있습니다. PostgreSQL 13 / 15 / 16, Python 3.9 / 3.11 / 3.12 이런 식으로. 이걸 가능하게 하는 게 modules.
이 분리는 RHEL 8부터 도입된 AppStream 컨셉입니다. RHEL 7 까지는 한 패키지에 한 메이저 버전만 가능해서 PostgreSQL 새 버전을 쓰려면 외부 저장소(
postgresql.org의 PGDG repo) 를 붙여야 했습니다. AppStream 이후로는 RHEL 공식 저장소 안에서 골라 쓸 수 있게 됐습니다.
dnf module — 같은 패키지의 여러 버전 #
PostgreSQL을 예로 들어봅시다.
$ dnf module list postgresql
Red Hat Enterprise Linux 9 for aarch64 - AppStream
Name Stream Profiles Summary
postgresql 13 client, server [d] PostgreSQL server and client module
postgresql 15 client, server [d] PostgreSQL server and client module
postgresql 16 client, server [d] PostgreSQL server and client module세 가지 메이저 버전이 보입니다. 각 버전 옆 Stream이 그 버전의 식별자고, Profile은 “어떤 용도로 설치할지"를 미리 묶어둔 세트입니다.
$ sudo dnf module enable postgresql:16
$ sudo dnf module install postgresql:16/serverpostgresql:16으로 모듈 stream을 활성화하고, postgresql:16/server로 server profile을 설치합니다. 활성화된 stream은 시스템에 한 번에 하나만 둘 수 있습니다. 같은 머신에 PG 13과 PG 16을 동시에 두지는 못합니다 (그건 컨테이너로).
$ dnf module info postgresql:16
$ sudo dnf module disable postgresql # 모든 stream 비활성화 (제거 전)
$ sudo dnf module reset postgresql # 활성화 / 비활성화 모두 초기화어떤 stream을 골라야 하나 #
default가 표시된 ([d]) stream을 그냥 따라가는 게 가장 무난합니다. RHEL 9에 들어 있는 그 stream은 RHEL의 라이프사이클 끝까지 (또는 모듈에 따라 5 년) 패치를 보장합니다.
특정 버전을 명시적으로 잡고 싶을 때만 stream을 골라 활성화. 한 번 stream을 정해두면 dnf update가 그 stream 안에서 마이너 업데이트만 적용해 — 어느 날 갑자기 PG 16이 PG 17로 점프하지 않습니다.
2026년 노트 — 사용자 패턴을 보고 RHEL 10부터 modules의 비중이 줄어들 거라는 신호가 있습니다. 새 RHEL일수록 “default stream"만 있는 모듈도 늘고 있는데, 그래도 RHEL 9에서는 modules가 핵심에 있습니다.
외부 저장소 — EPEL, COPR #
RHEL 공식 저장소 (BaseOS + AppStream) 에 없는 패키지가 필요할 때 두 가지가 자주 쓰입니다.
EPEL — Extra Packages for Enterprise Linux #
Fedora 커뮤니티가 RHEL 호환으로 빌드해 두는 추가 패키지 모음. RHEL 자체에 없는 도구 (예: htop, ncdu, bat, tmux 일부 모듈) 들이 여기 있습니다.
$ sudo dnf install -y epel-release
$ sudo dnf repolist
repo id repo name
epel Extra Packages for Enterprise Linux 9
epel-cisco-openh264 ...
rhel-9-for-aarch64-appstream-rpms ...
rhel-9-for-aarch64-baseos-rpms ...이제 EPEL 패키지를 깔 수 있습니다.
$ sudo dnf install htop ncduAlmaLinux / Rocky 사용자 —
epel-release를 깔 때dnf가 약간 다를 수 있습니다. 보통은sudo dnf config-manager --set-enabled crb로 CodeReady Linux Builder (CRB) 저장소를 먼저 켜야 EPEL의 일부 패키지가 의존성을 만족합니다. RHEL 에도 CRB가 있습니다 (subscription-manager repos --enable codeready-builder-for-rhel-9-aarch64-rpms).
COPR — 개인 프로젝트용 #
Fedora의 COPR은 사용자가 만든 임시 저장소들을 모아둔 곳. 정식 EPEL에 들어가기 전 단계의 도구나, 한 사람이 메인테이너인 패키지를 받을 때.
$ sudo dnf copr enable some-user/some-project
$ sudo dnf install some-package운영에는 권장하지 않습니다. 메인테이너가 사라지면 보안 패치가 끊겨요. 학습/실험용으로만.
외부 저장소를 붙일 때 신경 쓸 것 #
| 항목 | 왜 |
|---|---|
| 신뢰할 수 있는 저장소만 | rpm은 root로 깔립니다. 악의적 패키지면 끝 |
| GPG 서명 검증 | gpgcheck=1이 켜져 있어야 함 (기본값) |
| 우선순위 (priority) | 외부 저장소가 RHEL 핵심 패키지를 덮어써 버리면 곤란 |
| 활성화는 필요할 때만 | enabled=0으로 두고 --enablerepo로 그때만 켜기 |
운영 머신에서는 EPEL 정도만 켜두고, 나머지는 가능한 한 RHEL 공식 저장소 안에서 해결하는 게 안전한 길.
subscription-manager로 저장소 켜고 끄기 #
RHEL (AlmaLinux/Rocky가 아니라) 머신에서는 BaseOS / AppStream 외에도 추가 저장소가 있습니다. subscription에 따라.
$ sudo subscription-manager repos --list | head -30
+----------------------------------------------------------+
Available Repositories in /etc/yum.repos.d/redhat.repo
+----------------------------------------------------------+
Repo ID: rhel-9-for-aarch64-supplementary-rpms
Repo Name: Red Hat Enterprise Linux 9 for ARM 64 - Supplementary (RPMs)
Repo URL: ...
Enabled: 0
Repo ID: codeready-builder-for-rhel-9-aarch64-rpms
Repo Name: Red Hat CodeReady Linux Builder for RHEL 9 ARM 64 (RPMs)
...
Enabled: 0특정 저장소 켜기:
$ sudo subscription-manager repos \
--enable codeready-builder-for-rhel-9-aarch64-rpms
$ sudo dnf repolist | grep code
codeready-builder-for-rhel-9-aarch64-rpms ...EPEL의 일부 패키지가 CRB 의존성을 요구하기 때문에 EPEL을 켤 때 같이 켜는 일이 흔합니다.
자주 쓰는 명령 한 표 #
이번 글에서 두루 쓴 명령을 한 표에 모읍니다. 외울 필요는 없고, 막히면 돌아오세요.
| 명령 | 하는 일 |
|---|---|
dnf install <pkg> | 패키지 + 의존성 설치 |
dnf remove <pkg> | 패키지 + 안 쓰는 의존성 제거 |
dnf update [<pkg>] | 전체 또는 특정 패키지 업데이트 |
dnf check-update | 업데이트 가능 여부만 보기 |
dnf search <query> | 이름,요약에서 검색 |
dnf info <pkg> | 패키지 상세 정보 |
dnf list installed/available/updates | 목록 |
dnf repoquery -l <pkg> | 패키지가 설치한 파일 목록 |
dnf repoquery --whatrequires <pkg> | 이 패키지를 의존하는 것들 |
dnf history / history info N / history undo N | 트랜잭션 이력과 롤백 |
dnf module list <pkg> | 모듈 stream 목록 |
dnf module enable <pkg>:<stream> | 모듈 stream 활성화 |
dnf module install <pkg>:<stream>/<profile> | 모듈 설치 |
dnf repolist [--all] | 저장소 목록 |
dnf config-manager --set-enabled <repo> | 저장소 켜기 |
subscription-manager repos --enable <repo> | RHEL 저장소 켜기 |
자주 만나는 함정 #
“패키지를 찾지 못합니다” #
검색이 안 되면 보통 둘 중 하나입니다.
- 저장소가 비활성화 —
dnf repolist로 확인. AppStream이 꺼져 있으면 응용 패키지가 안 보입니다. - EPEL 등 외부 저장소가 필요 —
htop,ncdu같은 친구들은 RHEL 공식엔 없습니다.
“캐시가 이상합니다” #
오래된 메타데이터로 dnf가 헷갈릴 때:
$ sudo dnf clean all
$ sudo dnf makecache“modules가 충돌합니다” #
dnf install postgresql-server를 쳤는데 “module이 비활성화돼 있어 설치할 수 없다” 류 에러가 나오면, 해당 모듈을 활성화하지 않은 것입니다. dnf module list postgresql로 stream 확인 후 dnf module enable postgresql:16.
가끔 두 모듈이 같은 패키지를 두고 충돌하면 dnf module reset <패키지>로 초기화하고 다시 활성화.
“EPEL을 깔았는데 의존성이 안 풀려요” #
거의 99%는 **CRB (CodeReady Linux Builder)**가 안 켜진 경우입니다. 위에서 다룬 subscription-manager repos --enable codeready-builder-... 또는 AlmaLinux/Rocky라면 dnf config-manager --set-enabled crb.
정리 #
이번 글에서 잡은 그림:
rpm(단일 파일) /yum(옛 이름) /dnf(현재 표준) — RHEL 9 에서는 dnf로 통일- 일상은
install / remove / update / search / info / list만으로 거의 다 됨 dnf history와history undo가 RHEL 다운 기능 — 트랜잭션 단위 롤백 가능- BaseOS는 OS 코어 (10 년 안정), AppStream은 응용 (여러 버전)
- modules로 PostgreSQL 13/15/16 같은 패키지의 여러 메이저 버전을 골라 깔 수 있다
- EPEL은 Fedora가 만든 RHEL 호환 추가 저장소 —
htop,ncdu같은 도구의 출처. CRB와 함께 켜는 일이 잦음 - 외부 저장소는 신뢰할 수 있는 곳만 / GPG 검증 켜고 / 운영엔 EPEL 정도만
다음 — systemd #
이제 패키지를 깔 줄 압니다. 다음으로 다룰 건 깐 것을 어떻게 띄우고 멈추고 부팅 시 자동으로 올라오게 하느냐 — 그게 systemd가 하는 일입니다.
#4 systemd 입문 — 서비스, target, journalctl에서는 systemd가 PID 1로 어떻게 시스템 전체를 잡고 있는지, systemctl start/stop/enable/status의 명령군, target(multi-user / graphical / rescue)의 의미, 첫 .service 유닛 파일을 직접 작성해 띄워보기, 그리고 journalctl로 모든 서비스 로그를 한곳에서 보는 흐름까지 잡습니다.