// 이 파일이 하는 일: "DNS 깊이 보기" 코스 — 네트워크 코스 5섹션에서 맛본 DNS를
// 뿌리(루트 서버)부터 우리 회사의 실제 Route53 구성까지 7개 섹션으로 파고드는 정적 학습 페이지.
// (재귀 조회의 여행 → 레코드 타입 → TTL과 캐시 → hosts 파일 실습 → nslookup 실습 → 우리 Route53 → 정리 퀴즈)
// 학습 포인트: API 호출이 없는 '내용 고정' 페이지다. 스타일은 global.css의
// 가이드 전용 클래스(step-card, code-block, tip, warn 등)를 재사용한다 — 색을 여기서 하드코딩하지 않는다.
// 텍스트 다이어그램은 JSX 중괄호/백틱 충돌을 피하려고 파일 상단의 백틱 문자열 상수로 정의한다.

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

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

const CODE_RECURSIVE_TRIP = `edu.awesomedevapp.com 의 IP를 아무도 캐시에 안 갖고 있을 때 — 풀코스 여행

[내 PC] ── "edu.awesomedevapp.com의 IP 알려줘" ──> [리졸버(통신사 DNS)]
                                                        │
    리졸버가 대신 뛰어다니기 시작 (그래서 '재귀' 조회):     │
                                                        ▼
  ① 루트 서버 13곳 중 하나에게: "edu.awesomedevapp.com?"
     루트: "몰라. 근데 .com 담당은 쟤네야" ──> .com TLD 서버 주소를 알려줌

  ② .com TLD 서버에게: "edu.awesomedevapp.com?"
     TLD: "몰라. 근데 awesomedevapp.com 담당은 쟤네야" ──> 권한 서버 주소를 알려줌

  ③ 권한(Authoritative) 서버에게: "edu.awesomedevapp.com?"
     권한 서버(우리는 Route53!): "그건 내 담당! x.x.x.x 야" ── 드디어 정답!

[리졸버] ── "x.x.x.x 입니다" ──> [내 PC] ── 접속 시작!

포인트: 아무도 전체 전화번호부를 통째로 안 들고 있어요.
"거기 말고 저기 물어봐"를 두 번 거쳐 진짜 담당자를 찾는 구조.`;

const CODE_RECORD_TYPES = `자주 만나는 DNS 레코드 타입 4형제

타입     뜻                       예시 (우리 도메인이라면)
──────────────────────────────────────────────────────────────
A       이름 → IPv4 주소          edu.awesomedevapp.com → 3.x.x.x
CNAME   이름 → 다른 이름 (별명)    www → edu.awesomedevapp.com
MX      이 도메인의 메일은 어디로   awesomedev.dev → 메일 서버 주소
TXT     자유 메모장 (검증·정책용)   "이 도메인 주인 맞음" 증명 문자열 등

CNAME 주의: 별명의 별명도 가능하지만, 결국 끝에는 A 레코드가 있어야
진짜 IP에 도착해요. 별명만 뱅뱅 돌면 아무 데도 못 갑니다.
TXT 활용: 도메인 소유 확인(예: 인증서 발급), 스팸 방지 정책(SPF) 등
"사람이 읽는 공지"가 아니라 "다른 시스템이 읽는 증명서"로 쓰여요.`;

const CODE_TTL = `TTL(Time To Live) = "이 답, 몇 초 동안 믿고 재사용해도 돼"

권한 서버가 답을 줄 때 유통기한을 같이 붙여요:
  edu.awesomedevapp.com  A  3.x.x.x   TTL=300 (5분)

TTL이 길면(예: 86400 = 하루):
  + DNS 질문이 줄어 빠르고 서버 부담 적음
  - IP를 바꿔도 최대 하루 동안 옛 주소로 가는 사람이 남음

TTL이 짧으면(예: 60 = 1분):
  + 변경이 금방 퍼짐
  - 질문이 잦아짐 (Route53은 질문 수만큼 과금!)

실전 요령: 서버 이사 계획이 있으면 "미리" TTL을 줄여 두고,
이사가 끝나 안정되면 다시 늘린다.`;

