AI를 활용한 설계에서 요구사항, 모듈 경계, 데이터·API 계약, 테스트, 신뢰성을 명확히 하도록 유도하는 검증된 프롬프트 패턴을 배우세요—리팩터링과 재작성 주기를 줄입니다.

이 글에서 말하는 “더 깔끔한 아키텍처”는 특정 프레임워크나 완벽한 다이어그램을 의미하지 않습니다. 그것은 시스템을 간단히 설명할 수 있고, 관련 없는 부분을 깨뜨리지 않고 변경할 수 있으며, 영웅적인 테스트 없이 동작을 검증할 수 있다는 뜻입니다.
**명확성(Clarity)**은 짧은 설명만으로 시스템의 목적과 형태가 분명하다는 뜻입니다: 무엇을 하는지, 누가 사용하는지, 어떤 데이터를 다루는지, 절대 해서는 안 될 일이 무엇인지. AI 지원 작업에서는 모델이 요구사항을 당신이 승인할 수 있는 방식으로 다시 진술할 수 있어야 합니다.
**모듈성(Modularity)**은 책임이 깔끔한 경계로 나뉜다는 의미입니다. 각 모듈은 수행해야 할 일, 입력/출력, 그리고 다른 모듈 내부를 최소한만 알아야 합니다. AI가 코드를 생성할 때 모듈성이 없으면 비즈니스 규칙이 컨트롤러, UI, 데이터 접근 계층에 널리 퍼집니다.
**테스트 용이성(Testability)**은 ‘작동을 증명하는’ 비용이 싸야 한다는 뜻입니다. 비즈니스 규칙은 전체 실행 시스템 없이도 테스트할 수 있고, 통합 테스트는 모든 코드 경로 대신 몇 개의 계약에 집중합니다.
리라이트는 보통 “나쁜 코드” 때문이 아니라 누락된 제약, 모호한 범위, 그리고 숨은 가정 때문입니다. 예시:
AI는 설득력 있는 결과물을 빠르게 만들어내므로, 흔들리는 기반 위에 쉽게 구축되도록 만듭니다. 그럴수록 나중에 리라이트 가능성이 커집니다.
앞에 나오는 패턴들은 복제해서 쓰는 템플릿이지 마법의 명령어가 아닙니다. 실제 목적은 초기부터 올바른 대화를 강제하는 것입니다: 제약을 명확히 하고, 옵션을 비교하며, 가정을 문서화하고, 계약을 정의하세요. 만약 그 사고 과정을 건너뛰면 모델이 기꺼이 빈칸을 채울 것이고, 나중에 비용을 치르게 됩니다.
다음 전주기에서 사용하세요:
vibe-coding 같은 워크플로우(채팅으로 시스템을 생성하고 반복하는 방식)를 사용한다면, 이러한 체크포인트는 더 중요합니다. 예를 들어 Koder.ai에서는 React/Go/PostgreSQL 코드를 생성하기 전에 “계획 모드” 루프를 돌려 요구사항과 계약을 고정한 뒤, 스냅샷/롤백으로 가정이 바뀌더라도 안전하게 반복할 수 있습니다—모든 변경이 리라이트로 이어지지 않도록요.
프롬프트 패턴은 결정 회전을 줄일 때 가장 가치가 있습니다. 요령은 이를 짧고 반복 가능 한 체크포인트로 사용하는 것입니다—코드 전에, 설계 중에, 리뷰 중에—그래서 AI가 재사용할 수 있는 산출물을 내놓게 하고, 당신이 걸러야 하는 텍스트를 더 만드는 일이 없게 하세요.
코딩 전: 목표, 사용자, 제약, 성공 지표를 확인하는 한 번의 “정렬” 루프를 실행하세요.
설계 중: 대안과 리스크, 데이터 경계를 강제하는 패턴을 사용해 구현 전에 명확한 트레이드오프를 도출하세요.
리뷰 중: 체크리스트 스타일 프롬프트로 엣지 케이스(모서리 케이스), 모니터링, 보안, 성능의 결핍을 포착하세요.
작은 일관된 입력 번들이 더 나은 출력으로 이어집니다:
모르는 것이 있다면, 명시적으로 모른다고 말하고 AI에게 가정을 나열하게 하세요.
“설계를 설명해 달라” 대신 문서나 티켓에 붙여넣을 수 있는 아티팩트를 요청하세요:
10–15분 루프를 권장합니다: 프롬프트 → 훑어보기 → 다듬기. 항상 수용 기준(acceptance criteria) 을 포함하고, AI에게 그 기준에 대해 자기 검사를 시키세요. 이렇게 하면 끝없는 재설계로 흐르는 것을 막고 다음 섹션의 패턴을 빠르게 적용할 수 있습니다.
대부분의 ‘아키텍처 리라이트’는 나쁜 다이어그램 때문이 아니라 잘못된(혹은 불완전한) 문제를 위해 올바른 것을 만든 결과입니다. LLM을 초기에 쓸 때는 먼저 아키텍처를 요청하지 마세요. 모호성을 드러내게 하세요.
모델을 요구사항 인터뷰어로 사용하세요. 목표는 구성요소를 설계하거나 데이터베이스를 선택하거나 API를 확정하기 전에 확인할 수 있는 짧고 우선순위화된 스펙을 얻는 것입니다.
아래는 복사-붙여넣기 가능한 템플릿입니다:
You are my requirements analyst. Before proposing any architecture, do this:
1) Ask 10–15 clarifying questions about missing requirements and assumptions.
- Group questions by: users, workflows, data, integrations, security/compliance, scale, operations.
2) Produce a prioritized scope list:
- Must-have
- Nice-to-have
- Explicitly out-of-scope
3) List constraints I must confirm:
- Performance (latency/throughput targets)
- Cost limits
- Security/privacy
- Compliance (e.g., SOC2, HIPAA, GDPR)
- Timeline and team size
4) End with: “Restate the final spec in exactly 10 bullets for confirmation.”
Context:
- Product idea:
- Target users:
- Success metrics:
- Existing systems (if any):
당신이 원한 것은 결정하도록 강제하는 질문(일반적인 "더 말해달라"가 아닌 질문)과, 실제로 당신의 일정 내에 끝낼 수 있는 필수 항목의 목록입니다.
“10개의 불릿” 재진술은 계약으로 취급하세요: 티켓/PRD에 붙여넣고 이해관계자에게 빠른 찬반을 받으세요. 이렇게 하면 대부분의 늦은 리팩터링 원인—실제로 필요하지 않았던 기능을 만든 것—을 예방합니다.
“이벤트 소싱을 써야 하나?” 같은 도구 중심 질문으로 시작하면 종종 사용자가 아닌 아키텍처를 위해 설계하게 됩니다. 더 깔끔한 구조로 가는 빠른 길은 AI에게 먼저 사용자 여정을 평이한 언어로 설명하게 한 뒤, 그 여정을 구성요소·데이터·API로 번역하게 하는 것입니다.
복사-붙여넣기용 시작점:
그다음에 다음을 요청하세요:
“각 액션에 대해 단계별 흐름을 평이한 언어로 설명해라.”
“간단한 상태 다이어그램 또는 상태 목록을 제공해라(예: Draft → Submitted → Approved → Archived).”
“해피 패스가 아닌 시나리오를 나열해라: 타임아웃, 재시도, 중복 요청, 취소, 잘못된 입력.”
흐름이 명확해지면 AI에게 다음을 매핑하도록 하세요:
그런 다음 흐름 단계에 직접 연결된 아키텍처 스케치를 요청하세요(서비스/모듈, 경계, 책임).
마지막으로 AI에게 각 여정을 실제로 테스트할 수 있는 수용 기준으로 변환하게 하세요:
이 패턴은 아키텍처가 기술 가정이 아니라 사용자 행동에서 자라나도록 하여 리라이트를 줄입니다.
대부분의 아키텍처 재작업은 “나쁜 설계” 때문이 아니라 틀린 것으로 드러나는 숨은 가정 때문입니다. LLM에 아키텍처를 물어보면 모델은 흔히 그 빈칸을 그럴듯한 추측으로 채웁니다. 가정 로그는 그 추측을 초기 단계에 가시화해 변경 비용이 적을 때 대비하게 합니다.
목표는 당신이 제공한 사실과 모델이 추론한 가정을 깔끔하게 분리하도록 하는 것입니다.
다음 프롬프트 패턴을 사용하세요:
Template prompt “Before proposing any solution: list your assumptions. Mark each as validated (explicitly stated by me) or unknown (you inferred it). For each unknown assumption, propose a fast way to validate it (question to ask, metric to check, or quick experiment). Then design based only on validated assumptions, and call out where unknowns could change the design.”
짧게 유지하세요:
모델에게 전환점(tipping points)을 말하게 하세요:
이 패턴은 아키텍처를 조건부 결정의 집합으로 바꿉니다. 단순한 다이어그램뿐 아니라, 확정 전에 검증해야 할 지점의 지도가 생깁니다.
AI 도구는 단일 “최선” 설계를 잘 제시하지만, 그것은 종종 첫 번째 그럴듯한 옵션일 뿐입니다. 더 깔끔한 아키텍처는 초기에 비교를 강제할 때 자주 등장합니다—변경 비용이 적을 때 말입니다.
다음과 같은 프롬프트를 사용해 여러 아키텍처와 구조화된 트레이드오프 표를 요구하세요:
Propose 2–3 viable architectures for this project.
Compare them in a table with criteria: complexity, reliability, time-to-ship, scalability, cost.
Then recommend one option for our constraints and explain why it wins.
Finally, list “what we are NOT building” in this iteration to keep scope stable.
Context:
- Users and key journeys:
- Constraints (team size, deadlines, budget, compliance):
- Expected load and growth:
- Current systems we must integrate with:
비교는 모델(그리고 당신)로 하여금 숨은 가정을 드러내게 만듭니다: 상태가 어디에 저장되는가, 서비스들이 어떻게 통신하는가, 무엇이 동기식이어야 하고 지연될 수 있는가 등.
평가기준 표는 “마이크로서비스 vs 모놀리식” 같은 논쟁을 단순한 의견 싸움으로 끝나지 않게 합니다. 결정은 실제로 당신이 신경 쓰는 것(빠른 출시, 운영 오버헤드 감소, 신뢰성 향상 등)에 고정됩니다.
“상황에 따라 다르다” 식의 대답을 받아들이지 마세요. 분명한 추천과 그것이 최적화하는 구체적 제약을 요청하세요.
또한 이번 이터레이션에서 “우리가 만들지 않는 것”을 명확히 요구하세요. 예: “MVP에 멀티리전 페일오버 없음”, “플러그인 시스템 없음”, “실시간 알림 없음”. 이렇게 하면 아키텍처가 아직 확정하지 않은 기능을 지지하도록 은밀히 확장되는 것을 막을 수 있습니다.
대부분의 리라이트는 경계가 모호해서 발생합니다: 모든 것이 서로 연결되어 작은 변경이 코드베이스 전체에 영향을 줍니다. 이 패턴은 구현이나 클래스 다이어그램을 논쟁하기 전에 명확한 모듈 소유권을 강제합니다.
AI에게 모듈과 책임을 정의하게 하고, 각 모듈에 명시적으로 속하지 않는 것들도 적게 하세요. 그런 다음 인터페이스(입력/출력) 와 의존성 규칙을 요청하세요. 빌드 플랜이나 내부 구현은 요구하지 않습니다.
새 기능을 스케치하거나 지저분한 영역을 리팩터링할 때 사용하세요:
모듈 목록과:
각 모듈에 대해 인터페이스만 정의:
의존성 규칙:
미래 변경 테스트: 다음과 같은 가능성 있는 변경 3가지를 제시하고, 각각을 어느 단일 모듈이 흡수해야 하는지와 그 이유를 보여달라.
팀원에게 1분 이내로 설명할 수 있는 모듈을 목표로 하세요. AI가 “Utils” 같은 만능 모듈을 제안하거나 비즈니스 규칙을 컨트롤러에 넣으면 반박하세요: “의사결정은 도메인 모듈로 이동시키고 어댑터는 얇게 유지하라.”
이 과정을 거치면 변경 사항이 명확한 집을 갖게 되어, 변경이 발생해도 경계가 유지되어 우발적 결합을 막습니다.
통합 재작업은 종종 “나쁜 코드” 때문이 아니라 불명확한 계약 때문입니다. 데이터 모델과 API 스펙이 늦게 결정되면 각 팀(또는 각 모듈)이 빈칸을 다르게 채우고, 다음 스프린트에 불일치를 조정하느라 시간을 씁니다.
프레임워크나 DB, 마이크로서비스를 이야기하기 전에 계약을 먼저 프롬프트하세요. 명확한 계약은 UI, 백엔드, 데이터 파이프라인을 정렬시키는 공유 기준이 됩니다.
초기에 AI 어시스턴트에게 다음을 요청하세요:
그다음 바로 요청하세요:
문장이 아닌 구체적인 아티팩트를 원하세요. 예를 들어:
Subscription
그리고 API 스케치:
POST /v1/subscriptions
{
"customer_id": "cus_123",
"plan_id": "pro_monthly",
"start_date": "2026-01-01"
}
201 Created
{
"id": "sub_456",
"status": "active",
"current_period_end": "2026-02-01"
}
422 Unprocessable Entity
{
"error": {
"code": "VALIDATION_ERROR",
"message": "start_date must be today or later",
"fields": {"start_date": "in_past"}
}
}
AI에게 다음과 같은 규칙을 명시하게 하세요: “필드 추가는 버전 업 없이 허용; 이름 변경은 /v2 필요; 클라이언트는 알 수 없는 필드를 무시해야 한다.” 이 단일 단계가 묵시적 깨지는 변경을 막아 주고, 뒤따르는 리라이트를 방지합니다.
아키텍처는 해피 패스 설계가 실제 트래픽, 불안정한 의존성, 예상치 못한 사용자 행동을 만났을 때 재설계됩니다. 이 패턴은 신뢰성을 설계 산출물로 명시하게 해, 출시 후 급조하는 일을 줄입니다.
선택한 아키텍처 설명과 함께 다음을 사용하세요:
List failure modes; propose mitigations; define observability signals.
For each failure mode:
- What triggers it?
- User impact (what the user experiences)
- Mitigation (design + operational)
- Retries, idempotency, rate limits, timeouts considerations
- Observability: logs/metrics/traces + alert thresholds
응답을 집중시키려면 실패할 수 있는 인터페이스를 명시하세요: 외부 API, 데이터베이스, 큐, 인증 제공자, 백그라운드 잡 등. 그리고 구체적인 결정을 요구하세요:
프롬프트 끝에: “2분 안에 리뷰할 수 있는 간단한 체크리스트를 반환하라.”고 명시하세요. 좋은 체크리스트 항목 예:
시스템 내부가 아닌 사용자 순간에 연동된 이벤트를 요청하세요(예: “user_signed_up”, “checkout_submitted”, “payment_confirmed”, “report_generated”). 각 이벤트에 대해:
이렇게 하면 신뢰성이 코드 이전의 설계 산출물이 됩니다.
AI 지원 설계가 리라이트를 만들기 쉬운 또 다른 방식은 너무 이른 시점에 “완전한” 아키텍처를 권장하는 것입니다. 해결책은 가장 작은 ‘사용 가능한’ 슬라이스로 시작하게 강제하는 것입니다—가치 전달하고 설계를 검증하며 향후 옵션을 열어두는 최소 단위입니다.
해결책이 요구사항보다 빠르게 확장되고 있다는 느낌이 들면 다음을 사용하세요:
템플릿: “가장 작은 사용 가능한 슬라이스를 제안하라; 성공 지표를 정의하라; 후속 작업을 나열하라.”
AI에게 다음 항목을 응답하도록 요구하세요:
두 번째 지침을 추가하세요: “단계별 로드맵을 제시하라: MVP → v1 → v2 그리고 각 단계가 줄이는 리스크를 설명하라.” 이렇게 하면 나중의 아이디어를 가시화하면서도 초기 릴리스에 억지로 포함시키지 않습니다.
원하는 결과 예:
이 패턴에서 가장 강력한 문장은: “MVP에 명시적으로 범위에서 제외되는 항목을 적어라.”입니다. 제외 항목은 아키텍처 결정을 초기부터 과도하게 복잡하게 만드는 것을 막습니다.
좋은 제외 예:
마지막으로: “MVP를 티켓들로 변환하라. 각 티켓에 수용 기준과 의존성을 적어라.” 이렇게 하면 명료성이 강제되고 숨은 결합이 드러납니다.
일반적인 티켓 분해 예:
원하면 모델에게 팀의 형식(예: Jira 스타일 필드)으로 출력하게 해 바로 워크플로우에 연결하세요. 이후 단계는 별도 백로그로 유지합니다.
설계가 흐려지는 것을 막는 간단한 방법은 컴포넌트를 설계하기 전에 테스트를 강제하는 것입니다. LLM에게 수용 테스트부터 작성하라고 하면 동작, 입력/출력, 엣지 케이스를 명확히 해야 합니다. 이는 자연스럽게 누락된 요구사항을 드러내고 구현을 깔끔한 모듈 경계로 유도합니다.
컴포넌트를 설계하려 할 때 ‘게이트’ 프롬프트로 사용하세요:
다음 지시를 추가하세요: “테스트를 모듈 책임별로 그룹화하라(API 레이어, 도메인 로직, 영속성, 외부 통합). 각 그룹에 대해 무엇을 목(mock)하고 무엇을 실제로 할지 명시하라.”
이렇게 하면 모든 것이 얽힌 설계 대신 모듈화된 설계로 유도됩니다. 통합 테스트의 경계가 설명되지 않으면 아키텍처가 아직 명확하지 않다는 신호입니다.
요청사항: “테스트 데이터 계획을 제안하라: 픽스처 vs 팩토리, 엣지 케이스 생성 방법, 테스트를 결정론적으로 유지하는 방법. 어떤 의존성을 인메모리 페이크로 대체할지, 어떤 것은 CI에서 실제 서비스를 써야 하는지 목록화하라.”
많은 경우 ‘간단한’ 기능이 사실은 계약, 시드 데이터, 혹은 안정적인 ID가 필요하다는 것을 발견하게 됩니다—리라이트가 발생하기 전에 이를 찾는 것이 낫습니다.
가벼운 체크리스트로 마무리하세요:
설계 리뷰는 코드가 이미 존재한 이후에만 일어나면 안 됩니다. AI를 사용하면 아키텍처 초안(몇 문단이나 단어로 된 다이어그램-in-words라도)에 대해 “사전 사망 시나리오(pre-mortem)” 리뷰를 돌려 구체적인 약점을 코드화되기 전에 얻을 수 있습니다.
엄격한 리뷰어 입장으로 시작해 구체성을 강제하세요:
Prompt: “리뷰어로 행동하라; 이 설계의 리스크, 불일치, 빠진 세부사항을 나열하라. 구체적으로 적어라. 평가할 수 없으면 어떤 정보가 부족한지 말하라.”
설계 요약, 제약(예: 예산, 일정, 팀 역량), 비기능 요구사항(지연, 가용성, 규정)을 붙여넣으세요.
피드백이 모호하면 실패합니다. 다음을 요청하세요:
Prompt: “우선순위화된 펀치리스트를 제공하라. 각 항목에 대해: 심각도(Blocker/High/Medium/Low), 왜 중요한지, 제안 수정안, 그리고 가장 작은 검증 단계.”
이렇게 하면 토론 대신 결정 가능한 작업 목록이 산출됩니다.
간단한 강제 수단은 점수입니다:
Prompt: “1–10의 범위로 리라이트 위험 점수를 부여하라. 상위 3개 요인을 설명하라. 최소 노력으로 점수를 2점 낮추려면 무엇을 해야 하나?”
정밀도가 목적이 아니라, 리라이트에 취약한 가정을 표면화하는 것이 목적입니다.
리뷰가 범위를 확장하지 않도록 다음을 요청하세요:
Prompt: “차이 계획(diff plan)을 제공하라: 목표 설계에 도달하기 위해 필요한 최소 변경. 무엇을 유지하고, 무엇을 변경하며, 어떤 파급(브레이킹) 영향이 있는지 나열하라.”
이 패턴을 각 반복에서 사용하면 아키텍처는 작고 되돌릴 수 있는 단계로 진화합니다—큰 문제들은 초기에 잡히고 변경은 점진적으로 일어납니다.
이 팩을 매 기능마다 반복 가능한 가벼운 워크플로우로 사용하세요. 아이디어는 프롬프트를 연결(chain)해 각 단계가 다음 단계에서 재사용할 수 있는 아티팩트를 생성하게 하는 것입니다—잃어버린 컨텍스트와 깜짝 리라이트를 줄입니다.
실무에서는 팀이 이 체인을 ‘기능 레시피’로 구현하는 경우가 많습니다. Koder.ai로 빌드하는 경우, 동일한 구조가 채팅 주도 빌드 프로세스에 잘 맞습니다: 아티팩트를 한 곳에 캡처하고 첫 동작 슬라이스를 생성한 뒤, 스냅샷으로 실험을 되돌릴 수 있게 반복하세요. MVP가 준비되면 소스 코드를 내보내거나 커스텀 도메인으로 배포/호스팅할 수 있습니다—AI 지원 전달의 속도를 얻으면서 특정 환경에 잠기지 않도록 유용합니다.
SYSTEM (optional)
You are a software architecture assistant. Be practical and concise.
Guardrail: When you make a recommendation, cite the specific lines from *my input* you relied on by quoting them verbatim under “Input citations”. Do not cite external sources or general industry claims.
If something is unknown, ask targeted questions.
1) REQUIREMENTS CLARIFIER
Context: <product/system overview>
Feature: <feature name>
My notes: <paste bullets, tickets, constraints>
Task:
- Produce: (a) clarified requirements, (b) non-goals, (c) constraints, (d) open questions.
- Include “Input citations” quoting the exact parts of my notes you used.
2) ARCHITECTURE OPTIONS
Using the clarified requirements above, propose 3 architecture options.
For each: tradeoffs, complexity, risks, and when to choose it.
End with a recommendation + “Input citations”.
3) MODULAR BOUNDARIES
Chosen option: <option name>
Define modules/components and their responsibilities.
- What each module owns (and does NOT own)
- Key interfaces between modules
- “Input citations”
4) DATA & API CONTRACTS
For each interface, define a contract:
- Request/response schema (or events)
- Validation rules
- Versioning strategy
- Error shapes
- “Input citations”
5) TEST-FIRST ACCEPTANCE
Write:
- Acceptance criteria (Given/When/Then)
- 5–10 critical tests (unit/integration)
- What to mock vs not mock
- “Input citations”
6) RELIABILITY + DESIGN REVIEW
Create:
- Failure modes list (timeouts, partial failure, bad data, retries)
- Observability plan (logs/metrics/traces)
- Review checklist tailored to this feature
- “Input citations”
마지막으로: 더 깊은 동반자가 필요하면 /blog/prompting-for-code-reviews 를 참조하세요. 도구나 팀 롤아웃을 평가 중이라면 /pricing 이 실용적 다음 단계입니다.
“더 깔끔한 아키텍처”는 여기서 다음을 의미합니다:
AI 지원 작업에서는 모델이 요구사항을 당신이 승인할 수 있는 방식으로 다시 진술할 수 있다는 것도 포함합니다.
AI는 설득력 있는 코드와 설계를 빠르게 생성할 수 있어서 누락된 제약조건과 숨은 가정 위에 바로 구축해 버리기 쉽습니다. 이런 속도는 다음 같은 리라이트 트리거를 증폭시킵니다:
해결책은 “AI를 덜 쓰는 것”이 아니라, 제약·계약·가정을 초기에 드러내도록 유도하는 프롬프트를 사용하는 것입니다.
패턴을 짧은 체크포인트로 사용해 재작업을 줄이는 것이 핵심입니다. 산출물이 재사용 가능한 아티팩트(문서, 티켓용 텍스트 등)가 되게 하세요 — 불필요한 장황한 설명을 양산하지 않도록.
권장 사용 시점:
반복은 10–15분 정도의 짧은 루프(프롬프트 → 훑어보기 → 다듬기)로 유지하세요.
작은 일관된 입력 번들을 준비하세요:
모르는 항목은 모른다고 명시하고, 모델에게 추정한 가정을 나열하도록 요청하세요. 모델이 몰래 추정하지 못하게 하는 것이 목적입니다.
다음과 같은 재사용 가능한 산출물을 요청하세요:
이렇게 하면 AI 출력이 실행 가능해지고, 나중에 가정 불일치로 인한 재작업이 줄어듭니다.
모델을 요구사항 인터뷰어로 사용하세요. 다음을 하게 하세요:
그 10불릿 재진술을 이해관계자에게 붙여 빠른 동의를 얻은 뒤에야 설계로 넘어가세요.