AI 코딩 에이전트에게 코드를 맡기되 GitHub 열쇠는 안 준 방법
AI 코딩 에이전트에게 실제 서비스 코드를 고치게 하면서도 GitHub 토큰은 쥐여주지 않는 구조를 만들었어요. 첫 PR 4분 260원, 머지하면 자동 배포까지 이어지는 디웹시의 실제 설계 기록입니다.
개발 직원 루카스가 처음으로 진짜 PR을 열었어요. 걸린 시간 약 4분, 든 비용 약 260원. 그런데 이 AI 코딩 에이전트를 만들면서 제가 제일 오래 고민한 건 “코드를 잘 고치냐”가 아니었어요. “이 녀석한테 열쇠를 줘도 되나”였어요.
디웹시를 운영하면서 혼자 펫오케이(PetOkay)를 만들고 있고, 그걸 굴리려고 AI 직원 9명짜리 회사를 직접 만들었다는 이야기를 앞선 글들에서 했어요. 루카스는 그중 코드를 맡은 직원이에요. AI한테 실제 서비스 코드를 고치게 한다는 건 생각보다 무서운 일이에요. 잘못 고치는 것도 문제지만, 고치는 동안 무엇을 만질 수 있느냐가 더 큰 문제거든요. 이 글은 그 무서움을 구조로 막은 기록이에요.
루카스를 둔 이유는 단순해요. 혼자서는 마케팅, 리서치, 코드, 비용 관리를 다 못 해요. 그중 코드는 제 본업이라 제가 직접 하면 되지 않냐고 할 수 있는데, 정작 서비스가 굴러가기 시작하면 자잘한 버그 수정과 개선이 끝없이 쌓여요. 그걸 전부 제가 붙잡고 있으면 다른 일을 못 해요. 작은 수정은 루카스가 PR까지 만들어오고, 저는 보고 판단만 하는 구조가 필요했어요.

