[프롬프트] 에러 메시지 분석 및 해결책 제안 프롬프트 - 최적 프롬프트 레시피

에러 메시지 디버깅 및 시스템 장애 분석

[프롬프트] 에러 메시지 분석 및 해결책 제안 프롬프트 - 최적 프롬프트 레시피

💡 한 줄 요약: "이 에러 왜 발생해?"라는 단순 질의 시 터져 나오는 '반쪽짜리 try-catch 감싸기'와 '단순 라이브러리 재설치' 조언을 완전히 타파하고, Staff SRE 관점의 근본 원인 분석(5 Whys)과 P0 장애 긴급 격리/핫픽스를 정확하게 도출하는 실전 프롬프트 레시피입니다.

1. 페인포인트 & 작업 목표

  • 실제 작업 시나리오: 프로덕션 배포 직후 데이터베이스 커넥션 풀 고갈, 비동기 데드락, Node.js OOM(Out of Memory) 크래시 등 복잡한 장애가 발생했을 때 신속하게 원인을 규명하고 재발을 방지해야 하는 상황.
  • 단순 프롬프트 요청 시 발생하는 4대 전형적 문제:
    • 표면적 증상 땜질 (Symptom-Level Patching): 에러가 발생한 지점만 단순 try-catch로 덮거나 if (obj != null) 방어 코드만 제시하여, 내부 상태 불일치와 데이터 오염을 가중함.
    • 재현 조건 및 런타임 맥락 무시 (Context Blindness): 동시성(Concurrency), 트랜잭션 격리 수준, GC 주기, 네트워크 타임아웃 등 런타임 환경 맥락을 파악하지 않고 단일 스레드 관점의 안이한 답변만 반복함.
    • 재발 방지책(5 Whys) 결여: 왜 그런 코드 흐름이 허용되었는지 아키텍처 결함을 파헤치지 않아 동일한 장애가 며칠 뒤 다른 서비스에서 재발함.
    • P0 긴급 핫픽스와 영구 수정의 혼동: 서비스가 다운된 긴급 상황에서 즉각 트래픽 격리나 킬스위치 대신 대규모 리팩토링 코드를 제시하여 복구 골든타임을 허비함.
  • 최종 해결 목표:
    • Staff SRE / Principal Troubleshooting Engineer 페르소나 주입: 단순 코드 분석이 아닌 인프라·런타임·비즈니스 로직을 관통하는 입체적 트러블슈팅 수행.
    • 근본 원인 분석 5단계 강제: [에러 시그니처 정밀 해체 → 5 Whys 원인 규명 → 10분 즉시 완화 핫픽스 → 영구적 아키텍처 방어책 → 재현 및 검증 스트레스 테스트] 파이프라인 정립.
    • 긴급도별 레시피 분리: 비동기 교착/커넥션 누수를 위한 구조적 분석(레시피 B)과 P0 다운타임 전용 핫픽스(레시피 C)의 명확한 이원화.

2. 프롬프트 레시피 비교

❌ 레시피 A: 기본형 (단순 질의 초안)

스택 트레이스나 에러 문구만 툭 던지고 해결을 요구하는 초안입니다:

영문 프롬프트 (복사용)
Why does this error happen and how do I fix it?
[PASTE_ERROR_LOG_OR_STACKTRACE]
한글 프롬프트 (1:1 매칭 복사용)
이 에러가 왜 발생하고 어떻게 고치나요?
[에러_로그_또는_스택트레이스_붙여넣기]
💡 프롬프트 구조 및 핵심 파라미터 해설란
  • 구조적 결함: 런타임 환경, 프레임워크 버전, 트래픽 유입 상황, 호출된 SQL 쿼리 맥락이 전무함.
  • 부작용: AI가 가장 흔한 원인 하나만 임의로 찍어 맞추며, 에러 발생 함수를 try-catch로 감싸 로깅만 찍는 식의 위험한 임시방편을 제시함.
⚡ 레시피 B: 실무 종결형 Staff SRE 트러블슈팅 프롬프트

스택 트레이스, 런타임 환경, 최근 변경 사항을 결합하여 근원 분석(5 Whys), 즉시 완화책, 영구 구조 개선안, 회귀 방지 테스트까지 일괄 도출합니다:

영문 프롬프트 (복사용)
You are a Staff Site Reliability Engineer and Principal Systems Architect specializing in distributed systems, runtime diagnostics, and root-cause analysis (RCA).
Analyze the provided error log, runtime context, and system state to produce a battle-tested postmortem and remediation strategy.

