[프롬프트] 코드 리팩토링: 가독성 중심 최적화 프롬프트 - 최적 프롬프트 레시피
💡 한 줄 요약: "가독성 높여줘"라는 모호한 요청으로 인한 오버엔지니어링(디자인 패턴 남발, 불필요한 클래스 분리로 코드 3배 비대화)과 비즈니스 로직 왜곡을 원천 차단하고, 조기 반환(Guard Clauses)·단일 책임·동작 보존(Zero Logic Drift) 원칙으로 인지 복잡도를 극소화하는 실전 프로덕션 리팩토링 프롬프트 레시피입니다.
1. 페인포인트 & 작업 목표
- 실제 작업 시나리오: Cursor, Claude Code, Windsurf, GitHub Copilot 등 최신 바이브 코딩 환경에서 4~5단계 중첩 if/else 분기문과 비대한 스파게티 레거시 코드를 읽기 쉬운 클린 코드로 리팩토링하는 상황.
-
단순 프롬프트 요청 시 발생하는 3대 실패 원인:
- 오버엔지니어링 폭주 (Pattern Inflation): "가독성 높여줘"라는 지시에 LLM이 전략 패턴, 팩토리 클래스, 커스텀 예외를 남발하여 50줄짜리 함수를 200줄 4개 파일로 비대화시킴.
- 비즈니스 로직 왜곡 (Logic Drift): 코드를 짧게 줄이겠다며 null 체크 순서를 바꾸거나 미묘한 예외 분기를 누락하여 런타임 버그 유발.
- 과도한 난해한 한 줄 축약 (Cryptic One-Liners): 복합 삼항 연산자나 난해한 함수형 체이닝을 작성해 오히려 동료 개발자의 인지 부하 가중.
-
최종 해결 목표:
- Zero Logic Drift (동작 100% 보존): 기존 입출력 계약 및 에러 처리 순서 불변.
- 조기 반환(Guard Clauses) 평탄화: 깊은 중첩 구조를 최대 1~2단계 들여쓰기로 단순화.
- 인지 복잡도(Cognitive Complexity) 최소화: 불필요한 클래스 생성을 금지하고 함수 단위에서 직관적인 자기 서술적(Self-describing) 코드로 재구성.
2. 프롬프트 레시피 비교
3. 실행 결과 비교
function processOrder(order: any, user: any, promo: any): any {
let res = null;
if (order != null) {
if (user != null) {
if (user.isActive) {
if (order.items && order.items.length > 0) {
let total = 0;
for (let i = 0; i < order.items.length; i++) {
total += order.items[i].price * order.items[i].quantity;
}
if (promo != null) {
if (promo.isValid && !promo.isExpired) {
if (promo.type === 'PERCENT') {
total = total - (total * (promo.discount / 100));
} else if (promo.type === 'FLAT') {
total = total - promo.discount;
}
}
}
let tax = total * 0.1;
let finalPrice = total + tax;
res = { status: 'SUCCESS', finalPrice: finalPrice, orderId: order.id };
} else {
res = { status: 'EMPTY_CART', finalPrice: 0, orderId: null };
}
} else {
res = { status: 'INACTIVE_USER', finalPrice: 0, orderId: null };
}
} else {
res = { status: 'USER_NOT_FOUND', finalPrice: 0, orderId: null };
}
} else {
res = { status: 'INVALID_ORDER', finalPrice: 0, orderId: null };
}
return res;
}
interface OrderItem { price: number; quantity: number; }
interface Order { id: string; items?: OrderItem[]; }
interface User { isActive: boolean; }
interface Promo { isValid: boolean; isExpired: boolean; type: 'PERCENT' | 'FLAT'; discount: number; }
interface OrderResult { status: string; finalPrice: number; orderId: string | null; }
function processOrder(
order: Order | null,
user: User | null,
promo: Promo | null
): OrderResult {
// 1. Guard Clauses: 유효성 검증 및 빠른 실패 (Fast-Fail)
if (!order) return { status: 'INVALID_ORDER', finalPrice: 0, orderId: null };
if (!user) return { status: 'USER_NOT_FOUND', finalPrice: 0, orderId: null };
if (!user.isActive) return { status: 'INACTIVE_USER', finalPrice: 0, orderId: null };
if (!order.items || order.items.length === 0) {
return { status: 'EMPTY_CART', finalPrice: 0, orderId: null };
}
// 2. 비즈니스 로직: 명확한 계산 분리
const subtotal = calculateSubtotal(order.items);
const discountedTotal = applyPromotion(subtotal, promo);
const tax = discountedTotal * 0.1;
const finalPrice = discountedTotal + tax;
return { status: 'SUCCESS', finalPrice, orderId: order.id };
}
function calculateSubtotal(items: OrderItem[]): number {
return items.reduce((sum, item) => sum + item.price * item.quantity, 0);
}
function applyPromotion(amount: number, promo: Promo | null): number {
if (!promo || !promo.isValid || promo.isExpired) {
return amount;
}
if (promo.type === 'PERCENT') {
return amount * (1 - promo.discount / 100);
}
if (promo.type === 'FLAT') {
return amount - promo.discount;
}
return amount;
}
| 측정 지표 | 리팩토링 전 | 레시피 A (단순) | 레시피 B (최적화) | 개선 효과 |
|---|---|---|---|---|
| 최대 들여쓰기 깊이 | 5단계 (피라미드) | 3~4단계 | 1단계 (Flat) | 80% 감소 |
| 인지 복잡도 (Cognitive) | 18 (심각한 위험) | 12 (높음) | 3 (매우 안전) | 83% 감소 |
| 추가된 클래스/파일 수 | 0개 | 4개 (패턴 남발) | 0개 (적정 분리) | 오버엔지니어링 0건 |
| 동작 보존율 | 기준점 | 누락 위험 있음 | 100% 완전 일치 | 무결성 보장 |
4. 메커니즘 심층 분석 (왜 차이가 나는가?)
1. Negative Constraint로 불필요한 클래스/패턴 남발 차단 원리
LLM은 오픈소스의 방대한 객체지향 아키텍처 패턴을 학습했습니다. "클린 코드로 리팩토링하라"는 긍정 지시문만 주면, AI는 자신의 추론 능력을 증명하기 위해 전략 패턴, 팩토리, 인터페이스 위계를 불필요하게 생성합니다. NO OVER-ENGINEERING과 같은 엄격한 부정 제약(Negative Constraint)은 LLM의 토큰 생성 공간을 기존 함수 스코프 내의 구문 정렬로 강력하게 좁힙니다.
2. Guard Clause가 인지 부하(Cognitive Load)를 줄이는 메커니즘
5단계 중첩 if/else를 읽는 개발자의 두뇌는 각 분기 조건을 작업 기억(Working Memory) 스택에 계속해서 쌓아두어야 합니다. 반면 Guard Clause는 예외 조건이 발견되는 즉시 함수를 빠져나가는 빠른 실패(Fast-Fail) 구조를 갖춥니다. 가드 절을 통과한 순간부터는 "모든 입력값이 유효하다"는 전제 하나만 유지하면 되므로 인지 부하가 수평으로 평탄화됩니다.
3. Behavior Preservation(Zero Logic Drift) 제약이 버그 생성을 막는 원리
AI가 코드를 압축할 때 흔히 발생하는 실수는 단축 평가(Short-circuit evaluation) 순서를 바꾸어 undefined 참조 에러를 발생시키는 것입니다. 프롬프트에 ZERO LOGIC DRIFT와 Safety Verification을 명시하면, 모델은 생성 전에 원래의 엣지 분기 순서와 입출력 계약을 자체적으로 대조·검증하여 무결성을 보장합니다.
5. 실전 응용 팁 & 커스텀 가이드
Role: Senior Staff Engineer specializing in clean code and zero-defect refactoring.
Task: Refactor the following {LANGUAGE} code to optimize readability and reduce cognitive complexity.
Constraints:
- Preserve 100% identical external behavior and API contract for {FUNCTION_OR_MODULE_NAME}.
- Flatten nesting using Guard Clauses (maximum {MAX_DEPTH} level of indentation).
- Strictly forbid over-engineering: NO new classes, NO design patterns, NO unnecessary helper files.
- If code exceeds {MAX_LINES} lines, extract small pure helper functions within the same scope/file.
- Variable naming style: {NAMING_CONVENTION}.
Target Code:
```{LANGUAGE}
{PASTE_CODE_HERE}
```
{LANGUAGE}는 타깃 프로그래밍 언어, {MAX_DEPTH}는 최대 들여쓰기 깊이(1~2 권장), {FUNCTION_OR_MODULE_NAME}에는 리팩토링할 대상 함수명을 입력하세요.
-
Cursor Rules (
.cursorrules) 설정: 루트 디렉터리에"When refactoring, always prioritize Guard Clauses and early returns. NEVER introduce extra classes or design patterns unless explicitly requested."를 추가해 두면 단축키Cmd+K실행 시 자동으로 오버엔지니어링 없는 코드가 생성됩니다. -
Claude Code 터미널 단축 명령어: 터미널에서 즉시 실행할 경우:
claude "Refactor src/order.ts:processOrder focusing on Guard Clauses and readability. Zero logic drift, no extra classes."