
어제까지 멀쩡하던 서버에서 패키지 하나를 설치하려고 sudo apt update를 실행했는데, 화면에 W: GPG error ... NO_PUBKEY 871920D1991BC93C 같은 줄이 올라오고 그다음 줄에서 저장소 전체가 무시되었다는 경고가 뜬다. 설치는 시작도 못 했는데 목록 갱신에서 막힌 것이다.
우분투 26.04 LTS(Resolute Raccoon)로 올린 직후이거나, 도커·엔비디아·몽고DB 같은 외부 저장소를 추가한 다음에 특히 자주 나타난다. 오래된 블로그를 따라 apt-key 명령을 쓰다가 더 꼬이는 경우도 많다. 이 글에서는 왜 이 오류가 뜨는지와, 2026년 기준으로 통하는 정식 해결 절차를 순서대로 정리한다.
원인 — 저장소가 붙인 GPG 서명을 검증할 공개키가 apt가 들여다보는 키링에 없다.
해결의 정석 — 키를 내려받아 /etc/apt/keyrings 아래 저장소별 키링 파일로 만들고, 저장소 설정의 Signed-By 항목으로 연결한다.
안 될 때 — sudo apt modernize-sources 로 저장소 설정 형식을 먼저 정리한 뒤 다시 시도한다.
apt로 작업하다 Could not get lock /var/lib/dpkg/lock-frontend 쪽에서 먼저 막혔다면 dpkg 잠금 오류 5단계 해결을 먼저 정리하고 돌아오는 편이 빠르다.
NO_PUBKEY, 서명을 확인할 수 없습니다가 뜨는 이유

apt는 저장소에서 패키지를 바로 내려받지 않는다. 먼저 저장소가 배포하는 Release 파일과 그 서명(Release.gpg 또는 InRelease)을 받아, 패키지 목록이 중간에 바뀌지 않았는지 검증한다. 이 검증에 쓰이는 것이 저장소 운영자의 GPG 공개키다.
그 공개키를 찾지 못하면 apt는 서명을 확인할 방법이 없으므로 NO_PUBKEY 뒤에 필요한 키 ID 16자리를 그대로 찍어 주고, 해당 저장소를 통째로 신뢰하지 않는다. 다른 저장소가 모두 정상이어도 apt update 전체가 경고로 끝나는 이유가 여기에 있다.
중요한 점은 키가 손상된 것이 아니라 연결이 끊어진 상태라는 것이다. 그래서 해결은 키를 다시 받아 올바른 자리에 놓고, 저장소 설정에서 그 자리를 가리키게 해 주는 일이 전부다.
우분투 26.04에서 키를 두는 자리가 바뀐 배경
예전에는 sudo apt-key add 한 줄이면 끝났다. 그런데 이 방식은 추가한 키를 전역 신뢰 저장소에 넣는다. 프린터 드라이버 저장소에 넣은 키가 우분투 본 저장소의 패키지까지 서명할 수 있게 된다는 뜻이다. 저장소 하나가 뚫리면 시스템 전체가 영향을 받는 구조였다.
그래서 데비안과 우분투는 키를 저장소별로 분리하는 방향으로 바꾸었다. 지금 기준은 다음과 같다.
- apt-key는 폐기(deprecated) 상태다. 이 방식으로 넣은 키는 레거시 키링 경고를 달고 다닌다.
- 저장소 설정은 deb822 형식의 .sources 파일이 기본이다. 우분투 26.04의 기본 설정 파일은 /etc/apt/sources.list.d/ubuntu.sources이고, 예전 /etc/apt/sources.list는 비어 있는 것이 정상이다.
- 저장소별 키는 /etc/apt/keyrings(배포판 제공 키는 /usr/share/keyrings)에 두고, 설정의 Signed-By 항목으로 가리킨다.
- 우분투 26.04는 apt 3.1 계열을 탑재하며, 옛 .list 파일을 새 형식으로 바꿔 주는 apt modernize-sources 하위 명령을 제공한다.
즉 오류가 늘어난 것이 아니라, 키를 두는 규칙이 엄격해지면서 과거 방식으로 설정된 저장소가 걸러지고 있는 것이다.
NO_PUBKEY 오류 5단계 해결