### Incident Context:
- Tech Stack & Runtime: [e.g., Node.js v20.x, PostgreSQL 16, Redis 7, Kubernetes v1.29]
- Error Signature & Stack Trace:
[PASTE_FULL_STACKTRACE_AND_LOGS_HERE]
- Recent Changes / Deployment: [e.g., Migrated to async worker pool, changed query pagination]
- Traffic / Resource State: [e.g., Connection pool 95% exhausted, 2500 RPS spike]

### Analysis & Deliverable Requirements:
1. ERROR ANATOMY & ROOT CAUSE (5 WHYS):
   - Deconstruct the exact failure mechanism (e.g., deadlock cycle, lock acquisition order, race condition).
   - Trace the causal chain using the 5 Whys methodology down to the architectural or schema-level root.
2. IMMEDIATE MITIGATION (10-Minute Fix):
   - Provide safe, non-breaking tactical patch or config change to restore system stability without downtime.
3. PERMANENT ARCHITECTURAL REMEDIATION:
   - Provide production-grade, hardened code patch with idempotency, resource release guarantees (finally/RAII), and query/lock re-ordering.
4. VALIDATION & STRESS TEST HARNESS:
   - Provide a runnable reproduction script or concurrency stress test simulating high load to prove the fix.
5. OBSERVABILITY & ALERTING:
   - Specify exact Prometheus metric queries (PromQL) and alert thresholds to detect this failure pattern proactively.
한글 프롬프트 (1:1 매칭 복사용)
당신은 분산 시스템, 런타임 진단 및 근본 원인 분석(RCA)을 전문으로 하는 Staff Site Reliability Engineer(SRE)이자 수석 시스템 아키텍트입니다.
제공된 에러 로그, 런타임 컨텍스트 및 시스템 상태를 분석하여 실전에 즉시 투입 가능한 장애 보고서와 해결 전략을 도출하십시오.

### 장애 컨텍스트:
- 기술 스택 및 런타임 환경: [예: Node.js v20.x, PostgreSQL 16, Redis 7, Kubernetes v1.29]
- 에러 시그니처 및 스택 트레이스:
[여기에_전체_스택트레이스_및_로그_붙여넣기]
- 최근 변경 사항 및 배포 내역: [예: 비동기 워커 풀 마이그레이션, 쿼리 페이지네이션 방식 변경]
- 트래픽 및 자원 점유 상태: [예: 커넥션 풀 95% 고갈, 2500 RPS 급증]

### 분석 및 출력 요구사항:
1. 에러 해체 및 근본 원인 규명 (5 Whys):
   - 정확한 실패 메커니즘을 해체하십시오 (예: 데드락 사이클, 락 획득 순서 역전, 레이스 컨디션).
   - 5 Whys 방법론을 사용하여 아키텍처 또는 스키마 레벨의 근본 원인까지 인과 사슬을 추적하십시오.
2. 즉각적 완화 조치 (10분 핫픽스):
   - 무중단 상태에서 시스템 안정성을 복원할 수 있는 안전하고 비파괴적인 전술적 패치 또는 설정 변경안을 제시하십시오.
3. 영구적 아키텍처 개선책:
   - 멱등성 보장, 자원 해제 보장(finally/RAII), 쿼리/락 순서 재정렬이 적용된 프로덕션급 강화 코드 패치를 제공하십시오.
4. 검증 및 부하 스트레스 테스트 코드:
   - 수정 사항을 증명하기 위해 고부하 환경을 시뮬레이션하는 실행 가능한 재현 스크립트 또는 동시성 스트레스 테스트를 제공하십시오.
5. 옵저버빌리티 및 알림 설정:
   - 이 실패 패턴을 선제적으로 감지할 수 있는 정확한 Prometheus 메트릭 쿼리(PromQL) 및 임계값 알림을 명시하십시오.
💡 프롬프트 구조 및 핵심 파라미터 해설란
  • 5 Whys 인과 사슬: 에러 로그의 겉모습(NullPointer, Connection Timeout)을 넘어 데이터베이스 트랜잭션 락 순서와 비즈니스 흐름 간의 충돌 원인을 추적하도록 강제합니다.
  • 10분 완화 vs 영구 패치 분리: 즉각적인 커넥션 타임아웃/풀 크기 조절과 코드베이스 재작업을 분리해 서비스 복구 속도와 기술 부채 해소를 동시에 달성합니다.
  • PromQL 메트릭 연계: 수정 후 방치되지 않도록 모니터링 메트릭(예: pg_stat_activity, active_connections)을 함께 도출합니다.
🚀 레시피 C: 긴급 장애 P0 핫픽스 전용 프롬프트 (Emergency Incident Commander)

