// 이 파일이 하는 일: "SRE와 장애 대응 — 무너져도 빨리 일어나는 팀" 코스 — 특급(대규모 시스템·전문가)
// 과정의 정적 학습 페이지. SRE의 핵심 사상에서 출발해 SLI·SLO·에러 버짓, 장애 등급과 온콜,
// 인시던트 커맨드, 진단의 기술, 비난 없는 포스트모템, 카오스 훈련, 신뢰성 문화까지 8개 섹션으로 안내한다.
// 프레이밍은 "장애는 없앨 수 없다 — 다만 빨리 일어나는 팀은 만들 수 있다". 우리 플랫폼의
// 실제 구성요소(Valkey 시세 스트림, 일1회 백업 데몬)를 시나리오 재료로 삼아 실전 감각을 붙인다.
// 학습 포인트: API 호출이 없는 '내용 고정' 페이지다. 스타일은 styles/global.css의
// 가이드 전용 클래스(step-card, code-block, tip 등)를 재사용하고 색은 var(--*)만 쓴다(하드코딩 금지).
// 예제 코드는 JSX 중괄호/백틱 충돌을 피하려고 파일 상단의 백틱 문자열 상수로 정의한다.

import { Link } from 'react-router-dom';

// ── 예제 코드 상수들 ──

const CODE_COST_CURVE = `가용성          한 달 허용 다운타임        비용 곡선
──────────────────────────────────────────────────────
99%    (two nines)    약 7시간 18분          기본기만으로 도달
99.9%  (three nines)  약 43분                모니터링·자동 복구 필요
99.99% (four nines)   약 4분 19초            다중 리전·자동 페일오버
99.999%(five nines)   약 26초                사람 개입 불가능한 영역

핵심: 9가 하나 늘 때마다 비용은 대략 10배로 뜁니다.
"우리 서비스에 몇 개의 9가 정말 필요한가?"가 SRE의 첫 질문이에요.
100%는 목표가 아니라, 돈을 무한히 태우는 방향일 뿐입니다.`;

const CODE_SLO = `# 시세 스트림 서비스의 SLI → SLO 정의 예시 (문서로 합의하는 것이 핵심)

SLI (측정 지표 — 사용자가 실제로 느끼는 것만 고른다)
  - 가용성: /api/market/stream 연결 성공 수 / 전체 연결 시도 수
  - 지연:   tick 이벤트가 발행 후 1초 안에 클라이언트에 도착한 비율

SLO (내부 목표 — 우리가 우리에게 하는 약속)
  - 30일 이동 창(rolling window) 기준 가용성 99.9%
  - 지연 SLI 99% 이상

SLA (외부 약속 — 어기면 배상이 따르는 계약, SLO보다 느슨하게)
  - 고객 계약서: 월 가용성 99.5% 미만 시 이용료 10% 크레딧

에러 버짓 = 100% - SLO
  - 99.9% SLO → 한 달(30일)에 43.2분의 '써도 되는 실패'
  - 이 43분은 벌점이 아니라 예산: 배포·실험·마이그레이션에 쓴다`;

const CODE_BUDGET_POLICY = `# 에러 버짓 정책 — 숫자가 개발과 운영의 다툼을 중재한다

if (남은 에러 버짓 > 0) then
    신규 기능 배포 계속 진행
    카나리 배포·실험도 허용 (버짓이 곧 실험의 연료)

if (에러 버짓 소진) then
    신규 기능 배포 동결 (feature freeze)
    스프린트를 안정화 작업으로 전환:
      - 알림 정리, 자동 롤백, 재시도 로직, 용량 확충
    버짓이 다시 차오르면 동결 해제

포인트: 이 정책을 '장애가 난 다음'에 만들면 늦어요.
평시에 개발 리더와 운영 리더가 서명해 둬야,
장애 후 "배포를 멈추자 vs 일정이 급하다" 싸움이 숫자로 끝납니다.`;

const CODE_SEV = `# 심각도(SEV) 등급 정의 예시 — 기준은 '기술'이 아니라 '영향'

SEV1  전체 사용자가 핵심 기능을 못 쓴다 / 매출·데이터 유실 진행 중
      예: 게이트웨이 다운, 결제 불가, DB 유실 진행
      → 즉시 전원 소집, 상태 페이지 공지, 경영진 보고

SEV2  상당수 사용자에게 주요 기능 저하
      예: Valkey 다운으로 시세 스트림 전면 중단 (조회는 됨)
      → 온콜 + 담당 서비스 오너 소집, 내부 30분 주기 공유

SEV3  일부 기능·일부 사용자에게 영향, 우회로 존재
      예: 푸시 알림 지연, 특정 종목 차트 렌더 오류
      → 온콜이 단독 대응, 업무 시간 내 처리

SEV4  사용자 영향 없음 (내부 지표 이상, 디스크 80% 경보 등)
      → 티켓으로 전환, 다음 업무일 처리

포인트: 등급을 '장애 중'에 토론하지 마세요. 표를 미리 합의해 두고,
장애가 나면 표에 대조해 3초 안에 등급을 '선언'하는 겁니다.`;

