본문으로 건너뛰기
mokee.
Seoul--:--:--
2026.11.159 min read#Frontend#AI

AI 팀원을 매일 믿고 맡기기까지

슬랙에 사는 FE 봇을 만들며 배운 것 — 데모가 아니라 매일 일을 맡기려면 필요한 다섯 가지: 작업 공간 나누기, 통과해야 머지되는 검사, 여러 리뷰어, 권한 확인, 사람의 승인.

Claude Code 로 슬랙 봇을 만드는 것 자체는 어렵지 않습니다. 부르면 답하고, 코드를 고쳐 PR 을 올리는 데까지는 하루면 됩니다. 진짜 어려운 건 그다음, 팀이 매일 안심하고 일을 맡기게 만드는 것이었습니다.

동료의 작업을 덮어쓰지 않을 것, 확인하지 않은 걸 했다고 말하지 않을 것, 되돌릴 수 없는 일은 꼭 사람에게 물어볼 것. 이 세 가지를 프롬프트로 "부탁"하는 대신 코드로 "강제"하면서 만든 다섯 가지 장치를 정리했습니다.

봇은 이렇게 일합니다

구조는 단순합니다. Bun + NestJS 로 만든 봇 서버가 슬랙 메시지 하나당 Claude Code 의 CLI(claude -p)를 한 번 실행합니다. 실행하기 전에 rate limit(일정 시간 동안 쓸 수 있는 횟수 제한)·사용 한도·동시 실행 수를 확인하고, 봇의 역할과 팀 문서, 스레드 내용을 모아 프롬프트를 만듭니다. 실행 중에는 stream-json(진행 상황을 한 줄씩 흘려 주는 출력 형식)을 받아 "지금 뭐 하는 중인지"를 슬랙 스레드에 남깁니다.

diagram
sequenceDiagram
  participant U as 슬랙 사용자
  participant B as 봇 서버
  participant C as Claude CLI
  U->>B: 봇 멘션 · 스레드 답글
  B->>B: rate limit · 사용 한도 · 동시 실행 수 확인
  B->>B: 프롬프트 조립 (봇의 역할 · 팀 문서 · 스레드 · 첨부)
  B->>C: claude -p 실행
  C-->>B: stream-json 으로 진행 상황 전달
  B-->>U: "지금 뭐 하는 중" 한 줄씩
  C-->>B: 최종 답 · 이미지 · 슬라이드 덱(HTML)
  B-->>U: 답과 첨부 파일
슬랙 메시지 하나 = Claude CLI 실행 한 번

일하는 법은 스킬(마크다운으로 쓴 작업 절차서)로 쪼개 둡니다. "코드 리뷰는 이렇게", "PR 은 이렇게" 같은 것들이죠. 서른 개가 넘는 절차서를 매번 컨텍스트(모델이 한 번에 읽는 입력)에 다 넣으면 느리고 비쌉니다. 그래서 평소엔 이름과 한 줄 설명만 들고 있다가, 요청이 맞아떨어질 때만 그 절차서의 본문을 펼칩니다. 팀 리뷰 규칙도 이번 PR 에서 바뀐 파일에 해당하는 것만 골라 넣습니다.

봇이 하는 일

장치 이야기를 하기 전에, 봇이 실제로 무슨 일을 하는지부터 보겠습니다. 부르면 답하고, 부르지 않아도 아침마다 팀이 챙길 일을 정리해 보냅니다. 크게 네 가지 일을 합니다.

코드 리뷰 — 바뀐 줄만 보지 않습니다

바뀐 줄(diff)만 보지 않고, 그 코드를 부르는 곳까지 거슬러 올라가 문제의 심각도를 매깁니다. 문제를 찾으면 main 브랜치에서도 똑같은지 먼저 대조해서, 이번 PR 이 만든 문제인지 원래 있던 문제인지 가립니다.

  • 같은 버그 찾기 — 버그를 고치는 PR 이면, 같은 방식으로 짠 다른 코드도 뒤집니다.
  • 이미 있는 구현과 대조 — 새로 만든 모듈이 기존 코드를 다시 짠 건 아닌지 확인합니다.
  • 파일 전수 확인 — 바뀐 파일 중 하나라도 안 보고 넘어가면 스크립트가 리뷰 게시를 막습니다.
  • 팀 리뷰 규칙 — 노션에 저장소·경로별 리뷰 규칙을 모아 두고, 이번에 바뀐 파일에 맞는 규칙만 골라 읽습니다.

