// 이 파일이 하는 일: "HTTP와 HTTPS" 코스 — 브라우저와 서버가 나누는 대화(요청/응답)의
// 문법부터, 그 대화를 아무도 못 엿보게 봉인하는 HTTPS까지 7개 섹션으로 안내하는 정적 학습 페이지.
// (요청/응답 구조 → 상태코드 → 쿠키와 세션 → HTTPS/TLS → 인증서 → Network 탭 실습 → 정리 퀴즈)
// 학습 포인트: API 호출이 없는 '내용 고정' 페이지다. 스타일은 global.css의
// 가이드 전용 클래스(step-card, code-block, tip 등)를 재사용한다 — 색을 여기서 하드코딩하지 않는다.
// 텍스트 다이어그램은 JSX 중괄호/백틱 충돌을 피하려고 파일 상단의 백틱 문자열 상수로 정의한다.

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

// ── 텍스트 다이어그램 · 표 상수들 ──

const CODE_REQUEST = `브라우저가 서버에 보내는 편지 = HTTP 요청

GET /api/courses HTTP/1.1          ← ① 시작줄: "무엇을(경로), 어떻게(메서드)"
Host: edu.awesomedevapp.com        ← ② 헤더: 받는 사람 주소
Accept: application/json           ←    "답장은 JSON으로 주세요"
Cookie: SESSION=a1b2c3...          ←    "저 아까 로그인한 그 사람이에요"
                                   ← ③ 빈 줄 (헤더 끝 표시)
(GET은 보통 바디 없음)              ← ④ 바디: 보낼 내용물 (있을 때만)

서버가 돌려주는 답장 = HTTP 응답

HTTP/1.1 200 OK                    ← ① 시작줄: "결과는 이래(상태코드)"
Content-Type: application/json     ← ② 헤더: "내용물은 JSON이야"
Content-Length: 512                ←    "길이는 512바이트"

{"courses":[{"id":1,"title":"네트워크의 이해"}, ...]}   ← ④ 바디: 진짜 내용물`;

const CODE_METHODS = `메서드 = "무엇을 하고 싶은지"를 나타내는 동사

메서드    뜻            우리 플랫폼 실례
──────────────────────────────────────────────────────
GET      조회 (읽기)    GET  /api/courses        코스 목록 보여줘
POST     생성 (쓰기)    POST /api/auth/login     로그인 정보 보낼게 (바디에!)
PUT      수정 (교체)    PUT  /api/profile        내 프로필 이걸로 바꿔줘
DELETE   삭제           DELETE /api/posts/3      3번 글 지워줘

기억법: 게시판으로 생각하면 쉬워요.
글 목록 보기(GET) / 글 쓰기(POST) / 글 고치기(PUT) / 글 지우기(DELETE)
→ 데이터를 다루는 네 가지 기본 동작 = CRUD와 정확히 짝이 맞습니다.`;

const CODE_STATUS = `상태코드 = 서버의 대답 첫마디. 첫 숫자만 봐도 분위기를 알 수 있어요.

2xx "잘 됐어요"   3xx "다른 데로 가세요"   4xx "네가 잘못했어"   5xx "내(서버)가 잘못했어"

코드   이름                  우리 플랫폼에서 실제로 만나는 상황
─────────────────────────────────────────────────────────────
200   OK                   GET /api/courses 성공 — 코스 목록이 바디에 담겨 옴
301   Moved Permanently    http:// 로 접속 → Caddy가 "https:// 로 오세요" 안내
401   Unauthorized         로그인 안 하고 GET /api/me → "누구세요? 먼저 로그인!"
403   Forbidden            학생 계정으로 관리자 API 호출 → "누군진 알겠는데 권한 없음"
404   Not Found            GET /api/coursez (오타!) → "그런 주소 없는데요"
500   Internal Server Error 백엔드(Spring Boot) 코드가 터짐 → 서버 로그 볼 시간

401 vs 403 헷갈림 방지:
401 = 학생증 자체가 없음 (로그인부터)
403 = 학생증은 있는데 교무실 출입증은 아님 (권한 부족)`;