1단계 · 어떤 키가 없는지 확인한다
오류 메시지에서 NO_PUBKEY 뒤에 붙은 16자리 값이 필요한 키 ID다. 여러 저장소가 동시에 걸렸다면 아래처럼 한 번에 추려 본다.
sudo apt update 2>&1 | grep NO_PUBKEY
어느 저장소가 문제인지는 바로 윗줄의 URL로 알 수 있다. 그 저장소의 공식 설치 문서를 띄워 두면 다음 단계에서 지문을 대조할 때 쓸 수 있다.
2단계 · 키를 둘 디렉터리를 만든다
sudo install -m 0755 -d /etc/apt/keyrings
이미 있으면 그대로 두면 된다. 권한이 0755가 아니면 apt가 키를 읽지 못하는 경우가 있으므로 이 명령으로 맞춰 주는 편이 안전하다.
3단계 · 임시 작업공간에 키를 내려받는다
개인 키링을 더럽히지 않도록 임시 디렉터리를 만들어 그 안에서 받는다.
t=$(mktemp -d)
gpg --homedir "$t" --keyserver hkps://keyserver.ubuntu.com --recv-keys 키ID
키서버가 막혀 있다면 저장소가 직접 배포하는 키 파일 주소를 공식 문서에서 찾아 curl로 받는 방법도 있다.
4단계 · 지문을 대조하고 키링 파일로 내보낸다
여기가 이 글에서 가장 중요한 지점이다. 받은 키의 지문을 저장소 공식 문서에 적힌 값과 눈으로 대조한다.
gpg --homedir "$t" --fingerprint --with-subkey-fingerprint
값이 일치하면 내보낸다.
gpg --homedir "$t" --export-options export-minimal --export 키ID \
| sudo tee /etc/apt/keyrings/이름.gpg > /dev/null
sudo chmod 0644 /etc/apt/keyrings/이름.gpg
rm -rf "$t"
파일 이름은 저장소를 알아볼 수 있게 짓는다(예: docker.gpg, nvidia.gpg).
5단계 · 저장소 설정에서 키를 가리키게 한다
deb822 형식(.sources)이면 해당 항목에 한 줄을 추가한다.
Signed-By: /etc/apt/keyrings/이름.gpg
예전 .list 형식이면 대괄호 안에 적는다.
deb [signed-by=/etc/apt/keyrings/이름.gpg] https://repo.example.com/apt stable main
저장한 뒤 다시 갱신한다.
sudo apt update
경고 없이 목록이 내려오면 끝이다. 파이썬 패키지를 설치하려다 error: externally-managed-environment로 다시 막힌다면 pip externally-managed-environment 5단계 해결을 참고하면 된다.
방법별 난이도와 위험도 비교