프로덕션 서비스가 다운되었거나 OOM 연쇄 크래시가 발생하는 초비상 상황에서 시스템 격리와 긴급 복구에만 집중하는 프롬프트입니다:

영문 프롬프트 (복사용)
Act as an Emergency Incident Commander handling an active Production P0 Outage.
Drop all non-critical theoretical explanations. Focus purely on immediate containment, blast-radius reduction, and surviving the current traffic load.

### P0 Incident Telemetry:
- Incident Type: [e.g., OOM CrashLoopBackOff / Connection Starvation / CPU Throttling 100%]
- Error Signature:
[PASTE_ERROR_LINE_AND_TOP_STACK_HERE]
- Runtime & Deployment Specs: [e.g., AWS EKS, 12 Pods, Node.js memory limit 1.5GiB]

### Immediate Action Plan (Execute in Order):
1. BLAST RADIUS CONTAINMENT (Within 2 minutes):
   - Provide immediate traffic isolation command, circuit breaker flag, or kill-switch config.
2. QUICK-DRAIN / EMERGENCY MITIGATION (Within 5 minutes):
   - Exact kubectl/env patch to stabilize surviving instances (e.g., `--max-old-space-size`, horizontal scale-out, read-replica shed).
3. 10-MINUTE TACTICAL HOTFIX:
   - Minimal surgical code diff or hot-patch to stop memory leaks or infinite loop recursion immediately without schema migrations.
한글 프롬프트 (1:1 매칭 복사용)
현재 활성화된 프로덕션 P0 장애를 지휘하는 긴급 인시던트 커맨더(Incident Commander)로 행동하십시오.
모든 비핵심적인 이론적 설명을 배제하십시오. 즉각적인 장애 격리, 피해 반경(Blast Radius) 최소화, 현재 유입되는 트래픽 방어에만 집중하십시오.

### P0 인시던트 텔레메트리:
- 장애 유형: [예: OOM CrashLoopBackOff / 커넥션 고갈 / CPU 스로틀링 100%]
- 에러 시그니처:
[여기에_에러_핵심_한_줄_및_최상단_스택_붙여넣기]
- 런타임 및 배포 사양: [예: AWS EKS, 파드 12개, Node.js 메모리 제한 1.5GiB]

### 즉시 실행 조치 계획 (순서대로 실행):
1. 피해 반경 격리 (2분 이내 실행):
   - 즉각적인 트래픽 격리 명령, 서킷 브레이커 플래그, 또는 킬스위치 설정값을 제시하십시오.
2. 긴급 드레인 및 자원 완화 (5분 이내 실행):
   - 살아있는 인스턴스를 안정화할 수 있는 정확한 kubectl/환경변수 패치를 제공하십시오 (예: `--max-old-space-size`, 수평 스케일아웃, 읽기 전용 복제본 우회).
3. 10분 전술적 핫픽스:
   - 스키마 마이그레이션 없이 메모리 누수나 무한 루프 재귀를 즉각 차단할 수 있는 최소 단위의 정밀 코드 diff 또는 핫패치를 제공하십시오.
💡 프롬프트 구조 및 핵심 파라미터 해설란
  • 선 격리 후 분석 원칙: P0 장애 시 분석 글을 읽을 여유가 없습니다. 2분/5분/10분 단위로 실행할 CLI 명령어와 환경변수 플래그를 맨 위에 배치합니다.
  • 최소 단위 Diff(Surgical Diff): 전체 리팩토링 대신 배포 시 추가 장애 위험이 가장 적은 1~3라인 단위의 긴급 패치만 생성합니다.

3. 실전 적용 및 단계별 실행 결과

❌ 레시피 A 실행 결과: (반쪽짜리 try-catch 비판)

레시피 A에 QueryFailedError: deadlock detected (Process 1824 waits for ShareLock on transaction...) 로그를 입력했을 때의 전형적 결과입니다:

// ❌ AI의 반쪽짜리 해결책: 단순 catch 후 에러 무시 또는 단순 로그 출력
async function transferCredits(senderId: string, receiverId: string, amount: number) {
  try {
    await db.transaction(async (trx) => {
      await trx('users').where({ id: senderId }).decrement('balance', amount);
      await trx('users').where({ id: receiverId }).increment('balance', amount);
    });
  } catch (error) {
    console.error('트랜잭션 실패:', error);
    // 문제: 클라이언트는 송금 성공 여부를 알 수 없고, 커넥션 타임아웃 시 풀 누수가 지속됨
  }
}
👉 비판: 두 사용자가 동시에 서로에게 송금할 때 발생하는 락 획득 순서 역전(Lock Inversion)을 전혀 파악하지 못했습니다. catch 블록으로 에러를 숨겼을 뿐, 프로덕션 트래픽 환경에서는 여전히 수백 개의 프로세스가 데드락으로 묶여 커넥션 풀을 모두 잠식해버립니다.

