---
title: "Dependabot의 실제 작동 방식"
published: 2026-01-02T23:44:04.000Z
canonical: https://jeff.news/article/339
---
# Dependabot의 실제 작동 방식

dependabot-core는 MIT 라이선스 stateless Ruby 라이브러리이며, 스케줄링과 상태 관리는 GitHub 비공개 인프라가 담당. 폴링 기반의 비효율과 이벤트 기반 대안까지 분석한 딥다이브

## dependabot-core: MIT 라이선스인데 실제로는 반쪽짜리

- dependabot-core는 MIT 라이선스 Ruby 라이브러리지만 **완전히 stateless**함. 스케줄링, 상태 추적, PR 조율은 전부 GitHub의 비공개 인프라가 담당함
- 2024년 5월에 상용 제한이 있던 Prosperity Public License에서 MIT로 전환됨. 하지만 셀프호스팅하려면 조율 레이어를 직접 만들어야 함

## 33만 줄짜리 Ruby 코드베이스

- 25개 이상 패키지 생태계를 지원하는데, 네이밍이 독특함: rubygems가 아니라 `bundler`, pypi가 아니라 `pip`, `npm_and_yarn` 합체 등. PURL 표준과도 다르고 다른 도구와도 다름
- 생태계마다 4개 핵심 클래스를 구현함: **FileFetcher**(파일 다운로드), **FileParser**(의존성 추출), **UpdateChecker**(레지스트리 조회), **FileUpdater**(PR용 파일 변경 생성)
- 복잡도 편차가 큼. GitHub Actions FileParser는 194줄인데 Gradle은 615줄, npm file_updater_spec 테스트만 4,000줄임

## 네이티브 패키지 매니저에 의존하는 구조

- 업데이트 실행 시 네이티브 패키지 매니저를 shell out으로 호출함. Python Dockerfile이 209줄인 이유는 Python 3.9~3.14까지 6개 버전을 zstd 압축해서 동봉하기 때문
- npm 생태계는 고고학 수준: npm 6을 아직도 같이 배포하고, Yarn 1.x 포크를 `@dependabot/yarn-lib`로 유지 중
- Bundler는 몽키패칭이 심함. SSH URL을 HTTPS로 변환, `$LOAD_PATH` 조작, 가짜 Ruby 버전 주입 등

## Stateless의 대가

- 매 실행마다 repo 클론 → 매니페스트 파싱 → 레지스트리 체크 → 파일 변경 출력 → 종료. 이전 실행의 기억이 전혀 없음
- 자기가 만든 PR도 조회 못함. GitHub이 열린 Dependabot PR 목록을 찾아서 job 정의에 `existing-pull-requests` 필드로 넘겨줌. 보안 어드바이저리도 마찬가지
- job 정의 정보가 PR에 남지 않아서, PR 제목/설명에서 패키지명을 역추출하려면 400줄짜리 정규식 파싱이 필요했다고 함

> [!NOTE]
> GitHub은 Actions 인프라 위에서 Dependabot을 실행함. `dependabot.yml` → job → Docker 이미지가 올라간 러너 → JSON 파일로 job 정의 전달 → API로 PR 생성/수정/닫기

## dependabot-gitlab이 보여주는 스케줄러의 실체

- dependabot-gitlab은 GitHub의 비공개 조율 레이어를 GitLab용으로 오픈소스 구현한 Rails 앱임
- PostgreSQL에 `projects`, `configurations`, `update_jobs`, `update_runs`, `merge_requests`, `vulnerabilities` 테이블이 필요함
- `FOR UPDATE SKIP LOCKED`로 row-level 락을 걸어 이중 스케줄링을 방지하는 구조

## 폴링의 비효율과 이벤트 기반 대안

- 의존성 500개를 일간 스케줄로 돌리면 연간 **182,000번** 레지스트리 조회인데, 대부분 변경 사항이 없음
- 이벤트 기반으로 뒤집으면: lodash 새 버전 나오면 → 그걸 쓰는 repo만 업데이트, CVE 나오면 → 영향받는 repo 즉시 확인
- 이를 위해 레지스트리 피드 구독 + 의존성 인덱스 + webhook 수신기가 필요한데, ecosyste.ms에 이미 의존성 인덱스는 있음. 레지스트리 피드 연결과 코디네이터만 만들면 됨

> [!IMPORTANT]
> Renovate도 동일한 아키텍처임: AGPL CLI는 stateless, 스케줄러는 Mend의 비공개 소스. 다만 Renovate는 라이선스 키로 셀프호스팅용 래퍼를 제공하지만, GitHub의 조율 레이어는 아예 제공되지 않음

## 핵심 포인트

- dependabot-core는 33만 줄 Ruby로 25+ 생태계 지원하지만 완전히 stateless
- 생태계마다 FileFetcher/FileParser/UpdateChecker/FileUpdater 4개 클래스 구현
- 자기가 만든 PR도 조회 못하고 GitHub이 job 정의에 넘겨줘야 함
- 500개 의존성 일간 스케줄 시 연간 18.2만 회 레지스트리 조회의 비효율
- 이벤트 기반 대안으로 ecosyste.ms 의존성 인덱스 활용 가능성 제시
- Renovate도 동일 아키텍처지만 셀프호스팅 래퍼 제공 vs GitHub은 미제공

## 인사이트

오픈소스라고 해서 셀프호스팅이 되는 건 아님. Dependabot의 핵심 가치는 코드가 아니라 조율 인프라에 있음
