- 들어가며 — 한 문장짜리 정책 변경, 그리고 그 문장이 실제로 뜻하는 것
- 재현 가능한 빌드란 정확히 무엇인가
- 스트레스 테스트와 실제 재현 — 이 글에서 가장 중요한 구분
- reproduce.debian.net은 어떻게 도는가
- 게이트: britney가 실제로 막는 것
- 숫자 — 2026년 5월 9일 기준
- 무엇이 재현을 깨뜨리는가
- 정직한 한계
- 그래서 당신의 CI는 무엇을 가져갈 수 있나
- 마치며
- 참고 자료
들어가며 — 한 문장짜리 정책 변경, 그리고 그 문장이 실제로 뜻하는 것
2026년 5월 10일 새벽 4시 47분(UTC), Paul Gevers가 릴리스 팀을 대신해 debian-devel-announce에 메일을 하나 올렸습니다. 제목은 평범하게 "bits from the release team"이었고, 도입부에서 본인이 이렇게 표현했습니다 — 지금은 forky 릴리스 사이클의 절반쯤이고, "코드로는 작은 한 걸음이지만 약속으로는 거대한 도약"(a small step in code, but a giant leap in commitment)을 알리고 싶다고.
그 도약의 본문은 두 문장이었습니다.
Reproducibility
===============
Aided by the efforts of the Reproducible Builds project [1], we've decided it's
time to say that Debian must ship reproducible packages. Since yesterday, we
have enabled our migration software to block migration of new packages that
can't be reproduced [2] or existing packages (in testing) that regress in
reproducibility.
("since yesterday"이므로 실제로 켜진 날은 2026년 5월 9일입니다.)
기술 매체들은 여기서 앞 문장만 떼어 갔습니다. Phoronix는 "Debian Must Now Ship Reproducible Packages", The Register는 "Debian 14 cracks down on unreproducible packages"로 받았습니다. 헤드라인만 보면 Debian이 재현 불가능한 패키지를 이제 안 받는다는 얘기로 읽힙니다.
그런데 뒤 문장을 그대로 읽으면 범위가 훨씬 좁습니다. 막히는 것은 (1) 재현되지 않는 신규 패키지의 이행과, (2) testing에 이미 있으면서 재현 가능성이 회귀한 패키지의 이행. 이 두 가지뿐입니다. 이미 testing에 들어앉은 재현 불가능한 패키지 수백 개는 그대로 있습니다.
이 글은 그 간극에 관한 것입니다. Debian이 실제로 무엇을 켰는지, 그 검사가 기술적으로 어떻게 도는지, 지금 숫자가 어디까지 왔는지, 그리고 이 사례에서 당신의 빌드 파이프라인이 실제로 훔쳐 갈 만한 게 무엇인지.
재현 가능한 빌드란 정확히 무엇인가
Reproducible Builds 프로젝트의 정의는 이렇습니다.
A build is reproducible if given the same source code, build environment and build instructions, any party can recreate bit-by-bit identical copies of all specified artifacts.
여기서 중요한 건 세 조건이 모두 "같을 때"라는 단서입니다. 같은 소스, 같은 빌드 환경, 같은 빌드 명령. 이 조건에서 누가 빌드하든 비트 단위로 같은 산출물이 나와야 한다는 뜻입니다. 재현 가능성은 "아무 환경에서나 같은 결과"가 아니라 "명시된 환경을 재구성했을 때 같은 결과"입니다. 이 구분이 뒤에서 계속 발목을 잡습니다.
왜 하느냐. 문제는 이겁니다 — 자유 소프트웨어의 소스는 공개돼 있지만, 대부분의 사람은 미리 컴파일된 바이너리를 설치합니다. 그리고 그 둘이 실제로 대응하는지는 아무도 모릅니다. 바이너리를 빌드한 사람조차도요. 빌드 머신이 침해당했거나 컴파일러가 백도어를 심었다면, 소스를 아무리 감사해도 잡히지 않습니다. 재현 가능한 빌드는 이 구멍을 메웁니다 — 여러 독립된 당사자가 같은 소스에서 같은 비트를 만들어 내면, 배포된 바이너리가 그 소스에서 나왔다는 걸 검증할 수 있습니다.
다만 이 프로젝트가 스스로 붙이는 단서를 그대로 옮기는 게 공정합니다. Holger Levsen이 5월 발표에서 쓴 표현입니다.
Reproducible Builds are an important building block in making supply chains more secure. Nothing more, nothing less. (Un)secure software build reproducibly still remains (un)secure software.
재현 가능하게 빌드한 취약한 소프트웨어는 여전히 취약한 소프트웨어입니다. 재현 가능성은 "이 바이너리가 이 소스에서 나왔다"만 보장하지, 그 소스가 안전하다는 건 전혀 보장하지 않습니다.
스트레스 테스트와 실제 재현 — 이 글에서 가장 중요한 구분
Debian에는 재현 가능성을 보는 시스템이 둘 있습니다. 그리고 이 둘을 헷갈리면 숫자를 완전히 잘못 읽게 됩니다.
tests.reproducible-builds.org는 2015년부터 돌아온 오래된 쪽입니다. Paul Gevers의 표현으로 이건 스트레스 테스트입니다 — 같은 패키지를 일부러 다른 조건에서 두 번 빌드합니다. 슬라이드가 이 방식을 부르는 이름은 변동성 테스트(variance testing)이고, 목적은 "패키지의 재현을 방해할 수 있는 요인"을 사냥하는 것입니다. 일부러 변수를 흔들어서 약한 고리를 찾아냅니다.
reproduce.debian.net은 2024년에 시작된 새 쪽이고, 이번에 게이트에 연결된 게 이쪽입니다. 목적이 정반대입니다. 슬라이드의 문장 그대로:
The goal of reproduce.debian.net is to replicate the same build process that is used by Debian during package publication -- not to seek out additional sources of variance.
추가적인 변수를 찾아 나서지 않습니다. Debian이 패키지를 배포할 때 쓴 바로 그 빌드 과정을 그대로 복제하려 합니다.
Paul Gevers가 5월 30일 후속 메일에서 이 차이를 다시 강조한 대목이 이 글의 핵심이라 그대로 옮깁니다.
there is a very clear difference in the way reproducibility is tested on https://tests.reproducible-builds.org/ vs https://reproduce.debian.net/. While the former is a stress test, the latter tries, with the info in the .buildinfo file, to reproduce what we ship. It's the latter case what some people call "easy", but it's also what matters to our users: can the binaries they use be reproduced.
후자를 두고 어떤 사람들은 "쉽다"고 부른다는 걸 그가 먼저 인정합니다. 그리고 곧바로 반박합니다 — 쉽든 아니든, 사용자에게 중요한 건 그쪽이라고. 사용자가 실제로 쓰는 그 바이너리가 재현되는가.
이건 엔지니어링 판단으로서 곱씹을 만합니다. 게이트를 스트레스 테스트에 걸었다면 통과율이 훨씬 낮았을 테고, 정책은 몇 년 더 미뤄졌을 겁니다. 대신 "쉬운" 쪽에 걸어서 지금 켤 수 있었습니다. 완벽한 기준을 기다리는 대신 지금 강제할 수 있는 기준을 골랐다는 뜻이고, LWN 기사 댓글에서 나온 지적도 정확히 이 지점입니다 — 이 요구사항의 범위는 "Debian의 빌드 환경 인스턴스 안에서 빌드하는 것"에 한정되고, 재현 가능성은 예/아니오의 이분법이 아니라 스펙트럼이라는 것.
reproduce.debian.net은 어떻게 도는가
구조 자체는 정직하고 단순합니다. rebuilderd 인스턴스입니다.
rebuilderd는 kpcyrd가 Rust로 쓴 도구로, 2019년 Marrakech 서밋에서 개발이 시작됐고 Arch, Fedora, Debian, Tails의 재빌드를 지원합니다. Arch용 인스턴스가 5개쯤, Fedora용이 1개, Debian용이 5~6개 존재합니다. 즉 Debian 전용으로 새로 만든 물건이 아니라, 이미 다른 배포판에서 굴러가던 걸 그대로 가져다 쓴 겁니다.
reproduce.debian.net이 하는 일은 이렇습니다.
Attempts to bit-for-bit identically rebuild each Debian binary package found in the distribution archive, using the .buildinfo file produced when the buildd originally built the package. For each distributed package, rebuilderd calls debrebuild that calls debootsnap, mmdebstrap and finally sbuild to build that package within a user namespace.
여기서 축이 되는 게 .buildinfo 파일입니다. Debian의 빌드 데몬(buildd)이 패키지를 빌드할 때, 그 빌드 환경을 기록한 control 파일을 같이 남깁니다. 어떤 패키지가 어떤 버전으로 설치돼 있었는지가 여기 적힙니다. 재빌드는 이 파일을 읽어서 그 환경을 되살린 다음, 그 안에서 다시 빌드하고, 결과를 배포된 바이너리와 비트 단위로 비교합니다.
ftp.debian.org가 배포 중인 바이너리 패키지
│
│ buildd가 원래 빌드할 때 남긴 .buildinfo
│ (= 그때 그 빌드 환경의 기록)
▼
rebuilderd
└─► debrebuild ─► debootsnap ─► mmdebstrap ─► sbuild
└─ user namespace 안에서 재빌드
│
▼
배포된 바이너리와 비트 단위 비교
│
├─► 같다 ─► good
└─► 다르다 ─► bad (diffoscope로 무엇이 다른지 확인)
곁가지지만 재미있는 사실 하나. 슬라이드에서 Holger는 .buildinfo가 사실상 SBOM이라고 짚습니다 — 요즘 다들 얘기하는 Software Bill of Materials가, Debian에서는 2014년에 설계된 .buildinfo 파일과 대략 같은 물건이라는 것입니다.
커버리지는 2026년 5월 9일 발표 기준으로 이렇습니다. trixie 이후로 main과 non-free-firmware 전체를 담고 있고, 수록 스위트는 experimental, unstable, forky, trixie, trixie-security, trixie-updates, trixie-proposed-updates, trixie-backports입니다. 아키텍처는 s390x와 loong64를 제외한 전부(trixie에는 armel도 포함). 발표 시점 기준 아키텍처마다 인스턴스를 따로 띄워 8개를 굴리고 있었습니다.
loong64가 빠져 있다는 게 우연이 아닙니다. 같은 5월 10일 메일의 다른 섹션에 따르면 loong64는 그 2주 전에 아카이브에 막 추가된 아키텍처였고, 그래서 온갖 패키지를 전 아키텍처에서 다시 빌드해야 했으며 CI 큐가 밀려 있으니 인내심을 갖고 기다려 달라는 안내가 붙어 있었습니다. 새 아키텍처가 들어오면 재현 가능성 인프라도 뒤따라가야 한다는 뜻입니다.
게이트: britney가 실제로 막는 것
Debian에서 패키지는 unstable에 업로드된 뒤 일정 조건을 만족하면 testing으로 "이행"(migration)합니다. 이 이행을 결정하는 소프트웨어가 britney이고, 다음 안정 릴리스는 testing이 얼어붙어서 만들어집니다. 즉 testing 이행을 막는다는 건 다음 릴리스에 못 들어간다는 뜻입니다.
발표 슬라이드의 표현은 이렇습니다.
britney now finally has been configured to not let (most) unreproducible packages migrate to testing!
여기서 눈여겨볼 단어는 괄호 안의 most입니다. 전부가 아닙니다. 슬라이드가 스스로 나열한 실제 규칙은 이렇습니다.
이행이 막히는 경우:
- 재현되지 않는 신규(NEW) 패키지
- 회귀 — 전에는 재현되던 패키지가 재현되지 않게 된 경우
그리고 곧바로 붙는 단서들:
- 요청하면 풀어 줄 수 있다(can be unblocked on request)
- allowlist가 가능하다 (현재 예: udeb)
- 특정 아키텍처의 결과는 무시할 수도 있다
릴리스 팀의 입장은 슬라이드에 이렇게 정리돼 있습니다.
- 모든 패키지는 재현 가능해야 한다
- 하지만 지금은 신규 재현 불가 패키지와 회귀만 막는다
- 재현 불가능한 패키지는 아직 RC 버그로 취급되지 않으며, 아직 자동 삭제되지도 않는다
마지막 줄이 이 정책의 실제 강도를 말해 줍니다. Debian에서 RC(release-critical) 버그는 릴리스를 막는 등급이고, 오래 방치되면 패키지가 testing에서 자동으로 빠집니다. 재현 불가능은 아직 그 등급이 아닙니다. 그러니까 이미 들어가 있는 재현 불가능한 패키지들은 사실상 조부 조항으로 남습니다.
그리고 발표자 본인이 forky에 대해 이렇게 못박습니다.
for forky we will be rather liberal with accepting unreproducible packages.
forky에서는 재현 불가능한 패키지를 받아들이는 데 꽤 관대하게 가겠다는 겁니다. 다음 릴리스인 duke에 대해서는 슬라이드가 질문 형태로 열어 둡니다 — main에서 재현 불가능한 패키지 0을 목표로 선언할까요? 물음표가 붙어 있고, 정해진 게 아닙니다.
Paul Gevers가 5월 30일에 보낸 후속 메일도 같은 방향입니다. 원래 발표에서 빠뜨렸다며 이렇게 덧붙였습니다.
I forgot to mention that while we of course want all packages in testing to reproduce, we recognize there will be exceptions (which numbers hopefully will reduce over time). If you think your package needs an exception, please file a bug against the release.debian.org pseudo package (option 4 "other" in reportbug for now) and explain why you're not able to fix the issue.
예외는 있을 것이고, 필요하면 release.debian.org 의사 패키지에 버그를 올려 왜 못 고치는지 설명하라는 것입니다. 예외 신청 창구가 공식적으로 열려 있습니다.
정리하면 이 게이트는 래칫입니다. 문턱을 한 칸 올린 뒤 다시 내려오지 못하게 막는 장치. "지금부터 새로 들어오는 건 재현돼야 하고, 이미 되던 건 깨지면 안 된다." 존재하는 부채를 청소하는 장치가 아니라, 부채가 더 늘지 않게 막는 장치입니다. 이게 덜 인상적인 얘기로 들린다면, 반대로 생각해 보십시오 — 수만 개의 패키지를 굴리는 프로젝트에서 회귀를 막는 장치 없이 재현율을 올리는 건 밑 빠진 독입니다.
Holger의 슬라이드에 이 정치적 성격이 아주 솔직하게 적혀 있습니다.
100% reproducible is a political decision and nothing technical. We need to change debian-policy!
100% 재현 가능은 기술적 문제가 아니라 정치적 결정이라는 것. debian-policy는 2017년부터 패키지가 재현 가능하게 빌드돼야 한다고 "should"로만 적고 있고, 이걸 "must"로 바꾸는 건 정책 개정 절차입니다. 그래서 릴리스 팀이 정책보다 먼저 이행 게이트로 강제하는 길을 택했습니다. 슬라이드의 표현으로는 "In practice the release team will enforce this before it becomes official Debian policy."
숫자 — 2026년 5월 9일 기준
아래는 전부 Holger Levsen의 MiniDebConf Hamburg 2026 발표(2026년 5월 9일) 슬라이드에 적힌 reproduce.debian.net 수치입니다. 발표 시점의 스냅샷이고, 지금은 달라졌을 수 있습니다.
forky (다음 안정 릴리스가 될 스위트):
| 아키텍처 | good | bad sources |
|---|---|---|
| arch:all | 98.3% | 419 |
| amd64 | 97.2% | 512 |
| arm64 | 97.7% | 408 |
| armhf | 97.1% | 507 |
| i386 | 97.0% | 523 |
| ppc64el | 91.1% | 531 |
| riscv64 | 91.6% | 338 |
비교용으로 다른 스위트:
| 스위트 / 아키텍처 | good | bad sources |
|---|---|---|
| unstable arch:all | 98.0% | 515 |
| unstable amd64 | 97.6% | 469 |
| trixie arch:all | 91.7% | 2001 |
| trixie amd64 | 95.6% | 803 |
| trixie-backports arch:all | 79.5% | 53 |
| trixie-backports amd64 | 83.5% | 32 |
| trixie-security arch:all | 82.9% | 17 |
읽을 거리가 몇 개 있습니다.
주력 아키텍처와 나머지의 격차. amd64는 97.2%인데 ppc64el은 91.1%입니다. 6.1%포인트 차이입니다. 재현 가능성은 아키텍처마다 따로 달성해야 하는 속성이고, 관심과 인력이 몰리는 아키텍처가 먼저 올라갑니다. 게이트가 "특정 아키텍처의 결과는 무시할 수도 있다"는 단서를 단 이유가 이 표에 보입니다.
backports가 낮다. trixie-backports는 79.5% / 83.5%로 눈에 띄게 낮습니다. 안정 릴리스에 새 버전을 얹는 통로라 빌드 환경이 어긋나기 쉽다는 뜻으로 읽힙니다.
스트레스 테스트와 실제 재현이 거의 같은 값으로 수렴했다. 슬라이드에 "The diff between theory and practice today?"라는 제목으로 두 숫자가 나란히 놓여 있습니다 — CI(스트레스 테스트)에서 96.6%, amd64.reproduce.debian.net(실제 재현)에서 96.54%. 앞에서 후자를 "쉬운" 쪽이라고 했는데, 실제로는 두 값이 0.06%포인트 차이입니다. 물론 두 시스템은 대상 스위트와 집계 방식이 달라 엄밀한 동일 비교는 아니지만, "쉬운 테스트라 숫자가 부풀려진 것 아니냐"는 의심에 대한 반증으로는 충분히 흥미롭습니다. 슬라이드는 여기에 "we've only been doing this for 10 months & the freeze..."라는 단서를 답니다.
개인 시스템에서 직접 확인할 수 있다. debian-repro-status 패키지를 설치하면 지금 내 시스템에 깔린 패키지 중 몇 개가 재현되지 않는지 알려 줍니다. 발표자 본인 시스템의 출력이 슬라이드에 있습니다.
$ sudo apt install debian-repro-status
$ debian-repro-status
INFO debian-repro-status > 60/2268 packages are not reproducible.
INFO debian-repro-status > Your system is 97.35% reproducible.
이 도구가 제 눈에는 가장 인상적이었습니다. 재현 가능성이 웹사이트의 대시보드 숫자가 아니라, 내 노트북에서 한 줄로 확인되는 속성이 됐다는 뜻이니까요.
무엇이 재현을 깨뜨리는가
슬라이드가 이유를 나열하는 방식이 그 자체로 농담입니다.
Common reasons for unreproducibilities:
timestamps, timestamps, timestamps
timestamps, timestamps, timestamps
build paths, build paths
all the rest
(and somewhere in there there might be backdoors...)
타임스탬프가 여섯 번, 빌드 경로가 두 번, 나머지 전부가 한 번. 지난 12년간 이 프로젝트가 무엇과 싸웠는지에 대한 요약입니다. 그리고 마지막 줄이 왜 이 지루한 싸움을 하는지 말해 줍니다 — 그 어딘가에 백도어가 있을지도 모른다.
타임스탬프에 대한 표준 해법이 SOURCE_DATE_EPOCH입니다. 명세는 이렇습니다.
SOURCE_DATE_EPOCH specifies the last modification of something, usually the source code, measured in the number seconds since the Unix epoch, ie. January 1st 1970, 00:00:00 UTC.
배포판이 이 환경 변수를 중앙에서 설정하면, 빌드 도구들이 현재 시각 대신 이 값을 박습니다. 다만 Reproducible Builds 문서 본인이 다는 단서를 같이 읽어야 합니다 — "Setting the system clock is not enough for reliable reproducible builds." 시계를 고정하는 걸로는 부족합니다. SOURCE_DATE_EPOCH는 타임스탬프 문제만 다루고, 비결정적인 빌드 과정이나 불안정한 의존성에서 오는 변동은 손대지 못합니다.
규모 감각을 위해: 2026년 5월 8일 기준 CI 통계에 따르면 재현 가능성 관련 버그 4,347개가 수정됐고(대부분 업스트림에 반영), 262개 패치가 대기 중입니다. 12년간 하루 몇 건씩 꾸준히 밀어 온 결과가 지금의 97%입니다. 마법은 없었습니다.
그리고 아직 안 된 것들의 목록이 겸손하게 만듭니다. 슬라이드는 가장 인기 있는 패키지 1,337개 중 재현되지 않는 소스 패키지가 22개라고 밝히면서 이름을 답니다 — ffmpeg, vlc, bluez, nss, grub2, graphviz, pipewire, qtwebengine, bind9 등. 더 아픈 건 build-essential 의존 관계에 있는 5,500개 중 96개가 재현되지 않는다는 목록입니다. 거기 rustc, python3.12, python3.13, ghc, gcc-13-cross, qemu, valgrind, chromium이 들어 있습니다.
컴파일러와 인터프리터 자신이 아직 재현되지 않습니다. 이게 왜 어려운 일인지에 대한 가장 압축적인 설명입니다.
그렇다고 진전이 없는 것도 아닙니다. 2026년 6월 보고서에 따르면 debian-installer 업로드가 처음으로 재현에 성공했고, debian:sid 컨테이너는 100% 재현 가능해졌습니다. diffoscope는 그 한 달에만 319, 320, 321, 322, 323 다섯 버전이 나왔습니다.
정직한 한계
호의적으로 읽고 싶은 마음을 접고 정리하면 이렇습니다.
헤드라인이 정책보다 셉니다. "Debian must ship reproducible packages"는 강한 문장이지만, 켜진 장치는 신규 패키지와 회귀만 막습니다. 기존 재현 불가능 패키지는 그대로 있고, RC 버그도 아니고, 자동 삭제도 없습니다. forky에서는 관대하게 가겠다고 발표자가 명시했습니다.
빠져나갈 문이 여럿입니다. 요청 시 unblock, allowlist(현재 udeb), 아키텍처별 결과 무시, release.debian.org에 예외 신청. 각각 합리적인 장치지만, 합쳐 놓고 보면 게이트의 실효 강도는 릴리스 팀의 재량에 달려 있습니다.
검사 범위가 좁습니다. reproduce.debian.net은 Debian의 빌드 환경을 그대로 복제해서 비교합니다. 다른 빌드 경로, 다른 커널, 다른 로케일에서도 재현되는지는 이 게이트가 묻지 않습니다. LWN 댓글의 지적대로 "재현 가능하다"는 이분법이 아니라 스펙트럼이고, 이 게이트는 그 스펙트럼의 한 지점을 고른 것입니다. 그 지점이 사용자에게 가장 중요한 지점이라는 Paul Gevers의 반론도 타당하지만, 두 명제는 동시에 참입니다.
도구가 아직 거칠습니다. Paul Gevers 본인이 후속 메일에서 인정한 대목입니다 — NT_GNU_BUILD_ID 차이 때문에 재현되지 않는 패키지의 경우, 현재 diffoscope 로그는 이상적이지 않다고. 실제 차이가 잘려 나가고 dbgsym 패키지에서만 보일 텐데 그건 현재 자동 비교 대상이 아니라는 것입니다. 즉 메인테이너가 "왜 안 되는지"를 보려 해도 로그가 답을 안 주는 경우가 있습니다.
신뢰가 한 곳에 몰려 있습니다. 이건 발표자가 스스로 제기한 문제입니다. 슬라이드에 이렇게 적혀 있습니다 — "Because do you really want to put all your trust in me???" 지금은 reproduce.debian.net이라는 특정 인스턴스의 판정을 믿는 구조입니다. 재현 가능한 빌드의 원래 취지는 여러 독립된 당사자가 각자 검증하는 것인데, 검증자가 하나면 그 취지가 절반만 실현됩니다. 그래서 슬라이드는 rebuilderd 인스턴스를 더 세워 달라고 요청하고, 향후 과제로 투명성 로그를 이용한 신뢰 분산과 비교를 적어 두었습니다.
그래서 당신의 CI는 무엇을 가져갈 수 있나
이 사례에서 일반화할 수 있는 게 몇 가지 있습니다. 다만 Debian은 수만 개의 패키지와 12년치 인력을 쌓은 배포판이고, 당신의 서비스는 아닙니다. 그대로 옮기면 안 됩니다.
가져갈 만한 것 1 — 래칫이 목표보다 강합니다. Debian이 실제로 켠 건 "전부 재현되게 하라"가 아니라 "새 부채를 막고 회귀를 막아라"였습니다. 이건 재현 가능성에만 해당하는 얘기가 아닙니다. 테스트 커버리지든 타입 커버리지든 린트 경고든, 존재하는 부채를 한 번에 청소하려는 시도는 대개 실패하고 회귀를 막는 게이트는 대개 성공합니다. 기존 위반을 allowlist에 넣고 동결한 뒤, 신규와 회귀만 막으십시오. Debian이 udeb를 allowlist에 넣은 것과 같은 방식입니다.
가져갈 만한 것 2 — 빌드 환경을 기록하는 파일. .buildinfo의 발상은 단순합니다. 빌드할 때 무엇이 어떤 버전으로 있었는지를 산출물 옆에 남긴다. 이게 있으면 나중에 그 환경을 되살릴 수 있고, 없으면 재현은 시작조차 못 합니다. 요즘 SBOM이라 불리는 것과 대략 같은 물건이고, Debian은 이걸 2014년에 만들었습니다. lockfile을 커밋하고, 베이스 이미지를 태그가 아니라 다이제스트로 고정하고, 툴체인 버전을 기록하는 것이 같은 계열의 실천입니다.
가져갈 만한 것 3 — SOURCE_DATE_EPOCH. 타임스탬프가 가장 흔한 범인이라는 게 12년치 데이터의 결론입니다. 도구가 이 환경 변수를 지원한다면 켜는 비용이 거의 없습니다.
가져갈 만한 것 4 — 재현 검사는 별도 잡으로. rebuilderd가 빌드 파이프라인 안에 있는 게 아니라 배포된 산출물을 밖에서 다시 만들어 본다는 구조가 중요합니다. 재현 검사를 메인 CI에 인라인으로 넣으면 빌드 시간이 두 배가 되고, 결국 꺼집니다. 배포 후에 비동기로 재빌드하고 비교하는 별도 파이프라인이 현실적입니다.
하지 말아야 할 것. 솔직하게 말하면, 대부분의 팀에게 비트 단위 재현 가능성은 과잉입니다.
- 배포 산출물을 남이 검증할 필요가 없다면 — 사내 서비스를 컨테이너로 굴리고 이미지 다이제스트를 고정해 쓴다면 — 재현 가능성이 주는 추가 보증이 크지 않습니다. 이미 "그 다이제스트가 그 다이제스트"인 건 확실하니까요.
- 재현 가능성이 값을 하는 건 배포 대상이 다수의 신뢰하지 않는 제3자이고, 그들이 소스와 바이너리의 대응을 독립적으로 검증해야 할 때입니다. 배포판, 브라우저, 지갑, 메신저, 펌웨어. Debian이 12년을 쓴 이유가 이겁니다.
- 그 중간에 있다면, 전부 재현 대신 핵심 산출물 하나만 재현 대상으로 잡는 게 낫습니다. Debian도 트리 전체를 한 번에 하지 않았습니다.
- 그리고 재현 가능성을 보안 대책으로 파는 건 부정직합니다. 앞의 문장을 다시 인용하면, 재현 가능하게 빌드한 취약한 소프트웨어는 여전히 취약한 소프트웨어입니다.
마치며
2026년 5월 9일에 Debian에서 일어난 일은 이렇게 요약됩니다. britney가 reproduce.debian.net의 판정을 읽기 시작했고, 재현되지 않는 신규 패키지와 재현 가능성이 회귀한 패키지의 testing 이행을 막기 시작했습니다. 발표 기준 forky의 amd64 재현율은 97.2%이고, 재현되지 않는 소스 패키지가 512개 남아 있습니다.
헤드라인이 말하는 것보다 좁은 조치입니다. 예외 창구가 열려 있고, allowlist가 있고, 아키텍처별로 무시할 수 있고, 기존 재현 불가능 패키지는 그대로 남아 있고, forky에서는 관대하게 가겠다고 명시했습니다. 검사 범위도 Debian의 빌드 환경을 복제하는 데 한정됩니다.
그런데도 이게 의미 있는 이유는, 12년 동안 "should"였던 게 처음으로 실제로 무언가를 막기 시작했기 때문입니다. 정책 문서를 고치는 데는 프로젝트 차원의 합의 절차가 필요하지만, 게이트를 켜는 데는 britney 설정을 바꾸면 됩니다. 원 발표의 표현을 빌리면 코드로는 작은 한 걸음입니다. 릴리스 팀은 그 작은 쪽을 먼저 했고, 슬라이드의 표현대로 "정책이 되기 전에 실무에서 먼저 강제"하는 길을 택했습니다.
여기서 배울 건 재현 가능성 자체보다 그 방법론일지도 모릅니다. 목표는 100%라고 선언하되, 켜는 건 래칫 한 칸. 완벽한 기준을 기다리는 대신 지금 강제할 수 있는 기준을 고르고, 그게 "쉬운" 기준이라는 비판을 정면으로 받아들인 다음, 그래도 사용자에게 중요한 건 이쪽이라고 답하는 것. duke에서 0을 목표로 할지는 아직 물음표로 남아 있습니다.
참고 자료
- bits from the release team — Paul Gevers, debian-devel-announce, 2026년 5월 10일 (원 발표)
- Re: bits from the release team — Paul Gevers, debian-devel, 2026년 5월 30일 (예외 절차와 두 테스트 시스템의 차이)
- reproduce.debian.net: Reproducing Debian in the real world — Holger Levsen, MiniDebConf Hamburg 2026, 2026년 5월 9일 (모든 수치의 출처)
- Reproducible Builds in May 2026 — 월간 보고서
- Reproducible Builds in June 2026 — 월간 보고서 (debian-installer, debian:sid 컨테이너, diffoscope 319~323)
- Debian to require reproducible builds — LWN, 2026년 5월 11일
- reproduce.debian.net — 재빌드 판정 대시보드
- rebuilderd — kpcyrd, Rust로 작성된 재빌드 데몬
- SOURCE_DATE_EPOCH 명세
- 재현 가능한 빌드의 정의
- Debian Release Team: Debian Must Now Ship Reproducible Packages — Phoronix
- Debian 14 cracks down on unreproducible packages — The Register
현재 단락 (1/145)
2026년 5월 10일 새벽 4시 47분(UTC), Paul Gevers가 릴리스 팀을 대신해 debian-devel-announce에 메일을 하나 올렸습니다. 제목은 평범하게 "...