파일이 많은 큰 PR 에는 아키텍처 브리프를 만들어 주간 팀 회의 안건에 올립니다. 예를 들어 3주 동안 이어진 리팩터링(PR 47개)을 "다음 작업 전에 코드를 어디에 두나"라는 관점으로 다시 묶어, 설계 그림과 코드 지도 한 장으로 정리했습니다.

레이어 지도 — 위에서 아래로만 가져다 씁니다. 주황색 층이 흩어져 있던 사본 5벌을 모은 곳
코드 지도 — 공개 입구별로 가져다 쓰는 파일 수와 영향받는 화면. 숫자는 실제 코드 검색으로 센 값
새 위젯을 추가할 때 거치는 곳
새 모듈을 추가할 때 거치는 곳
회의에서 화면 공유하며 위에서부터 따라 읽는 파일 7곳

브리프에는 "구조만 옮겼는데 결과가 달라진 곳"도 따로 뽑아 둡니다. 리팩터링 리뷰에서 가장 놓치기 쉬운 부분이라, 리뷰어가 여기부터 보면 됩니다.

스레드 → PR — "이거 고쳐 줘" 다음에 일어나는 일

슬랙 스레드에서 "이거 고쳐 줘"라고 하면, 봇은 이런 순서로 PR 까지 갑니다.

  • 되묻기 — 요청이 애매하면 슬랙 버튼으로 한 번에 하나씩 묻습니다.
  • plan 승인 — 작업 계획을 사람이 승인하기 전에는 git 명령을 한 줄도 실행하지 않습니다.
  • 새 작업 폴더 — 공유 체크아웃은 건드리지 않고 PR 전용 worktree 에서 작업합니다.
  • 저장소 규칙 읽기 — CLAUDE.md · AGENTS.md 같은 저장소의 작업 규칙 문서를 먼저 읽습니다.
  • 셀프리뷰 — 설계 검토용 서브에이전트(별도로 띄운 검토 전담 AI)가 최대 4번까지 검토하고, 심각한 지적만 자동으로 반영합니다.
  • PR — 요청자를 담당자로 지정하고, 본문에 "돌려 본 검증 / 못 돌려 본 검증"을 나눠 적습니다. 버그 수정이면 고친 코드를 되돌렸을 때 실패하는 회귀 테스트까지 붙입니다.

QA · 스크린샷 — 눈으로 확인하고 증거를 남깁니다

코드만 고치고 끝내지 않고, 화면을 직접 찍어 확인합니다.

  • 진짜 iOS Safari — Xcode 시뮬레이터와 Appium XCUITest(iOS 앱을 자동으로 조작하는 테스트 도구)로 확인합니다. 작업하는 동안 사용자의 마우스 커서는 건드리지 않습니다.
  • 웹 화면 전·후 캡처 — Playwright 로 모바일 폭(390px) 화면을 찍습니다. 관리자 화면처럼 PC 에서 쓰는 화면은 1440×900 으로 찍습니다.
  • 디자이너 스레드에 바로 — GitHub 을 열지 않아도 슬랙에서 바로 검수할 수 있게 합니다.
  • 빈칸 금지 — 못 찍었으면 "못 찍음 — 이유"를 적습니다.

실제 사례. 디자이너가 "상품 목록에서 길게 누르면 글자가 선택되고 복사 메뉴가 뜬다"는 영상을 스레드에 올렸습니다. 봇은 영상에서 프레임을 뽑아 문제 장면(5초, 9~11초)을 짚고, 코드와 대조해 "막는 스타일이 실제로는 그 요소에 걸려 있지 않다"는 걸 파일·줄 단위로 찾았습니다. plan 승인을 받아 CSS 몇 줄을 고친 뒤, 시뮬레이터에서 같은 글자를 1.5초 길게 눌러 전·후를 비교했습니다.

수정 전 — 길게 누르면 글자 선택 + 복사 메뉴
수정 후 — 같은 곳을 눌러도 아무것도 안 뜸

그리고 확인한 것과 사람에게 넘길 것을 나눠 보고했습니다. 시뮬레이터에서 전·후를 확인했지만, 앱 안 웹뷰 설정과 실제 기기의 터치감은 시뮬레이터로 확인할 수 없으니 배포 후 폰으로 한 번 봐 달라고요. 검수한 디자이너는 캡처가 올라온 그 자리에서 바로 반응했습니다.

