SSD Nodes Learn 🎉 VPS $5.50/월부터
가이드 Matt Connor작성자 Matt Connor · 업데이트됨 2026-08-13

apt update 중복 소스 오류 해결 방법

apt update 실행 시 발생하는 Target is configured multiple times 오류를 해결합니다. 기존 .list 파일과 deb822 형식의 .sources 파일이 충돌하는 원인을 파악하고 중복된 설정을 제거하여 apt 업데이트를 정상화하는 방법을 안내합니다.

중복 apt 소스 오류의 의미

중복 apt 소스란 하나의 저장소가 서로 다른 두 파일에 선언되어 APT(advanced package tool)가 두 복사본을 모두 발견했음을 의미합니다. Ubuntu 24.04 이상 버전에서는 타사 설치 스크립트가 오래된 한 줄짜리 .list 파일을 작성하는 동안, 동일한 저장소에 대한 deb822 형식의 .sources 파일이 이미 디스크에 존재하여 발생하는 경우가 대부분입니다. 데이터가 손상된 것은 아니며 패키지에도 위험이 없습니다. 두 선언 중 하나를 삭제하면 메시지가 사라집니다.

사람들이 검색창에 붙여넣는 줄은 다음과 같습니다.

W: Target Packages (stable/binary-amd64/Packages) is configured multiple times in /etc/apt/sources.list.d/docker.list:1 and /etc/apt/sources.list.d/docker.sources:1

끝에서부터 읽어 보십시오. 각각 줄 번호가 포함된 두 파일이 동일한 내용을 선언하고 있습니다. Target Packages는 apt가 저장소에서 제공하는 패키지를 파악하기 위해 다운로드하는 인덱스이며, stable/binary-amd64/Packages은 해당 인덱스가 다루는 구성 요소(stable)와 아키텍처(amd64)를 나타냅니다. 즉, apt는 stable 구성 요소에 대한 amd64 인덱스가 docker.list의 1번 줄과 docker.sources의 1번 줄에 각각 설정되어 있다고 알리는 것입니다.

Ubuntu 25.04 이후 및 Debian 13부터 적용되는 apt 3.0 이상 버전에서는 동일한 메시지가 W: 대신 Warning:로 시작합니다. 접두사 뒤의 텍스트는 동일합니다.

위의 경고는 경미한 사례입니다. apt는 두 선언을 병합하며, 두 선언 모두 동일한 키를 가진 동일한 아카이브를 설명하므로 업데이트는 정상적으로 실행됩니다. 심각한 사례는 모든 작업을 중단시킵니다.

E: Conflicting values set for option Signed-By regarding source https://download.docker.com/linux/ubuntu/ noble: /usr/share/keyrings/docker-archive-keyring.gpg != /etc/apt/keyrings/docker.asc
E: The list of sources could not be read.

이 경우 apt는 두 선언이 하나의 아카이브에 대해 서로 다른 서명 키를 지정하고 있기 때문에 작업을 거부합니다. apt는 동일한 두 선언은 병합할 수 있지만, 두 개의 Signed-By 값 중 하나를 선택하지는 않습니다. 잘못된 키를 선택하면 아카이브 소유자가 서명하지 않은 키로 패키지 서명을 검증하게 되기 때문입니다. 따라서 apt는 소스 파일을 전혀 읽지 않습니다. 파일을 직접 수정하기 전까지는 apt updateapt install 모두 동일한 두 줄의 오류와 함께 실패합니다.

중복이 발생하는 원인

두 형식은 서로 다른 확장자를 가진 별도의 파일에 존재하므로, 디스크상에서 두 파일이 공존하는 것을 막는 요소는 없습니다. apt는 모든 소스 파일을 가져올 인덱스 대상 목록으로 확장하는 시점인, 아주 나중에야 이 중복을 감지합니다. 그 순간까지 docker.listdocker.sources은 서로 관련 없는 두 개의 파일일 뿐입니다.

