로드맵을 끝까지 소진한 앱이 다섯 개인데, 그중 한 앱에는 아직 통과하지 못한 마일스톤이 남아 있습니다. 정적 분석도 테스트도 코드 리뷰도 전부 통과했는데 통과가 아닙니다. 개선했다고 말하려면 개선됐는지 다시 재야 하기 때문입니다.
1. 로드맵을 다 쓴 앱이 다섯 개입니다
자율 파이프라인으로 만든 앱이 8개인데, 그중 5개가 로드맵을 다 썼습니다. 등록된 마일스톤을 전부 소진하고 출시 이후 단계로 넘어가 있다는 뜻입니다. 나머지 셋은 아직 하류 루프가 돌고 있습니다.
처음 설계할 때 저는 이 자리를 종점이라고 불렀습니다. 그런데 지난 글에서 말씀드린 사고가 여기서 나왔습니다. 문서에 종점이라고 적어 뒀더니 에이전트가 배포를 결승선으로 읽고, 그다음을 할지 말지 저에게 물어보러 왔습니다. 무중단으로 돌라고 만든 파이프라인이 정작 배포 직후에 멈춰 선 것입니다.
자율·무중단 워크플로 문서에서 중간 산출물을 “종점·완료·끝”으로 부르지 마라. 한 단어가 전체 무중단을 깬다.
— LESSONS.md 2026-07-07
그래서 이름을 바꿨습니다. 종점이 아니라 순환의 입구입니다.
2. 그 입구에 통과하지 못한 마일스톤이 있습니다
다섯 개 중 하나를 열어 보겠습니다. 빨래 앱인데, 여섯 번째 마일스톤이 텔레메트리 기반 튜닝입니다. 알림을 언제 보낼지, 태스크 점수 가중치를 어떻게 줄지를 실제 사용 기록을 보고 조정하겠다는 것입니다.
"id": "M6",
"title": "텔레메트리 기반 알림 타이밍·가중치 튜닝",
"type": "data-driven",
"passes": false
이 마일스톤에 붙은 합격 조건이 5개인데, 두 종류로 갈립니다.
앞의 셋은 코드 꼬리표입니다. 정적 분석이 0건인가, 테스트가 통과하는가, 아키텍처 검사를 지나는가. 8화에서 말씀드린 그 꼬리표입니다.
뒤의 둘에는 텔레메트리 꼬리표가 붙어 있습니다. 튜닝한 뒤에 알림 오픈율이 다시 측정되어야 하고, 태스크 조회 분포가 다시 측정되어야 한다는 조건입니다. 각 조건에는 재측정할 이벤트 이름이 박혀 있습니다.
실제 결과는 이렇습니다. 코드 쪽 셋은 전부 통과했습니다. 정적 분석은 깨끗했고, 테스트 180개가 통과했고, 아키텍처 검사도 지났습니다. 코드 리뷰는 별도 검증자 둘이 승인했습니다. 그런데 마일스톤 자체에는 통과 표시가 붙지 않았습니다. 감사 기록에는 텔레메트리 조건이 데이터를 기다린다고 적혀 있습니다.
구현을 다 하고 검증까지 마친 뒤에 게이트가 통과를 거부한 것입니다.
3. 출시 후에는 질문이 바뀝니다
왜 이렇게 만들어 뒀는지 말씀드리겠습니다. 출시 이후의 개선은 성격이 다릅니다.
그전까지는 만들었는가가 질문이었습니다. 여기서부터는 나아졌는가가 질문입니다. 그런데 나아졌다는 것은 코드를 봐서는 알 수가 없습니다. 알림 시각을 세 시간 당기는 변경은 코드로는 한 줄이고 테스트도 통과합니다. 그것이 개선인지 개악인지는 코드 안에 답이 없습니다.
그래서 개선 마일스톤을 만드는 명령에 조건을 하나 걸어 뒀습니다.
enqueue <app>/.factory \
--title "<개선명>" \
--spec "<지표 근거 + 구현 범위>" \
--success-event <event>
# --success-event 없으면 거부된다
성공을 다시 잴 이벤트를 지정하지 않으면 큐잉을 거부합니다. 개선하겠다는 제목과 근거만으로는 마일스톤이 만들어지지 않습니다. 무엇이 좋아졌다고 말할 것인지, 그것을 어떤 이벤트로 확인할 것인지를 같이 적어야 등록됩니다. 적을 수 없으면 그 개선은 애초에 큐에 들어가지 못합니다.
이것을 넣은 이유는 자기 채점을 막기 위해서입니다. 9화에서 심사원에게 점수를 물으면 후하게 나온다고 말씀드렸는데, 개선은 그것보다 더 심합니다. 만든 사람도 고친 사람도 좋아졌다고 믿습니다. 그래서 좋아졌다는 판정을 아무에게도 맡기지 않고 이벤트 하나에 묶어 뒀습니다.
4. 그런데 서버가 없습니다
여기서 문제가 하나 생깁니다. 3화에서 이 공장은 서버를 두지 않기로 했다고 말씀드렸습니다. 백엔드가 없으니 사용자가 무엇을 눌렀는지 우리 서버로 올라오는 것이 없습니다. 그럼 재측정을 무엇으로 하느냐. 서버를 안 두기로 한 결정이 개발 단계에서는 편했는데 출시 이후 단계에서 청구서를 내민 셈입니다.
그래서 지표원을 세 단으로 두고 우선순위를 매겼습니다.
- 로컬 텔레메트리 — 앱 안에서 이벤트를 기기에 직접 쌓아 두고 그 스냅샷을 뽑아 옵니다. 자격증명이 하나도 필요 없고 결정적입니다.
- GA4 실지표 — 자격증명이 있을 때만 씁니다.
- 사람 제공 지표 — 마지막 폴백입니다.
위에서부터 시도하는 것이 중요합니다. 1순위가 자격증명 0으로 도니까 사람 인계에서 멈추지 않습니다.
실제로 뽑아 둔 파일이 하나 있습니다. 계산 근육이라는 앱인데 이벤트 7종이 들어 있습니다. 앱을 연 것이 1번, 문제를 푼 것이 9번, 오답 신고가 1번.
{
"app_opened": 1,
"problem_solved": 9,
"answer_reported": 1,
"streak_updated": 1
}
여기서 정직해야 할 부분이 있습니다. 이것은 실사용 지표가 아닙니다. 에뮬레이터 검증 세션에서 쌓인 숫자입니다. 그래서 이 파일이 답하는 질문은 하나뿐입니다 — 계약된 이벤트가 실제로 발화되는가.
재겠다고 적어 둔 이벤트가 코드에 배선은 돼 있는데 실제로는 한 번도 안 불리는 경우가 있습니다. 그럼 나중에 재측정 자체가 불가능합니다. 이 파일은 사용자가 얼마나 쓰는지는 못 알려 주지만, 잴 준비가 됐는지는 알려 줍니다. 실사용 지표의 대체재가 아니라 그 앞 단계 점검입니다.
5. 없으면 지어내지 않습니다
세 단이 전부 비어 있으면 어떻게 하느냐. 여기가 제일 중요한 자리입니다.
어떤 소스도 없으면 지표를 지어내지 않는다 — sweep이 needs_data로 표기한다.
지표를 지어내지 않습니다. 개선 후보를 뽑는 명령이 데이터가 필요하다고 표기하고 거기서 멈춥니다. 그럴듯한 숫자를 만들어 넣으면 그 뒤 판정이 전부 오염됩니다. 근거 없이 만든 마일스톤은 통과 판정도 근거 없이 나고, 그것이 쌓이면 로드맵 전체가 소설이 됩니다.
멈추는 규칙도 같이 넣었습니다.
- 지표원이 전부 없다 →
needs_data보고 후 정지 - 근거 있는 개선 후보가 없다 → 종료 보고 후 정지
- 재측정 이벤트를 못 적는다 → 큐잉 거부
자율 루프에 개선이라는 이름을 붙여 두면 끝없이 돌 수 있습니다. 뭐라도 고칠 거리는 언제나 있으니까요. 그래서 돌 이유가 없으면 멈추는 것을 기본값으로 뒀습니다. 도는 것이 기본값이면 그 루프는 일하는 게 아니라 움직이는 것입니다.
정리하면 이 순환에는 관문이 두 개 있습니다. 들어갈 때는 재측정할 이벤트가 없으면 큐에 못 들어갑니다. 나올 때는 그 이벤트가 실제로 다시 측정되지 않으면 통과가 안 됩니다. 두 관문이 같은 이벤트 이름을 보고 있습니다.
6. 이 순환은 아직 한 바퀴를 돌지 못했습니다
이 글에서 제일 정직하게 말씀드려야 할 부분입니다.
설계는 끝났고 게이트도 실제로 작동했습니다. 마일스톤 하나를 실제로 묶어 뒀으니까요. 그런데 그 마일스톤을 풀어 줄 실사용 데이터가 아직 없습니다. 그래서 지금은 도는 중이 아니라 기다리는 중입니다. 성과를 말씀드릴 자리가 아니라 설계를 말씀드릴 자리입니다.
그런데 저는 이 상태가 실패라고 생각하지 않습니다. 데이터가 없을 때 자동화가 취할 수 있는 태도는 두 가지입니다.
| 돌게 만들기 | 멈추게 만들기 |
|---|---|
| 그럴듯한 근거를 만든다 | needs_data로 보고한다 |
| 통과 판정이 계속 난다 | 마일스톤이 미통과로 남는다 |
| 무엇이 개선됐는지 아무도 모른다 | 무엇이 없는지가 남는다 |
지금 이 파이프라인은 오른쪽을 하고 있고, 마일스톤 하나가 통과되지 않은 채로 남아 있는 것이 그 증거입니다.
7. 정리
출시는 종점이 아니라 순환의 입구고, 그 순환은 재측정으로 닫힙니다. 개선했다고 말하려면 개선됐는지 다시 재야 하고, 잴 수 없으면 등록하지도 통과시키지도 않습니다. 지금 통과하지 못한 마일스톤 하나가 그 규칙이 살아 있다는 증거입니다.
여기까지가 앱이 도는 이야기였습니다. 다음 글에서는 앱이 아니라 공장 자신이 어떻게 나아지는지 이야기하겠습니다.
앱 공장 · 12화
이전 글: 앱 공장 11화 – 콘솔을 기계가 운전하게 만들었더니, 그중 하나는 API가 있었습니다 · 앱 공장 시리즈 전체 보기


답글 남기기