검수한 디자이너의 한 줄 반응

또 다른 사례로, 서버가 내려주는 화면 구성(스키마)을 설명해 달라는 요청에서 시작해 실제 화면 QA 까지 간 적도 있습니다. 실제 요청을 확인하고(페이지 1번 + 부분 갱신 7번), 계정 상태에 따라 레이아웃이 달라진다는 걸 발견하고, 버튼을 하나씩 눌러 이동한 주소와 스크린샷으로 판정했습니다. 문제는 FE 결함 / 운영 데이터 / 서버로 나누고, 커밋 기록을 보고 누가 고치면 좋을지까지 정해 FE 결함 3건을 두 명에게 나눴습니다.

다른 봇과 협업 — 모르는 건 아는 봇에게

앱이나 서버 쪽 사실이 필요하면, 그 팀의 봇에게 직접 물어봅니다(A2A, Agent to Agent). 무엇을 확인할지 한 문장으로 정리해서, 한 번에 두 개까지만 묻습니다. 대신 안전장치를 겹겹이 둡니다.

  • 우리 쪽 코드와 문서로 확인할 수 없을 때만 묻습니다.
  • 받는 쪽은 허용한 봇만, 스레드 하나당 봇 호출은 최대 3번.
  • 봇이 시작한 실행에서는 다른 봇을 다시 부르지 않습니다 — 봇끼리 끝없이 서로 부르는 걸 막습니다.

다른 리뷰 봇의 지적도 같은 방식으로 처리합니다. 지적마다 코드로 확인해서 반영 / 반박 / 확인 / 논의 네 갈래로 나누고, 커밋 → 푸시 → 재리뷰 요청을 승인(approve)이 날 때까지 반복합니다.

운영 · 데이터 — 자리를 지키고, 숫자를 챙깁니다

  • 온콜(당번) — 팀 그룹 멘션에 바로 답하고 노션에 기록합니다. 빠진 기록은 정기 작업이 채웁니다. 다른 팀 담당 문의는 그 팀 그룹을 멘션해 넘깁니다.
  • 배포 — 스레드에서 알파·베타·정기 배포를 실행하고, CI 와 배포를 지켜보다 결과를 스레드에 답니다.
  • 부재 중 대리 응답 — 담당자가 없을 때, 질문은 지금 답하고 요청은 복귀 후로 나눠 안내합니다.
  • 지표 질문 — 데이터 웨어하우스(Databricks)를 먼저 보고, 없으면 Amplitude 로 넘어가 차트까지 그려 줍니다.
  • JIRA · 아침 브리핑 — 티켓을 만들고 넘기고, 착수 가능일 순으로 담당자를 추천합니다. 아침마다 미응답 스레드·팀 현황·이번 주 챙길 일을 DM 으로 보냅니다.

이 모든 일을 스킬 36개와 정해진 시간에 도는 정기 작업(크론) 11개로 나눠 맡깁니다.

작업 공간 나누기 — 서로 덮어쓰지 않게

봇은 여러 요청을 동시에 처리하고, 같은 저장소를 사람도 씁니다. 작업 폴더(체크아웃)가 하나뿐이면 누군가 브랜치를 바꾸는 순간 옆에서 고치던 내용이 날아갑니다. 실제로 몇 번 겪었습니다.

그래서 PR 하나마다 git worktree 를 새로 만듭니다. worktree 는 저장소 하나에서 서로 다른 브랜치를 담은 작업 폴더를 여러 개 만들 수 있게 해 주는 git 기능입니다. 새 작업 폴더는 항상 원격 저장소의 최신 커밋에서 시작하고, 원래 폴더는 읽기만 합니다 — 브랜치를 바꾸거나(checkout) 변경을 되돌리는(reset) 명령은 금지입니다.

diagram
flowchart TB
  subgraph before["전 — 작업 폴더가 하나"]
    direction LR
    P1["사람"] --> S[("같은 폴더 · 같은 브랜치")]
    A1["봇 작업 A"] --> S
    B1["봇 작업 B"] --> S
  end
  subgraph after["후 — PR 마다 따로"]
    direction LR
    A2["봇 작업 A"] --> WA[("작업 폴더 A")]
    B2["봇 작업 B"] --> WB[("작업 폴더 B")]
    P2["사람"] --> O[("원래 폴더")]
  end
  before ~~~ after