const CODE_COOKIE = `쿠키와 세션 — 우리 플랫폼 로그인이 유지되는 원리

HTTP는 원래 '금붕어 기억력'이에요. 요청 하나가 끝나면 상대가 누군지 다 잊습니다.
그래서 이런 순서로 "기억"을 만들어요:

① 로그인 요청
   POST /api/auth/login  (바디: 아이디+비밀번호)
        │
② 서버(Spring Boot): 확인 후 '번호표' 발급
   응답 헤더 → Set-Cookie: SESSION=a1b2c3; HttpOnly; Secure
   (서버는 "번호표 a1b2c3 = 3학년 김미림"을 자기 장부(세션 저장소)에 기록)
        │
③ 이후 모든 요청에 브라우저가 자동으로 번호표 동봉
   GET /api/me
   Cookie: SESSION=a1b2c3   ← 우리가 코드 안 짜도 브라우저가 알아서!
        │
④ 서버가 장부 대조: "a1b2c3? 아, 김미림 님" → 내 정보 응답

쿠키 = 손에 든 번호표(브라우저 보관)
세션 = 카운터 뒤의 장부(서버 보관)
번호표만 봐선 누군지 모르고, 장부와 맞춰봐야 아는 구조라 비밀번호가 오가지 않아요.`;

const CODE_COOKIE_FLAGS = `Set-Cookie 뒤에 붙는 옵션들 — 번호표 도난 방지 장치

HttpOnly  자바스크립트가 쿠키를 못 읽음
          → 악성 스크립트가 심어져도 번호표를 훔쳐가기 어려움
Secure    HTTPS일 때만 전송
          → 암호화 안 된 길로는 번호표를 아예 안 내보냄
SameSite  다른 사이트에서 시작된 요청엔 안 붙임
          → 낚시 사이트가 내 번호표를 슬쩍 쓰는 것(CSRF) 방지

이 세 줄이 로그인 보안의 기본기예요. 백엔드 과제에서 다시 만나게 됩니다!`;

const CODE_TLS = `HTTPS = HTTP + 봉투(TLS). 편지 내용은 같고, '봉인'이 추가된 것.

HTTP  = 엽서. 배달부(중간 라우터들)가 마음만 먹으면 내용을 다 읽어요.
        아이디·비밀번호도 그대로 노출!
HTTPS = 밀봉 봉투. 지나가는 누구도 내용을 못 보고, 뜯으면 티가 남.

TLS 핸드셰이크 — 봉투를 봉인하기 전 나누는 짧은 인사:

브라우저: "안녕! 나 이런 암호 방식들 쓸 줄 알아" (Client Hello)
서   버: "그럼 이걸로 하자. 그리고 이건 내 신분증(인증서)!" (Server Hello)
브라우저: (신분증 진짜인지 검사... 통과!)
          "좋아, 그럼 우리 둘만 아는 비밀 열쇠 만들자" (키 교환)
양   쪽: 지금부터 모든 대화를 그 열쇠로 잠가서 주고받음 🔒

핵심 아이디어:
- 신분 확인은 '자물쇠 공개 + 열쇠 비공개' 방식(공개키)으로,
- 실제 대화는 둘만 아는 빠른 열쇠(대칭키)로.
  느리지만 안전한 방법으로 '열쇠 전달'만 하고, 본대화는 빠른 열쇠로 하는 거예요.`;

const CODE_CERT = `인증서 = 서버의 신분증. 그런데 신분증은 누가 발급해 줄까?

[브라우저] ──"edu.awesomedevapp.com 맞아?"──> [우리 서버]
                                                │
                              "여기 인증서! CA가 보증했어"
                                                │
[브라우저]: 내 안에 미리 들어 있는 '신뢰 기관(CA) 목록'과 대조
            → 목록에 있는 기관의 도장이면 자물쇠 아이콘 🔒 표시
            → 아니면 "주의 요함" 빨간 경고!

우리 플랫폼의 인증서 발급 흐름 (자동!):

Let's Encrypt(무료 CA) <──"나 이 도메인 진짜 주인이야" 증명──> Caddy(우리 서버)

Caddy가 알아서:
1) Let's Encrypt에 "edu.awesomedevapp.com 인증서 주세요" 신청
2) "그 도메인 주인 맞는지 확인할게" 챌린지에 자동 응답
3) 발급받은 인증서로 HTTPS 서비스 + 만료(90일) 전에 자동 갱신

예전엔 인증서를 돈 주고 사서 수동 갱신했는데, 깜빡하면 사이트에
경고가 떠서 대형 사고였어요. 지금은 Caddy가 다 해줍니다. 고마운 친구!`;