const CODE_ONCALL = `# 작은 팀의 현실적 온콜 설계 (전담 SRE 0명에서 시작)

로테이션
  - 주(primary) 1명 + 부(secondary) 1명, 1주일 단위 교대
  - 개발자 전원이 로테이션에 포함 — "내가 짠 코드는 내가 받는다"

에스컬레이션 경로 (알림이 무시되지 않게 층을 쌓는다)
  1차: 주온콜 호출 → 5분 무응답 시
  2차: 부온콜 호출 → 10분 무응답 시
  3차: 팀 리드 호출 (여기까지 오면 프로세스 실패로 보고 회고)

작은 팀의 타협점
  - 야간엔 SEV1·SEV2만 호출, SEV3 이하는 아침에
  - 알림 기준을 '증상'(SLO 위반)에 걸지, '원인'(CPU 높음)에 걸지 않기
    → 새벽에 깨울 가치가 있는 알림만 남긴다`;

const CODE_ROLES = `# 인시던트 커맨드 — 역할을 나누는 순간 혼란이 절반으로 준다

인시던트 커맨더 (IC)
  - 사고의 '지휘자'. 직접 디버깅하지 않는다 (가장 흔한 실수!)
  - 우선순위 결정, 역할 배정, "지금 뭘 시도 중인가"를 항상 안다

커뮤니케이션 리드
  - 상태 페이지·사내 공지를 30분마다 갱신
  - "다음 업데이트는 30분 뒤"를 항상 명시 — 침묵이 최악의 공지

조사 담당 (Ops)
  - 실제로 손을 움직이는 사람(들). 시도한 것·결과를 타임라인 채널에 기록

한 사람이 겸직해도 됩니다 (3인 팀이면 IC+커뮤니케이션 겸직).
중요한 건 "지금 누가 IC인가"를 채팅에 선언해 두는 것.
지휘자가 없는 장애 대응은 전원이 각자 디버깅하는 각개전투가 됩니다.`;

const CODE_COMMS = `# 장애 중 커뮤니케이션 — 추측 금지, 주기 약속

[내부 채널 #incident-0714 — 좋은 예]
14:02 (IC 선언) SEV2. Valkey 다운, 시세 스트림 전면 중단. IC는 김OO.
14:05 조사: market 서비스 로그에 Valkey 연결 거부 다발. 재현 확인.
14:10 조치: Valkey 컨테이너 재기동 시도 → 실패 (디스크 풀 추정)
14:25 조치: 오래된 AOF 파일 정리 후 재기동 → 성공, 스트림 복구 확인
14:30 (IC) 모니터링 30분 지속 후 종료 선언 예정

[상태 페이지 — 좋은 예]
"시세 실시간 갱신이 지연되고 있습니다. 원인을 파악해 복구 중이며,
 다음 업데이트는 30분 이내에 드리겠습니다." (14:10)

[나쁜 예]
"해커 공격으로 추정됩니다" ← 확인 안 된 추측은 절대 금지.
틀리면 신뢰를 잃고, 맞아도 확인 전엔 말할 이유가 없습니다.`;

const CODE_DIAGNOSIS = `# 진단의 첫 질문: "최근에 뭐가 바뀌었나?"
# 장애의 대다수는 '변화' 직후에 온다 — 배포, 설정, 인프라, 트래픽.

체크 순서 (통계적으로 확률 높은 순)
  1. 배포: 최근 24시간 내 배포가 있었나? → 있으면 롤백부터 검토
  2. 설정: env·피처 플래그·인프라 설정 변경은?
  3. 의존성: 외부 API·인프라(DB·캐시·큐) 상태는?
  4. 트래픽: 갑작스런 급증·비정상 패턴은?

이분 탐색적 격리 — 용의자를 절반씩 줄이기
  Q1. 게이트웨이 지표는 정상인가?
      → 정상이면 문제는 게이트웨이 뒤쪽. 절반 제거.
  Q2. market 서비스 API 응답(REST)은 되는데 SSE만 죽었나?
      → 그럼 DB가 아니라 스트림 경로(Valkey pub/sub)가 용의자.
  Q3. Valkey에 직접 PING이 되나?
      → 안 되면 확정. 이제야 '왜'를 판다.

포인트: 가설 없이 로그의 바다에 뛰어들지 마세요.
"X라면 Y가 보일 것" 형태의 가설 → 대시보드·로그로 검증 → 절반 소거.
앞 강좌에서 익힌 관측성 도구(메트릭·로그·트레이스)가 여기서 실전 투입됩니다.`;