⚡ 레시피 B 실행 결과: [실전 사례 1] PostgreSQL 비동기 데드락 & 커넥션 풀 고갈 해결

동시 송금 및 포인트 정산 트래픽 급증 시 풀 고갈로 504 Gateway Timeout이 연쇄 발생한 인시던트를 5 Whys와 결정론적 락 순서 정렬로 완벽 해결한 사례입니다.

1) 1차 입력 프롬프트 (레시피 B 인시던트 컨텍스트 주입)

  • 스택: Node.js v20, PostgreSQL 16 (Knex/TypeORM), Hikari/pg-pool
  • 로그: error: deadlock detected / DETAIL: Process 812 waits for ExclusiveLock on tuple (4,12) of relation "wallets"; blocked by process 819. Process 819 waits for ExclusiveLock on tuple (4,9)...
  • 상황: 동시 송금 및 포인트 정산 트래픽 급증 시 풀 고갈로 504 Gateway Timeout 연쇄 발생

2) AI 생성 출력 결과 (핵심 발췌)

1. Root Cause Analysis (5 Whys)
### 1. Root Cause Analysis (5 Whys)
1. Why did 504 Timeouts occur? -> Database connection pool (max 50) was 100% saturated.
2. Why was the pool saturated? -> Active transactions were blocked waiting for row locks up to statement_timeout.
3. Why were transactions blocked? -> Mutual circular dependency (Deadlock) occurred between transaction A and transaction B.
4. Why did circular dependency happen? -> Transaction A locked User X then User Y; Transaction B locked User Y then User X (Lock Inversion).
5. Root Architectural Cause: Resource acquisition order was nondeterministic and uncoordinated at the application layer.
2. Immediate Tactical Mitigation (10-Minute Fix: 타임아웃 강제 회수)
ALTER SYSTEM SET statement_timeout = '3000ms';
ALTER SYSTEM SET lock_timeout = '2000ms';
SELECT pg_reload_conf();
3. Permanent Architectural Code Patch (결정론적 락 순서 정렬)
export async function executeAtomicTransfer(
  db: Knex,
  userAId: string,
  userBId: string,
  amount: number
): Promise<void> {
  // 1. 데드락 원천 차단: ID 알파벳 오름차순으로 락 획득 순서 강제
  const [firstId, secondId] = [userAId, userBId].sort((a, b) => a.localeCompare(b));
  const isSenderFirst = userAId === firstId;

  await db.transaction(async (trx) => {
    // 2. 일관된 순서로 비관적 배타락(FOR UPDATE) 선점
    const firstWallet = await trx('wallets')
      .where({ user_id: firstId })
      .forUpdate()
      .first();
    const secondWallet = await trx('wallets')
      .where({ user_id: secondId })
      .forUpdate()
      .first();

    const senderWallet = isSenderFirst ? firstWallet : secondWallet;
    const receiverWallet = isSenderFirst ? secondWallet : firstWallet;

    if (!senderWallet || senderWallet.balance < amount) {
      throw new InsufficientBalanceError(`Balance insufficient for user ${userAId}`);
    }

    await trx('wallets').where({ user_id: userAId }).decrement('balance', amount);
    await trx('wallets').where({ user_id: userBId }).increment('balance', amount);
  });
}

3) 후속 프롬프트 체이닝 (Prompt Chaining)

체이닝 1: 부하 스트레스 테스트 코드 자동 도출
👉 "위 락 순서 정렬 패치가 동시 트래픽 500개에서 데드락을 0건으로 만드는지 검증하는 Jest 동시성 테스트 코드를 작성해줘."
→ AI가 Promise.all과 역방향 교차 송금(A->B, B->A)을 250쌍 동시 발송하는 스트레스 테스트 코드를 반환하여 수정안을 즉시 입증.

체이닝 2: Cursor IDE 즉시 패치 프롬프트
👉 "Cursor Composer에서 src/modules/wallet/wallet.service.ts 파일의 transferCredits 메서드를 위 결정론적 락 정렬 로직으로 교체하는 규칙을 작성해줘."

4) 4단계 장애 진단 & 복구 워크플로우

  1. 로그 파싱: 스택트레이스에서 블록된 릴레이션 튜플 번호 및 쿼리 추출.
  2. 5 Whys 진단: 레시피 B로 락 역전 인과 사슬 및 즉시 타임아웃 세팅 확보.
  3. 결정론적 정렬 패치: ID 기반 정렬로 상호 대기 사이클 제거.
  4. 회귀 방지 검증: 동시성 시뮬레이션으로 데드락 0건 확인 후 배포.

