31만 스타 프로젝트가 AI 에이전트 8개를 동시에 돌리면서도 품질을 유지하는 방법
![]()
AGENTS.md에 "이것을 하지 마라"고 적어두면 AI 에이전트가 따를까요? 대개는 따르죠. 근데 항상은 아니에요. 외부 컨트리뷰터는 그 규칙이 있는지조차 모를 수도 있고요.
OpenClaw는 GitHub에서 가장 많은 스타를 받은 저장소(31만 이상)이자, 바이브 코딩의 대표 사례입니다. 메인테이너 Peter Steinberger가 3~8개의 AI 에이전트를 동시에 돌리며 쏟아내는 내부 변경. 전 세계 컨트리뷰터가 AI 보조로 만들어 제출하는 수천 건의 외부 PR. 이 두 가지 압력이 동시에 들어오는 환경이에요.
이전 글에서 정도현 수석 컨설턴트는 OpenClaw의 AGENTS.md가 담고 있는 생산성의 원칙을 분석했어요. 그 글의 핵심은 "규칙을 쓰는 것"이었습니다. 근데 규칙을 쓰는 것과 규칙을 강제하는 것은 완전히 다른 문제잖아요. AGENTS.md에 "이것을 하지 마라"고 쓰는 것은 소프트 가드레일이에요. AI 에이전트는 대개 따르지만, 항상 따르지는 않아요. 외부 컨트리뷰터는 그 규칙의 존재조차 모를 수도 있고요.
그래서 OpenClaw는 규칙 위에 5계층의 자동화된 강제 메커니즘을 쌓았습니다. 로보코의 정도현 수석 컨설턴트가 이 구조를 해부했는데, 하나씩 뜯어보면 꽤 정교하더라고요. 코드가 프로덕션에 도달하기까지 거치는 방어 깊이(defense in depth)가 드러납니다.
``` [개발자/에이전트] | 1계층: 프리커밋 --- 포맷/린트 자동수정, 타입/경계 위반 차단 | 2계층: pnpm check - 10+ 체크 체이닝, 15+ 아키텍처 경계 가드 | 3계층: CI -------- 15개 병렬 잡, 크로스 플랫폼, 보안 스캔 | 4계층: PR 자동화 -- 라벨 분류, 노이즈 필터, 증거 기반 템플릿, stale 정리 | 5계층: 릴리스 ----- 수동 트리거, 환경 승인, CODEOWNERS, 19단계 검증 | [프로덕션] ```
각 계층은 독립적이에요. 프리커밋이 실패해도 CI가 잡고, CI를 우회해도 PR 리뷰가 걸리고, PR이 통과해도 릴리스 게이트가 막는다. 하나의 계층이 뚫려도 다음 계층이 방어합니다.
1~2계층: 커밋 전에 잡고, 하나의 명령어로 10가지를 검증한다
첫 번째 방어선은 코드가 저장소에 도달하기도 전에 작동해요. `git-hooks/pre-commit`이 `package.json`의 `prepare` 스크립트를 통해 자동 활성화되고, 커밋할 때마다 실행됩니다.
동작 순서가 눈에 띄어요. 스테이지된 파일을 타입별로 필터링한 뒤, `oxlint --type-aware --fix`로 린트 오류를 자동 수정하고, `oxfmt --write`로 포매팅을 자동 수정합니다. 수정된 파일을 다시 스테이징한 다음, `pnpm check`로 전체 품질 게이트를 실행해요.
핵심 설계는 자동 수정과 차단의 분리예요. 포맷이나 린트 오류처럼 기계적으로 고칠 수 있는 문제는 훅이 알아서 고치고 통과시킵니다. 하지만 타입 오류나 아키텍처 경계 위반처럼 판단이 필요한 문제는 커밋 자체를 차단하고요. 이 구분이 없으면 에이전트는 사소한 포맷 오류 때문에 멈추거나, 구조적 결함을 그냥 통과시키거나. 둘 중 하나가 되거든요.
여기에 `.pre-commit-config.yaml`은 CI의 `security-fast` 잡에서도 실행되는 17개의 보안/품질 훅을 정의합니다. `detect-private-key`와 `detect-secrets`로 시크릿 유출을 차단하고, `zizmor`로 GitHub Actions 워크플로의 보안을 감사하며, `pnpm-audit-prod`로 프로덕션 의존성의 알려진 취약점을 검사해요. 17개나 되는 보안 훅이 프리커밋 단계에서 이미 돌아가고 있다는 건, 보안 문제가 CI까지 갈 일이 거의 없다는 뜻이기도 합니다.
2계층인 `pnpm check`는 로컬 훅과 CI 모두에서 실행되는 단일 품질 게이트예요. 하나의 명령어 뒤에 10개 이상의 체크가 체이닝되어 있거든요.
``` pnpm check = check:no-conflict-markers # 머지 충돌 마커 없음 check:host-env-policy:swift # Swift 호스트 환경 보안 정책 check:base-config-schema # 설정 스키마 드리프트 체크 check:bundled-plugin-metadata # 플러그인 메타데이터 일관성 check:bundled-provider-auth-env-vars # 프로바이더 인증 환경변수 일관성 format:check (oxfmt) # 포매팅 검증 tsgo # TypeScript 네이티브 타입 체킹 plugin-sdk:check-exports # 플러그인 SDK 익스포트 일관성 lint (oxlint --type-aware) # 타입 인식 린팅 + ~15개 커스텀 아키텍처 경계 린트 스크립트 ```
마지막 줄이 핵심이에요. 일반적인 린터는 "사용하지 않는 변수"나 "누락된 세미콜론" 같은 코드 수준 문제를 잡잖아요. OpenClaw의 커스텀 경계 가드 스크립트는 아키텍처 수준 위반을 잡습니다. Extension이 코어 `src/**`를 직접 임포트하거나, 플러그인 SDK의 내부 경로를 참조하거나, 패키지 루트 밖으로 상대 경로를 뻗는 것을 감지해요. AGENTS.md에 "하지 마라"고 쓴 것을 CI가 실제로 검증하고 차단하는 거예요. 규칙과 검증의 이중 장벽.
3계층: 15개 병렬 잡이 모든 변경을 검사한다
`ci.yml`은 PR과 main 푸시에서 실행되는 메인 게이트키퍼입니다. ~15개의 병렬 잡으로 구성되어 있고, Draft PR은 건너뛰어요.
모든 변경에 모든 테스트를 돌리면 철저하지만 느립니다. 관련 테스트만 돌리면 빠르지만 놓칠 수 있고요. OpenClaw는 `preflight` 잡으로 이 딜레마를 풀었어요. preflight 잡이 변경된 파일의 스코프를 감지해서 CI 매니페스트를 생성하거든요. 문서만 변경했다면 문서 체크만, Swift 파일을 건드렸다면 macOS 빌드+테스트를 추가하고, 특정 Extension만 변경했다면 해당 Extension 테스트만 실행합니다.
전체 CI 잡을 카테고리로 나누면 이렇습니다.
`check-additional` 잡의 아키텍처 경계 가드가 인상적이에요. 플러그인에서 Extension 임포트 위반, Extension SDK 내부 경로 참조, `raw window.open` 사용, 게이트웨이 watch 회귀 등을 커스텀 스크립트로 감지합니다. 일반적인 CI 파이프라인에서는 볼 수 없는, 바이브 코딩 환경에 특화된 가드레일이에요.
잠깐 생각해 봅시다. 이게 왜 중요할까요? AI 에이전트가 코드를 생성할 때 가장 흔히 저지르는 실수 중 하나가 모듈 경계 위반이거든요. "이 함수가 필요하니까 직접 import하자" — 사람도 하는 실수인데, 에이전트는 더 자주 해요. 아키텍처 경계를 모르니까요. 이걸 일반 린터로는 못 잡아요. 커스텀 스크립트가 필요한 이유가 여기 있습니다.
이 스마트 라우팅과 아키텍처 가드의 조합이 "느리지만 철저한" CI와 "빠르지만 불완전한" CI 사이의 균형을 만들어내는 거예요.
PR 수천 건을 사람 없이 걸러낸다
31만 스타 프로젝트에는 수천 건의 이슈와 PR이 쏟아집니다. 메인테이너가 하나하나 분류하는 건 불가능하죠. OpenClaw는 세 가지 자동화 워크플로로 이걸 풀었어요.
자동 라벨링부터 봅시다. `labeler.yml` 워크플로가 PR이 열리면 변경된 파일 경로를 분석해서 라벨을 자동 부여해요. 21개 채널 라벨(`channel: discord`, `channel: telegram` 등), 4개 앱 라벨(`app: ios`, `app: android` 등), 8개 영역 라벨(`gateway`, `agents`, `security` 등), 30개 이상의 Extension 라벨. 여기에 PR 크기 라벨(XS/S/M/L/XL)을 줄 수 기반으로 자동 부여하고, 메인테이너 라벨을 팀 멤버십으로 판별하고, `beta-blocker` 라벨을 PR 제목에서 자동 감지합니다.
자동 응답은 노이즈 필터링이에요. `auto-response.yml`이 라벨 기반으로 PR과 이슈를 자동 처리합니다. 실제 운영 경험에서 축적된 규칙들이에요.
스팸과 노이즈 차단부터 보면요. `r: spam` 또는 `r: moltbook` 라벨이 붙으면 자동 닫기 + 잠금. `dirty` 라벨이나 라벨 20개 초과 PR도 "noisy PR" 메시지와 함께 닫힙니다.
커뮤니티 행동 제한도 있어요. 비메인테이너의 오픈 PR이 10개를 초과하면 `r: too-many-prs` 라벨 부여 후 자동 닫기. 이슈/PR에서 메인테이너 3명 이상을 멘션하면 스팸 핑 경고 메시지가 나오고요.
적절한 채널 안내도 자동이에요. `r: skill` 라벨이 붙으면 스킬 관련 질문은 ClawHub으로 안내 후 닫기, `r: support` 라벨이면 지원 요청은 Discord로 안내 후 닫기, `r: no-ci-pr` 라벨이면 CI 설정만 변경하는 PR 거절.
인당 PR 10개 상한. 이게 바이브 코딩 시대에 특히 중요해요. AI 도구로 PR을 대량 생산하기 쉬워진 환경에서, 한 사람이 리뷰 큐를 독점하는 걸 방지하거든요. CONTRIBUTING.md도 이를 명시합니다: "Keep PRs focused (one thing per PR; do not mix unrelated concerns)". 메인테이너의 어텐션은 유한한 자원이에요. 자동 트리아지가 그 자원을 보호하는 겁니다.
수명 관리도 자동이에요. `stale.yml`이 매일 실행되면서 방치된 이슈와 PR을 정리합니다. 이슈는 7일 후 stale 표시 → 5일 후 닫기, PR은 5일 후 stale → 3일 후 닫기. 닫힌 이슈는 48시간 후 잠금. `enhancement`, `maintainer`, `pinned`, `security` 라벨이 붙은 항목은 면제돼요.
PR의 수명이 이슈보다 짧은 게 눈에 띄죠(5+3일 vs 7+5일). 코드 변경은 시간이 지날수록 컨텍스트와 멀어지고 충돌 가능성이 커지니까 당연한 거긴 합니다. 방치된 PR이 쌓이면 리뷰 큐 자체가 오염되거든요.
PR 템플릿은 증거를 구조적으로 요구해요. 일반적인 "무엇을 했는가" 수준을 넘어서 증거 기반 리뷰를 강제합니다. 특히 주목할 부분들:
마지막 항목이 좀 찔리는 부분이에요. "무엇을 테스트했는가"만 물으면 PR 작성자는 성공한 케이스만 나열하잖아요. "무엇을 테스트하지 않았는가"를 물으면 리뷰어가 위험 영역을 즉시 파악할 수 있습니다. Security Impact 항목도 마찬가지예요. "보안에 영향이 있나요?"라는 모호한 질문 대신, 권한/시크릿/네트워크/도구 실행/데이터 접근이라는 구체적 표면을 하나씩 점검하게 만들어요. 모호한 질문은 모호한 답을 낳거든요.
릴리스 앞에서는 무조건 멈춘다
CI는 완전 자동이에요. 릴리스는 절대 자동이 아닙니다. 여기서 OpenClaw의 철학이 드러나요. "빠르게 움직이되, 되돌릴 수 없는 행동 앞에서는 멈춘다."
`openclaw-npm-release.yml`은 `workflow_dispatch`로만 트리거돼요. 자동 릴리스는 없습니다. 실행되면 태그 포맷 검증, `pnpm check` + `pnpm build` + `pnpm release:check`, npm 버전 유일성 확인을 순서대로 거쳐요. 그 다음 `npm-release` 환경 승인에서 `@openclaw/openclaw-release-managers` 팀원의 명시적 승인이 필요하고, main 브랜치에서만 실행이 강제됩니다. 이후 태그 생성부터 appcast 업데이트까지 19단계 시퀀스를 밟아요.
CODEOWNERS는 GitHub가 강제하는 하드 가드레일이에요. AGENTS.md의 "보안 파일을 건드리지 마라"가 소프트 가드레일이라면, CODEOWNERS는 해당 팀의 리뷰 승인 없이는 머지 자체가 불가능하게 만듭니다. `@openclaw/secops`가 보안 코드(`src/security/`, `src/secrets/`, 게이트웨이 인증/시크릿, 에이전트 샌드박스), 보안 인프라(`dependabot`, `CodeQL`, `SECURITY.md`), 보안 문서 전체를 보호하고, `@openclaw/openclaw-release-managers`가 릴리스 워크플로, 퍼블리시 스크립트, 릴리스 문서를 보호합니다. CODEOWNERS 파일 자체는 `@steipete`(창시자)만 수정할 수 있어요. 게이트키퍼를 보호하는 게이트키퍼.
AI 에이전트용 스킬에도 게이트가 있어요. `$openclaw-pr-maintainer` 스킬은 버그 수정 PR에 대해 증거 기준을 강제합니다. 이슈 텍스트나 AI의 추론만으로는 머지할 수 없어요. 증상 증거, 검증된 근본 원인(파일/라인 수준), 관련 코드 경로 수정, 회귀 테스트가 필요합니다. 일괄 닫기/재오픈이 5건을 초과하면 반드시 사용자 확인을 받아야 하고요. `$openclaw-release-maintainer` 스킬은 버전 번호 변경과 npm publish 모두 매 단계마다 운영자 승인을 요구합니다. 스킬이 자동화를 돕지만, 비가역적 행동은 여전히 인간이 결정해요.
7가지 설계 원칙 — 이걸 왜 이렇게 만들었는지
5계층을 관통하는 설계 원칙을 정리하면 일곱 가지가 나와요.
1. 자동 수정과 차단을 분리하라. 포맷/린트 오류는 자동 수정, 타입/경계 위반은 하드 차단. 에이전트의 플로를 불필요하게 끊지 않으면서도 구조적 결함은 통과시키지 않습니다.
2. 스마트 라우팅으로 속도를 유지하라. 모든 변경에 모든 테스트를 돌리지 않아요. 변경 스코프를 감지해 관련 잡만 실행합니다. 빠른 피드백과 철저한 검증은 양립할 수 있어요.
3. 규칙 문서와 자동 검증을 겹쳐라. AGENTS.md에 "하지 마라"고 쓰고, CI에서 실제로 위반을 감지합니다. 소프트 가드레일과 하드 가드레일의 이중 장벽이 방어 깊이를 만들어요.
4. PR에 증거를 구조적으로 요구하라. "무엇을 했는가"뿐 아니라 "무엇을 하지 않았는가", "어떤 증거가 있는가", "보안 영향이 있는가"를 구조적으로 물어요. 리뷰어가 판단해야 할 정보를 작성자가 미리 제공하게 만드는 거예요.
5. 커뮤니티 노이즈를 자동으로 필터링하라. 인당 PR 10개 상한, stale 자동 닫기, 라벨 기반 자동 닫기/안내, 메인테이너 핑 스팸 감지. 메인테이너의 어텐션을 자동 트리아지가 보호합니다.
6. 비가역적 행동 앞에서는 멈춰라. CI는 완전 자동이지만 릴리스는 수동 트리거 + 환경 승인. AI 에이전트 스킬도 버전 변경과 퍼블리시는 매 단계 승인. "빠르게 움직이되, 되돌릴 수 없는 행동 앞에서는 멈춘다."
7. 게이트키퍼를 보호하는 게이트키퍼를 두라. CODEOWNERS 파일은 창시자만 수정할 수 있어요. 릴리스 워크플로는 릴리스 매니저 팀만 수정할 수 있고, 보안 코드는 secops 팀의 승인 없이 머지할 수 없습니다. 게이트키핑 시스템 자체를 보호하는 메타 계층이 있다는 거예요.
3번이 특히 와닿았어요. 규칙만 쓰면 "읽지 않았어요"로 끝나고, 자동 검증만 두면 "왜 막히는지 모르겠어요"가 나오거든요. 둘을 겹치는 게 답이에요.
이걸 어디서부터 도입할까
OpenClaw의 5계층 전체를 한 번에 도입할 필요는 없어요. 난이도와 ROI 순으로 정리하면:
즉시 도입 가능: pre-commit 훅(lint+format 자동 수정)으로 사소한 오류 때문에 CI가 실패하는 낭비를 제거하고, PR 템플릿에 증거/보안 섹션을 추가해서 리뷰 품질을 올립니다. 하루면 돼요.
1주: CI에 타입 체크 + 테스트 게이트를 추가해서 기본 품질 바닥선을 확보하고, CODEOWNERS로 보안 민감 파일을 하드 잠금합니다. 이것만으로도 "CI가 통과했으니 괜찮겠지"라는 최소한의 신뢰가 생겨요.
2주: stale 봇 + 자동 라벨링으로 PR 큐 관리를 자동화합니다.
1개월: 커스텀 아키텍처 경계 가드 스크립트로 아키텍처 부식을 방지하고, 스마트 라우팅(변경 스코프 기반 CI 잡 선택)으로 CI 속도를 최적화합니다.
분기: 릴리스 환경 승인 + 다단계 검증으로 릴리스 안전성을 확보합니다.
가장 ROI가 높은 건 pre-commit 훅과 PR 템플릿이에요. 둘 다 하루 안에 도입할 수 있고, 즉시 효과가 나타납니다. 나머지는 프로젝트의 규모와 위험도에 맞춰 점진적으로 추가하면 돼요.
결국 바이브 코딩 시대의 품질 관리는 "AI가 나쁜 코드를 만들지 않게 하는 것"이 아니에요. AI는 때로 나쁜 코드를 만들어요. 사람도 마찬가지고요. 핵심은 나쁜 코드가 프로덕션에 도달하지 못하게 하는 것. 프리커밋이 실패해도 CI가 잡고, CI를 우회해도 PR 리뷰가 걸리고, PR이 통과해도 릴리스 게이트가 막는다. 하나가 뚫려도 다음이 방어하는 구조. OpenClaw의 5계층 게이트키핑이 보여주는 건 바로 그 방법이에요.