rpm -i로 설치하면 왜 의존성 에러가 나는가 — RPM과 dnf의 역할 분담

nginx를 설치하려고 rpm -i nginx.rpm을 쳤더니 의존성 에러로 실패한다. 왜? RPM은 의존성을 풀어주지 않는다. 단순 설치만 한다. 의존성 해결은 dnf의 일이다. 그래서 로컬 .rpm 파일도 dnf install ./pkg.rpm으로 설치해야 dnf가 의존성까지 처리한다.

이 글은 Rocky 10이 패키지를 어떻게 관리하는지 다룬다 — RPM(포장 형식 + 저수준 도구)과 dnf(앱스토어 관리자)의 역할 분담, 그리고 Rocky 10의 두 가지 큰 변화: dnf5 전환modularity 폐지. 이 변화를 모르면 구형 자료의 명령이 Rocky 10에서 동작하지 않는다.

RPM과 dnf는 역할이 다르다

  역할 비유
RPM 단일 .rpm 패키지 파일 + 저수준 설치 도구 포장된 상자(내용물 + 설명서 + 조립법)
dnf5 저장소 관리 + 의존성 자동 해결 + 설치/업데이트 앱스토어 관리자(검색·배달·세트물 해결)

RPM은 패키지 형식(.rpm)이자 저수준 도구다. dnf는 그 위에서 저장소 관리와 의존성 자동 해결을 한다. 의존성 지옥(openssl, pcre... 각각 컴파일하던 시절)에서 벗어나게 한 것이 dnf의 핵심 가치다.

NEVRA — 패키지 식별자

nginx-1.26.3-1.el10.x86_64.rpm
  │     │     │  │     │
  │     │     │  │     └ 아키텍처(x86_64, aarch64, noarch)
  │     │     │  └ 배포 태그(el10 = Enterprise Linux 10)
  │     │     └ 릴리스(같은 버전의 빌드 회차)
  │     └ 버전(업스트림)
  └ 이름

noarch는 아키텍처 무관(스크립트/문서). RPM 파일 내부는 헤더(메타데이터) + 페이로드(cpio 압축) + 서명(GPG)으로 이루어진다.

트랜잭션 스크립트

패키지는 설치/제거 시점에 스크립트를 실행한다:
| 스크립트 | 실행 시점 |
|----------|-----------|
| %pre / %post | 설치 / |
| %preun / %postun | 제거 / |

Rocky 10의 큰 변화 — dnf5와 modularity 폐지

Rocky 10은 dnf4(구)에서 dnf5로 전환했다.

flowchart LR
    D[dnf5 명령] --> LIB[libdnf5<br/>C++ 라이브러리]
    LIB --> REPO[저장소 메타데이터]
    LIB --> RPM[RPM DB<br/>/var/lib/rpm]
항목 dnf4(구) dnf5(Rocky 10)
구현 Python + libdnf(C++) libdnf5(전체 C++ 재작성)
Python 의존 필수 제거(컨테이너에 유리)
속도 보통 더 빠름
modularity(dnf module) 지원 폐지
filelists metadata 기본 다운로드 기본 생략(필요 시 자동/수동)
사용자 캐시 ~/.cache/dnf ~/.cache/libdnf5

modularity 폐지 — 구형 자료가 동작하지 않는 이유

Rocky 8/9에선 특정 버전을 설치하려고 dnf module enable nginx:1.14 && dnf module install nginx:1.14를 썼다. Rocky 10에선 이 명령이 안 통한다. modularity가 폐지됐기 때문이다. 대신 버전을 직접 지정한다.

작업 구 방식(Rocky 8/9) 새 방식(Rocky 10)
특정 버전 설치 dnf module enable nginx:1.14 && dnf module install nginx:1.14 dnf install nginx-1.26.3
버전 목록 dnf module list nginx dnf repoquery nginx

구버전(Rocky 8/9)에서는 구 방식이 정상 동작한다. 버전에 따라 명령이 다르니, 자료의 Rocky 버전을 반드시 확인하라. nginx-1.26.3(하이픈)과 nginx:1.26(콜론, module 방식)은 다르다 — Rocky 10은 하이픈 방식만 된다.

dnf4와 dnf5는 같은 RPM DB(/var/lib/rpm)를 공유하지만, 트랜잭션 히스토리 DB는 다르다. dnf5로 깐 패키지를 dnf4로 보면 "user installed"로 보이고 그 반대도 마찬가지. Rocky 10은 dnf5가 기본이라 혼용할 일은 거의 없다.

저장소와 GPG 검증 — 변조를 막는다