| 방법 | 난이도 | 위험도 | 되돌리기 |
|---|---|---|---|
| 저장소별 키링 + Signed-By 지정 | 보통 | 낮음 | 쉬움 · 키 파일만 삭제 |
| apt modernize-sources 로 변환 후 지정 | 보통 | 낮음 | 쉬움 · .list 백업이 남는다 |
| apt-key adv 로 전역 추가(레거시) | 쉬움 | 높음 | 번거로움 · 전역 신뢰 오염 |
| [trusted=yes] 로 서명 검증 해제 | 쉬움 | 매우 높음 | 즉시 원복 필요 |
위험 고지 — 저장소 항목에 [trusted=yes]를 붙이면 apt는 서명을 아예 검증하지 않는다. 그 저장소에서 내려오는 모든 패키지를 무조건 신뢰하겠다는 뜻이므로, 중간에서 내용이 바뀐 패키지도 그대로 설치된다. 사내망 테스트처럼 통제된 상황의 최후 수단으로만 쓰고, 작업이 끝나면 반드시 해당 옵션을 지운 뒤 정식 절차로 키를 등록해야 한다. apt-key 방식 역시 보안이 약해지는 선택이라는 점은 같다.
그래도 apt update가 안 될 때
설정 형식이 섞여 있는 경우 — 같은 저장소가 .list와 .sources 양쪽에 중복으로 들어가 있으면 한쪽만 고쳐도 경고가 남는다. 아래 명령으로 형식을 정리한 뒤 Signed-By를 다시 확인한다. 변환 전 파일은 백업으로 남으므로 되돌리기도 쉽다.
sudo apt modernize-sources
키가 만료된 경우 — NO_PUBKEY가 아니라 EXPKEYSIG 또는 KEYEXPIRED가 뜬다면 키 자체는 있으나 유효기간이 지난 것이다. 저장소가 배포하는 새 키를 같은 절차로 다시 내려받아 덮어쓰면 된다.
시스템 시간이 틀어진 경우 — 가상머신이나 라즈베리파이처럼 시계가 쉽게 어긋나는 환경에서는 서명 유효기간 검증이 실패한다. timedatectl로 시간을 확인하고 NTP 동기화를 켠 뒤 다시 시도한다.
레거시 키링 경고가 남는 경우 — /etc/apt/trusted.gpg 에 남아 있는 옛 키들이 경고를 만든다. 저장소별 키링으로 모두 옮긴 뒤에는 해당 파일을 지우지 말고 이름을 바꿔 보관했다가, 문제가 없는 것을 확인하고 정리하는 편이 안전하다.
서버를 새로 올리면서 겪는 문제라면 리눅스 설치하기와 리눅스 원격 접속 SSH 설치 및 설정을 함께 보면 초기 설정을 한 번에 끝낼 수 있다.
요약
- NO_PUBKEY는 저장소 서명을 검증할 공개키를 apt가 찾지 못했다는 뜻이다.
- 키 ID 확인 → /etc/apt/keyrings 생성 → 키 수신 → 지문 대조 후 내보내기 → Signed-By 연결, 이 다섯 단계가 정석이다.
- 지문 대조는 생략하지 않는다. 이 단계가 빠지면 위조된 키를 신뢰하게 된다.
- apt-key와 [trusted=yes]는 보안을 낮추는 선택이므로 임시로만 쓰고 바로 원복한다.
- 경고가 계속 남으면 apt modernize-sources 로 설정 형식을 정리한 뒤 다시 확인한다.
자주 묻는 질문
키를 /usr/share/keyrings 와 /etc/apt/keyrings 중 어디에 두어야 합니까?
배포판이나 패키지가 설치해 주는 키는 /usr/share/keyrings 에 놓이고, 사용자가 직접 추가하는 키는 /etc/apt/keyrings 에 두는 것이 관례다. 어느 쪽이든 Signed-By 경로만 정확하면 동작한다. 직접 받은 키라면 /etc/apt/keyrings 를 권한다.
apt-key 로 넣은 키는 지워야 합니까?
저장소별 키링으로 모두 옮긴 뒤 정리하는 것이 맞다. 다만 한 번에 지우면 어떤 저장소가 그 키에 의존했는지 알기 어려워지므로, 먼저 저장소마다 Signed-By를 지정해 정상 동작을 확인한 다음 단계적으로 정리한다.
키 ID 대신 지문 전체를 확인해야 하는 이유는 무엇입니까?
짧은 키 ID는 서로 다른 키가 같은 값을 가지도록 만들어 낼 수 있다. 저장소 공식 문서가 공개한 지문 전체와 대조해야 내가 받은 키가 진짜인지 확인할 수 있다.
이 방법이 데비안이나 민트에서도 통합니까?
통한다. deb822 형식과 Signed-By, /etc/apt/keyrings 규칙은 데비안 계열 공통이다. 경로와 명령은 같고 저장소 주소만 배포판에 맞추면 된다.
'Computer_IT > Linux' 카테고리의 다른 글
| Could not get lock /var/lib/dpkg/lock-frontend 5단계 해결 (0) | 2026.09.23 |
|---|---|
| 리눅스 설치하기 (0) | 2018.07.23 |
| 리눅스 서버 시간 확인 및 설정 (1) | 2017.05.30 |
| Linux Zip 압축 파일 해제하기 (0) | 2017.05.11 |
| MariaDB 삭제 방법 Mysql 삭제 및 재설치 방법 (0) | 2017.05.07 |