const CODE_HOSTS = `hosts 파일 — 내 PC 전용 수제 전화번호부 (DNS보다 먼저 찾아봄!)

위치(Windows): C:\\Windows\\System32\\drivers\\etc\\hosts
편집: 메모장을 "관리자 권한으로 실행" → 이 파일 열기

맨 아래에 한 줄 추가해 보기:
127.0.0.1    haha.awesomedev.test

저장 후 브라우저에서 http://haha.awesomedev.test 접속
→ 127.0.0.1(내 PC 자신)로 가려다 실패하거나,
  로컬 개발 서버가 떠 있다면 그 화면이 보여요!

원리: OS는 DNS에 물어보기 전에 이 파일부터 봅니다.
여기 적힌 이름은 인터넷에 안 물어보고 즉시 그 IP로 연결해요.

실험 끝나면 추가한 줄을 꼭 지우고 저장! (원상복구)`;

const CODE_NSLOOKUP_DEEP = `# 1) 기본 조회 — 우리 플랫폼의 A 레코드
nslookup edu.awesomedevapp.com

서버:   ...              ← 답해 준 리졸버 (보통 통신사 DNS)
Name:   edu.awesomedevapp.com
Address: x.x.x.x         ← 우리 EC2(서울)의 IP!

# 2) 레코드 타입을 콕 집어 물어보기
nslookup -type=A   edu.awesomedevapp.com   # IPv4 주소
nslookup -type=TXT awesomedevapp.com       # TXT 레코드가 있다면 표시

# 3) 리졸버를 바꿔서 물어보기 (뒤에 DNS 서버 지정)
nslookup edu.awesomedevapp.com 8.8.8.8     # 구글 공용 DNS에게
nslookup edu.awesomedevapp.com 1.1.1.1     # 다른 공용 DNS에게

# 두 리졸버의 답(과 응답 속도)이 같은지 비교해 보세요.
# TTL이 남아 있는 리졸버는 캐시로 즉답, 처음 받는 리졸버는
# 섹션 1의 풀코스 여행을 다녀와서 답합니다.`;

const CODE_ROUTE53 = `우리 도메인은 AWS Route53이 '권한 서버' 역할을 해요

[도메인 등록] awesomedevapp.com
      │  "이 도메인의 권한 서버는 Route53 이 4대다" 라고 등록기관에 신고
      ▼
[Route53 호스팅 존] awesomedevapp.com
      ├── A     edu.awesomedevapp.com  → EC2(서울)의 공인 IP
      ├── (필요 시) CNAME·TXT 레코드 추가
      └── 각 레코드마다 TTL 설정
      ▼
[EC2 서울] ── Caddy가 443 받음 ── React 프론트 + Spring Boot 백엔드 + PostgreSQL

즉, 여러분이 주소창에 edu.awesomedevapp.com 을 치면:
섹션 1의 여행 끝에 Route53이 "서울 EC2의 IP"를 답하고,
브라우저가 그 IP의 443 포트로 접속 → Caddy → 우리 서비스!`;