패키지와 메타데이터를 제공하는 원격/로컬 소스가 저장소(repository)다.

  • 설정: /etc/yum.repos.d/*.repo.
  • 기본 저장소(Rocky 10): BaseOS, AppStream, Extras.
  • 메타데이터: repodata/(primary, filelists, updateinfo).

.repo 파일 예시:

[example-base]
name=Example Base
baseurl=https://example.com/linux/10/BaseOS/$basearch/os/
enabled=1
gpgcheck=1
gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-example

저장소/패키지의 GPG 서명으로 변조 여부를 확인한다. gpgcheck=1이면 서명 안 된 패키지 설치를 거부한다. 저장소 추가 시 공개 키를 먼저 등록: rpm --import <keyfile>. gpgcheck를 끄면 편하지만 위험하다 — 변조된 패키지가 설치될 수 있다.

Rocky 10에서 직접 확인하기

미검증(출처 인용). Rocky 10 VM에서 실행 권장.

dnf --version    # dnf5 버전 출력
# 패키지 조회
dnf list installed              # 설치된 패키지
dnf info nginx                  # 패키지 상세
dnf search "web server"         # 이름/요약 검색
dnf provides /usr/bin/curl      # 파일이 어느 패키지인지
dnf repoquery nginx             # 저장소의 모든 버전(modularity 대체)
sudo dnf install -y nginx             # -y 자동 yes
sudo dnf install -y nginx-1.26.3      # 특정 버전(새 방식)
sudo dnf remove nginx
sudo dnf update                       # 전체 업데이트(= upgrade)
sudo dnf check-update                 # 업데이트 가능 목록만
sudo dnf downgrade nginx
# 저장소 관리
dnf repolist                         # 활성 저장소
dnf repolist all                     # 전체
sudo dnf config-manager --add-repo https://example.com/repo.repo
sudo dnf config-manager --disable example-base
sudo dnf clean all                   # 캐시 삭제
# 히스토리 — 롤백
dnf history list                     # 트랜잭션 목록
dnf history info 5                   # 5번 상세
sudo dnf history undo 5              # 5번 취소(롤백)
sudo dnf history rollback 3          # 3번 이후 모두 취소

dnf5는 서브명령이 필수: dnf history만 치면 안 되고 dnf history list.

# 저수준 rpm (dnf로 안 될 때)
rpm -qa | grep nginx                 # 설치된 패키지 검색
rpm -qi nginx                        # 패키지 정보
rpm -ql nginx                        # 설치한 파일 목록
rpm -qf /usr/bin/curl                # 파일 소속 패키지
rpm -Va nginx                        # 검증(변조/무결성)
sudo rpm -ivh pkg.rpm                # 설치(로컬, 의존성 안 풀림)
dnf group list
sudo dnf group install "Server with GUI"

흔히 묻는 것, 흔히 틀리는 것

오해 정정
"rpm -i로 설치하면 된다" 의존성 안 풀림. dnf install ./pkg.rpm 사용
"Rocky 10에선 dnf module이 된다" 안 됨(폐지). dnf install pkg-ver
"filelists는 항상 받아진다" Rocky 10은 기본 생략. 필요 시 자동/optional_metadata_types=filelists
"dnf updatednf upgrade는 다르다" 현대 dnf에선 동일(upgrade가 alias)
"-y는 항상 좋다" 운영에선 의존성 변경 먼저 확인 권장. 자동 스크립트만 -y
"EPEL은 기본 저장소다" 아니다. 서드파티. 필요 시 별도 설치(dnf install epel-release)
"gpgcheck 끄면 편하다" 위험. 변조 패키지 설치 가능. 공식 외엔 더 엄격히
"dnf5 히스토리에 과거가 다 보인다" dnf4→5 전환 시 과거 히스토리 마이그레이션 안 됨

더 깊이

  • EPEL(Extra Packages for Enterprise Linux): Fedora 커뮤니티가 RHEL/Rocky용으로 제공하는 추가 패키지 저장소. RHEL 기본에 없는 도구(htop, nginx 최신 등) 설치에 유용. dnf install epel-release로 활성화. 단, 공식 지원 아님(운영 환경 주의).
  • dnf5 명령 변경: dnf shelldnf5 do, dnf updateinfodnf5 advisory summary, dnf mark installdnf5 mark user 등 서브명령이 바뀌었다. 자동화 스크립트 작성 시 dnf5 문서 확인.
  • RPM 직접 빌드: rpmbuild + .spec 파일로 커스텀 패키지를 생성. 소스 + 패치 + 설치 스크립트 + 메타데이터를 묶어 배포. 고급 주제.

요약 — 이 글의 결론

  • RPM = 패키지 형식(.rpm) + 저수준 도구. 의존성을 안 푼다 — 그래서 rpm -i는 실패하고 dnf install ./pkg.rpm을 써야 한다.
  • dnf5(Rocky 10) = libdnf5(C++ 재작성), Python 의존 제거, 더 빠름.
  • NEVRA: Name-Version-Release.Architecture.
  • modularity 폐지: dnf module이 안 통한다. dnf install pkg-ver로 버전 지정(하이픈). 구버전(8/9)은 콜론 module 방식.
  • filelists 기본 생략(필요 시 자동/optional_metadata_types=filelists).
  • 저장소: /etc/yum.repos.d/*.repo. GPG 서명(gpgcheck=1)으로 변조 방지 — 끄면 위험.
  • rollback: dnf history undo N / dnf history rollback N.
  • dnf update = upgrade(동일).

생각해 볼 문제

  1. RPM과 dnf의 역할 분담을 설명하라. 왜 rpm -i로 설치하면 안 되는가?
  2. NEVRA의 각 자리가 의미하는 바를 풀어 설명하라.
  3. dnf5가 dnf4보다 나은 점 3가지는?
  4. Rocky 10에서 특정 버전 패키지를 설치하는 명령은? 구버전(8/9) 방식과 비교하라.
  5. filelists metadata가 기본 생략된 이유와, 필요할 때 어떻게 하는가?
  6. /usr/bin/curl이 어느 패키지 소속인지 확인하는 두 명령은?
  7. 설치를 롤백하려면 어떤 명령을 쓰는가? gpgcheck를 끄면 왜 위험한가?

참고

'Tech Artifacts > Linux' 카테고리의 다른 글

Linux - 10. security  (0) 2026.07.09
Linux - 09. network  (0) 2026.07.09
Linux - 07. shell script  (0) 2026.07.09
Linux - 06. io device  (0) 2026.07.09
Linux - 05. filesystem  (0) 2026.07.09