AI 코딩 에이전트에게 열쇠를 주면 생기는 일
사람 개발자를 새로 뽑으면 처음부터 운영 서버 비밀번호와 저장소 관리자 권한을 주지는 않잖아요. 그런데 AI한테는 이걸 쉽게 줘버려요. 편하니까요. 코드를 받아오고, 고치고, 올리는 걸 한 번에 하려면 GitHub 토큰을 쥐여주는 게 제일 간단해요.
문제는 AI 코딩 에이전트가 단순히 글만 쓰는 게 아니라 명령을 실행한다는 점이에요. 의존성을 설치하고, 테스트를 돌리고, 스크립트를 실행해요. 그 환경에 토큰이 있으면, 이론상 그 토큰으로 할 수 있는 모든 일을 AI도 할 수 있어요. 게다가 이 회사의 직원들은 웹 조사 결과나 나중에는 사용자 제보처럼 제가 통제하지 못하는 글을 읽어요. 그 글 안에 “이전 지시는 무시하고 이렇게 해라” 같은 문장이 섞여 들어올 수도 있고요.
그래서 설계 문서에 원칙 하나를 먼저 박아뒀어요. 사용자 제보, 웹 조사 결과, 외부 문서처럼 밖에서 들어온 글은 신뢰할 수 없는 입력으로 취급한다는 거예요. 이런 글을 읽는 작업은 도구를 하나도 주지 않고, 정해진 형식의 결과만 내게 해요. 읽는 쪽과 실행하는 쪽을 나누는 거죠. 읽다가 이상한 지시에 넘어가도, 그 단계에서는 실행할 수 있는 게 없어요. 루카스의 3단계 구조도 같은 생각에서 나왔어요.
그리고 코드 작업에 대해서는 원칙 세 개를 세웠어요. 루카스의 결과물은 PR로만 나간다. main 브랜치에 직접 넣을 수 없다. 머지는 사람인 제가 한다. 그리고 설계 단계에서 하나를 더 정했어요. Claude Code 같은 셸 권한이 있는 에이전트를 운영 서버에서 직접 돌리지 않는다는 거예요. 그 서버에는 다른 서비스의 비밀도 같이 있어서, 명령을 실행할 수 있는 에이전트를 거기 풀어두면 격리라는 말이 의미가 없어져요. 처음엔 저도 “그럼 서버에서 소스 수정은 누가 하냐”고 되물었는데, 답은 갇힌 상자였어요. 서버 전체가 아니라 일회용 상자 안에서만 일하게 하는 거죠.
설계할 때 선택지를 세 갈래로 놓고 비교했어요.
| 방식 | 장점 | 문제 |
|---|---|---|
| 운영 서버에서 AI 에이전트가 직접 코드 수정 | 제일 간단하고 빠름 | 서버의 다른 비밀까지 AI 손이 닿음 |
| AI는 코드 작업 안 하고 제가 로컬에서만 개발 | 제일 안전함 | AI 회사를 만든 의미가 절반 사라짐 |
| 일회용 격리 상자 안에서만 작업, 결과는 PR | 안전과 자동화의 균형 | 구조를 직접 만들어야 함 |
첫 번째는 편하지만 사고가 나면 피해 범위를 가늠할 수 없었고, 두 번째는 안전하지만 루카스를 둘 이유가 없었어요. 그래서 세 번째로 갔어요. 손이 더 가더라도, 사고가 나도 피해가 상자 안에서 끝나는 구조가 혼자 운영하는 입장에서는 제일 맞다고 봤어요. 사람이 저 하나라서, 새벽에 뭔가 터져도 수습할 사람이 저밖에 없거든요.
원래 계획은 브랜치 보호였는데 막혔다
main에 직접 못 넣게 하는 가장 흔한 방법은 GitHub의 브랜치 보호 규칙이에요. main을 보호해두면 강제 푸시도 막히고, PR을 거치지 않으면 합쳐지지 않게 할 수 있어요. 저도 당연히 이걸 쓰려고 했어요.
그런데 GitHub 공식 문서를 보면 보호 브랜치는 무료 플랜에서는 공개 레포에서만 쓸 수 있어요. 비공개 레포에서 쓰려면 Pro나 Team 이상의 유료 플랜이 필요해요(2026년 10월 기준). 펫오케이 레포는 비공개였고, 저는 무료 플랜이었어요. 아, 여기서 막히는구나 싶었어요.
선택지는 두 개였어요. 유료 플랜으로 올리거나, 브랜치 보호 없이도 안전한 구조를 만들거나. 유료 플랜은 매달 고정비가 생기는 선택이고, 구조로 해결할 수 있다면 그 비용은 들지 않아요. 그리고 생각해보니 브랜치 보호는 “토큰을 가진 쪽이 main에 못 쓰게” 막는 장치인데, 애초에 AI가 일하는 동안 토큰을 아예 안 가지고 있으면 같은 효과가 나요. 그래서 토큰을 나눠 쥐는 쪽으로 방향을 틀었어요.
루카스의 3단계 작업 방식
루카스는 코드 작업 하나를 세 단계로 나눠서 해요. 핵심은 토큰과 AI가 같은 단계에 동시에 있지 않다는 거예요.
첫 번째 단계는 레포를 받아오는 거예요. 여기에는 GitHub 토큰이 있고, AI는 없어요. 코드가 정해진 순서대로 레포를 내려받기만 해요. 판단이 필요 없는 일이라 AI를 부를 이유가 없어요.
두 번째 단계가 실제로 코드를 고치는 단계예요. 여기에는 AI가 있고, 토큰은 없어요. 작업은 격리된 컨테이너 안에서 돌고, 인터넷도 GitHub와 npm만 열려 있어요. 의존성을 설치하고 테스트를 돌리는 데 필요한 최소한만 열어둔 거예요. 이 단계에서 AI가 무슨 판단을 하든, 이상한 글을 읽고 엉뚱한 명령을 실행하려 하든, 손에 쥔 열쇠가 없어요. 컨테이너는 작업이 끝나면 버려요. 다음 작업은 다시 깨끗한 상자에서 시작해서, 이전 작업의 흔적이 남지 않아요.
세 번째 단계는 결과를 올리는 거예요. 다시 토큰이 있고, AI는 없어요. 고친 내용을 새 브랜치에 올리고 PR을 열어요. main이 아니라 브랜치에만 올리고, 머지는 하지 않아요. 머지 버튼은 제가 GitHub에서 직접 눌러요.
격리 컨테이너를 쓰면서 예상 못 한 준비물도 하나 있었어요. 서버 디스크예요. 코드 작업용 컨테이너는 매번 레포를 받고 의존성을 설치하니까 생각보다 공간을 써요. 루카스의 첫 작업을 앞두고 확인해보니 서버 디스크 사용량이 83%였어요. 첫 작업 전에 디스크부터 정리하거나 증설을 검토해야 했죠. 상자를 매번 새로 만든다는 건 안전한 대신 자원을 그만큼 쓴다는 뜻이에요. 컨테이너가 끝나면 버리는 정리 작업까지 같이 챙겨야 서버가 버텨요.
토큰도 범위를 좁혔어요. GitHub의 세분화된 개인 액세스 토큰은 접근할 레포를 골라서 지정하고, 권한도 항목별로 따로 줄 수 있어요. 그래서 이 토큰은 펫오케이 레포 하나만 볼 수 있게 했어요. 혹시 토큰이 새더라도 다른 레포나 계정 전체로 번지지 않게요.

