Upgrade to Pro — share decks privately, control downloads, hide ads and more …

[DroidKnights 2026] Workflow AX: From Auto-Docu...

Avatar for raeminKang raeminKang
November 03, 2026

[DroidKnights 2026] Workflow AX: From Auto-Documented Policies to E2E Testing

Slides from DroidKnights 2026 (Nov 2, 2026) by Raemin Kang & Dayeon Baek, Yeogi Eottae. (Slides in Korean)

How our Android team made AI coding agents work the team's way — from start to finish, with proof.

1. Harness — a frame that keeps the AI on the team's workflow until the job is done
- v1: shared team skill, Stop hook, test-gated Phase/Step
- v2: per-repo config picks the checks; scripts, not the AI, decide pass/fail

2. LLM Wiki — recording team decisions that never make it into code, so the AI reads them before it works

3. Verification — not trusting "Done!" from the AI
- Convention: andcon (Konsist, detekt, ktlint)
- UI: Roborazzi + Figma value matching
- Behavior: Maestro E2E

—

DroidKnights 2026 발표 자료입니다. AI 코딩 에이전트를 안드로이드 개발에 도입하며 하네스, LLM Wiki, 검증 도구로 문제를 푼 과정을 공유합니다.

Avatar for raeminKang

raeminKang

November 03, 2026

More Decks by raeminKang

Other Decks in Programming