const CODE_NETWORK_LAB = `실습: 개발자 도구로 우리 API 요청 해부하기 (5분)

1) 우리 학습 플랫폼에 로그인한 상태로 아무 페이지나 열기
2) F12 → Network 탭 → 필터에서 "Fetch/XHR" 선택
   (이미지·CSS 말고 'API 요청'만 골라 보는 필터예요)
3) F5 새로고침 → 목록에서 /api/ 로 시작하는 요청 하나 클릭

이제 오늘 배운 걸 전부 실물로 확인:

Headers 탭
  Request Method: GET           ← 섹션 1의 메서드!
  Status Code: 200 OK           ← 섹션 2의 상태코드!
  Request Headers > Cookie:     ← 섹션 3의 번호표! (SESSION=...)
  Response Headers > Content-Type: application/json

Response 탭
  서버가 보낸 바디(JSON 원문)가 그대로 보여요.

주소창 자물쇠 🔒 클릭 > 인증서
  발급 대상: edu.awesomedevapp.com
  발급자: Let's Encrypt          ← 섹션 5의 그 CA!
  유효 기간: 90일짜리인지 확인해 보세요.`;

const CODE_QUIZ = `셀프 체크 5문항 — 답을 소리 내어 설명할 수 있으면 통과!

Q1. 로그인 요청은 왜 GET이 아니라 POST일까요?
    힌트: GET은 보낼 내용을 주소(URL)에 싣는 경우가 많아요.
    비밀번호가 주소창·기록에 남는다면? (섹션 1)

Q2. 401과 403의 차이를 학생증 비유로 설명해 보세요. (섹션 2)

Q3. 서버는 매 요청마다 내가 누군지 어떻게 알까요?
    "쿠키"와 "세션" 두 단어를 모두 써서 설명해 보세요. (섹션 3)

Q4. 카페 공용 와이파이에서 http:// 사이트에 로그인하면
    무엇이 위험할까요? https:// 라면 왜 괜찮을까요? (섹션 4)

Q5. 브라우저는 처음 보는 서버의 인증서를 뭘 근거로 믿을까요?
    힌트: 브라우저 안에 미리 들어 있는 것. (섹션 5)

→ 내가 쓴 답이 맞는지 멘토와 함께 확인해 보세요.
  "말로 설명하다 막히는 지점"이 진짜 복습 포인트입니다.`;

// ── 이 페이지 안에서만 쓰는 작은 부품들 ──
// 학습 포인트: 같은 모양이 반복되면 컴포넌트로 뽑는다. 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: '요청과 응답' },
  { n: 2, label: '상태코드 읽기' },
  { n: 3, label: '쿠키와 세션' },
  { n: 4, label: 'HTTPS와 TLS' },
  { n: 5, label: '인증서' },
  { n: 6, label: 'Network 탭 해부' },
  { n: 7, label: '정리 퀴즈' },
];