원래 폴더에서는 브랜치를 바꾸거나 변경을 되돌리지 않습니다

코멘트로 알려 주기보다, 통과해야 머지되게

GitHub 에서 리뷰를 Comment(의견만 남기기)로 달면 머지를 막지 못합니다. 지적이 다른 코멘트에 묻히면 그대로 머지되고, 배포 뒤에 문제가 터져서 다시 고치러 돌아오죠. 반대로 Request changes(수정 요청)나 required status check(통과해야만 머지되는 필수 CI 검사)는 통과하기 전까지 머지 버튼 자체가 눌리지 않습니다.

봇이 꼭 지켜야 하는 규칙은 모두 후자처럼 만들었습니다. 커밋 전에 스스로 다시 검토하는 셀프리뷰, 바뀐 파일 중 하나라도 안 보고 넘어가면 리뷰를 올리지 못하게 막는 스크립트, 버그를 고쳤다면 고친 코드를 되돌렸을 때 실패하는 회귀 테스트(고친 버그가 다시 생기지 않는지 확인하는 테스트)까지 — 전부 통과해야 다음 단계로 갑니다. 프롬프트에 "꼭 확인하세요"라고 쓰는 것보다 훨씬 확실합니다.

diagram
flowchart LR
  subgraph comment["Comment — 알려 주기만"]
    direction LR
    t1["작성"] --> t2["코멘트 남김"] --> t3["머지"] --> t4["배포 후 문제 · 다시 수정"]
  end
  subgraph block["Request changes · 필수 체크 — 통과해야 머지"]
    direction LR
    g1["작성"] --> g2{"검사 통과?"}
    g2 -- "아니오" --> g1
    g2 -- "예" --> g3["머지"]
  end
  comment ~~~ block

판단은 모델에게, 틀리면 안 되는 단계는 코드로. 바뀐 파일 목록을 세거나 화면을 캡처하는 것처럼 정해진 대로만 하면 되는 일은 스크립트가 합니다.

리뷰어를 여럿 두기

코드를 만든 쪽이 스스로 검토하면, 만들 때 놓친 부분을 검토할 때도 똑같이 놓칩니다. 그래서 관점이 다른 리뷰를 세 겹으로 둡니다.

diagram
flowchart TB
  C["같은 코드 변경"] --> R1["셀프리뷰<br/>요구사항대로인가 · 구조는 괜찮은가 · 테스트 결과가 진짜인가"]
  C --> R2["팀 리뷰 규칙으로 검토<br/>같은 실수를 한 다른 코드는 없나 · 이미 있는 기능을 또 만들지 않았나"]
  C --> R3["다른 리뷰 봇 · 동료 리뷰<br/>앞의 둘이 못 본 부분"]
  R3 -. "놓친 문제" .-> T["회귀 사례로 추가"]

리뷰를 정말 잘하고 있는지도 숫자로 봅니다. 봇이 받은 요청과 답, 걸린 시간과 비용을 모두 로그로 남기고, 대시보드가 매일 아침 채점합니다 — 첫 답까지 걸린 시간, 봇이 지적한 줄이 이후 커밋에서 실제로 바뀌었는지, 사람 답글 없이 끝난 스레드가 얼마나 되는지. 그리고 봇이 놓쳤던 버그는 그 당시 커밋으로 되돌려 다시 리뷰를 시켜 봅니다. 일종의 벤치마크(같은 문제로 성능을 비교하는 시험)입니다. 리뷰 스킬을 고친 PR 에는 "벤치마크를 돌려 보세요"라는 안내가 자동으로 붙습니다.

diagram
flowchart LR
  A["로그<br/>무엇을 했나"] --> B["채점<br/>잘했나"] --> C["벤치마크<br/>고치니 나아졌나"] --> D["스킬 · 규칙 수정"] --> A

누가 시킨 일인지부터 확인하기

한 스레드에도 권한이 다른 사람들이 섞여 있습니다. 그래서 봇은 일을 받으면 아래 네 가지를 순서대로 확인합니다.

diagram
flowchart TB
  W["우리 팀 일인가?<br/>아니면 담당 팀에 넘기고, 애매하면 되묻기"] --> F["무엇이 사실인가?<br/>문서보다 실제 API 응답과 코드로 확인"]
  F --> A["지금 손대도 되나?<br/>plan 을 사람이 승인한 뒤에만 · 일괄 변경은 dry-run 먼저"]
  A --> P["이 사람이 시켜도 되는 일인가?<br/>요청한 사람 기준으로 판단 · 앞서 다른 사람이 시킨 일의 결론은 그대로 쓰지 않기"]

