Iteration을 돌 때 "뭘 깊게 파야 하는지" 모르겠을 때
초보자가 Elaboration iteration을 돌 때 부딪히는 진짜 문제는 이거다: "다음 iteration에서 뭘 더 해야 하는지 모르겠다." 경험 많은 개발자는 코드를 보고 "여기가 깨지겠다"를 직감하지만, 초보자에게는 그 직감이 없다.
이건 Larman도 인정하는 문제다. 그래서 답은 직감 대신 체크리스트를 쓰는 것이다.
핵심 원리: Iteration이 문제를 드러내준다
Iterative development의 핵심 전제는 "첫 번째 시도는 반드시 불완전하다"는 것이다. 중요한 건 불완전함을 빨리 눈에 보이게 만드는 것이지, 처음부터 완벽하게 분석하는 게 아니다.
그래서 접근법이 이렇다:
Iteration 1: 가장 단순한 해피 패스를 끝까지 만든다 (Use Case → 코드)
↓
만들면서 부딪힌 것들을 기록한다
↓
Iteration 2: 기록된 문제 중 가장 중요한 것부터 해결한다
↓
반복
"뭘 해야 할지 모르겠다"는 건 아직 Iteration 1을 안 돌았기 때문일 가능성이 높다. 일단 가장 단순한 시나리오를 끝까지 만들어보면, 문제가 스스로 드러난다.
각 산출물별 "이거 부족한데?" 체크리스트
Use Case를 다시 봐야 할 때
- [ ] Main Success Scenario만 구현했는데, 실제로 쓰면 바로 에러가 나는 상황이 있다
- [ ] "이 경우는 어떻게 하지?"라는 질문이 생겼다 → Extensions에 추가
- [ ] Stakeholder 중 빠진 사람이 있다 (예: 관리자 화면이 필요한데 Admin이 없다)
- [ ] 유스케이스 간에 겹치는 부분이 보인다 →
<<include>>관계 고려
SSD를 다시 봐야 할 때
- [ ] 외부 시스템과 통신해야 하는데 SSD에 없다
- [ ] 시스템 이벤트의 파라미터가 부족하다 (구현하다 보니 더 많은 정보가 필요)
- [ ] 리턴값이 부정확하다 (실제로 UI에 뭘 보여줘야 하는지 바뀜)
Domain Model을 다시 봐야 할 때
- [ ] 코드에서 클래스를 만들었는데, 도메인 모델에 대응하는 개념이 없다
- [ ] 속성으로 넣었던 게 사실 별도 엔티티여야 한다 (예:
price가 시간에 따라 변한다 → PriceHistory 필요) - [ ] 상속/일반화가 필요해 보인다 (Payment → CashPayment, CreditPayment)
- [ ] 연관관계의 다중성이 틀렸다 (1:1인 줄 알았는데 1:N이었다)
Interaction Diagram을 다시 봐야 할 때
- [ ] 한 객체에 메시지가 너무 몰린다 → High Cohesion 위반, 책임 분산 필요
- [ ] 객체 A가 너무 많은 다른 객체를 알고 있다 → Low Coupling 위반
- [ ] 비슷한 메시지 흐름이 타입에 따라 분기(if/switch)한다 → Polymorphism 적용
- [ ] 외부 시스템 API가 바뀌면 내부 코드가 줄줄이 바뀐다 → Adapter + Protected Variations
DCD를 다시 봐야 할 때
- [ ] 실제 코드의 클래스 구조가 DCD와 많이 다르다 → DCD 업데이트하거나 설계 재검토
- [ ] 인터페이스 없이 구체 클래스끼리 직접 의존한다 → 변경에 취약
실전 흐름: 초보자의 Iteration 전략
Iteration 1 — "일단 돌아가게"
선택 기준: 가장 핵심적인 유스케이스의 가장 단순한 시나리오. 목표: Use Case → SSD → Domain Model → Interaction Diagram → DCD → 동작하는 코드.
이때 하지 않는 것:
- 모든 Extensions 처리
- 외부 시스템 연동
- 복잡한 비즈니스 로직
- 완벽한 에러 처리
Iteration 1이 끝나면 반드시 생기는 것들:
- "이 경우는 안 되네" → Extensions 후보
- "이 객체가 너무 많은 일을 하네" → 책임 분산 후보
- "외부 서비스를 붙여야 하네" → Adapter 후보
- "가격 계산이 이것보다 복잡하네" → Strategy 후보
이것들을 목록으로 적는다. 이게 Iteration 2의 입력이 된다.
Iteration 2 — "가장 아픈 곳부터"
목록에서 가장 영향이 큰 것을 고른다. 고르는 기준:
- 이거 안 하면 시스템이 의미가 없다 → 최우선 (예: 결제 연동)
- 이거 안 하면 아키텍처가 나중에 무너진다 → 차순위 (예: 외부 서비스 인터페이스 분리)
- 이거 하면 좋지만 없어도 돌아간다 → 나중에 (예: 시니어 할인)
Iteration 3+ — "구조를 다듬기"
여기까지 오면 패턴이 보이기 시작한다:
- 반복되는 구조 → 프레임워크/공통 모듈로 추출
- 비슷한 클래스들 → 상속/인터페이스로 정리
- 비대해진 클래스 → 분리
"나는 뭐가 문제인지도 모르겠다"일 때의 마지막 수단
위의 체크리스트로도 모르겠으면, 나(Claude)에게 현재 산출물을 보여주고 물어봐라.
프롬프트 예시:
"지금 내 프로젝트의 상태야:
[Use Case 텍스트]
[Domain Model - Mermaid]
[현재 코드 구조]
Iteration 1을 끝냈는데, Iteration 2에서 뭘 해야 할지 모르겠어.
GRASP 패턴 관점에서 현재 설계의 문제점을 찾아주고,
다음 iteration에서 다뤄야 할 우선순위를 정해줘."
이게 바이브 코딩의 진짜 힘이다. 직감이 없을 때 LLM을 설계 리뷰어로 쓰는 것. 코드를 짜달라는 게 아니라, 설계를 봐달라는 거다. 이 차이가 크다.
요약
핵심: 모르는 건 부끄러운 게 아니라, 아직 한 바퀴를 안 돌았다는 신호다. 일단 가장 단순한 것부터 끝까지 만들어봐라. Iteration이 문제를 대신 찾아준다.