const CODE_POSTMORTEM = `# 포스트모템 문서 골격 — 실습에서 이 구조 그대로 작성합니다

제목: 2026-07-14 Valkey 다운으로 시세 스트림 전면 중단 (SEV2)

1. 요약
   - 영향: 28분간 전체 사용자 시세 실시간 갱신 중단. REST 조회는 정상.
2. 타임라인 (판단이 아니라 사실만, 시각과 함께)
   - 13:57 Valkey 디스크 사용률 100% 도달 (경보 없었음)
   - 14:02 SLO 위반 알림 → 온콜 인지, SEV2 선언
   - 14:25 AOF 정리 후 재기동, 복구
3. 근본 원인 (사람 이름이 아니라 시스템의 빈틈)
   - AOF 무한 증가를 막는 rewrite 설정 부재 + 디스크 경보 부재.
     "누가 설정을 빼먹었다"가 아니라 "설정 누락을 잡을 검증이 없었다"
4. 잘된 점 / 아쉬운 점
   - 잘된 점: 이분 탐색으로 15분 만에 Valkey 특정
   - 아쉬운 점: 디스크가 6일에 걸쳐 차오르는 걸 아무도 못 봄
5. 액션 아이템 (담당자·기한 없으면 쓰지 않은 것과 같다)
   - [ ] Valkey AOF auto-rewrite 설정        — 담당: 박OO, 기한: 7/18
   - [ ] 디스크 80% 경보 추가 (전 노드)       — 담당: 이OO, 기한: 7/21
   - [ ] Valkey 다운 시 스트림 degraded 모드  — 담당: 김OO, 기한: 8/01`;

const CODE_GAMEDAY = `# 게임데이 시나리오 예시 — 통제된 환경에서 '미리' 무너져 보기

준비 (반드시 스테이징 또는 격리 환경에서)
  - 가설: "Valkey가 죽어도 REST 조회는 살고, 스트림은 5분 내 복구된다"
  - 범위: 스테이징의 Valkey 컨테이너 1개만. 중단 스위치(원복 명령) 준비.
  - 참관: 온콜 경험 없는 주니어를 IC 역할로 지정 (훈련 목적)

실행
  docker stop tbox-valkey        # 장애 주입
  # → 팀은 실제 장애처럼 대응: SEV 선언, 역할 분담, 타임라인 기록

관찰 포인트
  - 알림이 몇 분 만에 왔나? (안 왔다면 그게 첫 번째 수확)
  - 대시보드만으로 Valkey를 지목할 수 있었나?
  - 상태 공유는 주기적으로 이뤄졌나?

백업·복구 훈련 — 복구해 본 적 없는 백업은 백업이 아니다
  - 우리는 Postgres·Valkey를 일 1회 백업하는 데몬을 돌리고 있죠.
  - 분기 1회: 최신 백업으로 스테이징 DB를 실제 복원하고,
    앱을 붙여 로그인·조회가 되는지까지 확인해야 '검증된 백업'입니다.
  - 복원 소요 시간을 기록해 두세요 — 그게 곧 우리의 RTO(복구 목표 시간)입니다.`;

const CODE_TOIL = `# 토일(toil) 측정 — 자동화 우선순위는 감이 아니라 장부로

토일의 정의: 수작업 · 반복적 · 자동화 가능 · 서비스가 클수록 늘어나는 운영 작업

주간 토일 장부 예시
  작업                        주당 소요   자동화 난이도   우선순위
  ─────────────────────────────────────────────────────────
  배포 후 수동 헬스체크          90분        낮음          1순위
  디스크 정리 수동 실행          40분        낮음          2순위
  고객 문의용 로그 수동 조회      60분        중간          3순위
  인증서 갱신                   월 20분      낮음          4순위

규칙: 토일이 업무 시간의 50%를 넘으면 기능 개발을 멈추고 자동화한다.
      (구글 SRE의 기준. 작은 팀이라면 30%쯤에서 경보를 울리는 게 안전)`;