🚀 레시피 C 실행 결과: [실전 사례 2] Node.js OOM 메모리 누수 핫픽스

대용량 엑셀 다운로드 요청 폭주로 Node.js 파드가 OOM CrashLoopBackOff에 빠진 P0 상황을 2분 격리 / 5분 힙 증설 / 10분 스트림 전환으로 무중단 복구한 사례입니다.

1) 1차 입력 프롬프트 (레시피 C 긴급 텔레메트리 주입)

  • 유형: JavaScript heap out of memory (1420 MB reached), Pod CrashLoopBackOff 반복
  • 환경: Kubernetes v1.28, 컨테이너 메모리 제한 2GiB, 트래픽 유입 중

2) AI 생성 출력 결과 (핵심 발췌)

1. 피해 반경 격리 & 2. 긴급 드레인 (Kubectl CLI)
### 1. 피해 반경 격리 (즉시 실행)
# 비정상 종료 파드로 들어오는 인그레스 트래픽 일시 차단
kubectl label pod -l app=order-api traffic=isolated --overwrite

### 2. 긴급 드레인 & Node V8 힙 완화 (5분 이내)
# 컨테이너 크래시 방지를 위해 V8 최대 힙 크기를 메모리 제한의 75% 수준으로 강제 설정
kubectl set env deployment/order-api-deployment \
  NODE_OPTIONS="--max-old-space-size=1536"
kubectl scale deployment/order-api-deployment --replicas=18
3. 10분 전술적 핫픽스 (Surgical Diff: Array → Stream)
### 3. 10분 전술적 핫픽스 (Surgical Diff)
// src/services/export.service.ts
// 문제: 대용량 주문 내역을 배열(Array.push)로 메모리에 전량 적재하여 OOM 발생
// 수정: PassThrough Stream 파이프라인으로 전환하여 메모리 점유율을 상수로 고정 (10MB 유지)

- const allOrders = await OrderModel.find({ status: 'completed' }); // 10만 건 적재
- return generateExcel(allOrders);
+ const cursor = OrderModel.find({ status: 'completed' }).cursor();
+ res.setHeader('Content-Type', 'text/csv');
+ return cursor.pipe(new CsvTransformStream()).pipe(res);

3) 후속 체이닝: V8 힙 덤프(Heapdump) 분석 프롬프트 연계

사용자 추가 프롬프트:
👉 "긴급 핫픽스 배포 후 프로덕션에서 수집한 heapdump-001.heapsnapshot에서 메모리를 점유하고 있는 지배적 객체(Retainer tree)를 찾는 Chrome DevTools 분석 단계를 안내해줘."

4) 3단계 긴급 복구 워크플로우

  1. 트래픽 격리 및 힙 크기 조절: CrashLoop 파드를 격리하고 환경변수로 임시 버퍼 확보.
  2. 스트림 전환 핫픽스: 배열 전체 적재 로직을 커서 기반 스트리밍으로 즉각 교체.
  3. 안정화 후 덤프 분석: 복구 후 취득한 힙 덤프로 영구 누수 참조자 제거.

4. 프롬프트 활용 팁 & 주의사항

  • 로그 마스킹 필수: 프로덕션 에러 로그에는 고객의 개인정보(PII), JWT 시크릿, 내부 DB 비밀번호가 포함될 수 있습니다. AI 입력 전 sed나 스크립트로 Bearer eyJ... 또는 비밀번호 필드를 반드시 마스킹하십시오.
  • 스택 트레이스만 던지지 말 것: 같은 Connection refused라도 "DB 이전 작업 중"인지, "단순 트래픽 스파이크"인지에 따라 해결책이 180도 달라집니다. 시스템 자원 점유 상태와 최근 배포 커밋을 반드시 함께 제공하십시오.
  • 단순 try-catch 제안은 즉시 기각할 것: AI가 원인을 모호하게 여길 때 가장 자주 내놓는 답변이 단순 예외 삼키기(Swallowing Exceptions)입니다. "원인을 설명하지 않는 try-catch는 거부한다"는 제약을 프롬프트에 유지하십시오.
  • Cursor/Copilot 에이전트 모드 연동: 도출된 영구 수정 패치를 복사하여 Cursor IDE Composer의 프롬프트 창에 넣으면, 관련 엔티티와 서비스 레이어 코드 전체를 파일 간 종속성을 고려해 원클릭으로 리팩토링할 수 있습니다.

댓글 쓰기

다음 이전