여기서 dry-run 은 실제로 바꾸지 않고 "이렇게 바뀔 예정"만 미리 보여 주는 실행입니다. 그리고 사소하지만 효과가 컸던 것 하나. 한 사람이 슬랙·GitHub·JIRA·Notion 에 계정이 넷입니다. 팀원마다 네 서비스의 계정 ID 를 한 표로 묶어 두고, 이름이 아니라 ID 로 연결했더니 PR 담당자(assignee)를 짐작으로 지정하는 일이 사라지고 알림도 정확히 그 사람에게 갑니다.

사람은 되돌리기 어려운 두 지점에만

단계마다 사람이 확인하면 봇을 쓰는 의미가 없습니다. 사람은 되돌리기 어려운 두 지점에만 섭니다. 작업 계획(plan)을 승인할 때, 그리고 머지할 때. 그 사이는 봇이 혼자 몇 번이고 고치고 되돌립니다.

diagram
flowchart LR
  R["요청"] --> Q{"요청이 애매한가?"}
  Q -- "예" --> K["슬랙 버튼으로 되묻기"] --> Q
  Q -- "아니오" --> PL["plan 작성"]
  PL --> H1(("사람이 plan 승인"))
  H1 --> W["새 worktree 에서<br/>수정 · 테스트"]
  W --> SR["셀프리뷰<br/>최대 4번"] --> PR["PR"]
  PR --> H2(("사람이 머지"))
사람이 서는 곳은 plan 승인과 머지, 두 곳뿐

PR 본문의 검증 결과는 돌려 본 것과 못 돌려 본 것을 나눠 적게 했습니다. 스크린샷을 못 찍었으면 비워 두지 말고 "못 찍음 — 이유"를 쓰게 하고요. 이게 쌓이니 봇이 만든 PR 을 믿고 보는 속도가 확실히 빨라졌습니다.

정리하면

  • 사고 하나에 규칙 한 줄. 날짜와 실제 사례를 같이 적어 두면, 나중에 "이 규칙 왜 있지?" 싶을 때 답이 됩니다.
  • 프롬프트로 부탁하지 말고 검사로 막기. 꼭 지켜야 하는 건 코멘트가 아니라 머지를 막는 검사로 만드세요.
  • 모델에겐 판단만. 세고, 찍고, 확인하는 일은 스크립트에 맡기는 편이 결과가 훨씬 안정적입니다.
  • 리뷰어는 여럿. 만든 쪽과 분리하고, 보는 관점이 다른 리뷰를 겹쳐 두세요.
  • "해 봤다"와 "못 해 봤다"를 나눠 쓰게 하기. 봇에 대한 신뢰는 대부분 여기서 쌓였습니다.
  • 사람은 되돌리기 어려운 지점에만. 나머지는 봇이 알아서 고치고 되돌리게 두는 편이 서로 편합니다.
diagram
flowchart LR
  R["규칙<br/>봇의 역할 · 스킬 · 교훈 노트"] --> E["실행<br/>답 · 리뷰 · PR"] --> L["로그<br/>대화 · 비용 · 반영 여부"] --> V["평가<br/>대시보드 · 벤치마크"] --> U["규칙 수정"] --> R
한 번 고치고 끝이 아니라, 이 고리를 계속 돌립니다

마치며

돌아보면 봇에게 요구한 건 좋은 동료에게 기대하는 것과 크게 다르지 않았습니다. 남의 작업을 덮어쓰지 않고, 확인한 것과 못 한 것을 솔직하게 나눠 말하고, 되돌리기 어려운 결정은 함께 내리는 것. 다른 점은 하나였습니다. 사람에게는 팀 문화로 기대하는 것을, 봇에게는 코드로 강제해야 했다는 것.

팀에 AI 봇을 들이려고 고민하고 있다면, 기능을 하나 더 붙이기 전에 "이걸 매일 믿고 맡길 수 있나?"부터 물어보세요. 저희는 그 질문에 답하느라 기능보다 장치를 더 많이 만들었고, 그 덕분에 봇이 신기한 데모가 아니라 팀의 일상이 됐습니다.

Comments