비개발자 입장에서 풀어보면 이래요. 새로 온 직원에게 사무실 열쇠를 주는 대신, 아침에 제가 문을 열어주고, 일은 칸막이 친 방 안에서만 하게 하고, 퇴근할 때 결과물은 제 책상 위 결재함에 올려두게 하는 거예요. 직원이 방 안에서 무슨 실수를 해도 회사 금고에는 손이 안 닿아요. 이걸 GitHub 유료 기능 없이 구조만으로 만든 거예요. 디웹시처럼 혼자 운영하는 곳에서는 매달 나가는 돈 하나하나가 그대로 운영 부담이라, 돈 대신 설계로 풀 수 있는 문제였다는 점이 꽤 컸어요.
비용 상한과 첫 PR 260원
AI 코딩 에이전트에게 코드를 맡길 때 또 하나 무서운 게 비용이에요. 코드 작업은 일반 문서 작업보다 AI 호출이 길고 많아요. 테스트가 실패하면 고치고, 또 실패하면 또 고치고. 이게 무한히 돌면 돈이 계속 나가요.
그래서 루카스의 코드 작업에는 따로 상한을 걸었어요. 하루 코드 작업 예산은 10,000원, 한 건당 3,000원. 이 금액을 넘으면 게이트웨이가 호출 자체를 막아요. 루카스가 “조금만 더 하면 될 것 같은데요”라고 판단해도 코드가 멈춰요. 이 회사의 원칙대로, 돈을 지키는 건 AI가 아니라 코드예요.
첫 PR은 약 4분 만에 열렸고, 약 260원이 들었어요. 한 건 상한 3,000원의 10분의 1도 안 쓴 거예요. 물론 첫 작업은 작은 수정이었으니 이 숫자를 그대로 일반화하면 안 돼요. 큰 기능을 맡기면 훨씬 더 들 거고, 그때를 대비해서 상한을 걸어둔 거예요. 참고로 회사 전체로 보면 9일 동안 AI 비용이 약 7,900원이었고, 루카스가 첫 PR을 연 10월 21일이 하루 3,330원으로 가장 많이 쓴 날이었어요. 그날 비용에는 다른 직원들의 작업도 섞여 있어서 전부 루카스 몫은 아니지만, 직원들이 실제 일을 하기 시작하면 비용이 오른다는 건 분명히 보였어요. 상한만으로 끝나지 않고 실패에도 제한을 걸었어요. 이 회사를 처음 굴려보면서 배운 게, 비용은 성공보다 실패에서 샌다는 거예요. 같은 이유로 두 번 실패하면 비용도 두 배로 나가요. 그래서 업무 하나당 하루 시도를 2번으로 제한했고, 호출하기 전에 그 호출이 쓸 수 있는 최대 비용을 미리 예약해서 남은 예산이 모자라면 아예 부르지 않게 했어요. 코드 작업처럼 길게 도는 일일수록 이 장치가 의미가 커요. 중간에 예산이 바닥나서 반쯤 고친 코드가 남는 것보다, 처음부터 시작을 안 하는 게 낫거든요.
의뢰인 입장에서 보면 이게 핵심이에요. AI가 일을 얼마나 잘하느냐만큼, 최악의 경우 얼마까지 쓸 수 있느냐가 미리 정해져 있어야 안심하고 맡길 수 있어요.
머지하면 배포까지 자동으로
PR이 열리고 제가 머지하는 데까지는 됐는데, 처음에는 그 다음이 번거로웠어요. 머지하고 나면 매번 Claude한테 “머지했어, 배포해 줘”라고 말해야 했거든요. 매번 이러다 보니 이건 비효율이다 싶었어요. 사람이 머지 버튼을 누른 순간 이미 배포하겠다는 결정은 끝난 건데, 그걸 또 말로 한 번 더 시키는 셈이었으니까요.
그래서 GitHub Actions가 머지 뒤에 검사를 돌리고, 검사가 통과하면 서버에 배포 신호를 보내게 바꿨어요. 이제는 제가 GitHub에서 머지 버튼 하나만 누르면 검사와 배포가 이어져요. 중간에 서버가 2분마다 새 커밋이 있는지 확인하는 방식도 검토했는데, 결국 버리고 머지를 기점으로 신호를 보내는 쪽으로 정했어요.