// ── 이 페이지 안에서만 쓰는 작은 부품들 ──
// 학습 포인트: 같은 모양이 반복되면 컴포넌트로 뽑는다. props만 바꿔 재사용.
function Section({ n, title, sub, children }) {
  return (
    <section className="step-card" id={`sec-${n}`}>
      <div className="step-head">
        <span className="step-num">{n}</span>
        <div>
          <h3>{title}</h3>
          {sub && <span className="step-sub">{sub}</span>}
        </div>
      </div>
      <div className="step-body">{children}</div>
    </section>
  );
}

function Code({ children }) {
  return <pre className="code-block"><code>{children}</code></pre>;
}

const SECTIONS = [
  { n: 1, label: 'SRE란' },
  { n: 2, label: 'SLI·SLO·에러 버짓' },
  { n: 3, label: '장애 등급·온콜' },
  { n: 4, label: '장애 지휘' },
  { n: 5, label: '진단의 기술' },
  { n: 6, label: '포스트모템' },
  { n: 7, label: '카오스와 훈련' },
  { n: 8, label: '신뢰성 문화' },
];

export default function Lv4SreIncidentResponsePage() {
  return (
    <div>
      {/* 히어로: 이 코스가 어디서 출발해 어디까지 가는지 */}
      <div className="hero">
        <div className="eyebrow">Course · 특급 과정</div>
        <h1>🚨 SRE와 장애 대응<br />— 무너져도 빨리 일어나는 팀</h1>
        <p>
          장애 없는 시스템은 없습니다. 규모가 커질수록 질문은 "장애를 어떻게 없앨까"에서{' '}
          <strong>"장애가 났을 때 얼마나 빨리, 얼마나 침착하게 일어날까"</strong>로 바뀌어요.
          이 코스에서는 <strong>SLO와 에러 버짓</strong>으로 신뢰성을 숫자로 관리하고, 사고
          현장을 역할 분담으로 지휘하고, <strong>비난 없는 포스트모템</strong>으로 같은 장애를
          두 번 겪지 않는 팀의 작동법을 익힙니다.
        </p>
        <div className="chip-row">
          <span className="chip">예상 소요 80분</span>
          <span className="chip">실습: 포스트모템 작성·모의 리뷰</span>
          <span className="chip">선수 지식: 관측성·배포 파이프라인</span>
        </div>
      </div>

      {/* 섹션 바로가기 */}
      <nav className="pill-nav">
        {SECTIONS.map((s) => (
          <a key={s.n} href={`#sec-${s.n}`}>
            <b>{s.n}</b>
            {s.label}
          </a>
        ))}
      </nav>

      <Section n={1} title="SRE란 무엇인가" sub="운영을 소프트웨어 문제로 다루는 태도">
        <p>
          <strong>SRE(Site Reliability Engineering)</strong>는 구글에서 나온 한 문장으로
          요약됩니다 — <strong>"운영은 소프트웨어 문제다."</strong> 서버 재기동, 디스크 정리,
          배포 후 확인 같은 반복 수작업(이걸 <strong>토일(toil)</strong>이라 불러요)을 사람이
          손으로 계속 하는 대신, 코드로 없애 버리는 겁니다. 운영자를 뽑는 게 아니라,{' '}
          <strong>운영을 자동화하는 엔지니어</strong>를 두는 발상의 전환이죠.
        </p>
        <p>
          두 번째 사상이 더 급진적입니다. <strong>100% 가용성은 목표가 아니에요.</strong>{' '}
          사용자의 인터넷, 기기, 통신사부터가 100%가 아니기 때문에, 어느 선을 넘으면 아무리
          돈을 부어도 사용자는 차이를 <strong>느끼지 못합니다</strong>. 반면 비용은 9 하나에
          10배씩 뛰죠.
        </p>
        <Code>{CODE_COST_CURVE}</Code>
        <p>
          그럼 SRE는 조직에서 뭘 하는 존재일까요? 개발팀은 빨리 배포하고 싶고, 운영은 아무것도
          안 바뀌길 바랍니다. 이 긴장을 목소리 큰 쪽이 아니라 <strong>숫자로 중재</strong>하는
          것 — 그게 SRE의 역할이에요. 그 숫자가 바로 다음 섹션의 SLO와 에러 버짓입니다.
        </p>
        <div className="tip">
          <b>규모의 감각</b> "우리는 작은 팀이라 SRE는 사치"라고 생각하기 쉬운데, 반대예요.
          작은 팀일수록 한 사람이 새벽에 깨는 비용이 크고, 토일이 개발 시간을 직접 갉아먹습니다.
          전담 SRE를 뽑으라는 게 아니라, <strong>SRE의 사고방식</strong>(측정하고, 자동화하고,
          숫자로 중재하기)을 팀 전체가 나눠 갖자는 이야기입니다.
        </div>
      </Section>

      <Section n={2} title="SLI·SLO·에러 버짓" sub="신뢰성을 '느낌'에서 '숫자'로">
        <p>
          "요즘 서비스가 좀 불안하지 않아?" — 이런 대화는 아무것도 바꾸지 못해요. 신뢰성을
          관리하려면 먼저 <strong>측정</strong>해야 합니다. 세 단어의 관계를 정확히 잡으세요.{' '}
          <strong>SLI</strong>(Indicator)는 <strong>측정 지표</strong>, <strong>SLO</strong>
          (Objective)는 그 지표에 거는 <strong>내부 목표</strong>, <strong>SLA</strong>
          (Agreement)는 어기면 배상이 따르는 <strong>외부 계약</strong>입니다. SLA는 항상
          SLO보다 느슨하게 잡아요 — 내부 목표를 어겨도 계약 위반까지는 여유가 있도록요.
        </p>
        <Code>{CODE_SLO}</Code>
        <p>
          좋은 SLI의 기준은 하나입니다. <strong>사용자가 실제로 느끼는 것인가?</strong> CPU
          사용률·메모리는 SLI로 부적합해요 — CPU가 90%여도 응답이 빠르면 사용자는 행복하고,
          CPU가 20%여도 응답이 안 오면 장애입니다. 그래서 SLI는 대부분{' '}
          <strong>성공률</strong>(요청 중 성공 비율)과 <strong>지연</strong>(N초 안에 응답한
          비율) 두 계열로 수렴합니다.
        </p>
        <p>
          그리고 SLO의 진짜 힘은 뒤집었을 때 나옵니다. 99.9%를 약속했다는 건,{' '}
          <strong>0.1%는 실패해도 된다고 약속한 것</strong>이기도 해요. 한 달이면 약 43분 —
          이걸 <strong>에러 버짓(error budget)</strong>이라 부릅니다. 벌점이 아니라{' '}
          <strong>예산</strong>이에요. 새 기능 배포, 위험한 마이그레이션, 카나리 실험이 모두
          이 예산을 소비하는 활동입니다.
        </p>
        <Code>{CODE_BUDGET_POLICY}</Code>
        <div className="tip">
          <b>왜 이게 '중재'인가</b> 버짓이 남아 있으면 개발팀은 당당하게 배포합니다 — "우린
          예산 안에서 움직이고 있다". 버짓이 바닥나면 운영은 당당하게 배포를 멈춥니다 — "예산
          초과다, 안정화가 먼저다". <strong>어느 쪽도 감정이 아니라 숫자를 근거로 말하게</strong>{' '}
          되는 것, 이것이 에러 버짓이 조직에 주는 가장 큰 선물이에요.
        </div>
      </Section>

      <Section n={3} title="장애 등급과 온콜 체계" sub="새벽 3시에 판단하지 않기 위한 사전 설계">
        <p>
          장애 대응의 절반은 <strong>장애가 나기 전에</strong> 끝나 있어야 합니다. 첫 번째가{' '}
          <strong>심각도(SEV) 등급표</strong>예요. 기준은 기술적 화려함이 아니라{' '}
          <strong>영향</strong>입니다 — 매출이 새는가, 전체 사용자인가 일부인가, 우회로가
          있는가. 이 표가 미리 합의돼 있어야, 장애가 터진 순간 등급을 '토론'하지 않고
          '선언'할 수 있어요.
        </p>
        <Code>{CODE_SEV}</Code>
        <p>
          두 번째가 <strong>온콜(on-call) 체계</strong>입니다. 핵심은 "누가 받나"보다{' '}
          <strong>"안 받으면 어떻게 되나"</strong> — 즉 에스컬레이션 경로예요. 알림이 한 사람의
          무음 모드에 막혀 사라지는 구조라면, 온콜이 없는 것과 같습니다.
        </p>
        <Code>{CODE_ONCALL}</Code>
        <div className="warn">
          <b>알림 피로가 온콜을 죽인다</b> 온콜 설계에서 가장 흔한 실패는 사람이 아니라{' '}
          <strong>알림 그 자체</strong>예요. 새벽에 울렸는데 조치할 게 없는 알림이 반복되면,
          사람은 곧 알림을 무시하도록 학습됩니다 — 그리고 진짜 장애가 그 사이로 빠져나가요.
          알림은 <strong>SLO 위반(증상)</strong>에 걸고, CPU·메모리 같은 원인 지표는 대시보드로
          내리세요. "이 알림을 받으면 내가 뭘 해야 하지?"에 답이 없는 알림은 삭제 대상입니다.
        </div>
      </Section>

      <Section n={4} title="장애 지휘 — 사고 현장의 역할 분담" sub="전원이 디버깅하면 아무도 지휘하지 않는다">
        <p>
          장애가 터지면 유능한 엔지니어일수록 반사적으로 터미널을 엽니다. 그런데 전원이
          디버깅에 뛰어드는 순간, <strong>전체 그림을 보는 사람이 0명</strong>이 돼요. 같은 걸
          두 명이 조사하고, 누군가 알리지 않고 서비스를 재기동하고, 대표는 "지금 어떤 상황이냐"고
          물을 사람을 못 찾죠. 그래서 소방·재난 대응에서 빌려온 것이{' '}
          <strong>인시던트 커맨드</strong> 체계입니다.
        </p>
        <Code>{CODE_ROLES}</Code>
        <p>
          두 번째 원칙: <strong>복구가 먼저, 원인 규명은 나중.</strong> 사용자는 "왜 죽었는지"가
          아니라 "언제 되는지"에만 관심이 있어요. 최근 배포가 의심되면 <strong>일단 롤백</strong>
          하세요. 롤백은 패배 선언이 아니라, 상황을 안전한 상태로 되돌리는 가장 빠르고 검증된
          복구 수단입니다. "내 코드가 원인이 아닐 텐데…"라며 롤백을 미루는 30분이 SEV2를 SEV1로
          키웁니다. 원인은 서비스가 살아난 뒤 로그가 도망가지 않으니 천천히 파면 돼요.
        </p>
        <Code>{CODE_COMMS}</Code>
        <div className="tip">
          <b>침묵이 최악의 공지</b> 장애 중 사용자와 동료가 가장 못 견디는 건 나쁜 소식이 아니라{' '}
          <strong>소식이 없는 것</strong>이에요. "원인 파악 중이며 다음 업데이트는 30분 뒤"라는
          한 줄이, 어설픈 추측 열 줄보다 신뢰를 지킵니다. 그리고 확인 안 된 추측은 내부 채널에서도
          "추정"이라고 명시하세요 — 추측이 사실처럼 번지면 조사 방향 전체가 오염됩니다.
        </div>
      </Section>

      <Section n={5} title="진단의 기술 — 가설과 검증" sub="로그의 바다에 뛰어들기 전에 지도를 그린다">
        <p>
          진단의 첫 질문은 정해져 있습니다. <strong>"최근에 뭐가 바뀌었나?"</strong> 멀쩡히
          돌던 시스템이 스스로 무너지는 경우는 드물어요. 장애의 대다수는 <strong>변화</strong> —
          배포, 설정 변경, 인프라 작업, 트래픽 급증 — 직후에 옵니다. 그래서 성숙한 팀은 배포·설정
          변경 이력을 대시보드에 겹쳐 그려 두죠. 지표가 꺾인 시각과 배포 시각이 겹치면, 조사의
          80%가 끝난 겁니다.
        </p>
        <Code>{CODE_DIAGNOSIS}</Code>
        <p>
          변화가 안 보일 때 쓰는 무기가 <strong>이분 탐색적 격리</strong>입니다. 코드에서
          버그를 반씩 좁혀 찾듯, 시스템에서도 계층별·서비스별로 용의자를 절반씩 소거해요.
          "게이트웨이는 정상인가 → 뒤쪽 절반만 남는다. REST는 되는데 SSE만 죽었나 → 스트림
          경로만 남는다." 질문 몇 개면 수십 개 컴포넌트가 한두 개로 줄어듭니다.
        </p>
        <p>
          이 과정 전체를 받치는 것이 앞 강좌에서 익힌 <strong>관측성 도구</strong>예요. 메트릭으로
          "어디가 아픈지" 넓게 보고, 트레이스로 "요청이 어느 구간에서 죽는지" 따라가고, 로그로
          "그 순간 무슨 일이 있었는지" 확정합니다. 도구를 배우는 것과 장애의 압박 속에서 꺼내
          쓰는 건 전혀 다른 문제라서 — 섹션 7의 훈련이 필요한 거고요.
        </p>
        <div className="warn">
          <b>확증 편향 주의</b> "아 이거 지난번 그 문제네"라는 직감은 강력하지만 위험합니다.
          직감이 가설을 주는 건 좋아요 — 단, <strong>검증 없이 조치하지 마세요.</strong> 지난번과
          증상이 같아도 원인이 다르면, 지난번 처방이 상황을 악화시킬 수 있습니다. 가설 → 예측
          ("X라면 Y가 보일 것") → 확인 → 조치. 이 리듬을 압박 속에서도 지키는 게 시니어의
          디버깅입니다.
        </div>
      </Section>

      <Section n={6} title="비난 없는 포스트모템" sub="'누가'가 아니라 '무엇이 그 행동을 합리적으로 보이게 했나'">
        <p>
          장애가 끝나면 진짜 중요한 일이 시작됩니다 — <strong>포스트모템(postmortem)</strong>,
          장애 회고 문서예요. 여기서 절대 원칙이 <strong>비난 없음(blameless)</strong>입니다.
          이유는 도덕이 아니라 공학이에요. 사람을 벌하면 다음부터 사람들은 실수를{' '}
          <strong>숨깁니다</strong>. 숨겨진 실수는 학습되지 않고, 같은 장애가 반복돼요. 그래서
          질문을 바꿉니다. "누가 그랬나?"가 아니라 <strong>"무엇이 그 행동을 그 시점에
          합리적으로 보이게 했나?"</strong> — 잘못된 설정을 넣은 사람이 아니라, 잘못된 설정이
          검증 없이 운영까지 흘러갈 수 있었던 <strong>시스템의 빈틈</strong>을 파는 겁니다.
        </p>
        <Code>{CODE_POSTMORTEM}</Code>
        <p>
          문서의 심장은 <strong>액션 아이템</strong>입니다. 그리고 철칙 하나 —{' '}
          <strong>담당자와 기한이 없는 액션 아이템은 쓰지 않은 것과 같아요.</strong> "모니터링을
          강화한다" 같은 문장은 아무도 움직이지 않습니다. "디스크 80% 경보 추가 — 담당 이OO,
          기한 7/21"처럼 티켓으로 만들어 일반 업무와 같은 트래킹에 태우세요. 포스트모템 리뷰
          때 지난 장애의 액션 아이템 완료 여부를 먼저 확인하는 팀이, 실제로 장애가 줄어드는
          팀입니다.
        </p>
        <div className="tip">
          <b>같은 장애가 두 번 나면</b> 그건 사람 잘못이 아니라 <strong>시스템 잘못</strong>
          입니다. 첫 번째 장애 때 액션 아이템이 안 나왔거나, 나왔는데 실행이 안 됐거나, 실행됐는데
          불충분했다는 뜻이니까요. 재발은 개인의 부주의가 아니라 <strong>포스트모템 프로세스의
          실패</strong>로 회고해야, 세 번째가 없습니다.
        </div>
      </Section>

      <Section n={7} title="장애를 미리 겪기 — 카오스와 훈련" sub="첫 실전이 진짜 장애여선 안 된다">
        <p>
          소방관은 불이 나기 전에 훈련합니다. 그런데 많은 개발팀의 첫 장애 대응 경험은{' '}
          <strong>실제 장애</strong>예요 — 가장 비싼 수업료를 내고 배우는 셈이죠. 대안이{' '}
          <strong>게임데이(game day)</strong>입니다. 가상 장애 시나리오를 통제된 환경에 주입하고,
          팀이 실제 장애처럼 대응해 보는 훈련이에요. 목적은 시스템 테스트가 아니라{' '}
          <strong>사람과 프로세스 테스트</strong>입니다 — 알림은 울리는가, 역할 분담은 되는가,
          런북은 쓸 만한가.
        </p>
        <Code>{CODE_GAMEDAY}</Code>
        <p>
          이걸 한 단계 밀어붙인 것이 <strong>카오스 엔지니어링</strong>입니다. 넷플릭스가 운영
          환경에서 서버를 무작위로 죽이는 도구(Chaos Monkey)로 유명해졌죠. 다만 원칙을 놓치면
          그냥 방화입니다. <strong>① 작게</strong> 시작하고(컨테이너 1개부터),{' '}
          <strong>② 통제된 범위</strong>에서(중단 스위치·폭발 반경 제한 필수),{' '}
          <strong>③ 가설을 갖고</strong>("Valkey가 죽어도 REST는 산다") 실험해야 해요. 가설이
          깨지면 그게 수확입니다 — 진짜 장애가 알려주기 전에 약점을 찾은 거니까요.
        </p>
        <div className="warn">
          <b>복구해 본 적 없는 백업은 백업이 아니다</b> 백업 파일이 매일 쌓이는 것과, 그걸로
          실제 복구가 되는 건 완전히 다른 문제예요. 백업 스크립트의 버그, 빠진 스키마, 복원
          절차의 문서 누락 — 전부 <strong>복원을 시도해 봐야만</strong> 드러납니다. 우리도 일
          1회 백업 데몬을 돌리고 있으니, 분기에 한 번은 스테이징에 실제 복원하고 앱을 붙여
          동작까지 확인하세요. 그때 잰 복원 소요 시간이 곧 우리의 실제 복구 능력입니다.
        </div>
      </Section>

      <Section n={8} title="신뢰성 문화 만들기" sub="제도와 인센티브가 행동을 만든다">
        <p>
          마지막 조각은 도구가 아니라 <strong>문화</strong>입니다. 냉정한 진실 하나 —{' '}
          <strong>장애 공유가 승진에 불리하면, 아무도 공유하지 않습니다.</strong> 장애를 잘
          수습하고 좋은 포스트모템을 쓴 사람이 조용히 넘어간 사람보다 나쁜 평가를 받는 조직에서,
          비난 없는 포스트모템은 문서 양식일 뿐이에요. 반대로 훌륭한 포스트모템이 팀 전체에
          공유되고 칭찬받는 조직에서는, 실패가 조직의 자산으로 바뀝니다. 제도가 행동을 만들어요.
        </p>
        <p>
          두 번째는 <strong>토일의 가시화</strong>입니다. "요즘 운영 잡무가 많다"는 느낌으로는
          자동화 투자를 설득할 수 없어요. 주 단위로 토일을 장부에 적으면, 어떤 자동화가 몇 시간을
          돌려주는지 <strong>투자수익</strong>으로 말할 수 있게 됩니다.
        </p>
        <Code>{CODE_TOIL}</Code>
        <p>
          세 번째는 <strong>주니어가 온콜에서 성장하는 구조</strong>예요. 온콜을 "시니어가
          견디는 벌"로 두면 병목과 번아웃이 오고, 주니어를 준비 없이 던지면 사고가 납니다. 계단을
          놓으세요. <strong>① 섀도잉</strong> — 시니어의 온콜에 동행하며 관찰만 한다 →{' '}
          <strong>② 부온콜</strong> — 알림을 같이 받되 최종 판단은 시니어가 → <strong>③
          주온콜</strong> — 든든한 에스컬레이션 경로를 등에 업고 홀로 선다. 장애 대응 능력은
          강의가 아니라 이 계단에서 길러집니다.
        </p>
        <div className="tip">
          <b>실습 안내 — 이 코스의 마무리</b> 과거에 겪은 실제 장애 하나(없다면 가상 시나리오
          "Valkey 다운으로 시세 스트림 전면 중단")를 골라, 섹션 6의 골격대로{' '}
          <strong>포스트모템 문서를 완성</strong>하세요. 타임라인 복원 → 영향 산정 → 근본 원인
          (사람이 아니라 시스템의 빈틈으로) → 담당자·기한 있는 액션 아이템까지. 다 쓰면 동료
          한 명과 <strong>모의 리뷰</strong>를 진행합니다 — 리뷰어의 역할은 "비난하는 문장
          찾아내기"와 "담당자·기한 없는 액션 아이템 반려하기" 두 가지예요.
        </div>
      </Section>

      <div className="step-card">
        <div className="step-body">
          <h3 style={{ marginBottom: 6 }}>🚨 여기까지 왔다면</h3>
          <p className="muted">
            이제 신뢰성을 "느낌"이 아니라 <strong>SLO와 에러 버짓이라는 숫자</strong>로 다루고,
            장애 현장을 역할 분담으로 지휘하고, 비난 없는 포스트모템으로 실패를 자산으로 바꾸는
            팀의 작동법을 손에 쥐었습니다. 무너지지 않는 시스템이 아니라{' '}
            <strong>빨리 일어나는 팀</strong> — 그게 대규모 시스템을 오래 운영하는 유일한
            방법이에요. 다음은 지금까지 배운 확장·신뢰성·관측성 감각을 총동원하는 종합 훈련입니다.{' '}
            <Link to="/learn/lv4-system-design-url-shortener"><strong>시스템 설계 훈련 1 —
            URL 단축기를 처음부터 끝까지</strong></Link> 코스에서, 작아 보이는 서비스 하나를
            대규모 트래픽 기준으로 처음부터 끝까지 설계해 봅시다.
          </p>
        </div>
      </div>
    </div>
  );
}