export default function HttpPage() {
  return (
    <div>
      {/* 히어로: 이 코스가 다루는 대화의 '문법'과 '봉인' */}
      <div className="hero">
        <div className="eyebrow">Course · 네트워크</div>
        <h1>HTTP와 HTTPS<br />— 브라우저와 서버의 대화법, 그리고 봉인</h1>
        <p>
          브라우저와 서버가 주고받는 편지(요청/응답)의 문법을 배우고, 그 편지를
          아무도 못 엿보게 봉인하는 HTTPS까지 따라갑니다. 마지막엔 개발자 도구로
          <strong> 우리 플랫폼의 진짜 API 요청</strong>을 직접 해부해 봐요 —
          이 페이지를 여러분에게 배달한 바로 그 요청들을요.
        </p>
        <div className="chip-row">
          <span className="chip">예상 소요 50분</span>
          <span className="chip">실습 2개 + 퀴즈 5문항</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="HTTP 요청과 응답의 구조" sub="편지의 겉봉(시작줄·헤더)과 내용물(바디)">
        <p>
          <Link to="/learn/network">네트워크의 이해</Link> 코스에서 데이터가 달리는
          <strong> 길</strong>을 배웠다면, 이번엔 그 길 위를 오가는 <strong>편지의 형식</strong>을
          배울 차례예요. HTTP는 브라우저(클라이언트)와 서버가 주고받는 편지의
          <strong> 약속된 양식</strong>입니다. 요청도 응답도 구조는 똑같이 세 부분 —
          <strong> 시작줄, 헤더, 바디</strong>예요.
        </p>
        <Code>{CODE_REQUEST}</Code>
        <p>
          <strong>헤더</strong>는 편지 겉봉에 적는 메모예요. "받는 사람"(Host),
          "답장 형식 요청"(Accept), "내가 누군지"(Cookie) 같은 <strong>편지에 대한 정보</strong>가
          들어가고, <strong>바디</strong>엔 진짜 내용물(로그인 정보, JSON 데이터 등)이 들어갑니다.
        </p>
        <svg className="diagram" viewBox="0 0 640 360" xmlns="http://www.w3.org/2000/svg" role="img" aria-label="HTTP 요청과 응답의 구조 해부 — 브라우저와 서버가 주고받는 편지를 시작줄, 헤더, 빈 줄, 바디 네 부분으로 라벨링한 도해">
          <rect x="40" y="14" width="130" height="40" rx="8" fill="var(--card)" stroke="var(--teal)" strokeWidth="1.5" />
          <text x="105" y="39" fontSize="13" fill="var(--ink)" textAnchor="middle">브라우저</text>
          <rect x="470" y="14" width="130" height="40" rx="8" fill="var(--card)" stroke="var(--primary)" strokeWidth="1.5" />
          <text x="535" y="39" fontSize="13" fill="var(--ink)" textAnchor="middle">서버</text>
          <text x="320" y="22" fontSize="12" fill="var(--muted)" textAnchor="middle">요청 — 편지를 보낸다</text>
          <line x1="178" y1="30" x2="454" y2="30" stroke="var(--muted)" strokeWidth="1.5" />
          <path d="M462 30 l-8 -4 v8 z" fill="var(--muted)" />
          <line x1="186" y1="46" x2="462" y2="46" stroke="var(--muted)" strokeWidth="1.5" />
          <path d="M178 46 l8 -4 v8 z" fill="var(--muted)" />
          <text x="320" y="66" fontSize="12" fill="var(--muted)" textAnchor="middle">응답 — 답장이 돌아온다</text>
          <rect x="22" y="88" width="294" height="260" rx="10" fill="var(--card)" stroke="var(--line)" strokeWidth="1.5" />
          <text x="169" y="110" fontSize="13.5" fontWeight="700" fill="var(--ink)" textAnchor="middle">HTTP 요청 — 보내는 편지</text>
          <text x="34" y="130" fontSize="12" fill="var(--primary)">① 시작줄 — 용건: 메서드+경로</text>
          <rect x="34" y="136" width="270" height="30" rx="6" fill="none" stroke="var(--primary)" strokeWidth="1.5" />
          <text x="169" y="155" fontSize="12" fill="var(--ink)" textAnchor="middle">GET /api/courses HTTP/1.1</text>
          <text x="34" y="184" fontSize="12" fill="var(--teal)">② 헤더 — 편지에 대한 정보</text>
          <rect x="34" y="190" width="270" height="58" rx="6" fill="none" stroke="var(--teal)" strokeWidth="1.5" />
          <text x="169" y="206" fontSize="12" fill="var(--ink)" textAnchor="middle">Host: edu.awesomedevapp.com</text>
          <text x="169" y="222" fontSize="12" fill="var(--ink)" textAnchor="middle">Accept: application/json</text>
          <text x="169" y="238" fontSize="12" fill="var(--ink)" textAnchor="middle">Cookie: SESSION=a1b2c3...</text>
          <text x="34" y="258" fontSize="12" fill="var(--muted)">③ 빈 줄 — 헤더 끝 표시</text>
          <line x1="34" y1="263" x2="304" y2="263" stroke="var(--muted)" strokeWidth="1" strokeDasharray="4 4" />
          <text x="34" y="282" fontSize="12" fill="var(--amber)">④ 바디 — 진짜 내용물</text>
          <rect x="34" y="288" width="270" height="48" rx="6" fill="none" stroke="var(--amber)" strokeWidth="1.5" strokeDasharray="5 4" />
          <text x="169" y="315" fontSize="12" fill="var(--muted)" textAnchor="middle">(GET은 보통 바디 없음)</text>
          <rect x="324" y="88" width="294" height="260" rx="10" fill="var(--card)" stroke="var(--line)" strokeWidth="1.5" />
          <text x="471" y="110" fontSize="13.5" fontWeight="700" fill="var(--ink)" textAnchor="middle">HTTP 응답 — 돌아온 답장</text>
          <text x="336" y="130" fontSize="12" fill="var(--primary)">① 시작줄 — 결과: 상태코드</text>
          <rect x="336" y="136" width="270" height="30" rx="6" fill="none" stroke="var(--primary)" strokeWidth="1.5" />
          <text x="471" y="155" fontSize="12" fill="var(--ink)" textAnchor="middle">HTTP/1.1 200 OK</text>
          <text x="336" y="184" fontSize="12" fill="var(--teal)">② 헤더 — 내용물에 대한 정보</text>
          <rect x="336" y="190" width="270" height="58" rx="6" fill="none" stroke="var(--teal)" strokeWidth="1.5" />
          <text x="471" y="212" fontSize="12" fill="var(--ink)" textAnchor="middle">Content-Type: application/json</text>
          <text x="471" y="232" fontSize="12" fill="var(--ink)" textAnchor="middle">Content-Length: 512</text>
          <text x="336" y="258" fontSize="12" fill="var(--muted)">③ 빈 줄 — 헤더 끝 표시</text>
          <line x1="336" y1="263" x2="606" y2="263" stroke="var(--muted)" strokeWidth="1" strokeDasharray="4 4" />
          <text x="336" y="282" fontSize="12" fill="var(--amber)">④ 바디 — 진짜 내용물</text>
          <rect x="336" y="288" width="270" height="48" rx="6" fill="none" stroke="var(--amber)" strokeWidth="1.5" />
          <text x="471" y="307" fontSize="12" fill="var(--ink)" textAnchor="middle">{'{"courses":[{"id":1, ...}]}'}</text>
          <text x="471" y="326" fontSize="12" fill="var(--muted)" textAnchor="middle">요청한 진짜 데이터(JSON)</text>
        </svg>
        <p className="muted" style={{ fontSize: 12.5, textAlign: 'center', marginTop: 2 }}>그림: 요청도 응답도 같은 3부분 구조 — 시작줄(용건·결과) · 헤더(겉봉 메모) · 바디(내용물)</p>
        <p>
          시작줄 맨 앞의 <strong>메서드</strong>는 "이 편지의 용건"이에요.
          같은 주소라도 메서드에 따라 서버가 하는 일이 완전히 달라집니다.
        </p>
        <Code>{CODE_METHODS}</Code>
        <div className="tip">
          <b>우리 코드에서는</b> 프론트(React)에서 <span className="icode">fetch('/api/courses')</span>를
          쓰면 GET 요청이, <span className="icode">{'fetch(url, { method: "POST", body: ... })'}</span>를
          쓰면 POST 요청이 나갑니다. 백엔드(Spring Boot)는
          <span className="icode">@GetMapping</span>·<span className="icode">@PostMapping</span>으로
          받고요. 프론트와 백엔드가 <strong>같은 HTTP 문법</strong>으로 만나는 거예요.
        </div>
      </Section>

      <Section n={2} title="상태코드 읽기" sub="서버의 대답 첫마디 — 첫 숫자만 봐도 반은 안다">
        <p>
          응답의 시작줄엔 항상 세 자리 숫자, <strong>상태코드</strong>가 옵니다.
          시험 점수처럼 숫자대마다 의미가 정해져 있어서, <strong>첫 숫자만 봐도</strong>
          성공인지(2), 이사 갔는지(3), 요청한 쪽 잘못인지(4), 서버 잘못인지(5)를 알 수 있어요.
        </p>
        <Code>{CODE_STATUS}</Code>
        <div className="warn">
          <b>디버깅 황금률</b> — API가 안 될 때 첫 질문은 언제나 "상태코드가 뭐야?"입니다.
          <strong> 4xx면 내 요청부터 의심</strong>(주소 오타? 로그인 했나? 바디 형식 맞나?),
          <strong> 5xx면 서버 로그부터 확인</strong>. 이 습관 하나로 디버깅 시간이 반으로 줄어요.
        </div>
        <div className="tip">
          <b>직접 확인해 보기 ①</b> 브라우저 주소창에
          <span className="icode"> https://edu.awesomedevapp.com/api/이런주소는없어요 </span>
          처럼 일부러 엉터리 경로를 쳐 보세요. <span className="kbd">F12</span> →
          <span className="kbd"> Network</span> 탭에서 방금 요청의 상태가
          <strong> 404</strong>로 빨갛게 찍히는 걸 확인! 로그아웃 상태로 내 정보 API를
          호출하면 <strong>401</strong>도 만날 수 있어요. 에러 코드를 "일부러" 만들어 보면
          실전에서 만났을 때 하나도 안 무섭습니다.
        </div>
      </Section>

      <Section n={3} title="쿠키와 세션" sub="금붕어 기억력의 HTTP에게 '단골 손님'을 알아보게 하는 법">
        <p>
          HTTP의 중요한 성격 하나 — <strong>무상태(stateless)</strong>. 요청 하나를 처리하고
          나면 서버는 그 손님을 <strong>깨끗이 잊어버려요</strong>. 그런데 우리 플랫폼은
          로그인하면 페이지를 옮겨 다녀도 계속 "김미림 님"으로 알아보죠? 그 비밀이
          <strong> 쿠키와 세션</strong>, 카페의 <strong>진동벨(번호표)과 주문 장부</strong>입니다.
        </p>
        <Code>{CODE_COOKIE}</Code>
        <p>
          핵심은 <strong>역할 분담</strong>이에요. 브라우저는 번호표(쿠키)를 들고 다니며
          매 요청에 자동으로 내밀고, 서버는 장부(세션)에서 "이 번호표 = 이 사람"을 대조합니다.
          비밀번호는 <strong>로그인 그 한 번</strong>만 전송되고, 이후엔 번호표만 오가요.
        </p>
        <svg className="diagram" viewBox="0 0 640 300" xmlns="http://www.w3.org/2000/svg" role="img" aria-label="쿠키와 세션으로 로그인이 유지되는 4단계 도해 — 로그인 요청, 번호표(쿠키) 발급, 매 요청 자동 동봉, 서버의 장부(세션) 대조">
          <rect x="30" y="40" width="120" height="210" rx="10" fill="var(--card)" stroke="var(--teal)" strokeWidth="1.5" />
          <text x="90" y="64" fontSize="13" fontWeight="700" fill="var(--ink)" textAnchor="middle">브라우저</text>
          <text x="90" y="82" fontSize="12" fill="var(--muted)" textAnchor="middle">번호표 보관</text>
          <text x="90" y="186" fontSize="12" fill="var(--muted)" textAnchor="middle">쿠키(번호표)</text>
          <rect x="40" y="192" width="100" height="28" rx="6" fill="none" stroke="var(--amber)" strokeWidth="1.5" />
          <text x="90" y="210" fontSize="12" fill="var(--ink)" textAnchor="middle">SESSION=a1b2c3</text>
          <rect x="490" y="40" width="120" height="210" rx="10" fill="var(--card)" stroke="var(--primary)" strokeWidth="1.5" />
          <text x="550" y="64" fontSize="13" fontWeight="700" fill="var(--ink)" textAnchor="middle">서버</text>
          <text x="550" y="82" fontSize="12" fill="var(--muted)" textAnchor="middle">장부 보관</text>
          <text x="550" y="178" fontSize="12" fill="var(--muted)" textAnchor="middle">세션(장부)</text>
          <rect x="498" y="184" width="104" height="44" rx="6" fill="none" stroke="var(--amber)" strokeWidth="1.5" />
          <text x="550" y="201" fontSize="12" fill="var(--ink)" textAnchor="middle">a1b2c3 =</text>
          <text x="550" y="218" fontSize="12" fill="var(--ink)" textAnchor="middle">김미림 님</text>
          <text x="320" y="100" fontSize="12" fill="var(--teal)" textAnchor="middle">① POST /api/auth/login — 아이디+비밀번호</text>
          <line x1="158" y1="108" x2="474" y2="108" stroke="var(--teal)" strokeWidth="1.5" />
          <path d="M482 108 l-8 -4 v8 z" fill="var(--teal)" />
          <text x="320" y="132" fontSize="12" fill="var(--primary)" textAnchor="middle">② Set-Cookie: SESSION=a1b2c3 — 번호표 발급</text>
          <line x1="166" y1="140" x2="482" y2="140" stroke="var(--primary)" strokeWidth="1.5" />
          <path d="M158 140 l8 -4 v8 z" fill="var(--primary)" />
          <text x="320" y="164" fontSize="12" fill="var(--teal)" textAnchor="middle">③ 모든 요청에 Cookie: SESSION=a1b2c3 자동 동봉</text>
          <line x1="158" y1="172" x2="474" y2="172" stroke="var(--teal)" strokeWidth="1.5" />
          <path d="M482 172 l-8 -4 v8 z" fill="var(--teal)" />
          <text x="320" y="196" fontSize="12" fill="var(--primary)" textAnchor="middle">④ 장부 대조: a1b2c3 = 김미림 님 → 내 정보 응답</text>
          <line x1="166" y1="204" x2="482" y2="204" stroke="var(--primary)" strokeWidth="1.5" />
          <path d="M158 204 l8 -4 v8 z" fill="var(--primary)" />
          <text x="320" y="280" fontSize="12" fill="var(--muted)" textAnchor="middle">비밀번호는 ①에서 딱 한 번 — 그 뒤로는 번호표(쿠키)만 오간다</text>
        </svg>
        <p className="muted" style={{ fontSize: 12.5, textAlign: 'center', marginTop: 2 }}>그림: 번호표(쿠키)는 브라우저가, 장부(세션)는 서버가 보관 — 둘을 맞춰봐야 누군지 안다</p>
        <Code>{CODE_COOKIE_FLAGS}</Code>
        <div className="tip">
          <b>직접 확인해 보기 ②</b> 우리 플랫폼에 로그인한 뒤 <span className="kbd">F12</span> →
          <span className="kbd"> Application</span> 탭(파이어폭스는 Storage) → 왼쪽에서
          <strong> Cookies</strong>를 열어 보세요. 내 번호표(세션 쿠키)가 실제로 저장돼 있어요.
          이름과 <strong>HttpOnly·Secure 체크 표시</strong>를 확인해 보고 —
          그 쿠키를 <strong>삭제</strong>한 뒤 새로고침하면? 번호표를 잃어버렸으니
          로그아웃 상태가 됩니다. 방금 로그인 유지의 원리를 직접 부숴서(!) 증명한 거예요.
        </div>
      </Section>

      <Section n={4} title="HTTPS와 TLS 핸드셰이크" sub="엽서를 봉투에 넣기 — 그리고 봉인 전의 짧은 인사">
        <p>
          HTTP 편지는 사실 <strong>엽서</strong>예요. 내 PC에서 서버까지 가는 길에
          수많은 중간 지점(공유기, 통신사 장비...)을 지나는데, 엽서니까
          <strong> 지나가는 누구나 내용을 읽을 수 있어요</strong>. 로그인 요청이라면
          아이디와 비밀번호가 그대로 보인다는 뜻이죠. 그래서 편지를
          <strong> 밀봉 봉투</strong>에 넣기로 한 것이 <strong>HTTPS</strong>,
          그 봉투 기술의 이름이 <strong>TLS</strong>입니다.
        </p>
        <Code>{CODE_TLS}</Code>
        <p>
          이 인사(핸드셰이크)가 해결하는 문제는 두 가지예요.
          하나, <strong>"너 진짜 그 서버 맞아?"</strong> — 인증서로 신분 확인(다음 섹션!).
          둘, <strong>"열쇠를 어떻게 안전하게 나눠 갖지?"</strong> — 도청당하는 길 위에서
          둘만 아는 열쇠를 만드는 수학적 마법(공개키 암호)으로요. 인사가 끝나면
          그 열쇠로 잠근 대화만 오가서, 중간에서 훔쳐봐도 <strong>암호문 덩어리</strong>만 보입니다.
        </p>
        <div className="warn">
          <b>그래서 공용 와이파이가 무서운 거예요</b> — 카페 와이파이의 주인은 그 길을 지나는
          트래픽을 들여다볼 수 있어요. <span className="icode">http://</span> 사이트에서 입력한 건
          엽서처럼 노출되지만, <span className="icode">https://</span>라면 봉투 속이라 안전합니다.
          우리 플랫폼이 항상 자물쇠(🔒)를 달고 있는 이유, 그리고 섹션 3의 쿠키에
          <strong> Secure</strong> 옵션을 붙이는 이유가 바로 이거예요.
        </div>
      </Section>

      <Section n={5} title="인증서와 Let's Encrypt" sub="신분증은 아무나 발급하면 안 되니까">
        <p>
          봉투만으로는 부족해요. <strong>가짜 서버</strong>가 "내가 edu.awesomedevapp.com이야"
          라고 속이면서 봉투 대화를 걸어올 수도 있으니까요. 그래서 서버는
          <strong> 인증서</strong>라는 신분증을 내밀고, 그 신분증은 아무나 못 만들고
          <strong> CA(인증 기관)</strong>라는 공인된 발급처의 도장이 있어야 합니다.
          주민등록증을 문방구가 아니라 주민센터에서 발급하는 것과 같아요.
        </p>
        <Code>{CODE_CERT}</Code>
        <p>
          우리 플랫폼의 인증서는 <strong>Let's Encrypt</strong>라는 무료 CA에서 받아요.
          더 좋은 건, 서버 현관을 지키는 <strong>Caddy</strong>가 발급 신청부터
          <strong> 90일마다의 갱신까지 전부 자동</strong>으로 처리한다는 것.
          여러분이 나중에 개인 프로젝트를 EC2에 올릴 때도 같은 방법으로 자물쇠를 달 수 있습니다.
        </p>
        <div className="tip">
          <b>미리 보기</b> 주소창의 자물쇠 아이콘을 클릭하면 <strong>인증서 보기</strong> 메뉴가
          있어요. 발급자(Issuer)에 Let's Encrypt가 적혀 있는지, 유효 기간이 90일짜리인지 —
          다음 섹션의 실습에서 함께 확인해 볼 거예요.
        </div>
      </Section>

      <Section n={6} title="Network 탭으로 우리 API 해부하기" sub="오늘 배운 전부를 실물로 — 종합 실습">
        <p>
          이제 이론은 끝. <strong>이 페이지를 여러분에게 배달한 진짜 요청들</strong>을 열어서
          섹션 1~5에서 배운 걸 전부 눈으로 확인할 시간이에요. 개발자 도구의
          <strong> Network 탭</strong>은 앞으로 여러분이 프론트·백엔드를 만들 때
          <strong> 매일 열게 될 창</strong>이니, 오늘 손에 익혀 두세요.
        </p>
        <Code>{CODE_NETWORK_LAB}</Code>
        <p>
          여기서 본 <strong>Request Headers / Response Headers / Response 바디</strong>가
          섹션 1의 편지 구조 그대로고, <strong>Status Code</strong>가 섹션 2,
          <strong> Cookie 헤더</strong>가 섹션 3, <strong>자물쇠와 인증서</strong>가
          섹션 4~5입니다. 한 화면에 이 코스 전체가 들어 있는 셈이에요.
        </p>
        <div className="tip">
          <b>한 걸음 더</b> Network 탭에서 요청을 <strong>우클릭 → Copy → Copy as cURL</strong>을
          해 보세요. 브라우저가 보낸 요청을 터미널에서 그대로 재현할 수 있는 명령어가 복사됩니다.
          메서드·헤더·쿠키가 어떻게 명령어 옵션으로 바뀌는지 구경해 보면, "브라우저도 결국
          HTTP 편지를 조립해서 보내는 프로그램일 뿐"이라는 게 실감 나요.
        </div>
      </Section>

      <Section n={7} title="정리 퀴즈 — 셀프 체크 5문항" sub="설명할 수 있어야 아는 것">
        <Code>{CODE_QUIZ}</Code>
        <div className="tip">
          <b>공부 팁</b> 답을 종이에 쓰지 말고 <strong>옆 사람에게 말로 설명</strong>해 보세요.
          엽서·봉투·번호표·장부 — 오늘 나온 비유로 설명할 수 있으면 진짜 이해한 거예요.
          막히는 문항은 해당 섹션으로 돌아가 실습을 한 번 더!
        </div>
      </Section>

      <div className="step-card">
        <div className="step-body">
          <h3 style={{ marginBottom: 6 }}>🔒 여기까지 왔다면</h3>
          <p className="muted">
            이제 브라우저와 서버가 나누는 대화의 <strong>문법(요청/응답)</strong>과
            <strong> 봉인(HTTPS)</strong>을 모두 알게 됐어요. 데이터가 달리는 길이 궁금하면{' '}
            <Link to="/learn/network"><strong>네트워크의 이해</strong></Link>로,
            이 편지에 실려 오는 화면(HTML·JS)이 어떻게 만들어지는지 궁금하면{' '}
            <Link to="/learn/coding"><strong>코딩 기초</strong></Link>로 이어가 보세요.
            그리고 다음 과제에서 여러분이 직접 만들 API가 — 바로 오늘 해부한 그 편지들을
            보내는 쪽이 됩니다.
          </p>
        </div>
      </div>
    </div>
  );
}