Transcript

  1. ✦ DROIDKNIGHTS 2026 Workflow AX 적용기 자동 정책 정리부터 E2E까지

    강래민 백다연 여기어때컴퍼니 여기어때컴퍼니 2026.11.02 · ST센터, 서울
  2. ✦ AGENDA 목차 강래민 강래민 백다연 하네스 LLM Wiki 검증

    01 v1 하네스 04 결정을 AI가 읽게 남기기 05 컨벤션 검증 — andcon 02 v1의 한계 06 화면 검증 — Roborazzi 03 v2 하네스 07 동작 검증 — E2E 02
  3. ✦ 저희 팀 개발 프로세스 AI를 개발에 먼저 써 봤어요

    AI 투입 기획 개발 QA 배포 무엇을, 어떤 정책으로 설계하고 코드를 짜요 제대로 동작하는지 확인해요 사용자에게 내보내요 03
  4. ✦ 문제 01 제각각인 방식 PROBLEM 01 프롬프트도 스킬도 사람마다

    달랐어요 → 같은 일을 시켜도 결과물이 다 달랐어요 04
  5. ✦ 문제 02 끝까지 안 가는 개발 반만 하고 TODO로

    남겨요 적어 둔 커밋 지시도 까먹어요 05
  6. ✦ 문제 03 확인 없는 중간 과정 PROBLEM 03 한

    번에 몰아서 만들고 중간 확인이 없었어요 → 다 만든 뒤에야 문제가 보였어요 06
  7. ✦ 문제 04 정책을 모르는 AI PROBLEM 04 티켓이 잘못

    올라왔는데 바로 고쳐 버렸어요 정책은 코드에 없어서 AI는 알 수가 없었어요 07
  8. ✦ 그래서 · 하네스 일하는 방식은 하네스로, 정책은 LLM Wiki로

    01 제각각인 방식 02 끝까지 안 가는 개발 03 확인 없는 중간 과정 04 정책을 모르는 AI 하네스 LLM Wiki AI가 정해진 방식대로 끝까지 일하게 감싸 주는 틀 팀의 결정을 기록해 AI가 찾아 읽게 하는 곳 08
  9. v1 하네스, 세 문제를 풀었어요 팀 공통 스킬, Stop 훅,

    Phase·Step 확인으로 첫 하네스를 만들었어요. 9
  10. ✦ v1 하네스 · 문제 풀기 먼저, 제각각인 방식부터 문제

    01 제각각인 방식 이제 볼 문제 이제 문제 10
  11. ✦ v1 · 문제 01 제각각이면, 한곳에 모으면 돼요 문제

    사람마다 프롬프트도, 스킬도 달라 결과물이 다 달랐어요 → 그래서 떠올린 생각 "그럼 한곳에 모으면 되지 않을까?" 해결 각자의 규칙 CLAUDE.md · Rule.md · 훅 → 팀 공통 규칙 한곳에 정리 → 스킬 하나 부르면 이 규칙대로 개발 11
  12. ✦ v1 하네스 · 문제 풀기 다음은, 끝까지 안 가는

    개발 문제 02 끝까지 안 가는 개발 ✓ 해결 해결 ✓ 이제 볼 문제 이제 문제 12
  13. ✦ v1 · 문제 02 · 훅이란? 훅은 길목마다 끼우는

    스크립트예요 + 스크립트 + 스크립트 ↓ + 스크립트 ↓ → + 스크립트 ↓ → + 스크립트 ↓ → ↓ → 세션 시작 사용자 입력 도구 쓰기 직전 도구 쓴 직후 끝내려 할 때 SessionStart UserPromptSubmit PreToolUse PostToolUse Stop 13
  14. ✦ v1 · 문제 02 끝나기 전엔 못 멈추게 했어요

    1 state.json 2 에이전트가 끝내려 해요 "다 했습니다" 지금 개발이 어느 단계인지 적어 두는 파일 ↓ state.json 3 { Stop 훅이 state.json을 봐요 지금 완료 단계인가? "task_name": "qa-60255-black-curation", "base_branch": "develop", ↓ "stage": "step_implementation" } ↑ 계획 → 구현 → 검증 → 완료 순서로 바뀌어요 계획 구현 검증 아니요 완료 못 멈추게 해요 → 하던 작업을 계속해요 네 그대로 멈춰요 14
  15. ✦ v1 하네스 · 문제 풀기 마지막, 확인 없는 중간

    과정 문제 03 확인 없는 중간 과정 ✓ 해결 ✓ 해결 이제 이제볼 볼문제 문제 15
  16. ✦ v1 · 문제 03 단계마다 테스트로 확인했어요 큰 작업

    하나 ↓ 잘게 나눠요 Phase 1 Phase 2 Step 1-1 TC ✓ TC ✓ Step 2-1 Step 1-2 TC ✓ TC … Step 2-2 Phase와 Step을 state.json에 적어 두고, 훅이 순서를 지키게 해요 TC TC TC 1 Step마다 테스트를 먼저 적어요 ↓ 훅이 확인 · 테스트가 없으면 코드를 못 써요 2 테스트를 통과하며 Step을 진행해요 ↓ 훅이 확인 · Phase 테스트가 다 통과해야 커밋 3 다음 Phase로 넘어가요 16
  17. ✦ 완성된 v1 하네스 통과해야 다음 단계로 가요 1 2

    3 4 계획 구현 최종 검증 완료 Plan 모드로 항상 계획부터 → Phase마다 반복 Phase 1, 2, 3 … 구현 테스트 → QA 에이전트가 한 번 더 확인 → state.json에 완료라고 적어요 커밋 ↺ 통과 못 하면 다시 구현 ↺ 문제면 다시 고침 17
  18. ✦ v1의 한계 · 팀원들의 후기 모아 보니, 결국 두

    가지였어요 피드백 1 피드백 2 너무 오래 걸려요 다른 플랫폼에서 못 써요 문구 하나 고치는데 검증이 너무 무거워요 웹 저장소에선 못 쓰겠어요 작은 일에도 계획 세우느라 오래 걸려요 iOS에도 도입할 수 있나요? phase·step으로 나누는 게 정말 도움 되나요? 웹 작업인데 안드로이드 검증 스킬을 불러와요 … … 19
  19. ✦ v2 하네스 · 달라진 점 v1에서 이렇게 달라졌어요 피드백

    1 · 너무 오래 걸려요 - 검사는 고른 것만 - 계획은 필요할 때만 피드백 2 · 다른 플랫폼에서 못 써요 - 검사 목록은 config에 - 웹에도 같은 하네스 어떻게 만들었는지, 하나씩 볼게요 21
  20. ✦ v2 하네스 · 피드백 풀기 먼저, 오래 걸리는 이유

    피드백 1 · 원인 1 검사가 매번 전부 돌아요 이제 볼 문제 이제 문제 22
  21. ✦ 피드백 1 · 원인 1 검사가 매번 전부 돌았어요

    작은 작업 큰 작업 문구 하나 바꾸는 QA 여러 화면을 건드리는 개발 돌아간 검사 ✓ 컨벤션 검사 돌아간 검사 = ✓ 컨벤션 검사 ✓ unit-test ✓ unit-test ✓ 최종 QA 에이전트 ✓ 최종 QA 에이전트 23
  22. ✦ 해결 1-1 · 검사를 골라 쓰려면? config로 빼서 동적으로

    넣으면? 개발자가 고름 config.yaml verifications: - andcon 1 → [✓] andcon ] ui-verify - ui-verify [ - e2e [✓] e2e 검사 목록은 config에 저장소가 가진 검사 전부 하네스 (코드는 그대로) QA 티켓 수정 2 개발 시작할 때 골라서 이번 작업에 필요한 것만 → 검증 계획 → 구현 → andcon → 마무리 e2e 3 검증 단계에 동적으로 하네스 코드는 그대로 24
  23. ✦ 해결 1-1 · 훅의 원리 훅은 끝나는 숫자와 출력으로

    움직여요 훅 스크립트 정해진 순간에 실행되고, 끝날 때의 숫자와 출력을 Claude Code가 읽어요 exit 2 멈춰 세워요 exit 0 말을 걸어요 스크립트 끝부분 스크립트 끝부분 echo "force push 금지" >&2 exit 2 echo '{ "hookSpecificOutput": { "hookEventName": "PostToolUse", "additionalContext": "지시문" } }' exit 0 하려던 일이 실행되지 않고, 이유가 전달돼요 통과시키면서, 적은 글이 추가 지시로 들어가요 예: git push --force 를 못 하게 해요 예: "바뀐 화면을 디자인과 대조하라" 25
  24. ✦ 해결 1-1 · 그래서 떠올린 것 두 가지를 합치면

    될 것 같았어요 알게 된 것 1 알게 된 것 2 하네스는 일을 정한 순서대로 해요 계획 → 구현 → 검증 → 마무리 → + 완료 훅은 Claude Code에 말을 걸 수 있어요 exit 0 + JSON → 추가 지시 ↓ 그럼 검증 단계에 들어갈 때, 훅이 config를 읽어서 넣어 주면 되겠다! 26
  25. ✦ 해결 1-1 · 동적 주입 훅 — 원리 config의

    검사를 지시로 넣어 줘요 1 config에서 꺼내요 2 안드로이드 저장소 · config.yaml JSON으로 내보내요 3 AI에게 들어가요 훅이 내보내는 JSON { verifications: - name: andcon prompt: 컨벤션에 맞는지 andcon으로 확인 - name: ui-verify prompt: 바뀐 화면을 디자인과 대조 - name: e2e prompt: 바뀐 흐름을 E2E로 확인 → "hookSpecificOutput": { "hookEventName": "PostToolUse", "additionalContext": "검증 단계예요. - 컨벤션에 맞는지 andcon으로 확인 - 바뀐 화면을 디자인과 대조 - 바뀐 흐름을 E2E로 확인" } 검증 단계예요. → · 컨벤션에 맞는지 andcon으로 확인 · 바뀐 화면을 디자인과 대조 · 바뀐 흐름을 E2E로 확인 } exit 0 훅은 검사 내용을 몰라요. config에 적힌 글을 옮겨 줄 뿐이에요 27
  26. ✦ 해결 1-1 · 그런데, 숨겨진 문제 "통과했습니다"를 믿을 수밖에

    없었어요 통과했어요 ✓ 검증 단계 지시 > E2E 돌려서 확인해 줘 → → ? 돌렸다는 증거 시키기만 하고, 정말 했는지는 확인하지 않았어요 28
  27. ✦ 해결 1-1 · 동적 검사 훅 넘어가려는 순간, 직접

    돌려서 확인해요 2 1 다음 단계로 넘어가려 해요 AI "검증 끝났어요" 그때 훅이 떠요 run을 돌려요 성공 → 넘어가요 안드로이드 config (요약) → - name: e2e prompt: gc-e2e를 활용해서 E2E 시나리오를 만들어줘 run: e2e-latest-pass.py → 실패 → 못 넘어가요 이유가 다음 지시가 돼요 ↺ 통과할 때까지 고치고 다시 prompt는 시키고, run은 확인해요 29
  28. ✦ 해결 1-1 · 정리 이제 작업마다, 필요한 검사만 돌아가요

    QA 티켓을 고칠 때 문구 하나 바꿀 때 코드 구조만 바꿀 때 > QA-60255 고쳐줘 > 빈 화면 문구 바꿔줘 > 화면 이동을 UiEffect로 바꿔줘 [✓] ui-verify [✓] ui-verify [ [ [ ] andcon [✓] andcon [ ] e2e [ ] andcon [✓] e2e run run ] ui-verify ] e2e run ↳ 훅이 E2E 통과를 직접 확인해요 실패하면 고치고 다시 돌아요 고쳐진 흐름까지 확인해요 화면만 확인해요 팀 규칙만 확인해요 고른 검사만 들어가고, run이 있는 검사는 통과해야 넘어가요 30
  29. ✦ v2 하네스 · 피드백 풀기 오래 걸리는 두 번째

    이유 피드백 1 · 원인 2 작은 일도 매번 계획하고 나눠요 ✓ 해결 해결 ✓ 이제 볼 문제 이제 문제 31
  30. ✦ 원인 2 · 작은 일도 매번 계획부터 스킬을 둘로

    나누고, 사람이 골라요 dev-workflow-plan dev-workflow-simple 크고, 여러 화면을 건드리는 일 작고, 범위가 분명한 일 계획 → 구현 → 검증 작은 작업 · 걸린 시간 구현 → 검증 여러 화면을 건드리는 큰 작업 · 결함이 나온 비율 평균 19.1분 plan simple 사람이 골라요 평균 9.3분 simple도 결함 없이, 절반 가까이 빨랐어요 plan simple 25% 78% simple은 결함이 세 배 넘게 나왔어요 (plan 4번 중 1번 · simple 9번 중 7번) 32
  31. ✦ 원인 2 · 잘게 나누는 게 꼭 필요할까? 나눠도

    완성도는 같았어요 작은 작업 (안드로이드) 100% phase로 나눔 = 차이 없음 큰 작업 (웹빌더) 100% 안 나눔 93.1% ≈ 94.4% phase로 나눔 안 나눔 안 나눴을 때가 1.3%p 높음 phase로 나누는 것만 켜고 끄고 · 같은 작업 · 같은 시작 코드 · 같은 채점 기준 · 조건마다 3번 35
  32. ✦ 해결 1-2 · 단계를 단순하게 이제 구현은 모델에게 맡겨요

    v1 v2 계획 계획 하네스가 안내 → → 구현 phase × step 반복 하네스가 잘게 통제 구현 모델에게 맡김 최종 검증 → → 검증 하네스가 확인 → 마무리 하네스가 확인 → 완료 → 완료 36
  33. ✦ v2 하네스 · 피드백 풀기 마지막, 다른 플랫폼 피드백

    2 다른 플랫폼에서 못 써요 ✓ 해결 ✓ 해결 이제 이제볼 볼문제 문제 37
  34. ✦ 해결 2 · 다른 플랫폼에도 그대로 같은 훅, 저장소마다

    다른 검사 같은 훅 스크립트 config 읽기 → JSON → exit 0 웹 저장소 · config.yaml 안드로이드 저장소 · config.yaml LLM Wiki 저장소 · config.yaml verifications: - lint - typecheck - unit-test - build verifications: - andcon - ui-verify - e2e verifications: - bats ↓ ↓ AI에게 들어가는 지시 AI에게 들어가는 지시 lint typecheck ↓ unit-test andcon ui-verify … AI에게 들어가는 지시 e2e bats build 하네스도 훅도 그대로, 저장소마다 config만 달라요 38
  35. ✦ v2 하네스 · 정리 v2 하네스의 흐름 실패하면 다시

    구현 → → → → 사람 사람 AI 하네스 하네스 계획할지 고르기 검증 고르기 구현 검증 마무리 plan · simple 이번 작업에 필요한 것만 통째로 맡겨요 고른 검사를 확인해요 이번에 정한 정책 정리 39
  36. ✦ 여기까지 · 하네스 남은 건 흩어진 정책이에요 기획 개발

    QA 무엇을, 어떤 정책으로 설계하고 코드를 짜요 제대로 동작하는지 확인해요 정책은 기획에도, 개발에도 흩어져 있었어요 40
  37. 코드에 남지 않는 결정, LLM Wiki로 코드만으로는 알 수 없는

    히스토리와 정책. AI가 스스로 찾아 읽고 판단할 수 있게, 지식 라이브러리로 남겨요. yeogi-library 41
  38. ✦ 문제 · 정책을 모르는 AI AI가 엉뚱하게 고쳐요 1

    QA 티켓 2 AI가 고친 화면 → "리뷰 사진에 스크린샷이 안 골라져요" 3 실제 정책 → 스크린샷도 업로드되도록 수정해 버렸어요 스크린샷은 일부러 막았어요 적립금 어뷰징을 막으려고요 → 2번은 정책 위반 42
  39. ✦ 문제 · 커밋 커밋엔 '왜'가 안 남아요 commit a1f3c

    블랙 홈 큐레이션은 20개까지만 보여 준다 개발자 "왜 20개까지만이지? 버그인가?" → 커밋 기록 무엇을 바꿨는지만 있고 이유는 없어요 43
  40. ✦ 문제 · 흩어진 결정 결정의 이유가 흩어져 있었어요 →

    "이 정책, 이게 맞아요?" 퇴사 "그거 정한 담당자가 퇴사했어요…" Slack "슬랙에 있었는데… 어느 스레드였더라" Confluence "컨플에 적어 뒀는데, 갱신이 안 됐어요" 회의 "회의 때 말로만 정했던 것 같은데…" 결정의 이유가 흩어져 있거나, 아예 사라져 버렸어요 44
  41. ✦ LLM Wiki · 고민했던 점 AI가 읽는 결정 기록을

    만들었어요 01 · 시점 언제 기록할까 이제 볼 고민 이제 고민 45
  42. ✦ 고민 01 · 시점 끝날 때 쓰고, 시작할 때

    읽어요 계획 시작할 때 기록부터 찾아 읽어요 관련 정책을 검색해서 구현 → 다음 작업에서 ← → 팀 라이브러리 정책 기록이 쌓여요 검증 마무리 → 올려요 ← 끝날 때 정한 정책을 남겨요 템플릿에 맞춰, 있으면 갱신 policy-sync 46
  43. ✦ LLM Wiki · 고민했던 점 다음은, 무엇을 담을지 02

    · 내용 어떤 내용을 담을까 ✓ 해결 해결 ✓ 이제 볼 고민 이제 고민 47
  44. ✦ 고민 02 · 기술 기록 (fact) 어디서나 통하는 사실은,

    기술 기록으로 라이브러리·플랫폼을 쓰다 알게 된, 다른 회사에서도 맞는 사실 AI fact ab-testing/statsig-android-init….md > 로그인하면 Statsig 사용자 정보도 바꿔 줘 kind: fact tags: [statsig, 초기화, crash] # Statsig는 초기화가 끝나기 전에 updateUserAsync를 부르면 앱이 죽는다 ## 확인된 동작 값 읽기는 괜찮고, 사용자 갱신만 크래시 ⏺ yeogi-library - library_search (MCP)(query: "Statsig updateUserAsync") 찾아 읽음 → ⎿ fact · 초기화 전 updateUserAsync는 크래시 ⏺ 초기화가 끝난 뒤에 사용자 정보를 바꾸도록 넣을게요. ## 확인 방법 ⏺ Update(StatsigManager.kt) IllegalStateException 로그 · 공식 문서 대조 ⎿ Updated StatsigManager.kt with 2 additions and 1 removal ## 함의 사용자 갱신은 초기화 완료 콜백 뒤로 미룬다 12 - Statsig.updateUserAsync(user) 12 + onReady { updateUserAsync(user) } ## 안 다룬 것 iOS SDK · 서버 SDK 48
  45. ✦ 고민 02 · 결정 기록 (decision-record) 팀 결정은 결정

    기록으로 저희 서비스와 팀이 정한 규칙, 그리고 그 이유 AI decision-record black/black-home-curation-max-20….md kind: rule tags: [블랙, 큐레이션, 노출개수] > QA 티켓: 블랙 홈 상품이 20개에서 끊겨요. 고쳐 줘 # 블랙 홈 큐레이션은 20개까지만 보여 주고, 더보기 는 두지 않는다 ## 규칙 CMS에 21개 이상 등록돼도 앱이 20개까지만 자른다 ## 적용 범위 블랙 홈 큐레이션 (국내·해외 모두) ## 근거 2026-09-07 기획 논의 · Slack 스레드 출처: yourteam.slack.com/archives/C01AB2CD3EF/p1757200000000000 찾아 읽음 → ⏺ yeogi-library - library_search (MCP)(query: "블랙 큐레이션 20개") ⎿ decision-record · 칩셋당 20개까지, 더보기 없음 ⏺ 버그가 아니라 기획에서 정한 정책이에요. 20개까지만 보여 주기로 했 어요. 어떻게 할까요? ❯ 1. 지금 정책 유지 (기존 결정) 2. 결정을 바꾸고 전부 보여 주기 ## 예외 없음 49
  46. ✦ LLM Wiki · 만든 뒤 확인 정말 쓰이는지 확인했어요

    03 · 확인 정말 쓰이고 있을까 ✓ 해결 ✓ 해결 이제 이제볼 볼확인 확인 50
  47. ✦ 확인 · 판단이 바뀌었나 같은 티켓인데, 판단이 정반대였어요 "버그네요,

    고칠게요" QA 티켓 ✕ 정책을 뒤집음 "정책이에요, 반려할게요" 스크린샷이 안 골라져요 ✓ 기록을 찾아 읽음 LLM Wiki 프롬프트는 같고, LLM Wiki 연결만 달라요 51
  48. ✦ 확인 · 얼마나 쓰였나 AI는 기록을 읽고 반영했어요 최근

    한 달 · 세션마다 검색 · 열람 · 반영을 기록 2,322 회 검색 열람한 기록이 실제 작업에 반영된 비율 열람 540 회 작업 반영 504 회 52
  49. ✦ 확장성 · 지식 공유 AI를 위한 기록, 팀의 창구로

    예전 # DM QA팀 동료 지금 QA QA팀 동료 LLM Wiki QA팀 동료가 직접 질문 QA QA팀 동료 블랙 홈 큐레이션에 상품이 20개에서 끊기고 더보기도 없어요. 버그로 올려야 할까요? 오후 2:14 다니 오후 2:20 블랙 홈 큐레이션 상품이 20개에서 끊기고 더보기가 없어요. 의 도된 정책이에요, 버그예요? → LLM Wiki 잠시만요, 슬랙이랑 회의록 찾아볼게요… 오후 2:14 오후 2:41 의도된 정책이에요. 20개까지만 보여 줘요. 묻는 사람도, 답하는 사람도 매번 시간을 소비 오후 2:14 의도된 정책이에요. 칩셋 하나당 20개까지만 보여 주고, 모듈 안에 더보기 버튼은 두지 않아요. 근거 · decision-record · 2026-09-07 기획 논의로 결정 사람이 아닌 기록이 바로 답변 53
  50. ✦ 여기까지 · LLM Wiki 남은 건 검증이에요 LLM Wiki

    기획 개발 QA 무엇을, 어떤 정책으로 설계하고 코드를 짜요 제대로 동작하는지 확인해요 54
  51. ✦ 검증 검증, 믿고 넘겨도 될까요? AI로 구현은 빨라졌지만, 빌드하고

    실행해서 눈으로 확인하는 일은 여전히 사람 몫이었어요. 55
  52. ✦ 지금까지의 검증 확인은 결국 사람이 했어요 AI · 개발

    완료 사람이 확인 01 02 03 빌드하고, 앱 켜고, 시안 띄워 놓고 규칙 팀 규칙대로 짰을까? 화면 시안대로 그려졌을까? QA 동작 끝까지 이어질까? ↺ 하나라도 이상하면, 처음부터 다시 56
  53. ✦ 문제 · 코드 규칙 동작은 하는데, 팀 컨벤션과 달랐어요

    MR !2871 숙소 상세 화면 구현 DetailViewModel.kt class DetailViewModel : ViewModel() { fun onLoadFailed(e: Throwable) { Log.e("Detail", "숙소 정보 로드 실패", e) R Reviewer 변경 요청 이 줄에 코멘트 · 1시간 전 Log 말고 GCLog 써 주세요. 팀 컨벤션이에요 58
  54. ✦ 첫 번째 시도 컨벤션을 주고, AI에게 판단을 맡겼어요 convention-check.md

    # 팀 컨벤션 체크 검사자: AI · 대상: 숙소 상세 화면 - [x] 1. 화면 이동은 UiEffect로 보내자 - [x] 2. collectAsStateWithLifecycle로 구독하자 - [x] 3. 로그는 Log 대신 GCLog를 쓰자 **AI 판단: 모두 지킴** (3 / 3) 그런데 실제 코드를 열어 보니 ✓ 1. 화면 이동은 UiEffect로 보내자 sendEffect(UiEffect.GoToBooking) ✓ 2. collectAsStateWithLifecycle로 구독하자 .collectAsStateWithLifecycle() ✕ 3. 로그는 Log 대신 GCLog를 쓰자 Log.e("Detail", "로드 실패", e) "왜 안 지켰어?" — "아차, 잊었네요" 59
  55. ✦ andcon을 만든 계기 AI와 정적 분석 도구를 합쳤어요 AI

    규칙 뽑기 코드에서 규칙을 잘 뽑아내요 정적 분석 도구 andcon 검사 검사하면 언제나 같은 결과가 나와요 규칙은 AI가 뽑고, 검사는 도구가 해요 60
  56. ✦ andcon andcon은 세 가지 일을 해요 Android Convention ·

    우리 팀 컨벤션을 지키게 하는 도구 1 2 3 규칙 뽑기 도구가 읽게 옮기기 검사하기 가끔 · AI가 초안, 팀이 OK 규칙이 바뀔 때 · 검사 설정으로 매번 · AI 없이, 점수로 61
  57. ✦ 첫 번째 일 · 규칙 뽑기 규칙은 AI가 제안하고,

    팀이 정해요 AI가 뽑은 규칙 HomeViewModel.kt DetailScreen.kt BookingRepository.kt ✓ UiEffect는 sealed 계층 conventions.yml ✓ collectAsStateWithLifecycle 사용 + compose.ui_effect_sealed ✓ 로그는 GCLog로 남기기 ✓ GlobalScope 사용 금지 + flow.collect_with_lifecycle + logging.no_android_util_log + flow.no_globalscope 우리 코드베이스 팀 확인했어요, 이대로 넣어 주세요 62
  58. ✦ 두 번째 일 · 도구가 읽게 규칙을 도구별로 나눠

    맡겨요 conventions.yml Konsist → Konsist 테스트 detekt → detekt.yml andcon이 도구마다 읽는 설정으로 옮겨 적어요 AI 없이, 정해진 틀대로 ktlint → .editorconfig 63
  59. ✦ 세 번째 일 · 맞는 도구가 검사 · 1/3

    Konsist는 구조를 봐요 Konsist 이런 규칙을 맡아요 ViewModel은 presentation 레이어에 UI 레이어는 data 구현체 import 금지 UiState는 sealed 계층으로 예시 규칙 UI 레이어는 data 구현체 직접 import 금지 ✕ 위반 // …/home/presentation/HomeViewModel.kt import …data.home.HomeRepositoryImpl ✓ 통과 // …/home/presentation/HomeViewModel.kt import …domain.home.HomeRepository 64
  60. ✦ 세 번째 일 · 맞는 도구가 검사 · 2/3

    detekt는 쓰면 안 되는 것을 봐요 detekt 이런 규칙을 맡아요 android.util.Log 직접 사용 금지 GlobalScope 사용 금지 Material2 컴포넌트 사용 금지 예시 규칙 android.util.Log 직접 사용 금지 ✕ 위반 import android.util.Log Log.e("Detail", "숙소 정보 로드 실패", e) ✓ 통과 GCLog.e("숙소 정보 로드 실패", e) 65
  61. ✦ 세 번째 일 · 맞는 도구가 검사 · 3/3

    ktlint는 형식을 봐요 ktlint 이런 규칙을 맡아요 파일명은 최상위 클래스명과 같게 @Composable 함수는 PascalCase 허용 선언·호출의 trailing comma 허용 예시 규칙 파일명은 최상위 클래스명과 같게 ✕ 위반 // HomeScreen.kt class HomeViewModel : ViewModel() ✓ 통과 // HomeViewModel.kt class HomeViewModel : ViewModel() 66
  62. ✦ 세 번째 일 · 검사 — 판정 점수를 깎아

    통과 여부를 정해요 andcon check warning UiEffect를 sealed로 안 만듦 100 결과는 파일로 남아요 −5 .andcon/last-check.json info 줄 길이 초과 · HomeScreen.kt −1 info 줄 길이 초과 · DetailScreen.kt −1 ✓ 통과 { "passed": true, "score": 93, "violations": [ … ] } 67
  63. ✦ 결과 이제 AI가 알아서 팀 규칙에 맞춰요 Before After

    리뷰어가 잡아 줬어요 R Log 말고 GCLog 써 주세요. 팀 컨벤션이에요 AI가 알아서 → GCLog로 고쳐 왔어요 Log.e → GCLog.e ✓ andcon 통과 리뷰어가 말하기 전에, AI가 먼저 맞춰 와요 68
  64. ✦ 정답 · 겹쳐 보기 상품명 아래 간격이 2dp 달라요

    상품명 아래 간격이 시안보다 2dp 넓어요 71
  65. ✦ 화면 확인 화면 하나에 매번 빌드했어요 숙소 상세 화면,

    시안대로 다 만들었어요 ✓ 지금은 이러면 어떨까요 확인하려면 매번 빌드하고 화면을 찾아가요 빌드 없이, 바뀐 화면만 바로 시안을 따로 띄워 번갈아 봐요 시안 옆에 나란히 2dp 같은 차이는 눈으로 못 찾아요 어디가 몇 dp 다른지 짚어 주기 72
  66. ✦ 화면 검증 흐름 도구가 먼저, 사람은 판정만 지금은, 사람이

    직접 사람 빌드하고 화면 찾아가서 시안과 비교 바뀐 화면만 찾고 빌드 없이 그리고 다른 곳만 짚고 ↺ 고칠 때마다 반복 이제는, 도구가 먼저 사람은 판정만 73
  67. ✦ Roborazzi · 활용 빌드 없이 화면을 그려요 에뮬레이터 없이,

    테스트 코드 없이. 직접 확인 Roborazzi 빌드 → IDE · 기기에 띄우기 프리뷰 또는 APK 컴파일 바뀐 모듈만 → 화면 하나씩 확인 사람이 직접 → @Preview 찾기 프리뷰 스캐너 → JVM 위에서 렌더 Robolectric → PNG로 저장 이미지 파일 generateComposePreviewRobolectricTests Robolectric 프리뷰 스캐너 기기 없이 JVM 렌더 코드에 이미 있는 @Preview를 자동으로 찾아, 테스트 코드 없이 캡처해요 앱을 기기에 올리지 않고, JVM 위에서 바로 화면을 그려 이미지로 남겨요 75
  68. ✦ 첫 번째 시도 · 픽셀 비교 픽셀로는 진짜 차이를

    못 찾았어요 겹쳐 보니 카드 전체가 빨갛게 나왔어요 그래서 정말 다른 곳이 어디인지 한눈에 알기 어려웠어요. 그래서 이미지가 아니라, 숫자를 비교하기로 했어요. 76
  69. ✦ 해결 · 수치 대조 비슷해 보여도, 수치까지 확인해요 AI가

    이미지를 한 번 보고, 스크립트가 Figma 수치와 코드를 1:1로 비교해요 77
  70. ✦ 결과 리포트 보고 사람이 판정해요 01 시안과 구현을 나란히

    02 다른 곳만 짚어 줘요 03 판정은 사람이 78
  71. 동작 검증, 화면과 화면 사이 확인하기 버튼을 눌렀을 때 실제로

    동작하는지, 진입부터 완료까지 확인해요. 79
  72. ✦ 문제 · 기존 방식 따로 보면 맞는데, 흐름에서 어긋나요

    01 02 03 검색 숙소 상세 날짜 변경 ✓ 화면은 시안대로 ✓ 화면은 시안대로 ✓ 화면은 시안대로 ? 04 예약 ✓ 화면은 시안대로 "어? 날짜 바꿨는데, 예약 화면엔 예전 날짜가 나와요!" QA 화면 하나하나는 맞아도, 화면과 화면 사이에서 문제가 생겨요 80
  73. ✦ 첫 번째 시도 시키면 사라지고, 남기면 쌓여요 이 QA

    티켓 재현해 줘 adb $ screencap $ input tap 540 1200 $ input text 제주 ≡ wishlist-empty.yaml → ≡ login-entry.yaml ≡ qa-search-result.yaml 매번 처음부터 파일로 남아 쌓여요 시키면 사라지고, 남기면 쌓여요 81
  74. ✦ 도구 고르기 YAML 하나로 끝나는 Maestro Appium Maestro 작성·검토

    요소 찾기부터 동작까지 코드로 다 짜야 해요 화면 문구로 찾고, YAML 몇 줄이면 끝나요 안정성 로딩마다 wait·sleep을 직접 넣어야 해요 화면이 준비될 때까지 알아서 기다려요 AI 연결 서버·드라이버를 먼저 띄워 둬야 해요 MCP로 만들고, CLI로 반복해서 돌려요 82
  75. ✦ Maestro만 쓸 때 형식은 같아도, 내용은 제각각이에요 > 이메일로

    로그인하는 시나리오 짜 줘 A가 만든 yaml A B가 만든 yaml - tapOn: "이메일로 시작하기" ✕ 글자로만 찾기 - runFlow: /Users/b/entry.yaml - inputText: "[email protected]" ✕ 계정이 그대로 - tapOn: "로그인" - tapOn: "로그인" - assertVisible: "홈" B ✕ 내 PC에서만 ✕ 로그인됐는지 모름 이대로 남겨 두면, 다시 쓰기 어려워요 83
  76. ✦ 팀 규칙 그래서 팀 규칙을 넣었어요 common/login.yaml 팀 규칙

    적용 - openLink: "yeogi://user?actionDetail=login" - tapOn: id: "login_btn_email" - inputText: ${MAESTRO_LOGIN_EMAIL} ← 태그를 먼저 ← 계정은 파일 밖에 - inputText: ${MAESTRO_LOGIN_PW} - tapOn: id: "login_btn_submit" - runFlow: ../common/login-verify.yaml ← 확인은 공통 플로우로 누가 시켜도 같은 규칙으로, 팀 누구나 다시 쓸 수 있어요 84
  77. ✦ 활용 1 · 피처 개발 개발 중에도 E2E로 확인해요

    여러 화면을 오가는 흐름 검색 → 숙소 상세 → 날짜 변경 → 예약 → 바뀐 날짜가 예약 화면까지 이어지는지 프록시 · 팀에서 직접 만든 MCP 행동 로그 실제 서버로 못 만드는 상황까지 로그가 실제로 쌓였는지까지 서버 응답을 바꿔 시나리오와 함께 실행 나가야 할 이벤트·횟수·값을 정의하고, 수집 서버에 쌓였는지 확인 500 에러 home_view × 1 느린 네트워크 빈 응답 banner_click ✕ 85
  78. ✦ 활용 2 · 회귀 테스트 태그 한 줄이면, 회귀

    케이스가 돼요 개발하며 만든 시나리오 중, 계속 볼 것을 골라 login-entry.yaml home-category-hotel.yaml wishlist-empty.yaml 이럴 때 한 번에 돌려요 모아서 flows/home-category-hotel.yaml ✓ 배포 전 새 버전 통합 검증 때 회귀 묶음 name: home-category-hotel tags: [regression, foreign] + 한 줄 추가 regression --- runFlow: ../common/app-entry.yaml ✓ 리팩터링 후 기존 기능이 깨지지 않았는지 개발하며 만든 시나리오가, 배포 전 확인 목록이 돼요 86
  79. ✦ 결과 고친 결과가 영상으로 남아요 [QA-12345] 날짜 변경 후

    예약 화면 날짜 미반영 수정 QA-12345 날짜를 바꿨는데 예약 화면엔 예전 날짜가 나와요 ↓ 시나리오로 Merged 개요 커밋 - tapOn: "11월 7일" 예약 날짜 변경 사항 수정 전 수정 후 ✕ 예전 날짜 그대로 ✓ 바꾼 날짜로 6.23.2 빌드 - tapOn: "예약하기" - assertVisible: "11.7 (토)" 파이프라인 검증 booking-date-change.yaml - tapOn: "날짜 변경" !1234 영상 - takeScreenshot: booking-date-change ▶ ▶ before.mp4 after.mp4 87
  80. ✦ 정리 · 하네스 설정 검증을 하네스에 담았어요 하네스 검증

    단계 .dev-workflow/config.yaml verifications: - andcon # 규칙 - unit-test # 로직 - ui-verify # 화면 - e2e # 동작 검증마다 한 줄씩 적어요 → ✓ 통과하면 01 02 규칙 로직 andcon 유닛 테스트 03 04 화면 동작 ✕ 실패하면 UI 검증 E2E 무엇이 왜 실패했는지 받아서 ↺ 통과할 때까지 고쳐요 훅이 지시하고, 결과를 직접 확인해요 다음 단계로 넘어가요 → 통과하지 못하면, AI는 끝낼 수 없어요 88
  81. ✦ 마무리 AI와 함께 이렇게 개발해요 LLM Wiki 하네스 andcon

    · UI · E2E 기획 개발 QA 무엇을, 어떤 정책으로 설계하고 코드를 짜요 넘기기 전에 먼저 확인해요 89