다음 네 가지 일반적인 상황에서 이 쌍이 생성됩니다.

  • 벤더 설치 스크립트나 오래된 게시물에서 복사한 명령어가 tee 라인이 포함된 /etc/apt/sources.list.d/vendor.list를 작성합니다.
  • 이후 벤더의 패키지가 /etc/apt/sources.list.d/vendor.sources을 릴리스하고 이를 설치합니다.
  • Ubuntu 24.04 이상에서 add-apt-repository는 deb822 형식의 .sources 파일을 작성하므로, 이전에 수동으로 추가했던 .list 형식의 PPA(personal package archive)가 .sources 형식으로 다시 나타납니다.
  • 릴리스 업그레이드 과정에서 배포판 자체의 소스 파일이 deb822 형식으로 다시 작성되었으나, 사용자가 직접 작성한 .list 파일은 그대로 남겨집니다.

각 경로는 개별적으로는 합리적입니다. 중복은 이 중 두 가지 상황이 동일한 시스템에서, 종종 수개월의 간격을 두고 발생할 때 나타나는 결과입니다.

두 가지 형식의 비교

기존 형식은 저장소당 한 줄씩 작성하며, 모든 구성 요소가 위치에 따라 결정됩니다.

deb [arch=amd64 signed-by=/etc/apt/keyrings/docker.asc] https://download.docker.com/linux/ubuntu noble stable

순서는 고정되어 있습니다. 유형(바이너리 패키지는 deb, 소스 패키지는 deb-src), 대괄호로 묶인 옵션, 아카이브의 URI(Uniform Resource Identifier), 스위트(suite), 그리고 하나 이상의 컴포넌트 순입니다. 위치에 따라 의미가 결정되므로, 공백 하나만 잘못 들어가도 apt가 읽어 들이는 내용이 달라집니다.

deb822는 동일한 내용을 이름이 지정된 필드들의 스탠자(stanza)로 표현합니다. 이 이름은 Debian이 패키지 제어 파일에 이미 사용 중인 메일 헤더 스타일인 RFC 822에서 유래했습니다.

Types: deb
URIs: https://download.docker.com/linux/ubuntu
Suites: noble
Components: stable
Architectures: amd64
Signed-By: /etc/apt/keyrings/docker.asc

동일한 저장소, 동일한 키를 사용하며 추가된 내용은 없습니다. 매핑은 직접적입니다. debTypes이 되고, 아카이브 주소는 URIs, 스위트는 Suites, 컴포넌트는 Components이 됩니다. 대괄호 안의 각 옵션은 개별 필드가 되어 signed-by=Signed-By:로, arch=Architectures:로 변환됩니다.

모든 필드는 공백으로 구분된 목록을 허용하므로 필드 이름은 복수형입니다. 하나의 스탠자 내에서 Suites: noble noble-updates noble-backports은 세 개의 개별 deb 줄을 대체합니다. 빈 줄은 스탠자의 끝을 의미하므로, 하나의 .sources 파일에 여러 저장소를 담을 수 있습니다. 또한 deb822는 기존 한 줄 형식에서 다루기 어려웠던 설정들도 지원합니다. 저장소를 비활성화하는 Enabled: no, Trusted, Check-Valid-Until, 그리고 모든 줄을 한 칸 들여쓰고 빈 줄은 점 하나로 표기하여 Signed-By에 직접 붙여넣는 인라인 키 등이 이에 해당합니다.

