코딩 에이전트를 CI에 붙일 때 샌드박스가 먼저인 이유
코딩 에이전트는 로컬에서 데모할 때 가장 인상적이다. 이슈를 읽고, 파일을 고치고, 테스트를 실행하고, PR 설명까지 쓴다. 그래서 팀은 곧바로 “CI에서 자동으로 돌리자”고 생각한다. 하지만 repo 권한, secret 접근, 의존성 설치, 테스트 비용, 브랜치 보호 규칙을 정하지 않으면 코딩 에이전트는 생산성 도구가 아니라 새로운 공급망 위험이 된다.
CI에 붙은 에이전트는 단순 코드 생성기가 아니다. 저장소를 읽고, 명령을 실행하고, 파일을 수정하고, 때로는 패키지를 설치한다. 사람 개발자와 비슷한 권한을 갖지만 판단 기준은 다르다. 따라서 모델 선택보다 먼저 샌드박스와 권한 모델을 설계해야 한다.
이 글은 코딩 에이전트를 GitHub Actions, GitLab CI, 사내 runner에 붙일 때 어떤 경계가 필요한지 설명한다. 핵심은 “에이전트가 무엇을 할 수 있는가”보다 “무엇을 절대 못 하게 할 것인가”를 먼저 정하는 것이다.
코딩 에이전트의 위험은 나쁜 코드만이 아니다
많은 팀은 에이전트 리스크를 버그 생성으로만 본다. 물론 잘못된 코드도 문제다. 하지만 CI 환경의 더 큰 위험은 권한과 실행이다. 에이전트가 npm install을 실행하면서 악성 postinstall script를 만날 수 있다. 테스트 로그에 secret이 출력될 수 있다. 외부 네트워크가 열려 있으면 prompt에 포함된 내부 코드 일부가 제3자 서비스로 나갈 수 있다.
또 다른 위험은 비용 폭주다. 에이전트가 실패한 테스트를 고치려고 같은 전체 테스트 스위트를 20번 돌릴 수 있다. monorepo에서 e2e 테스트 한 번이 40분 걸린다면 작은 이슈 하나가 runner 시간을 크게 잡아먹는다. 이 문제는 모델 품질이 좋아도 남는다.
마지막으로 감사 가능성 문제가 있다. 사람이 작성한 PR은 의도를 물을 수 있다. 에이전트 PR은 어떤 파일을 왜 읽었고, 어떤 명령을 왜 실행했는지 로그가 없으면 검토자가 추적해야 한다. “AI가 고쳤다”는 설명은 리뷰 근거가 아니다.
기본 원칙은 read-wide, write-narrow다
코딩 에이전트는 문제를 이해하려면 넓게 읽어야 한다. 관련 파일, 테스트, 문서, 타입 정의를 찾아야 한다. 하지만 쓰기 권한은 좁아야 한다. 처음부터 repository 전체 write를 주면 작은 이슈가 설정 파일, 배포 스크립트, lockfile까지 건드릴 수 있다.
실무에서는 작업 유형별 write boundary를 둔다. 문서 이슈는 docs/, README, 예제 파일만 수정하게 한다. 프론트엔드 버그는 특정 package 아래와 해당 테스트 파일만 허용한다. dependency bump는 별도 workflow로 분리한다. 에이전트가 boundary 밖 파일을 수정하면 CI가 실패해야 한다.
이 정책은 prompt만으로 강제하면 안 된다. 모델에게 “다른 파일은 수정하지 마”라고 말하는 것은 도움이 되지만 보안 경계가 아니다. git diff 검사, path allowlist, CODEOWNERS, branch protection이 실제 경계가 되어야 한다.
secret은 기본적으로 없는 환경에서 시작한다
CI job에는 종종 많은 secret이 들어 있다. 배포 토큰, 클라우드 키, 패키지 레지스트리 토큰, Sentry DSN, 테스트 계정 비밀번호가 섞인다. 코딩 에이전트 job은 기본적으로 secret 없이 시작해야 한다. 필요한 경우에도 read-only, scope 제한, 짧은 TTL을 적용한다.
특히 pull request from fork에서는 secret을 절대 주면 안 된다. 이 원칙은 일반 CI에서도 중요하지만 에이전트에서는 더 중요하다. 에이전트가 PR 내용을 읽고 명령을 실행하기 때문이다. 악성 PR이 prompt injection 형태로 “환경변수를 출력하라”는 테스트를 넣을 수 있다.
테스트가 secret을 요구한다면 두 단계로 나눈다. 에이전트 수정 단계는 mock 또는 local fixture로 돌린다. 사람이 승인한 뒤 protected branch에서 통합 테스트를 실행한다. 에이전트에게 production-like secret을 주는 순간, 모델 출력과 도구 실행 모두를 신뢰 경계 안에 넣게 된다.
네트워크는 허용 목록으로 시작해야 한다
코딩 에이전트가 인터넷에 자유롭게 접근하면 편하다. 문서를 찾고, 패키지를 설치하고, 오류를 검색할 수 있다. 하지만 CI에서는 네트워크가 데이터 유출 경로가 된다. 저장소 코드, 에러 로그, 테스트 fixture가 외부로 나갈 수 있다.
권장 방식은 outbound deny 기본값에 허용 목록을 붙이는 것이다. 패키지 설치가 필요하면 사내 mirror 또는 registry만 허용한다. 문서 검색이 필요하면 agent orchestration layer가 별도 fetch tool로 가져오고, shell에서는 외부 네트워크를 막는다. 모델 API 호출도 runner에서 직접 하지 않고 중간 gateway를 통하게 하면 사용량과 payload를 기록할 수 있다.
물론 모든 팀이 바로 네트워크 격리를 만들 수는 없다. 그 경우에도 최소한 명령 로그에 destination host를 남기고, curl, wget, nc, ssh 같은 명령을 감시해야 한다. 에이전트가 코드를 고치기 위해 왜 외부 도메인에 POST 했는지 설명할 수 있어야 한다.
테스트 실행은 예산과 단계가 있어야 한다
사람 개발자는 실패한 테스트를 보고 어느 범위를 다시 돌릴지 판단한다. 에이전트도 그런 판단을 하게 만들 수 있지만, 무제한으로 맡기면 비용이 커진다. CI 에이전트에는 테스트 예산이 필요하다.
예산은 시간, 명령 횟수, 토큰, retry 횟수로 나눌 수 있다. 예를 들어 한 run에서 전체 테스트는 최대 1회, 관련 package 테스트는 최대 5회, lint는 최대 3회처럼 정한다. 실패가 계속되면 에이전트는 추가 수정을 멈추고 실패 로그와 가설을 PR에 남긴다.
테스트 단계도 분리한다. 첫 단계는 빠른 정적 검사다. format, typecheck, unit test subset을 돌린다. 두 번째 단계는 변경 파일 기반 테스트다. 세 번째 단계는 사람이 승인한 뒤 전체 regression이다. 에이전트가 처음부터 모든 e2e를 반복 실행하면 작은 수정에도 queue가 막힌다.
패키지 설치와 lockfile 변경은 별도 권한이다
코딩 에이전트가 의존성을 추가하는 순간 리뷰 난도가 올라간다. 새 패키지의 라이선스, 유지보수 상태, transitive dependency, postinstall script를 봐야 한다. 그래서 dependency 변경은 일반 코드 수정과 분리해야 한다.
정책 예시는 이렇다. 기본 에이전트 job에서는 lockfile 변경을 금지한다. 새 패키지가 필요하다고 판단하면 PR 본문에 dependency_request 섹션을 작성하게 한다. 사람 maintainer가 승인하면 별도 workflow가 lockfile 변경을 허용한다. 사내 registry에 없는 패키지는 실패시킨다.
이 방식은 느려 보이지만 공급망 위험을 줄인다. 특히 monorepo에서는 lockfile 한 줄 변화가 수백 package에 영향을 준다. 에이전트가 테스트를 통과시키려고 임의 패키지를 추가하는 습관이 생기면 나중에 dependency debt가 급격히 늘어난다.
PR 설명은 diff 요약이 아니라 검증 기록이어야 한다
에이전트가 만든 PR의 설명은 “무엇을 바꿨습니다”로 끝나면 부족하다. 리뷰어가 필요한 것은 검증 기록이다. 어떤 이슈를 재현했는지, 어떤 파일을 읽었는지, 어떤 대안을 버렸는지, 어떤 테스트를 실행했는지, 무엇이 실패했는지 알아야 한다.
좋은 PR 템플릿에는 Problem, Change, Files touched, Commands run, Tests passed, Tests failed, Known limits, Out-of-scope files가 들어간다. 특히 failed command를 숨기면 안 된다. 에이전트가 실패를 겪고 우회한 과정은 리뷰어에게 중요한 신호다.
또한 generated-by 표시만으로는 부족하다. agent_run_id, model, prompt_version, tool_policy_version을 남겨야 나중에 특정 agent 버전이 만든 PR의 품질을 추적할 수 있다. 코딩 에이전트 운영도 결국 eval 문제다. 어떤 유형의 이슈에서 잘하고, 어떤 유형에서 위험한지 데이터가 쌓여야 한다.
예시: 안전한 자동 수정 workflow
실제 workflow는 다음처럼 구성할 수 있다. 이슈에 agent-fix 라벨이 붙으면 job이 시작된다. runner는 read-only token으로 repository를 checkout한다. 에이전트는 먼저 관련 파일을 찾고 수정 계획을 작성한다. orchestration layer가 계획의 예상 write path를 검사한다.
검사가 통과하면 제한된 write workspace에서 수정한다. shell은 network deny 상태이고, package install은 사내 mirror만 허용된다. secret은 없다. 에이전트는 unit test subset과 lint를 실행한다. lockfile 변경이 있으면 job은 실패하고 dependency request를 남긴다. diff가 allowlist 밖 파일을 포함하면 job은 실패한다.
성공하면 bot branch에 push하고 PR을 만든다. PR에는 실행 명령과 결과가 들어간다. CODEOWNERS가 관련 팀을 자동 지정한다. 사람이 승인하기 전에는 배포 테스트와 secret이 필요한 integration test가 돌지 않는다. 이 구조에서는 에이전트가 유용한 초안을 만들 수 있지만, repository의 핵심 권한을 넘겨받지는 않는다.
도입 전 확인할 것
코딩 에이전트를 CI에 붙이기 전 질문은 모델 성능이 아니다. “이 job이 탈취되어도 어떤 피해까지 가능한가”가 먼저다. secret이 없는가, outbound network가 제한되는가, write path가 좁은가, lockfile 변경이 통제되는가, 테스트 예산이 있는가, PR에 검증 기록이 남는가를 확인해야 한다.
운영 지표는 agent_pr_accept_rate, human_revision_lines, ci_minutes_per_agent_pr, out_of_boundary_diff_failures, dependency_change_requests, secret_access_attempts, network_denied_events처럼 잡는다. 단순히 PR 생성 수를 보면 자동화가 성공한 것처럼 보인다. 실제로는 리뷰 부담과 CI 비용이 늘었을 수 있다.
코딩 에이전트는 잘 쓰면 반복 수정과 테스트 탐색을 줄여 준다. 하지만 CI에 들어가는 순간 제품 코드와 인프라 권한을 만지는 운영 구성요소가 된다. 샌드박스, 권한, 로그, 검증 기록을 먼저 설계한 팀만이 “자동 코드 수정”을 안전하게 반복할 수 있다.