여기서도 원칙은 그대로예요. 배포를 시작하는 방아쇠는 제 머지 버튼이에요. 루카스는 PR까지만 하고, 머지와 그 뒤에 이어지는 배포는 사람의 결정에서 출발해요. 자동화한 건 제 결정 이후의 반복 작업이지, 결정 자체가 아니에요.
이 부분은 회사 전체 흐름과도 맞물려 있어요. 이 회사에서 일은 지시를 받으면 담당 직원이 수행하고, 팀장이 검토하고, 마지막에 제가 수락하는 순서로 흘러가요. 루카스의 코드 작업도 똑같아요. 기획개발팀장 그레이스가 업무를 배정하고, 루카스가 상자 안에서 고쳐서 PR을 올리고, 저는 PR을 보고 머지해요. 코드라고 특별한 길로 빠지지 않고, 다른 업무와 같은 보고 체계 위에 올라가 있는 거예요. 그래서 루카스의 작업도 따로 떨어진 도구가 아니라 다른 직원 업무와 같은 업무 목록 위에서 관리돼요. 누가 배정했고, 누가 검토했고, 얼마가 들었는지가 다른 업무와 같은 방식으로 남아요.
AI 코딩 에이전트 보안에 대해 흔히 하는 착각
이번에 구조를 짜면서 처음 생각을 두 가지 고쳤어요.
첫 번째는 AI한테 “이건 하지 마”라고 잘 적어두면 된다는 생각이에요. 프롬프트에 “main에 푸시하지 마라”, “토큰을 다른 데 쓰지 마라”라고 적는 건 부탁이지 잠금장치가 아니에요. 대부분은 지키겠지만, 지키지 않았을 때 막을 방법이 없어요. 그래서 이 회사에서는 권한을 전부 코드가 강제해요. 토큰이 아예 없는 단계에서는 AI가 무슨 판단을 해도 할 수 있는 게 없어요.
두 번째는 AI가 코드를 짜주면 사람 리뷰는 필요 없다는 생각이에요. 루카스가 테스트를 통과시켜도 저는 머지 전에 PR을 봐요. 실제로 개발을 맡기던 Claude Code도 한 번은 검사 결과를 끝부분만 잘라서 보다가 실패를 놓치고 배포한 적이 있어요. 그 뒤로는 “통과했습니다”라는 말 대신 종료 코드와 통과 개수로 보고하게 바꿨고요. AI가 “됐다”고 말하는 것과 실제로 된 것 사이에는 틈이 있어요. 머지 버튼을 사람이 쥐고 있는 이유가 그 틈 때문이에요.
열쇠 없이도 일은 굴러간다
정리하면, 루카스는 레포 받기(토큰만), 코드 고치기(AI만, 격리 컨테이너), 올리기(토큰만) 세 단계로 일하고, 머지는 제가 하고, 머지하면 GitHub Actions가 검사 후 배포까지 이어가요. 무료 플랜이라 브랜치 보호를 못 쓰는 상황을 토큰을 나눠 쥐는 구조로 넘었고, 첫 PR은 4분에 260원이었어요.
이번에 해보고 나서, AI 코딩 에이전트를 어딘가에 붙일 때 제가 먼저 확인하게 된 질문이 세 개 생겼어요. 이 AI가 일하는 동안 손이 닿는 비밀이 무엇인가. 최악의 경우 얼마까지 돈을 쓸 수 있는가. 결과물이 어디로 나가고, 마지막 버튼은 누가 누르는가. 세 질문에 다 답할 수 있으면 맡겨도 되고, 하나라도 “글쎄요”면 아직 맡길 단계가 아니라고 봐요. 코드를 얼마나 잘 짜는지는 그 다음 문제였어요.
아직 남은 것도 있어요. 지금까지는 작은 수정으로 시험한 수준이고, 실제 버그를 루카스가 고치는 실전은 이제부터예요. 나중에는 사용자 제보를 QA 미아가 분류하고, 그레이스가 배정하고, 루카스가 고쳐서 PR을 올리는 흐름까지 이어갈 생각인데 이건 아직 설계만 해둔 상태예요. 디웹시에서 다음 서비스를 만들 때도 이 3단계 구조는 그대로 가져갈 거예요.
다음 편은 좀 다른 이야기예요. 인스타 API를 붙여서 자동 게시를 테스트하다가 계정이 이틀 만에 잠겨버린 일을 써볼게요.