파일 위치

  • /etc/apt/sources.list: 원본 단일 파일입니다. Ubuntu 24.04 이상 버전에서는 보통 비어 있거나 새로운 위치를 가리키는 주석만 포함되어 있습니다.
  • /etc/apt/sources.list.d/*.list: 한 줄짜리 항목이며, 일반적으로 저장소당 파일 하나를 사용합니다.
  • /etc/apt/sources.list.d/*.sources: deb822 형식의 스탠자(stanza)입니다. Ubuntu 24.04 이상 버전은 배포판 자체 저장소를 이곳의 ubuntu.sources에 보관합니다.
  • /etc/apt/keyrings/: 사용자가 추가한 키가 위치하는 곳입니다. /usr/share/keyrings/에는 패키지를 통해 설치된 키가 저장됩니다.

apt는 .list 또는 .sources로 끝나는 파일만 읽으며, 파일 이름에는 영문자, 숫자, 밑줄, 하이픈, 마침표만 사용할 수 있습니다. 다른 확장자를 가진 파일은 알림과 함께 무시되는데, 이는 아래의 수정 작업에서 중요합니다.

중복 쌍 찾기

디렉터리 목록으로 시작합니다:

ls -l /etc/apt/sources.list.d/
-rw-r--r-- 1 root root  195 Aug  3 09:12 docker.list
-rw-r--r-- 1 root root  254 Aug  9 14:40 docker.sources
-rw-r--r-- 1 root root 2683 Jun 11 08:02 ubuntu.sources

이름은 같지만 확장자가 다른 두 파일이 일반적인 중복 쌍이지만, 파일 이름만 믿어서는 안 됩니다. 파일 내용은 무엇이든 될 수 있으므로 내용을 직접 읽어 확인해야 합니다:

grep -rn -E '^(deb |deb-src |Types:|URIs:|Suites:|Signed-By:)' /etc/apt/sources.list /etc/apt/sources.list.d/
/etc/apt/sources.list.d/docker.list:1:deb [arch=amd64 signed-by=/usr/share/keyrings/docker-archive-keyring.gpg] https://download.docker.com/linux/ubuntu noble stable
/etc/apt/sources.list.d/docker.sources:1:Types: deb
/etc/apt/sources.list.d/docker.sources:2:URIs: https://download.docker.com/linux/ubuntu
/etc/apt/sources.list.d/docker.sources:3:Suites: noble
/etc/apt/sources.list.d/docker.sources:6:Signed-By: /etc/apt/keyrings/docker.asc

동일한 호스트와 동일한 스위트를 가진 두 항목이 중복 쌍입니다. 두 파일 모두 https://download.docker.com/linux/ubuntu을 가리키고 스위트 noble를 사용하므로, 동일한 저장소가 두 번 작성된 것입니다. 또한 Signed-By 경로가 서로 달라 앞서 표시된 Conflicting values 오류가 발생합니다.

이 단계에서는 apt 명령 대신 grep을 사용하십시오. apt는 충돌이 발생하면 소스 목록을 표시하지 못하고 멈추기 때문에, apt-cache policy을 실행하면 원하는 답변 대신 동일한 오류만 출력됩니다.

수정: deb822 파일은 유지하고 레거시 파일은 삭제하십시오

.sources 파일을 유지하십시오. 이 형식은 현재 apt 도구가 작성하는 방식이며, Debian과 Ubuntu 모두 이 방향으로 나아가고 있습니다. 삭제하기 전에 디스크에 다음 두 키 경로 중 어느 것이 존재하는지 확인하십시오:

ls -l /etc/apt/keyrings/ /usr/share/keyrings/ | grep -i docker
-rw-r--r-- 1 root root 4813 Aug  9 14:40 docker.asc

/etc/apt/keyrings/docker.asc만 존재하므로 deb822 파일이 올바른 정보를 담고 있으며, .list 파일은 삭제된 키를 가리키고 있습니다. 유지하려는 파일에 누락된 키가 명시되어 있다면, 먼저 작동하는 경로를 해당 파일에 복사한 뒤 다른 파일을 삭제하십시오.

레거시 파일을 즉시 삭제하는 대신 디렉터리 밖으로 이동시키십시오:

sudo mkdir -p /root/apt-sources-backup
sudo mv /etc/apt/sources.list.d/docker.list /root/apt-sources-backup/
sudo apt update

파일 이름을 docker.list.bak로 변경하여 제자리에 두는 방법도 가능합니다. apt는 알 수 없는 확장자를 무시하기 때문입니다. 하지만 이 경우 apt를 실행할 때마다 다음 메시지가 출력됩니다:

N: Ignoring file 'docker.list.bak' in directory '/etc/apt/sources.list.d/' as it has an invalid filename extension

파일을 다른 곳으로 옮기면 화면에 해당 알림이 나타나지 않으며 백업본도 유지할 수 있습니다. 이후 정상적인 apt update 상태는 다음과 같으며, 두 파일을 가리키는 줄이 없어야 합니다:

Hit:1 http://archive.ubuntu.com/ubuntu noble InRelease
Get:2 https://download.docker.com/linux/ubuntu noble InRelease [48.8 kB]
Get:3 http://security.ubuntu.com/ubuntu noble-security InRelease [126 kB]
Fetched 175 kB in 1s (146 kB/s)
Reading package lists... Done
Building dependency tree... Done
Reading state information... Done
All packages are up to date.

이제 저장소가 편집 후에도 정상적으로 유지되는지 확인하십시오:

apt-cache policy | grep download.docker.com
 500 https://download.docker.com/linux/ubuntu noble/stable amd64 Packages
     origin download.docker.com

공급업체의 문서가 여전히 한 줄짜리 파일을 가정한다면, 해당 파일을 유지하고 .sources 파일을 대신 삭제해도 됩니다. 어떤 경우든 하나의 규칙만 기억하십시오: 특정 아카이브와 제품군을 선언하는 파일은 반드시 하나여야 합니다.

단 하나의 손상된 서드파티 소스가 apt update를 멈추게 하는 이유

인접한 오류는 다르게 보이지만 근본 원인은 동일합니다. apt가 사용할 수 없는 서드파티 소스 때문입니다. 첫 번째 버전은 키가 누락된 경우입니다.

Err:5 https://download.docker.com/linux/ubuntu noble InRelease
  The following signatures couldn't be verified because the public key is not available: NO_PUBKEY 7EA0A9C3F273FCD8
E: The repository 'https://download.docker.com/linux/ubuntu noble InRelease' is not signed.
N: Updating from such a repository can't be done securely, and is therefore disabled by default.

Signed-By 필드가 누락되었거나, 사용 가능한 키가 아닌 파일을 가리키고 있어 apt가 아카이브의 InRelease 파일에 대한 서명을 검증할 수 없습니다. apt는 검증할 수 없는 패키지 목록을 신뢰하는 대신 해당 저장소 전체를 폐기합니다. 키 파일 자체를 확인하십시오.

ls -l /etc/apt/keyrings/docker.asc
gpg --show-keys /etc/apt/keyrings/docker.asc

정상적인 키는 키 ID가 포함된 pub 라인과 공급업체 이름이 명시된 uid 라인을 출력합니다. gpg: no valid OpenPGP data found.는 해당 파일이 키가 아님을 의미하며, 이는 보통 키 URL이 변경되어 다운로드 시 오류 페이지가 저장되었을 때 발생합니다. 키를 다시 가져와 파일을 확인한 다음 apt update을 실행하십시오.

두 번째 버전은 릴리스 업그레이드 후에 발생합니다.

Err:6 https://ppa.launchpadcontent.net/ondrej/php/ubuntu plucky InRelease
  404  Not Found [IP: 10.0.0.80 443]
E: The repository 'https://ppa.launchpadcontent.net/ondrej/php/ubuntu plucky Release' does not have a Release file.

PPA가 해당 제품군에 대해 아무것도 게시하지 않았으므로 서버에 경로가 존재하지 않아 요청이 404를 반환합니다. 다른 저장소는 여전히 업데이트되며 이미 보유한 패키지는 영향을 받지 않습니다. 그러나 실행 결과가 0이 아닌 값으로 종료되므로 apt update의 종료 상태를 확인하는 모든 스크립트는 이제 실행될 때마다 실패를 보고합니다. 이것이 바로 무인 보안 업그레이드가 구성된 서버에서 죽은 소스를 정리해야 하는 이유입니다. 실제 장애는 매일 발생하는 소음 속에 숨어 있기 때문입니다.

나머지 설정에 영향을 주지 않고 특정 소스 비활성화하기

deb822 형식 파일의 경우, 해당 스탠자에 필드를 하나 추가하고 저장합니다:

Types: deb
URIs: https://ppa.launchpadcontent.net/ondrej/php/ubuntu
Suites: plucky
Components: main
Signed-By: /etc/apt/keyrings/ondrej-php.asc
Enabled: no

apt 매뉴얼은 스탠자의 각 줄을 주석 처리하는 것보다 이 방법을 권장하며, 되돌리기도 더 쉽습니다. 한 줄로 된 파일의 경우, 줄 시작 부분에 #를 추가하십시오. 두 형식 모두 /etc/apt/sources.list.d/에서 파일을 이동시키는 방법도 유효하며, 저장소가 영구적으로 삭제된 경우 이 방법을 선택해야 합니다.

sudo apt update를 다시 실행하십시오. 해당 저장소에 대한 Err: 블록이 사라지며, 종료 상태는 0으로 반환됩니다. 이는 다음 줄에서 echo $?을 통해 확인할 수 있습니다.

sudo rm /etc/apt/sources.list.d/*을 사용하여 손상된 소스를 수정하지 마십시오. Ubuntu 24.04 이상 버전에서는 이 명령이 배포판 자체 저장소를 담고 있는 ubuntu.sources을 삭제해 버립니다. 이로 인해 apt는 패키지 목록을 전혀 확보하지 못하게 되며, 분명히 존재하는 소프트웨어에 대해서도 E: Unable to locate package curl 오류를 보고하게 됩니다. 만약 이미 실행했다면, 파일을 다시 작성하십시오:

Types: deb
URIs: http://archive.ubuntu.com/ubuntu/
Suites: noble noble-updates noble-backports
Components: main restricted universe multiverse
Signed-By: /usr/share/keyrings/ubuntu-archive-keyring.gpg

Types: deb
URIs: http://security.ubuntu.com/ubuntu/
Suites: noble-security
Components: main restricted universe multiverse
Signed-By: /usr/share/keyrings/ubuntu-archive-keyring.gpg

이 내용을 /etc/apt/sources.list.d/ubuntu.sources으로 저장하십시오. 이때 noblelsb_release -cs에서 확인한 본인의 릴리스 이름으로 대체해야 합니다. 그 후 sudo apt update을 실행하십시오.

레거시 .list 파일을 deb822 형식으로 변환

2026년 8월부터 apt 3.0 이상 버전은 이를 위한 변환기를 제공합니다. Debian 13, Ubuntu 25.04 및 26.04를 포함한 이후의 모든 릴리스에 이 기능이 포함되어 있습니다. 버전을 확인한 후 다음 명령을 실행하십시오.

apt --version
sudo apt modernize-sources

이 명령은 /etc/apt/sources.list.d/ 아래의 한 줄짜리 파일들을 deb822 형식의 .sources 파일로 다시 작성합니다. 출력 내용을 확인한 다음, 직접 디렉터리 목록을 확인하고 apt update을 실행하여 결과를 신뢰할 수 있는지 검증하십시오. Ubuntu 24.04는 해당 하위 명령이 없는 이전 버전의 apt를 사용하므로, 이 명령을 실행하면 E: Invalid operation modernize-sources이라는 응답이 출력됩니다. 해당 릴리스에서는 위에서 설명한 필드 매핑을 사용하여 수동으로 변환해야 합니다.

현재 apt는 두 형식 모두 읽을 수 있으므로 변환은 선택 사항입니다. 하지만 계속 운영할 서버라면 변환하는 것이 좋습니다. 현재 소스 파일을 작성하는 모든 도구는 deb822 형식을 사용하며, .sources 파일만 존재하는 시스템에서는 이러한 형식의 중복 문제가 발생하지 않기 때문입니다.

서버의 서드 파티 소스를 깔끔하게 유지하기

서드 파티 저장소는 서버에서 가장 빠르게 노후화되는 부분입니다. 각 저장소는 누군가가 사용자의 Ubuntu 릴리스를 위해 패키지를 계속 배포하겠다는 약속이지만, 릴리스 업그레이드를 수행하는 당일 오후에 그 모든 약속이 시험대에 오르게 됩니다.

  • 배포판 패키지로 목적을 달성할 수 없을 때만 서드 파티 저장소를 추가하십시오. 일반적인 Ubuntu 24.04의 LAMP 스택은 서드 파티 저장소가 필요 없습니다. Ubuntu 아카이브는 해당 스택이 사용하는 모든 패키지를 포함하며, 릴리스 수명 동안 보안 업데이트를 제공합니다.
  • 키는 /etc/apt/keyrings/에 저장하고, 벤더당 하나의 파일을 사용하며, 권한은 644로 설정하십시오. 권한이 없는 _apt 사용자가 다운로드를 수행하며 키를 읽어야 하므로, root만 읽을 수 있는 키 파일은 저장소에서 데이터를 가져올 때마다 권한 오류를 발생시킵니다.
  • 각 스탠자(stanza)에서 Signed-By가 해당 파일을 정확히 가리키도록 설정하십시오. /etc/apt/trusted.gpg/etc/apt/trusted.gpg.d/에 위치한 키는 서버의 모든 저장소에 대해 신뢰되므로, 수년 전에 추가된 벤더 키가 어디서든 가져온 패키지를 검증할 수 있게 됩니다.
  • 릴리스 업그레이드 전에 소스 목록을 읽고, 각 벤더가 업그레이드하려는 릴리스를 이미 지원하는지 확인하십시오.

오래된 전역 키링에 있는 키는 업데이트할 때마다 경고를 발생시킵니다:

W: https://download.docker.com/linux/ubuntu/dists/noble/InRelease: Key is stored in legacy trusted.gpg keyring (/etc/apt/trusted.gpg), see the DEPRECATION section in apt-key(8) for details.

해당 키 하나만 별도의 파일로 내보낸 뒤, 스탠자에서 해당 파일을 가리키도록 설정하십시오:

gpg --no-default-keyring --keyring /etc/apt/trusted.gpg --export 7EA0A9C3F273FCD8 | sudo tee /etc/apt/keyrings/docker.gpg > /dev/null
sudo chmod 644 /etc/apt/keyrings/docker.gpg

저장소 스탠자에 Signed-By: /etc/apt/keyrings/docker.gpg를 추가하고 sudo apt update를 실행하십시오. 더 이상 해당 키링에 의존하는 저장소가 없으면 경고가 사라지며, 이후 sudo gpg --no-default-keyring --keyring /etc/apt/trusted.gpg --delete-key 7EA0A9C3F273FCD8을 사용하여 해당 항목을 삭제할 수 있습니다.

한 가지 습관이 가장 큰 고통을 줄여줍니다. do-release-upgrade은 업그레이드 시 서드 파티 소스를 비활성화하고 업그레이드 후에도 꺼진 상태로 둡니다. 이를 하나씩 수동으로 다시 켜는 과정에서 중복 선언이 발생하기 쉽습니다. 시작하기 전에 Ubuntu 24.04에서 26.04로의 업그레이드 가이드를 읽고, 여전히 필요한 저장소가 무엇인지 기록해 두십시오. 새로 구축한 머신이라면, 소스를 올바르게 설정하기 가장 좋은 시점은 새 VPS에서의 처음 10분 동안입니다. 이때는 서버에 Ubuntu가 기본으로 제공한 항목들만 존재하기 때문입니다.

FAQ

Why does apt say a target is configured multiple times?

Because two files under /etc/apt/sources.list.d/ declare the same repository, suite and component. The message names both files with line numbers, such as docker.list:1 and docker.sources:1. apt merges them and carries on, so the update itself still works. The duplicate is worth clearing anyway: as soon as the two files name different signing keys, apt stops with E: Conflicting values set for option Signed-By and refuses to read any source at all, which blocks apt install too.

Should I keep the .list file or the .sources file?

Keep the .sources file. deb822 is what add-apt-repository writes on Ubuntu 24.04 and newer, it holds one named field per setting instead of positional text in square brackets, and it is where the distributions are heading. Before deleting the .list file, confirm the Signed-By path inside the .sources file points at a key that exists, with ls -l /etc/apt/keyrings/. Move the old file out of /etc/apt/sources.list.d/ instead of renaming it inside the directory, because a leftover .bak name makes apt print an ignored-file notice on every run.

How do I turn off one apt repository without removing it?

In a deb822 .sources file, add Enabled: no to the stanza. In a one line .list file, put a # at the start of the line. Either way, run sudo apt update afterwards and the Err: block for that repository disappears. This is the right move when a third party repository has no packages for your Ubuntu release yet and its 404 is making apt update exit non-zero.

Is the one line sources.list format going away?

It is deprecated, not removed. apt still reads .list files and will for a long time, so nothing on your server breaks tomorrow. New tooling writes deb822: Ubuntu 24.04 and newer keep the distribution repositories in /etc/apt/sources.list.d/ubuntu.sources, and add-apt-repository writes .sources files. On apt 3.0 and newer, sudo apt modernize-sources converts the files you still have.

#apt#ubuntu#deb822#package-management#troubleshooting