크롤러 프로세스와 스케줄이 정상이어도 일부 패키지나 버전은 빠질 수 있었습니다. 일시적인 HTTP 오류를 완료로 기록하거나, 레지스트리의 대소문자를 잘못 다루거나, 피드에서 한 번 놓친 버전을 다시 확인하지 않는 식으로 원인이 달랐습니다.
한 언어의 수정법을 다른 언어에 그대로 적용할 수 없어서 각 레지스트리 원본과 DB를 직접 비교했습니다. RubyGems에서는 이 비교를 주간 작업으로 남겼고, 백필 뒤 누락 후보가 101개에서 4개로 줄었는지 같은 명령으로 다시 확인했습니다.
1배경
제품 데이터는 Go, Java/Maven, npm, PyPI, RubyGems, Composer, CocoaPods, NuGet 등 언어별 패키지 크롤러에서 시작합니다. 저장소와 실행 방식이 서로 달랐고, 같은 PRODUCT_KEY도 레지스트리와 DB에서 표현이 달라 단순 비교로는 누락 여부를 판단하기 어려웠습니다.
일시 오류 뒤에도 작업행이 완료로 남으면 다음 배치가 그 패키지를 다시 보지 않았습니다.
생태계마다 제품 테이블과 대소문자 규칙이 달라, 잘못된 스키마를 보면 누락이 0건처럼 보이기도 했습니다.
기존 데이터를 새 플랫폼으로 옮길 때는 컬럼과 JSON 형식을 그대로 지켜야 했습니다.
2무엇을 어떻게 확인했나
① 원본 목록레지스트리의 패키지·버전 목록 확보
→
② DB 비교생태계별 실제 테이블과 차집합 계산
→
③ 재검증404·삭제·별칭과 실제 누락 분리
→
④ 수정·백필크롤러를 고친 뒤 같은 목록으로 재확인
12개 생태계의 수집 루프와 완료 조건을 같은 체크리스트로 읽었습니다. 그중 8개 생태계는 레지스트리 원본과 제품 DB를 전수 비교해 실제 누락 수를 따로 계산했습니다.
비교 기준은 레지스트리별로 따로 세웠습니다. Maven은 중앙 인덱스와 메타데이터를 다시 요청했고, Go는 모듈 경로·별칭·하위 패키지를 구분했으며, RubyGems는 공개 버전 목록을 사용했습니다.
Java/Maven 크롤러는 Java/Spring 구현을 Python으로 옮겼습니다. DB 적재 컬럼 순서와 JSON 인코딩을 byte-compatible하게 맞추고 162개 테스트를 통과했으며, 인덱스에서 버전 뼈대를 넣는 작업과 POM 메타데이터를 채우는 작업을 분리했습니다.
수정안은 바로 반영하지 않았습니다. 기존 데이터 포맷, 작업 상태값, 재시도 경로를 확인하고 단위 테스트나 소량 스모크 테스트가 붙은 변경만 골라 적용했습니다.
플랫폼 이관용 transformer에서는 컬럼과 JSON 인코딩이 기존 크롤러 출력과 달라지지 않는지 확인했습니다.
3실제로 잡힌 누락
누락 원인은 생태계마다 달랐습니다. 완료 상태를 너무 일찍 기록한 경우, 대소문자와 escape 규칙을 놓친 경우, 레지스트리 피드가 메타데이터보다 먼저 도착한 경우를 각각 다른 방식으로 고쳤습니다.
대문자가 들어간 버전의 .mod·.info 요청에서 escape가 빠진 오류 패턴이 45,508건임을 확인했습니다. 세 호출 경로를 고치고 회귀 테스트 4개를 추가했습니다. 당시 상태 34의 268건은 PROCESSED=0으로 되돌렸습니다.
반복된 결함은 7종으로 기록했습니다. 증분 수집 미동작, 완료 상태 오기록, product_key 인코딩, organization·release date 누락, LICENSE 컬럼 혼용 등이었습니다.
Maven 중앙 인덱스의 제품 838,155개와 DB를 비교해 실제 누락 1,689개를 확인했습니다. 메타데이터 요청과 디렉터리 목록을 함께 사용해 거짓 누락을 걸러냈습니다.
NPM은 전체 약 3,825,366개 패키지 대비 누락 890개를 약 104분 검사로 식별하는 일일 점검 체계로 운영합니다.
RubyGems는 공개 버전 목록과 수집·배포 DB를 비교해 gem 48개·1,310개 버전을 백필했습니다. 같은 검사를 주간 작업으로 두고 남은 후보가 101개에서 4개로 줄었는지 확인했습니다.
4결과
Go 45,508건 영향 범위 — 세 호출 경로 수정·회귀 테스트 4개, 당시 상태 34의 268건 복구
Maven 1,689개 — 중앙 인덱스와 DB 대조에서 확인한 실제 누락 제품
RubyGems 101→4개 — 백필 뒤에도 주간 전수 비교를 남겨 재발 여부 확인
48개 gem·1,310버전 — 기존 크롤러와 같은 형식으로 멱등 백필
Java/Maven Python 전환 — 인덱스 적재와 POM 메타데이터 수집을 분리
12개 생태계 문서 — 저장소별 시작점, 수집 루프, DB 위치, 수정 이력을 코드와 함께 확인
5역할
각 언어 담당자는 자기 크롤러의 평소 수정과 운영을 맡았습니다. 제 몫은 12개 생태계에 같은 누락 점검 기준을 적용하고, 레지스트리와 DB를 비교하는 도구를 만들며, 반복되는 결함을 7종으로 기록하는 일이었습니다. Java/Maven Python 전환과 플랫폼 이관용 transformer는 직접 맡았습니다. 다른 담당자가 고친 크롤러는 테스트 결과와 출력 데이터 형식을 함께 확인했습니다.
Java/Maven Python 전환, transformer, 누락 점검 도구는 직접 만들었고, 나머지 크롤러는 공통 점검 기준 적용과 수정 검토로 참여했습니다.