바이브 코딩에서 LLM에게 설계 방향 전달하기
Larman의 OOA/D 프로세스에서 만드는 산출물은 LLM에게 설계 의도를 전달하는 데 최적화된 형태다. 각 산출물이 프롬프트에서 어떤 역할을 하는지, 그리고 프로젝트의 어떤 시점에 어떤 걸 전달해야 하는지를 정리한다.
산출물 → 프롬프트 매핑
| 산출물 | LLM에게 전달하는 정보 | 프롬프트에서의 역할 | |---|---|---| | use-case-writing-larman\|Use Case | 시스템이 해야 할 일의 전체 범위 | 기능 요구사항의 경계 설정 | | system-sequence-diagram-larman\|SSD | API 엔드포인트 / 서비스 메서드 시그니처 | 함수 인터페이스 명세 | | domain-model-larman\|Domain Model | 엔티티, 관계, 속성 | 데이터 모델/스키마 설계 | | grasp-patterns\|GRASP 패턴 | 책임 할당 원칙 | 왜 이 메서드가 이 클래스에 있는지 설명 | | interaction-diagram-use-case-realization\|Interaction Diagram | 객체 간 메시지 호출 체인 | 메서드 구현 순서와 위임 구조 | | design-class-diagram-larman\|DCD | 완전한 클래스 명세 | 코드 생성의 직접 입력 | | gof-patterns-larman\|GoF 패턴 | 아키텍처 패턴 적용 지시 | 확장 가능한 구조 설계 |
프로젝트 단계별 프롬프트 전략
Phase 1: 프로젝트 시작 — "큰 그림 잡기"
이 시점에서 LLM에게 전달할 것: Use Case + Domain Model
"다음 유스케이스와 도메인 모델을 기반으로 프로젝트 구조를 잡아줘.
[Use Case 텍스트 - Main Success Scenario + 주요 Extensions]
[Domain Model - 엔티티 목록과 관계]
기술 스택: [원하는 스택]
아키텍처: 레이어드 아키텍처 (UI → Application/Controller → Domain → Infrastructure)
"
Phase 2: 기능 구현 — "시스템 이벤트 단위로"
이 시점에서 전달할 것: SSD의 시스템 이벤트 + Interaction Diagram의 메시지 흐름
한 번에 전체를 구현하지 말고, 시스템 이벤트 하나씩 구현한다. 이게 Larman의 iteration 방식이고, LLM 프롬프팅에서도 가장 효과적이다.
"enterItem(itemID, qty) 기능을 구현해줘.
처리 흐름:
1. Controller가 요청을 받는다
2. ProductRepository에서 itemID로 상품 조회
3. 현재 Order에 LineItem 추가 (Order가 LineItem을 생성 — Creator 패턴)
4. description과 running total을 리턴
제약:
- Order가 LineItem 컬렉션을 소유한다
- 총액 계산은 Order.getTotal()이 담당한다 (Expert 패턴)
- Controller는 Repository와 Order만 안다 (Low Coupling)
"
Phase 3: 복잡한 요구사항 — "패턴으로 구조 지시"
이 시점에서 전달할 것: GoF 패턴 이름 + 적용 대상 + GRASP 근거
"외부 결제 연동을 추가해줘.
현재 구조:
- OrderController → Order → Payment (기존 cash-only)
변경:
- Adapter 패턴: IPaymentGateway 인터페이스, StripeAdapter/TossAdapter 구현
- Factory 패턴: PaymentGatewayFactory가 환경 변수에서 어댑터 결정
- Strategy 패턴: 할인 정책을 IDiscountStrategy로 분리
원칙:
- 도메인 객체(Order)는 IPaymentGateway만 안다 (Protected Variations)
- Factory는 도메인 레이어가 아닌 Infrastructure 레이어에 배치 (Separation of Concerns)
"
핵심 원칙: LLM에게 "왜"를 알려줘야 한다
LLM은 코드를 잘 생성하지만, 설계 근거를 모르면 다음 변경에서 구조를 깨뜨린다. 프롬프트에 패턴 이름과 이유를 함께 넣으면:
- LLM이 패턴에 맞는 관용적 코드를 생성한다
- 후속 작업에서도 같은 구조를 유지한다
- 코드 리뷰 시 설계 의도가 명확하다
❌ "Payment 클래스 만들어줘"
✅ "Sale이 Payment를 생성해줘 (Creator 패턴: Sale이 Payment와 밀접하고,
Register가 만들면 불필요한 결합이 생김)"
프롬프트 템플릿
## 기능: [시스템 이벤트 이름]
### 컨텍스트
- 유스케이스: [관련 유스케이스]
- 현재 iteration에서 다루는 시나리오: [간단히]
### 처리 흐름 (Interaction Diagram 기반)
1. [Controller]가 [시스템 이벤트]를 받는다
2. [객체A]에게 [메시지]를 보낸다 — [GRASP 근거]
3. [객체B]가 [객체C]를 생성한다 — [GRASP 근거]
4. [리턴값]
### 클래스 설계 (DCD 기반)
- [클래스명]: [메서드 목록], [속성 목록]
- 관계: [A → B (이유)]
### 적용 패턴
- [패턴명]: [적용 대상] — [왜]
### 제약
- [Low Coupling/High Cohesion 관련 제약]
- [Protected Variations 지점]
이 템플릿을 채워서 LLM에게 주면, 구조적으로 일관된 코드를 생성할 수 있다. 핵심은 매번 전체를 다 쓰는 게 아니라, 해당 시스템 이벤트에 필요한 만큼만 쓰는 것이다.