const CODE_DNS_QUIZ = `셀프 체크 5문항 — 말로 설명할 수 있으면 통과!

Q1. 루트 서버는 edu.awesomedevapp.com의 IP를 모르는데,
    왜 여행의 첫 목적지일까요? (섹션 1)

Q2. www를 CNAME으로 걸었는데 사이트가 안 열려요.
    별명 사슬의 끝에서 뭘 확인해야 할까요? (섹션 2)

Q3. 서버 IP를 바꿨는데 친구 PC에선 아직 옛날 화면이 보여요.
    고장일까요? 언제까지 기다리면 될까요? (섹션 3)

Q4. hosts 파일에 적은 주소는 왜 DNS 서버 설정과 상관없이
    항상 이길까요? (섹션 4)

Q5. nslookup 뒤에 8.8.8.8을 붙이는 건 무엇을 바꾸는 걸까요?
    권한 서버가 바뀌는 걸까요, 질문받는 심부름꾼이 바뀌는 걸까요? (섹션 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: 'TTL과 캐시' },
  { n: 4, label: 'hosts 파일 실습' },
  { n: 5, label: 'nslookup 실습' },
  { n: 6, label: '우리 Route53' },
  { n: 7, label: '정리 퀴즈' },
];

export default function DnsDeepPage() {
  return (
    <div>
      {/* 히어로: 네트워크 코스의 DNS 섹션을 뿌리까지 파고드는 심화 코스 */}
      <div className="hero">
        <div className="eyebrow">Course · 네트워크</div>
        <h1>DNS 깊이 보기<br />— 전화번호부의 뒷면까지</h1>
        <p>
          네트워크 코스에서 "DNS는 인터넷의 전화번호부"라고 배웠죠. 이번엔 그 전화번호부를
          <strong> 누가, 어떤 순서로, 얼마나 오래 들고 다니는지</strong>까지 파고듭니다.
          마지막엔 우리 회사 도메인이 실제로 어떻게 굴러가는지(Route53) 직접 확인해요.
        </p>
        <div className="chip-row">
          <span className="chip">예상 소요 50분</span>
          <span className="chip">실습 2개 + 명령어 다수</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="재귀 조회의 전체 여행" sub="루트 → TLD → 권한 서버, 세 번의 환승">
        <p>
          "DNS 서버에 물어보면 IP를 알려준다"고 했는데 — 그 DNS 서버는 전 세계 도메인
          수억 개의 IP를 다 외우고 있을까요? <strong>아니요.</strong> DNS의 진짜 설계는
          "다 아는 한 명"이 아니라 <strong>"담당자를 아는 사람들의 릴레이"</strong>예요.
          모르는 문제를 교무실에 물으러 갔더니 "그건 3학년부 선생님께", 3학년부에선
          "그건 담임 선생님께" 하고 정확한 담당자에게 안내받는 것과 같아요.
        </p>
        <Code>{CODE_RECURSIVE_TRIP}</Code>
        <ol className="olist">
          <li>
            <strong>리졸버(Resolver)</strong> — 내 PC 대신 뛰어다니는 심부름꾼.
            보통 통신사가 운영하고, 이 심부름을 "재귀(recursive) 조회"라고 불러요.
          </li>
          <li>
            <strong>루트 서버</strong> — 여행의 출발점. 도메인을 뒤에서부터 읽어
            "<span className="icode">.com</span>이면 저쪽" 하고 TLD 서버를 안내해요.
          </li>
          <li>
            <strong>TLD 서버</strong> — <span className="icode">.com</span>·
            <span className="icode">.dev</span>·<span className="icode">.kr</span> 같은
            최상위 도메인별 안내소. "<span className="icode">awesomedevapp.com</span>의
            담당은 저기"라고 권한 서버를 알려줘요.
          </li>
          <li>
            <strong>권한(Authoritative) 서버</strong> — 그 도메인의 진짜 명부를 가진 최종 담당자.
            우리 도메인은 <strong>AWS Route53</strong>이 이 역할이에요(섹션 6에서 자세히!).
          </li>
        </ol>
        <svg className="diagram" viewBox="0 0 640 380" xmlns="http://www.w3.org/2000/svg" role="img" aria-label="DNS 재귀 조회 여행도: 내 PC가 리졸버에게 물으면, 리졸버가 루트, TLD, 권한 서버 순서로 물어 IP를 받아 온다">
          <text x="24" y="24" fontSize="13" fontWeight="700" fill="var(--ink)">미션: edu.awesomedevapp.com의 IP 찾기</text>

          <rect x="20" y="160" width="104" height="64" rx="8" fill="var(--card)" stroke="var(--line)" strokeWidth="1.5" />
          <text x="72" y="188" textAnchor="middle" fontSize="14" fontWeight="700" fill="var(--ink)">내 PC</text>
          <text x="72" y="207" textAnchor="middle" fontSize="12" fill="var(--muted)">브라우저</text>

          <rect x="204" y="160" width="132" height="64" rx="8" fill="var(--card)" stroke="var(--primary)" strokeWidth="1.5" />
          <text x="270" y="188" textAnchor="middle" fontSize="14" fontWeight="700" fill="var(--ink)">리졸버</text>
          <text x="270" y="207" textAnchor="middle" fontSize="12" fill="var(--muted)">통신사 DNS 심부름꾼</text>

          <rect x="470" y="28" width="150" height="52" rx="8" fill="var(--card)" stroke="var(--line)" strokeWidth="1.5" />
          <text x="545" y="50" textAnchor="middle" fontSize="14" fontWeight="700" fill="var(--ink)">루트 서버</text>
          <text x="545" y="68" textAnchor="middle" fontSize="12" fill="var(--muted)">전 세계 13곳</text>

          <rect x="470" y="164" width="150" height="52" rx="8" fill="var(--card)" stroke="var(--line)" strokeWidth="1.5" />
          <text x="545" y="186" textAnchor="middle" fontSize="14" fontWeight="700" fill="var(--ink)">.com TLD 서버</text>
          <text x="545" y="204" textAnchor="middle" fontSize="12" fill="var(--muted)">최상위 도메인 안내소</text>

          <rect x="470" y="300" width="150" height="52" rx="8" fill="var(--card)" stroke="var(--teal)" strokeWidth="1.5" />
          <text x="545" y="322" textAnchor="middle" fontSize="14" fontWeight="700" fill="var(--ink)">권한 서버</text>
          <text x="545" y="340" textAnchor="middle" fontSize="12" fill="var(--teal)">우리는 Route53!</text>

          <line x1="124" y1="178" x2="196" y2="178" stroke="var(--muted)" strokeWidth="1.5" />
          <path d="M204 178 l-9 -4.5 v9 z" fill="var(--muted)" />
          <text x="163" y="169" textAnchor="middle" fontSize="12" fill="var(--muted)">IP 알려줘!</text>

          <line x1="212" y1="206" x2="136" y2="206" stroke="var(--teal)" strokeWidth="1.8" />
          <path d="M124 206 l10 -4.5 v9 z" fill="var(--teal)" />
          <text x="164" y="221" textAnchor="middle" fontSize="12" fontWeight="700" fill="var(--teal)">x.x.x.x!</text>

          <polyline points="300,160 300,46 462,46" fill="none" stroke="var(--muted)" strokeWidth="1.5" />
          <path d="M470 46 l-9 -4.5 v9 z" fill="var(--muted)" />
          <polyline points="470,66 320,66 320,151" fill="none" stroke="var(--muted)" strokeWidth="1.5" strokeDasharray="4 3" />
          <path d="M320 160 l-4.5 -9 h9 z" fill="var(--muted)" />
          <text x="398" y="86" textAnchor="middle" fontSize="12" fill="var(--muted)">몰라, .com 담당은 저쪽</text>
          <circle cx="352" cy="46" r="10" fill="var(--card)" stroke="var(--muted)" strokeWidth="1.2" />
          <text x="352" y="50" textAnchor="middle" fontSize="12" fontWeight="700" fill="var(--ink)">1</text>

          <line x1="336" y1="178" x2="462" y2="178" stroke="var(--muted)" strokeWidth="1.5" />
          <path d="M470 178 l-9 -4.5 v9 z" fill="var(--muted)" />
          <line x1="470" y1="202" x2="344" y2="202" stroke="var(--muted)" strokeWidth="1.5" strokeDasharray="4 3" />
          <path d="M336 202 l10 -4.5 v9 z" fill="var(--muted)" />
          <text x="402" y="224" textAnchor="middle" fontSize="12" fill="var(--muted)">몰라, 담당 서버는 저쪽</text>
          <circle cx="399" cy="178" r="10" fill="var(--card)" stroke="var(--muted)" strokeWidth="1.2" />
          <text x="399" y="182" textAnchor="middle" fontSize="12" fontWeight="700" fill="var(--ink)">2</text>

          <polyline points="300,224 300,326 462,326" fill="none" stroke="var(--muted)" strokeWidth="1.5" />
          <path d="M470 326 l-9 -4.5 v9 z" fill="var(--muted)" />
          <polyline points="470,346 320,346 320,233" fill="none" stroke="var(--teal)" strokeWidth="1.8" />
          <path d="M320 224 l-4.5 9 h9 z" fill="var(--teal)" />
          <text x="398" y="368" textAnchor="middle" fontSize="12.5" fontWeight="700" fill="var(--teal)">정답! x.x.x.x 야</text>
          <circle cx="352" cy="326" r="10" fill="var(--card)" stroke="var(--muted)" strokeWidth="1.2" />
          <text x="352" y="330" textAnchor="middle" fontSize="12" fontWeight="700" fill="var(--ink)">3</text>
        </svg>
        <p className="muted" style={{ fontSize: 12.5, textAlign: 'center', marginTop: 2 }}>
          그림: 재귀 조회의 여행 — 리졸버가 1 루트, 2 TLD, 3 권한 서버 순서로 담당자를 찾아 IP를 받아 온다
        </p>
        <div className="tip">
          <b>비유 한 줄 정리</b> 도메인은 <strong>뒤에서부터</strong> 읽는 주소예요.
          <span className="icode">edu.awesomedevapp.com</span> =
          "com 나라 → awesomedevapp 동네 → edu 건물". 여행도 정확히 그 순서로 갑니다.
        </div>
      </Section>

      <Section n={2} title="레코드 타입 — 전화번호부의 항목 종류" sub="A · CNAME · MX · TXT">
        <p>
          전화번호부에도 "집 전화", "휴대폰", "팩스" 칸이 나뉘어 있듯이,
          DNS의 답변에도 <strong>종류(레코드 타입)</strong>가 있어요.
          같은 도메인이라도 "IP 주세요(A)"와 "메일 서버 주세요(MX)"는 다른 질문이고,
          답도 다르게 옵니다.
        </p>
        <Code>{CODE_RECORD_TYPES}</Code>
        <p>
          <strong>A와 CNAME의 차이</strong>가 제일 헷갈려요. A는
          <strong> "이름 → 숫자"</strong>로 여행이 끝나는 종착역이고, CNAME은
          <strong> "이름 → 다른 이름"</strong>이라 한 정거장 더 가야 해요.
          별명(CNAME)을 아무리 겹쳐도 사슬의 맨 끝에는 반드시 A 레코드가 있어야
          브라우저가 실제 IP에 도착합니다.
        </p>
        <div className="warn">
          <b>실무 함정</b> 도메인의 맨 꼭대기(루트, <span className="icode">awesomedevapp.com</span> 자체)에는
          원칙적으로 CNAME을 못 걸어요. 그래서 Route53에는 이를 우회하는
          "별칭(Alias)" 기능이 따로 있습니다 — "규칙엔 없는데 다들 필요해서 만든 편법"이
          실무엔 종종 있어요.
        </div>
      </Section>

      <Section n={3} title="TTL과 캐시 — 전파가 늦는 진짜 이유" sub="우리 도메인 등록 때 실제로 겪은 일">
        <p>
          섹션 1의 풀코스 여행은 사실 <strong>매번 일어나지 않아요</strong>. 리졸버도,
          내 PC도, 브라우저도 한 번 받은 답을 <strong>캐시(임시 저장)</strong>해 두고 재사용하거든요.
          "몇 초 동안 재사용해도 되는지"를 정하는 게 <strong>TTL</strong>입니다.
        </p>
        <Code>{CODE_TTL}</Code>
        <p>
          <strong>우리 회사 실화</strong> — <span className="icode">edu.awesomedevapp.com</span>을
          처음 등록하던 날, 사무실 PC에서는 사이트가 열리는데 어떤 폰에서는 한동안
          "사이트에 연결할 수 없음"이 떴어요. 고장이 아니었습니다. 각자 쓰는 통신사
          리졸버가 <strong>"그런 이름 없음"이라는 옛 답을 캐시</strong>하고 있었던 거예요.
          기다리니 자연히 풀렸죠. 흔히 "DNS 전파가 느리다"고 말하는 현상의 정체는
          전파가 아니라 <strong>세계 곳곳의 캐시가 각자 만료되기를 기다리는 것</strong>입니다.
        </p>
        <div className="tip">
          <b>직접 확인해 보기</b> Windows에서 내 PC의 DNS 캐시를 구경하고 비워 볼 수 있어요.
          터미널에서 <span className="icode">ipconfig /displaydns</span>로 캐시 목록을 본 다음,
          <span className="icode"> ipconfig /flushdns</span>로 싹 비워 보세요. 비운 직후
          사이트에 접속하면 내 PC는 리졸버에게 다시 질문합니다. (사이트가 안 열리게 되는
          명령이 아니니 안심하고 해봐도 돼요.)
        </div>
      </Section>

      <Section n={4} title="[실습 1] hosts 파일 장난" sub="DNS를 통째로 건너뛰는 내 PC 전용 명부">
        <p>
          OS에는 DNS보다 <strong>먼저</strong> 찾아보는 나만의 수제 전화번호부가 있어요 —
          바로 <strong>hosts 파일</strong>입니다. 여기에 이름과 IP를 적어 두면 인터넷에
          물어보지도 않고 그 IP로 연결돼요. 개발자들이 "진짜 도메인을 내 로컬 서버로
          잠깐 돌려서 테스트"할 때 실제로 쓰는 기법입니다.
        </p>
        <Code>{CODE_HOSTS}</Code>
        <ol className="olist">
          <li>메모장을 <strong>관리자 권한으로 실행</strong>해 hosts 파일을 열어요.</li>
          <li>맨 아래에 <span className="icode">127.0.0.1 haha.awesomedev.test</span> 한 줄을 추가하고 저장해요.</li>
          <li>브라우저에서 <span className="icode">haha.awesomedev.test</span>로 접속해 보고, 어떤 일이 생기는지 관찰해요.</li>
          <li>실험이 끝나면 <strong>추가한 줄을 지우고 저장</strong>해 원래대로 돌려놔요.</li>
        </ol>
        <div className="warn">
          <b>안전 수칙</b> ① 원래 있던 내용은 절대 지우거나 고치지 마세요 — 한 줄
          <strong> 추가</strong>만! ② 실존 사이트(포털·우리 플랫폼 등)의 도메인은 적지 마세요.
          그 사이트가 내 PC에서만 이상하게 열리며 한참 헤매게 됩니다. ③ 실습용 가짜
          이름(<span className="icode">.test</span>로 끝나는 이름)만 쓰고, 끝나면 꼭 원상복구.
          학교·회사 공용 PC에서는 하지 마세요.
        </div>
        <div className="tip">
          <b>여기서 배우는 것</b> "이름 → IP" 변환에는 우선순위가 있다는 사실!
          브라우저 캐시 → OS 캐시 → <strong>hosts 파일</strong> → 리졸버(DNS) 순서로 찾고,
          먼저 답을 찾으면 뒤에는 안 물어봐요. 악성코드가 hosts를 조작해 가짜 사이트로
          유인하는 수법이 있는 것도 이 우선순위 때문 — 그래서 관리자 권한이 필요한 거예요.
        </div>
        <svg className="diagram" viewBox="0 0 640 240" xmlns="http://www.w3.org/2000/svg" role="img" aria-label="이름 풀이 우선순위: 브라우저 캐시, OS 캐시, hosts 파일, 리졸버 순서로 확인하고 먼저 답을 찾으면 거기서 끝난다">
          <text x="320" y="34" textAnchor="middle" fontSize="13" fontWeight="700" fill="var(--ink)">이름 → IP 찾는 순서 — 먼저 답을 찾으면 거기서 끝!</text>

          <rect x="20" y="92" width="120" height="56" rx="8" fill="var(--card)" stroke="var(--line)" strokeWidth="1.5" />
          <text x="80" y="116" textAnchor="middle" fontSize="13" fontWeight="700" fill="var(--ink)">브라우저 캐시</text>
          <text x="80" y="134" textAnchor="middle" fontSize="12" fill="var(--muted)">가장 먼저 확인</text>

          <rect x="180" y="92" width="120" height="56" rx="8" fill="var(--card)" stroke="var(--line)" strokeWidth="1.5" />
          <text x="240" y="116" textAnchor="middle" fontSize="13" fontWeight="700" fill="var(--ink)">OS 캐시</text>
          <text x="240" y="134" textAnchor="middle" fontSize="12" fill="var(--muted)">flushdns로 비움</text>

          <rect x="340" y="92" width="120" height="56" rx="8" fill="var(--card)" stroke="var(--amber)" strokeWidth="1.5" />
          <text x="400" y="116" textAnchor="middle" fontSize="13" fontWeight="700" fill="var(--ink)">hosts 파일</text>
          <text x="400" y="134" textAnchor="middle" fontSize="12" fill="var(--muted)">내 수제 명부</text>

          <rect x="500" y="92" width="120" height="56" rx="8" fill="var(--card)" stroke="var(--line)" strokeWidth="1.5" />
          <text x="560" y="116" textAnchor="middle" fontSize="13" fontWeight="700" fill="var(--ink)">리졸버 (DNS)</text>
          <text x="560" y="134" textAnchor="middle" fontSize="12" fill="var(--muted)">인터넷에 질문</text>

          <line x1="144" y1="120" x2="172" y2="120" stroke="var(--muted)" strokeWidth="1.5" />
          <path d="M180 120 l-9 -4.5 v9 z" fill="var(--muted)" />
          <text x="160" y="110" textAnchor="middle" fontSize="12" fill="var(--muted)">없으면</text>

          <line x1="304" y1="120" x2="332" y2="120" stroke="var(--muted)" strokeWidth="1.5" />
          <path d="M340 120 l-9 -4.5 v9 z" fill="var(--muted)" />
          <text x="320" y="110" textAnchor="middle" fontSize="12" fill="var(--muted)">없으면</text>

          <line x1="464" y1="120" x2="492" y2="120" stroke="var(--muted)" strokeWidth="1.5" />
          <path d="M500 120 l-9 -4.5 v9 z" fill="var(--muted)" />
          <text x="480" y="110" textAnchor="middle" fontSize="12" fill="var(--muted)">없으면</text>

          <line x1="400" y1="148" x2="400" y2="174" stroke="var(--amber)" strokeWidth="1.5" />
          <path d="M400 182 l-4.5 -9 h9 z" fill="var(--amber)" />
          <text x="400" y="202" textAnchor="middle" fontSize="12" fontWeight="700" fill="var(--amber)">실습 1에서 만진 파일!</text>

          <line x1="560" y1="148" x2="560" y2="174" stroke="var(--muted)" strokeWidth="1.5" />
          <path d="M560 182 l-4.5 -9 h9 z" fill="var(--muted)" />
          <text x="560" y="202" textAnchor="middle" fontSize="12" fill="var(--muted)">섹션 1의 여행 시작</text>
        </svg>
        <p className="muted" style={{ fontSize: 12.5, textAlign: 'center', marginTop: 2 }}>
          그림: 이름 풀이 우선순위 — hosts 파일이 리졸버(DNS)보다 먼저 답한다
        </p>
      </Section>

      <Section n={5} title="[실습 2] nslookup으로 우리 도메인 캐보기" sub="리졸버에게 직접 질문 던지기">
        <p>
          <span className="icode">nslookup</span>은 브라우저 없이 DNS 질문만 쏙 던져 보는
          도구예요. 네트워크 코스에서 한 번 써봤죠? 이번엔 <strong>레코드 타입을 지정</strong>하고,
          <strong> 질문받는 리졸버를 바꿔 가며</strong> 물어봅니다.
        </p>
        <Code>{CODE_NSLOOKUP_DEEP}</Code>
        <ol className="olist">
          <li>기본 조회로 <span className="icode">edu.awesomedevapp.com</span>의 IP를 확인해요. 이게 우리 서울 EC2의 공인 IP예요.</li>
          <li><span className="icode">-type=</span> 옵션으로 A·TXT를 각각 물어보고, 답의 모양이 어떻게 다른지 비교해요.</li>
          <li>명령 끝에 <span className="icode">8.8.8.8</span>·<span className="icode">1.1.1.1</span>을 붙여 다른 리졸버에게도 물어봐요 — 답이 같은가요?</li>
          <li>같은 질문을 곧바로 한 번 더 던져 보세요. 두 번째가 눈에 띄게 빠르다면, 방금 섹션 3의 캐시를 목격한 거예요.</li>
        </ol>
        <div className="tip">
          <b>관찰 포인트</b> 어느 리졸버에 묻든 <strong>최종 답은 같아야 정상</strong>이에요.
          왜냐하면 누구에게 묻든 여행의 종착역은 똑같은 권한 서버(우리 Route53)니까요.
          만약 리졸버마다 답이 다르다면? 캐시 만료 시점이 달라서 생기는 일시적 현상이거나,
          레코드를 방금 바꾼 직후라는 신호입니다.
        </div>
      </Section>

      <Section n={6} title="우리 도메인의 실제 구성 — Route53" sub="권한 서버 자리에 앉아 있는 AWS 서비스">
        <p>
          섹션 1 여행의 종착역, <strong>권한 서버</strong>를 우리 회사는 직접 운영하지 않아요.
          AWS의 DNS 서비스 <strong>Route53</strong>에 그 역할을 맡겼습니다. Route53 콘솔에서
          레코드를 추가·수정하면, 전 세계 리졸버가 받아 가는 "공식 답변"이 바뀌는 구조예요.
        </p>
        <Code>{CODE_ROUTE53}</Code>
        <p>
          <strong>호스팅 존(Hosted Zone)</strong>은 "<span className="icode">awesomedevapp.com</span>이라는
          도메인의 공식 명부 한 권"이라고 생각하면 돼요. 그 명부 안에 A·CNAME·TXT 같은
          레코드들이 줄줄이 적혀 있고, 각 줄마다 TTL이 붙어 있죠. 여러분이 섹션 5에서
          <span className="icode"> nslookup</span>으로 받은 답은 전부 이 명부에서 출발한 거예요.
        </p>
        <div className="tip">
          <b>점 잇기</b> 이 코스의 전부가 한 줄로 이어집니다 —
          Route53 명부에 적힌 레코드(섹션 2)를, 리졸버가 여행 끝에 받아 와서(섹션 1),
          TTL만큼 캐시하고(섹션 3), 그걸 여러분이 <span className="icode">nslookup</span>으로
          들여다본 것(섹션 5). 단, 내 PC의 hosts 파일이 먼저 답하면 이 모든 게 생략(섹션 4)!
        </div>
      </Section>

      <Section n={7} title="정리 퀴즈 — 셀프 체크 5문항" sub="설명할 수 있어야 아는 것">
        <Code>{CODE_DNS_QUIZ}</Code>
        <div className="tip">
          <b>공부 팁</b> 특히 Q3(전파 지연)은 실무에서 반드시 다시 만나는 상황이에요.
          "고장인가?"와 "캐시 만료 대기 중인가?"를 구분해 말할 수 있으면,
          도메인 관련 장애의 절반은 이미 진단할 수 있는 겁니다.
        </div>
      </Section>

      <div className="step-card">
        <div className="step-body">
          <h3 style={{ marginBottom: 6 }}>📇 여기까지 왔다면</h3>
          <p className="muted">
            이제 주소창에 도메인을 치는 순간 벌어지는 릴레이(루트→TLD→권한 서버)와,
            그 답이 캐시로 도는 원리(TTL), 그리고 우리 도메인의 진짜 명부(Route53)까지
            알게 됐어요. 다음 과제로 <strong>오늘 배운 nslookup 결과를 캡처해 멘토에게
            설명</strong>해 보고, 전체 그림이 다시 궁금해지면{' '}
            <Link to="/learn/network"><strong>네트워크의 이해</strong></Link> 코스의
            5·7섹션을 복습해 보세요 — DNS가 전체 여행의 첫 단추라는 게 새롭게 보일 거예요.
          </p>
        </div>
      </div>
    </div>
  );
}
