AI로 일하기

같은 커밋 하나에, 팀 넷이 각자 다른 이유로 브레이크를 밟았습니다 🛑

생각에 잠긴 초록이 아빠

아침에 커피를 내리면서 리포트 넷을 훑어보는 게 요즘 제 루틴입니다. 돈독(제가 혼자 만드는 가족 자산관리 앱, https://don-doc.com )을 개발·기획·디자인·마케팅 네 역할로 나눠서 AI 에이전트가 매일 점검하거든요. 오늘 아침엔 좀 다른 걸 봤습니다. 같은 날 아침에 막 병합된 기능 하나를, 네 역할이 각자 다른 이유로 “아직 쓰면 안 된다”고 멈춰 세운 겁니다.

오늘 아침 병합된 기능

08시 41분, 잔액 0인 미사용 계좌를 정리하자는 제안 배너 기능이 main에 들어갔습니다. 6개월 넘게 거래가 없고, 잔액도 예수금도 0이고, 보유 종목이나 하위 계좌·연결된 부채도 없는 계좌를 찾아서 “정리해도 될까요?” 배너로 보여주는 기능입니다. 스펙 문서 없이 커밋 하나(62d02a9)로 바로 병합됐는데, 9월 7일 자산 연결 보드 때와 똑같은 패턴입니다 — 만들고 나서야 다른 역할들이 열어보는 방식이요.

개발이 코드를 열어보니, 정반대의 결함 두 개가 나왔습니다 ⚠️

삽질하다 멘붕한 초록이 아빠

정리 후보를 뽑는 함수는 거래 이력이 있는지는 안 봅니다. 잔액·보유종목·하위계좌·연결부채, 이 네 가지만 검사합니다. 실제로 테스트 코드에도 거래가 41건 있는 계좌가 정상 후보로 통과하는 케이스가 그대로 들어 있었습니다.

문제는 그다음입니다. 후보를 실제로 지우는 함수가 계좌 삭제 함수를 호출할 때 force 옵션을 안 넘깁니다. 그런데 계좌 삭제 함수 쪽은 거래 이력이 있는 계좌를 force 없이 지우려고 하면 거부하고 “한 번 더 누르면 지워집니다” 안내만 돌려줍니다. 결과가 뭐냐면, 거래 이력이 있는 계좌(가장 흔한 케이스일 겁니다)는 정리를 몇 번을 눌러도 매번 같은 방식으로 거부당해서 영원히 정리되지 않습니다.

반대로 거래가 아예 없는 계좌는 어떨까요. 이쪽은 조건 검사를 다 통과하자마자 곧바로, 되돌릴 장치 없이 영구히 지워집니다. 정리해야 할 흔한 계좌는 아무리 눌러도 안 지워지고, 진짜 위험한 즉시삭제는 조용히 실행되는 셈입니다. 방향이 완전히 반대로 뒤집혀 있었던 겁니다.

기획이 가설을 세우고, 개발이 그날 안에 확정했습니다

같은 날 기획 담당이 먼저 이 기능을 열어보고 “소프트 삭제 흔적이 안 보인다, 하드 삭제로 추정된다”고 가설을 남겼습니다. 몇 시간 뒤 개발 담당이 코드와 테스트 파일을 직접 대조해서 이 가설을 확정했고, 위에서 설명한 정반대 결함까지 추가로 찾아냈습니다. 가설을 낸 역할과 확정한 역할이 갈려 있으니, 추정과 사실이 문서에 섞이지 않습니다.

디자인이 센 것 — 삭제 진입점 네 곳 중, 확인 단계가 있는 곳은 한 곳뿐

같은 커밋이 계좌를 영구히 지우는 진입점을 네 곳 만들었습니다. 기존에 있던 개별 삭제 버튼 하나만 2단계 확인(눌러서 안내 뜨고, 한 번 더 눌러야 실행)을 거칩니다. 이번에 새로 생긴 나머지 세 곳 — 배너 개별 삭제, 배너 일괄 정리, 보드 일괄 정리 — 는 전부 클릭 한 번에 바로 실행됩니다. 정리 후보는 애초에 거래가 없다는 전제라 기존 확인 로직을 그대로 못 쓴 게 원인인데, 그렇다고 확인 자체를 생략하면 안 된다는 게 디자인 담당의 판단이었습니다. 버튼 색도 문제였습니다 — 파괴적인 일괄 정리 버튼이 “계좌 추가” 버튼과 똑같은 고강조 스타일을 쓰고 있었거든요.

같은 커밋이 삭제 진입점을 네 곳 만들었는데, 확인 단계가 있는 곳은 한 곳뿐이었습니다.

마케팅은 이번 주 소재에서 이 기능을 뺐습니다

마케팅 담당의 판단은 셋과 결이 달랐습니다. 코드를 고치라는 게 아니라, “지금 상태로는 이 기능을 밖에 알리지 않는다”였습니다. 이유는 간단합니다 — 그동안 “정리 전에 확인부터, 그다음엔 되돌리기까지”라는 메시지를 계속 만들어왔는데, 지금 이 기능은 그 약속과 정반대로 동작합니다. 실제 코드에 없는 안전장치를 있는 것처럼 알리지 않는다는 원칙을 그대로 지킨 겁니다.


따라 하기

비슷하게 역할을 나눠 AI 에이전트 팀을 굴리고 있다면, 오늘 이 넷이 실제로 한 것들은 그대로 옮겨 쓸 수 있습니다.

1. 오늘 들어온 커밋부터 먼저 확인하기

git log --since="1 day ago" --oneline
git show <커밋해시> --stat
  • 첫 줄로 오늘 뭐가 들어왔는지부터 훑습니다. 스펙 문서 없이 원샷으로 병합된 커밋이 있는지가 특히 중요합니다 — 그런 커밋일수록 아무도 검토를 안 했을 가능성이 높습니다.

2. 조건이 실제로 코드에 다 들어갔는지 호출부까지 따라가기

grep -rn "<함수이름>" .
  • 함수를 실제로 부르는 곳이 몇 군데인지, 어떤 옵션을 넘기고 어떤 옵션을 빼먹었는지 직접 봅니다. “리포트가 안전하다고 했다”를 그대로 믿지 않고, 호출부까지 따라가 봅니다.

3. 한 역할의 가설을 다른 역할이 diff로 확정하게 하기

git diff <브랜치명> main -- <파일경로>
git merge-tree main <브랜치명>
  • 첫 번째로 실제 코드가 다른지 확인하고, 두 번째로 병합했을 때 충돌이 나는지 미리 시뮬레이션합니다. “추정”과 “확정”을 프롬프트에서부터 구분해두면, 나중에 어느 쪽이 맞았는지 되짚기가 쉬워집니다.

4. 위험 신호가 하나라도 뜨면 다른 역할이 자동으로 멈추게 규칙 심어두기

마케팅 역할 프롬프트에 이런 문장 하나면 충분합니다.

같은 주 다른 역할(개발·디자인) 리포트에 P0/P1 급 위험이 남아 있는 기능은
이번 라운드 소재에서 제외하고, 제외 사유를 한 줄로 남긴다.
  • 이렇게 되면 성공 — 코드를 고치기 전엔 그 기능이 홍보 자료에 등장하지 않습니다.
  • 막히면 — 역할별 리포트가 서로 다른 파일에 흩어져 있으면 이 교차 확인이 안 됩니다. 최소한 “오늘 리포트”끼리는 한곳에서 같이 읽을 수 있게 모아두세요.

배운 것

화이팅하는 초록이 아빠

오늘 배운 건 하나입니다. 기능 하나를 빨리 만드는 것보다, 그 기능을 서로 다른 눈으로 멈춰 세울 수 있는 구조를 만드는 게 더 오래갑니다. 개발은 코드가 약속대로 동작하는지를 보고, 디자인은 되돌릴 수 없는 액션에 확인 단계가 있는지를 보고, 기획은 추정과 확정을 가르고, 마케팅은 지금 알려도 되는지를 봅니다. 네 역할이 각자 다른 질문을 들고 있어야, 한 커밋의 위험이 어느 한쪽 눈에서라도 걸립니다.

이 기능은 아직 고쳐지지 않았습니다. 다음에 이어서 어떻게 고쳤는지, 혹은 왜 못 고쳤는지 적겠습니다.

오늘도 한 걸음. 🐴

이 글은 산업 구조와 만드는 과정을 정리한 개인 기록입니다.
특정 종목의 매수·매도 추천이 아니며, 투자 판단과 그 결과는 독자 본인에게 있습니다.

← 글 목록으로