Renovate Bot 실전 설정 — groupName·schedule·automerge로 의존성 PR 노이즈를 80% 줄이는 방법
Renovate를 기본값 그대로 도입했을 때 하루 30개씩 PR이 생성되는 일을 직접 경험했습니다. 팀원들의 첫 반응은 "이 봇 좀 꺼줄 수 있어요?"였고, 며칠에 걸쳐 설정을 하나씩 뜯어봐야 했습니다.
핵심은 세 가지 파라미터의 조합입니다. groupName으로 관련 패키지를 묶어 PR 수를 줄이고, schedule로 PR 생성 시점을 팀의 리뷰 주기에 맞추고, automerge로 위험도가 낮은 업데이트는 CI가 검증 후 처리하도록 위임하는 것입니다. 설정을 제대로 이해하고 쓰면 의존성 PR 노이즈를 최대 80% 수준까지 줄일 수 있으며, 패키지가 수십 개 이상 흩어진 모노레포에서 그 효과가 더욱 두드러집니다.
Renovate Bot이란
Renovate Bot은 Mend.io(구 WhiteSource)가 개발·유지보수하는 오픈소스 의존성 자동 업데이트 도구입니다. npm, pip, Maven, Gradle, Cargo, Helm, Dockerfile, GitHub Actions 등 수십 종 이상의 패키지 매니저를 단일 설정 파일로 관리할 수 있다는 점이 경쟁 도구와의 가장 큰 차이입니다. 지원 매니저 목록 전체는 공식 문서 Supported Managers에서 확인할 수 있습니다.
GitHub, GitLab, Bitbucket, Azure DevOps, Gitea를 모두 지원하며 운영 방식은 두 가지입니다. GitHub Marketplace App을 설치하는 관리형 방식은 별도 서버 운영 없이 바로 시작할 수 있고, self-hosted 방식은 GitHub Actions나 GitLab CI에서 직접 실행해 기업 보안 정책에 맞게 통제할 수 있습니다.
설정 파일은 저장소 루트의 renovate.json이 기본입니다. 모노레포라면 루트에 하나만 두고 모든 하위 패키지를 중앙에서 제어합니다.
Renovate vs Dependabot
여러 실무 사례에서 공통으로 권장되는 선택 기준은 비교적 명확합니다. 모노레포, 멀티플랫폼, 세밀한 그룹화 정책이 필요하면 Renovate, 단순한 GitHub 단일 저장소라면 Dependabot이 적합합니다.
| 비교 항목 | Renovate | Dependabot |
|---|---|---|
| 지원 플랫폼 | GitHub, GitLab, Bitbucket, Azure DevOps, Gitea | GitHub만 |
| 그룹화 | groupName + glob/정규식으로 세밀하게 제어 |
제한적 |
| 모노레포 지원 | 강력 (matchFileNames, additionalBranchPrefix) |
기본 수준 |
| 지원 패키지 매니저 | 수십 종 이상 | npm, pip 등 일부 |
| automerge 세분화 | 패키지별·업데이트 타입별 제어 가능 | 제한적 |
| 학습 곡선 | 높음 | 낮음 |
두 도구를 동시에 사용하면 동일 패키지에 PR이 중복 생성되므로 반드시 하나만 선택해야 합니다. Dependabot을 비활성화하려면 .github/dependabot.yml을 제거하거나 Security 탭에서 version updates만 끄면 됩니다.
작동 방식
Renovate가 실행되면 세 단계를 거칩니다.
감지 단계에서 저장소 내 모든 의존성 파일을 파싱해 현재 버전과 최신 버전을 비교합니다. 그룹화·필터링 단계에서 packageRules의 groupName, matchPackageNames, matchUpdateTypes 등을 적용해 관련 패키지를 묶습니다. 마지막으로 생성·자동머지 단계에서 설정된 시간 창에서만 PR 또는 브랜치를 생성하고, 조건 충족 시 자동 병합합니다.
핵심 제어 파라미터 세 가지
솔직히 이 세 가지만 제대로 이해해도 80%는 해결됩니다.
groupName
groupName은 여러 패키지를 하나의 PR과 브랜치로 묶는 레이블입니다. react, react-dom, @types/react가 각각 업데이트됐을 때 PR 3개가 아닌 "React ecosystem" PR 1개로 묶어줍니다.
{
"packageRules": [
{
"groupName": "React ecosystem",
"matchPackageNames": ["react", "react-dom", "@types/react", "@types/react-dom"]
}
]
}packageRules 배열에서는 나중에 선언된 규칙이 앞선 규칙을 덮어씁니다. 예를 들어 Testing tools 그룹에 automerge: true를 설정하더라도, 배열 마지막에 major 업데이트에 automerge: false를 선언하면 major 업데이트는 항상 수동 리뷰를 거치게 됩니다. 규칙 순서를 바꾸면 결과가 달라지므로 배열 구성 시 의도적으로 순서를 잡아야 합니다.
schedule
PR 생성과 리베이스를 허용할 시간 창을 지정합니다. 기본값은 언제든지 PR을 만드는 것이기 때문에, schedule을 설정하지 않으면 의존성 변경이 감지될 때마다 PR이 열릴 수 있습니다.
{
"schedule": ["before 6am on Monday"]
}"after 10pm and before 5am", "every weekend", "on the first day of the month" 같은 자연어 표현을 지원합니다.
automerge
CI 테스트가 통과하면 Renovate가 직접 머지하도록 허용하는 플래그입니다. automergeType에 따라 동작 방식이 달라집니다.
{
"automerge": true,
"automergeType": "branch"
}공급망 위험 방어:
automerge를 활성화할 때는 반드시minimumReleaseAge를 함께 설정해야 합니다. 릴리스 직후 악성 코드가 삽입된 패키지가 자동 병합되는 공급망 공격을 방어하는 핵심 설정입니다. 패키지 성격에 따라 3~14일 사이를 권장합니다.
automergeType에 따른 동작 차이는 아래 다이어그램에서 확인할 수 있습니다.
automergeType: "branch"는 PR 생성 단계를 건너뛰어 PR 알림 자체가 발생하지 않습니다. CI가 실패할 경우에만 PR이 생성되어 팀에 알림이 전달됩니다. 린팅·타입 체크 도구처럼 위험도가 낮은 패키지에 적합합니다.
실전 적용
아래 시나리오들은 하나의 renovate.json에 통합해서 사용하는 구성입니다. 시나리오 1이 기본 골격이고, 시나리오 2~4는 상황에 맞게 packageRules 배열이나 최상위 설정에 추가하는 방식으로 조합합니다.
시나리오 1 — 프론트엔드 모노레포 PR을 최대 80% 수준으로 줄이기
React, ESLint, Testing 관련 패키지를 각각 groupName으로 묶고, 린팅·테스트 도구는 minor/patch 업데이트를 automerge로 처리합니다. prConcurrentLimit으로 동시 PR 수를 제한해 CI 부하를 분산하고, major 업데이트는 배열 마지막에서 automerge: false를 덮어써 항상 수동 리뷰를 거치도록 합니다.
{
"$schema": "https://docs.renovatebot.com/renovate-schema.json",
"extends": ["config:recommended", "group:monorepos"],
"schedule": ["before 6am on Monday"],
"prConcurrentLimit": 5,
"packageRules": [
{
"groupName": "React ecosystem",
"matchPackageNames": ["react", "react-dom", "@types/react", "@types/react-dom"]
},
{
"groupName": "ESLint and Prettier",
"matchPackageNames": ["eslint", "eslint-*", "@eslint/*", "prettier", "prettier-*"],
"automerge": true,
"automergeType": "branch",
"minimumReleaseAge": "3 days"
},
{
"groupName": "Testing tools",
"matchPackageNames": ["jest", "jest-*", "@jest/*", "vitest", "@testing-library/*"],
"automerge": true,
"minimumReleaseAge": "5 days"
},
{
"matchUpdateTypes": ["major"],
"automerge": false,
"labels": ["major-update", "needs-review"]
}
]
}"group:monorepos" 프리셋은 이미 알려진 모노레포 패키지들(예: Babel 플러그인 묶음)을 자동으로 그룹화해주기 때문에 extends에 포함해두면 편합니다.
시나리오 2 — 보안 업데이트는 즉시, 일반 업데이트는 5일 대기
시나리오 1 설정의 최상위에 아래 내용을 추가합니다.
vulnerabilityAlerts를 별도 블록으로 분리하면 CVE 대응 PR은 minimumReleaseAge 제한 없이 즉시 생성되고, 일반 업데이트는 5일 대기 후 처리됩니다.
{
"minimumReleaseAge": "5 days",
"prHourlyLimit": 10,
"prConcurrentLimit": 50,
"vulnerabilityAlerts": {
"minimumReleaseAge": "0 days",
"labels": ["security"]
}
}prConcurrentLimit을 50으로 높게 잡은 것은 보안 PR이 집중적으로 생성되는 상황을 수용하기 위한 의도적인 선택입니다. 일반적인 운영 환경에서는 3~5로 시작해 점진적으로 늘리는 편이 CI 부하 분산에 유리합니다.
vulnerabilityAlerts로 생성된 보안 PR이 prConcurrentLimit·prHourlyLimit에 미치는 영향은 설정 조건에 따라 다를 수 있습니다. 세부 동작은 공식 문서의 Vulnerability Alerts 항목을 참조하세요.
시나리오 3 — 멀티팀 모노레포에서 팀별 PR 격리
시나리오 1의 packageRules 배열에 추가합니다.
matchFileNames로 팀 영역을 구분하고 additionalBranchPrefix로 브랜치 네임스페이스를 격리합니다. additionalBranchPrefix는 Renovate가 생성하는 브랜치 이름 앞에 접두사를 붙이는 설정입니다. 예를 들어 "frontend/" 설정 시 renovate/react-18.x 브랜치가 frontend/renovate/react-18.x로 생성됩니다. 덕분에 프론트엔드 팀은 frontend/renovate/... 브랜치만 보고, 백엔드 팀은 backend/renovate/... 브랜치만 리뷰하면 됩니다.
{
"packageRules": [
{
"matchFileNames": ["apps/frontend/**"],
"additionalBranchPrefix": "frontend/",
"reviewers": ["team:frontend"]
},
{
"matchFileNames": ["apps/backend/**"],
"additionalBranchPrefix": "backend/",
"reviewers": ["team:backend"]
}
]
}nx나 Turborepo 기반 모노레포에서 서브프로젝트 경계가 명확할 때 특히 잘 맞습니다.
시나리오 4 — Android Gradle 의존성 통합 관리
시나리오 1의 packageRules 배열에 추가합니다.
Gradle, Kotlin 플러그인, Android Gradle Plugin(AGP)은 서로 버전 호환성이 얽혀 있어 개별 업데이트 시 빌드가 깨지기 쉽습니다. groupName으로 묶으면 한 번에 업그레이드해 이 문제를 피할 수 있습니다.
{
"packageRules": [
{
"groupName": "Android build tools",
"matchPackageNames": [
"com.android.tools.build:gradle",
"org.jetbrains.kotlin:kotlin-gradle-plugin",
"com.android.application"
],
"matchUpdateTypes": ["minor", "patch"],
"automerge": true,
"minimumReleaseAge": "7 days"
}
]
}"com.android.tools.build:gradle"은 Maven 좌표 형식이고, "com.android.application"은 Gradle 플러그인 ID 형식으로 표기 방식이 다릅니다. Renovate의 Gradle 매니저가 두 형식을 감지하는 방식은 프로젝트 구성에 따라 다를 수 있으므로, renovate-config-validator로 실제 동작을 검증한 후 적용하는 것을 권장합니다.
장단점 분석
장점
| 항목 | 설명 |
|---|---|
| 다양한 패키지 매니저 통합 | npm, pip, Maven, Gradle, Cargo, Helm, Dockerfile 등 단일 도구로 관리 가능 |
| 세밀한 그룹화 | matchPackageNames glob/regex, matchUpdateTypes, matchFileNames 조합으로 정교한 제어 |
| 플랫폼 독립성 | GitHub 외 GitLab, Bitbucket, Azure DevOps, Gitea까지 동일 설정으로 운영 |
lockFileMaintenance |
lock 파일 전체를 별도 PR로 주기적으로 갱신해 간접 의존성 버전 드리프트를 방지. renovate.json에 "lockFileMaintenance": {"enabled": true}로 활성화하며, 주기 설정은 공식 문서를 참조 |
| 온보딩 PR | 처음 설치 시 감지된 모든 의존성 목록을 미리보기 PR로 제공, 설정 검토 후 활성화 가능 |
| Changelog 자동 삽입 | PR 본문에 업스트림 release note와 changelog 링크 자동 포함 |
| Renovate Dashboard Issue | 저장소 Issues 탭에 대기 중인 모든 업데이트를 한눈에 파악하고 on-demand 실행 가능 |
단점 및 고려사항
| 항목 | 설명 |
|---|---|
| 초기 설정 복잡도 | Dependabot 대비 학습 곡선이 가파름. 기본값 그대로 쓰면 오히려 PR이 더 많아질 수 있음 |
| 잘못된 groupName 범위 | matchPackageNames 범위가 너무 넓으면 무관한 패키지가 같은 PR에 묶여 리뷰가 어려워짐 |
| automerge 공급망 위험 | minimumReleaseAge 없이 활성화하면 악성 패키지 자동 병합 위험. 최소 3~14일 대기 권장 |
| prConcurrentLimit | 프리셋·버전에 따라 기본값이 다름. 대형 모노레포는 3~5로 시작해 점진적으로 늘릴 것을 권장 |
| self-hosted 운영 부담 | GitHub App 방식의 self-hosted는 초기 설정과 비밀키 관리가 복잡함 |
| 전이적 의존성 한계 | poetry.lock 등 일부 생태계에서는 전이 의존성 취약점을 감지하지 못하는 알려진 한계가 있음 |
흔한 실수 세 가지
① matchPackageNames 범위를 너무 넓게 설정
// 위험: "/test/" 정규식이 예상치 못한 패키지까지 모두 묶음
{
"groupName": "All test packages",
"matchPackageNames": ["/test/"]
}
// 권장: 구체적인 glob 또는 정규식 접두사 사용
{
"groupName": "Testing tools",
"matchPackageNames": ["jest", "jest-*", "@jest/*", "vitest", "@testing-library/*"]
}matchPackageNames에 너무 짧거나 범위가 넓은 패턴을 쓰면 예상치 못한 패키지까지 같은 PR에 묶입니다. 접두사 glob이나 스코프 패턴처럼 구체적인 표현을 쓰는 것이 좋습니다.
② automerge를 켜고 minimumReleaseAge를 설정하지 않음
릴리스 직후 악성 코드가 삽입된 패키지 사례는 실제로 발생하고 있습니다. Camunda 같은 엔터프라이즈 프로젝트들이 패키지 매니저별로 1~14일의 대기 기간을 명시적으로 선언하는 이유가 여기에 있습니다.
③ Dependabot과 Renovate 동시 사용
두 도구가 동일한 패키지에 대해 각각 PR을 생성하면서 브랜치 충돌과 알림 혼잡이 발생합니다. 반드시 하나만 선택해야 합니다.
마치며
세 가지 조합이 핵심입니다. groupName으로 관련 패키지를 묶어 PR 수를 줄이고, schedule로 PR이 올라오는 시점을 팀의 리뷰 주기에 맞추고, automerge로 위험도가 낮은 업데이트는 CI 검증 후 처리하도록 위임합니다. automerge에는 반드시 minimumReleaseAge를 함께 설정해야 공급망 위험을 방어할 수 있습니다.
시작하는 순서를 정리하면 이렇습니다.
- GitHub Marketplace에서 Mend Renovate App을 설치합니다. 온보딩 PR에 저장소의 모든 의존성과 현재 버전이 자동으로 목록화됩니다.
renovate.json에schedule과prConcurrentLimit을 먼저 설정합니다. PR 생성 시점과 개수를 통제하는 것만으로도 노이즈가 크게 줄어듭니다.packageRules에groupName1~2개를 추가합니다. React나 ESLint처럼 함께 업데이트되는 패키지 묶음부터 시작하면 부담이 적습니다.
renovate-config-validator CLI로 renovate.json 문법을 로컬에서 미리 검증하고 올리면, 잘못된 설정으로 PR이 쏟아지는 상황을 사전에 막을 수 있습니다.
참고 자료
- Renovate 공식 문서 — Noise Reduction
- Renovate 공식 문서 — Automerge 설정 및 트러블슈팅
- Renovate 공식 문서 — Configuration Options
- Renovate 공식 문서 — Group Presets
- Renovate 공식 문서 — Supported Managers
- Renovate 공식 문서 — Self-Hosting Examples
- Mend.io — Common Practices for Renovate Configuration
- Jamie Tanna — Tips for optimising Renovate for multi-team monorepos (2025.07)
- DEV Community — 5+1 tips to reduce the noise of Renovate Bot
- DEV Community — Renovate vs. Dependabot: Which Bot Will Rule Your Monorepo?
- DevOpsBoys — Renovate vs Dependabot 2026
- Securimancy — Renovate rangeStrategy + vulnerabilityAlerts
- Christian Emmer — Keep Lerna Monorepos Updated with Renovate
- Renovate Bot GitHub 저장소 — Releases
- Augmented Mind — Renovate Bot Cheat Sheet