// 이 파일이 하는 일: "TCP와 UDP" 코스 — 데이터가 패킷으로 쪼개지는 순간부터
// 3-way 핸드셰이크, 순서 보장·재전송, UDP의 속도 철학, 포트 번호, netstat 실습,
// "채팅은 TCP·게임은 UDP" 토론까지 7개 섹션으로 안내하는 정적 학습 페이지.
// 학습 포인트: API 호출이 없는 '내용 고정' 페이지다. 스타일은 global.css의
// 가이드 전용 클래스(step-card, code-block, tip 등)를 재사용한다 — 색을 여기서 하드코딩하지 않는다.
// 텍스트 다이어그램은 JSX 중괄호/백틱 충돌을 피하려고 파일 상단의 백틱 문자열 상수로 정의한다.

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

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

const CODE_PACKET = `큰 데이터는 통째로 못 가요 — 패킷(작은 택배 상자)으로 쪼개서 보냅니다.

[10MB짜리 사진 한 장]
        │  잘게 쪼개기 (보통 상자 하나 ≈ 1,500바이트!)
        ▼
┌────┐┌────┐┌────┐      ┌────┐
│ #1 ││ #2 ││ #3 │ ...  │#7000│   ← 상자마다 번호표(순서 번호)
└────┘└────┘└────┘      └────┘
        │  각자 알아서 길을 찾아 출발 (경로가 서로 달라도 OK)
        ▼
[받는 쪽] 번호 순서대로 다시 쌓기 → 원래 사진 복원!

왜 쪼갤까?
1) 거대한 트럭 한 대가 길을 독점하면 다른 차(남의 데이터)가 못 지나가요.
2) 상자 하나가 분실되면 그 상자만 다시 보내면 돼요. 통째로 다시 안 보내도 됨!`;

const CODE_HANDSHAKE = `TCP 3-way 핸드셰이크 — 연결 맺기 연극 (등장인물: 내 PC, 서버)

내 PC                                     서버
  │                                        │
  │── ① SYN ────────────────────────────▶│
  │   "저기요, 대화 좀 할 수 있을까요?"       │
  │                                        │
  │◀─────────────────────── ② SYN+ACK ──│
  │   "네 들려요! 저도 준비됐어요. 그쪽도     │
  │    제 목소리 들리나요?"                  │
  │                                        │
  │── ③ ACK ────────────────────────────▶│
  │   "잘 들려요! 그럼 시작할게요."           │
  │                                        │
  │========= 연결 수립! 데이터 전송 시작 =====│

세 번 오가야 하는 이유: 양쪽 모두
"내 말이 상대에게 닿는다 + 상대 말이 나에게 닿는다"
두 가지를 전부 확인해야 안심하고 보낼 수 있으니까요.`;

const CODE_RETRANSMIT = `순서 보장 + 재전송 — TCP가 '확실한 택배'인 이유

보내기:  #1  #2  #3  #4  #5
도착:    #1  #2  ✕   #4  #5     ← #3이 길에서 실종!

받는 쪽: "#3 못 받았어요. 다시 보내 주세요." (ACK로 알려줌)
보내는 쪽: #3만 골라서 재전송 →  #3 도착!

받는 쪽 조립: #1 #2 #3 #4 #5  ← 늦게 온 #3을 제자리에 끼워 넣음
→ 원본과 100% 동일한 데이터 완성. 이게 TCP의 약속이에요.

대가(트레이드오프):
- 확인 답장(ACK)을 기다리는 시간
- 재전송하는 동안 뒤 상자들이 대기하는 시간
→ 확실한 만큼 '느려질 수 있다'는 비용을 냅니다.`;

const CODE_UDP = `UDP — 인사도 확인도 없이, 그냥 던진다!

TCP (전화 통화)                 UDP (확성기 방송)
──────────────────────      ──────────────────────
연결부터 맺음 (3-way)           연결? 그런 거 없음
받았는지 확인(ACK)              확인 안 함
분실 시 재전송                  분실돼도 그냥 다음 것 전송
순서 맞춰 조립                  온 순서대로 그냥 사용
헤더 20바이트~                  헤더 딱 8바이트

UDP가 빠른 진짜 이유 = "안 하는 일이 많아서"예요.
생방송에서 0.5초 전 화면 조각이 늦게 오면?
→ 기다렸다 틀면 방송이 계속 밀려요. 버리고 다음 장면!
게임에서 0.1초 전 캐릭터 위치가 유실되면?
→ 재전송받아 봤자 이미 과거. 최신 위치가 더 소중!`;

const CODE_PORTS = `잘 알려진 포트 — 전부 우리 회사(AWESOMEDEV)에서 매일 쓰는 것들!

포트    프로토콜   무엇          우리 회사에서는
────────────────────────────────────────────────────────
22     TCP       SSH          AWS EC2(서울) 서버에 원격 접속할 때
80     TCP       HTTP         Caddy가 받아서 443으로 돌려보냄(리다이렉트)
443    TCP       HTTPS        학습 플랫폼(edu.awesomedevapp.com) 접속
3000   TCP       HTTP(웹앱)    Gitea(edu.awesomedevapp.com:3000) 접속
5432   TCP       PostgreSQL   백엔드(Spring Boot)가 DB랑 대화하는 문
8080   TCP       HTTP(대체)    Spring Boot 개발 서버의 단골 기본 포트

공통점 발견? 전부 TCP예요.
접속·웹·DB는 "한 바이트도 틀리면 안 되는" 일이라서요.
(0~1023 = 잘 알려진 포트, 49152~ = 임시 포트: 내 PC가
서버에 접속할 때 자동으로 배정받는 '내 쪽 방 번호'입니다.)`;

const CODE_NETSTAT = `# 내 PC가 '지금' 맺고 있는 TCP 연결 전부 보기 (Windows 터미널에서):
netstat -ano | findstr ESTABLISHED

  프로토콜  로컬 주소            원격 주소             상태          PID
  TCP      192.168.0.5:52310   x.x.x.x:443         ESTABLISHED   1234
  TCP      192.168.0.5:52488   y.y.y.y:443         ESTABLISHED   5678
  ...

읽는 법:
- 로컬 주소의 52310 = 내 쪽 임시 포트 (자동 배정!)
- 원격 주소의 :443  = 상대 서버의 HTTPS 방 번호
- ESTABLISHED       = 3-way 악수가 끝나고 연결이 살아 있다는 뜻!

# PID(맨 오른쪽 숫자)가 어떤 프로그램인지 알아내기:
tasklist | findstr 1234
→ chrome.exe ...  ← "아, 이 연결은 브라우저가 만든 거구나!"`;

const CODE_DEBATE = `토론거리 — "왜 채팅은 TCP, 게임은 UDP일까?"

상황 1) 채팅 메시지 "내일 3시에 보자"에서 '3'이 유실된다면?
  → "내일 시에 보자" ... 약속이 통째로 어긋나요.
  → 한 글자도 잃으면 안 됨 = 느려도 TCP.

상황 2) 게임에서 상대 캐릭터의 0.1초 전 좌표가 유실된다면?
  → 어차피 0.1초 뒤 좌표가 곧 도착. 옛날 좌표는 쓸모없음.
  → 빠른 최신 정보가 생명 = 유실 감수하고 UDP.

더 깊은 토론 질문 (멘토·동기들과 이야기해 보세요):
Q1. 게임의 '아이템 구매' 버튼도 UDP로 보내도 될까요?
    (힌트: 결제가 유실되면...?)
Q2. 영상통화 중 '화면'과 '채팅창'이 같이 있다면 각각 뭘 쓸까요?
Q3. 요즘 웹의 HTTP/3는 오히려 UDP 위에 지어졌어요.
    "믿을 수 없는 UDP 위에 믿을 수 있는 층을 직접 쌓는" 발상 —
    왜 그런 선택을 했을지 상상해 보세요.

정답보다 중요한 것: "이 데이터는 유실돼도 되는가?"를
스스로 물어보는 습관입니다. 그게 프로토콜 선택의 전부예요.`;

// ── 이 페이지 안에서만 쓰는 작은 부품들 ──
// 학습 포인트: 같은 모양이 반복되면 컴포넌트로 뽑는다. 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: '3-way 핸드셰이크' },
  { n: 3, label: '순서 보장과 재전송' },
  { n: 4, label: 'UDP는 왜 빠른가' },
  { n: 5, label: '포트 번호 총정리' },
  { n: 6, label: 'netstat 실습' },
  { n: 7, label: '토론: 채팅 vs 게임' },
];

export default function TcpUdpPage() {
  return (
    <div>
      {/* 히어로: 이 코스가 다루는 두 주인공 소개 */}
      <div className="hero">
        <div className="eyebrow">Course · 네트워크</div>
        <h1>TCP와 UDP<br />— 확실한 택배와 빠른 방송</h1>
        <p>
          인터넷의 데이터 배송에는 딱 두 가지 철학이 있어요 — "느려도 한 개도 잃지 않겠다"는
          TCP와 "몇 개 잃어도 빠르게 가겠다"는 UDP. 이 코스에서는 두 방식이 실제로 어떻게
          움직이는지 따라가고, <strong>내 PC의 진짜 연결 목록</strong>을 직접 열어 봅니다.
        </p>
        <div className="chip-row">
          <span className="chip">예상 소요 50분</span>
          <span className="chip">실습 2개 + 토론 1개</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="이삿짐 트럭이 아니라 택배 상자 수천 개">
        <p>
          사진 한 장, 영상 한 편 — 뭐든 네트워크를 지날 때는 <strong>패킷</strong>이라는
          작은 조각으로 쪼개져서 갑니다. 이삿짐을 트럭 한 대에 전부 싣는 게 아니라,
          택배 상자 수천 개에 <strong>번호표를 붙여</strong> 나눠 보내는 거예요.
          상자들이 서로 다른 길로 가도, 도착지에서 번호 순서대로 쌓으면 원본이 됩니다.
        </p>
        <Code>{CODE_PACKET}</Code>
        <p>
          그런데 여기서 진짜 질문이 시작돼요. <strong>상자가 길에서 사라지면? 순서가 뒤죽박죽
          도착하면?</strong> 이 문제를 "끝까지 책임진다"가 TCP, "신경 안 쓰고 계속 던진다"가
          UDP입니다. 이제 한 명씩 만나 볼게요.
        </p>
        <div className="tip">
          <b>미리 감 잡기</b> 우리 학습 플랫폼의 페이지 하나도 패킷 수십~수백 개로 나뉘어
          도착한 거예요. 지금 보고 있는 이 글자들도 상자에 담겨 왔다가 방금 조립된 겁니다.
        </div>
      </Section>

      <Section n={2} title="TCP 3-way 핸드셰이크" sub="데이터를 보내기 전, 세 마디 악수">
        <p>
          TCP는 데이터를 보내기 전에 반드시 <strong>연결부터 맺어요</strong>. 전화를 걸면
          "여보세요?" — "네, 여보세요!" — "아 들리시죠? 저 말할게요"처럼, 서로 목소리가
          닿는지 확인하고 나서야 본론을 시작하죠. 이 세 마디를
          <strong> 3-way 핸드셰이크</strong>(세 번의 악수)라고 부릅니다.
        </p>
        <Code>{CODE_HANDSHAKE}</Code>
        <ol className="olist">
            <li><strong>SYN</strong> — 내 PC가 "대화 시작하고 싶어요" 하고 손을 내밀어요.</li>
            <li><strong>SYN+ACK</strong> — 서버가 "네 잘 받았어요(ACK), 저도 시작할게요(SYN)" 하고 맞잡아요.</li>
            <li><strong>ACK</strong> — 내 PC가 "확인했어요!" 하고 악수를 완성해요. 이제 데이터 출발!</li>
          </ol>
        <svg className="diagram" viewBox="0 0 640 340" xmlns="http://www.w3.org/2000/svg" role="img" aria-label="TCP 3-way 핸드셰이크 시퀀스: 내 PC가 SYN을 보내고, 서버가 SYN+ACK로 답하고, 내 PC가 ACK를 보내면 연결이 수립된다">
          <rect x="75" y="16" width="130" height="38" rx="8" fill="var(--card)" stroke="var(--line)" />
          <text x="140" y="40" textAnchor="middle" fontSize="14" fontWeight="600" fill="var(--ink)">내 PC</text>
          <rect x="435" y="16" width="130" height="38" rx="8" fill="var(--card)" stroke="var(--line)" />
          <text x="500" y="40" textAnchor="middle" fontSize="14" fontWeight="600" fill="var(--ink)">서버</text>
          <line x1="140" y1="54" x2="140" y2="284" stroke="var(--line)" strokeDasharray="4 4" />
          <line x1="500" y1="54" x2="500" y2="284" stroke="var(--line)" strokeDasharray="4 4" />
          <line x1="140" y1="104" x2="492" y2="104" stroke="var(--primary)" strokeWidth="2" />
          <polyline points="482,98 494,104 482,110" fill="none" stroke="var(--primary)" strokeWidth="2" strokeLinecap="round" />
          <text x="320" y="92" textAnchor="middle" fontSize="14" fontWeight="600" fill="var(--primary)">① SYN</text>
          <text x="320" y="122" textAnchor="middle" fontSize="12" fill="var(--muted)">"저기요, 대화 좀 할 수 있을까요?"</text>
          <line x1="500" y1="168" x2="148" y2="168" stroke="var(--teal)" strokeWidth="2" />
          <polyline points="158,162 146,168 158,174" fill="none" stroke="var(--teal)" strokeWidth="2" strokeLinecap="round" />
          <text x="320" y="156" textAnchor="middle" fontSize="14" fontWeight="600" fill="var(--teal)">② SYN+ACK</text>
          <text x="320" y="186" textAnchor="middle" fontSize="12" fill="var(--muted)">"잘 받았어요! 그쪽도 제 목소리 들리나요?"</text>
          <line x1="140" y1="232" x2="492" y2="232" stroke="var(--amber)" strokeWidth="2" />
          <polyline points="482,226 494,232 482,238" fill="none" stroke="var(--amber)" strokeWidth="2" strokeLinecap="round" />
          <text x="320" y="220" textAnchor="middle" fontSize="14" fontWeight="600" fill="var(--amber)">③ ACK</text>
          <text x="320" y="250" textAnchor="middle" fontSize="12" fill="var(--muted)">"잘 들려요! 그럼 시작할게요."</text>
          <rect x="120" y="284" width="400" height="40" rx="8" fill="var(--card)" stroke="var(--primary)" strokeDasharray="6 4" />
          <text x="320" y="309" textAnchor="middle" fontSize="13" fontWeight="600" fill="var(--ink)">연결 수립! 이제 데이터 전송 시작</text>
        </svg>
        <p className="muted" style={{ fontSize: 12.5, textAlign: 'center', marginTop: 2 }}>그림: 3-way 핸드셰이크 — 세 마디 악수가 끝나야 데이터가 출발한다</p>
        <p>
          왜 두 번이 아니라 세 번일까요? 두 번만 오가면 <strong>서버는</strong> 자기 답장이
          내 PC에 닿았는지 알 수 없어요. 양쪽 모두 "보내기·받기가 다 된다"를 확인하려면
          최소 세 번이 필요합니다. 브라우저에 <span className="icode">https://edu.awesomedevapp.com</span>을
          치는 순간, 이 악수가 서버의 443번 방 앞에서 눈 깜짝할 새 벌어져요.
        </p>
        <div className="warn">
          <b>흔한 오해</b> 핸드셰이크는 '로그인'이 아니에요. 아이디·비밀번호와 무관하게,
          "회선 양쪽이 서로 통한다"는 것만 확인하는 <strong>배송 준비 절차</strong>입니다.
          로그인은 그 위에서 오가는 데이터(HTTP)의 일이에요.
        </div>
      </Section>

      <Section n={3} title="순서 보장과 재전송" sub="잃어버리면 다시, 뒤섞이면 제자리에">
        <p>
          연결을 맺었으면 이제 상자를 보냅니다. TCP의 자랑은 여기서부터예요.
          받는 쪽은 상자를 받을 때마다 <strong>"몇 번까지 잘 받았어요"</strong> 하고
          영수증(ACK)을 보내 줘요. 그래서 보내는 쪽은 어떤 상자가 실종됐는지 바로 알고,
          <strong> 그 상자만 골라 다시</strong> 보냅니다.
        </p>
        <Code>{CODE_RETRANSMIT}</Code>
        <p>
          순서가 뒤섞여 도착해도 문제없어요 — 상자마다 붙은 번호 덕분에 받는 쪽이
          <strong> 제자리에 끼워 넣어</strong> 조립하니까요. 그래서 TCP 위에서는 파일이 절대
          중간이 빠진 채 완성되지 않습니다. Gitea에서 <span className="icode">git clone</span>을
          받을 때 코드가 한 글자도 안 깨지는 이유, 백엔드가 PostgreSQL에서 읽어 온 데이터가
          정확한 이유가 전부 이 재전송·순서 보장이에요.
        </p>
        <svg className="diagram" viewBox="0 0 640 310" xmlns="http://www.w3.org/2000/svg" role="img" aria-label="TCP 재전송과 순서 보장: 패킷 5개 중 3번이 유실되면 받는 쪽이 ACK로 알리고, 보내는 쪽이 3번만 재전송해 제자리에 끼워 조립한다">
          <text x="16" y="51" fontSize="13" fill="var(--muted)">보내기</text>
          <rect x="180" y="28" width="64" height="36" rx="8" fill="var(--card)" stroke="var(--line)" />
          <text x="212" y="51" textAnchor="middle" fontSize="13" fill="var(--ink)">#1</text>
          <rect x="264" y="28" width="64" height="36" rx="8" fill="var(--card)" stroke="var(--line)" />
          <text x="296" y="51" textAnchor="middle" fontSize="13" fill="var(--ink)">#2</text>
          <rect x="348" y="28" width="64" height="36" rx="8" fill="var(--card)" stroke="var(--line)" />
          <text x="380" y="51" textAnchor="middle" fontSize="13" fill="var(--ink)">#3</text>
          <rect x="432" y="28" width="64" height="36" rx="8" fill="var(--card)" stroke="var(--line)" />
          <text x="464" y="51" textAnchor="middle" fontSize="13" fill="var(--ink)">#4</text>
          <rect x="516" y="28" width="64" height="36" rx="8" fill="var(--card)" stroke="var(--line)" />
          <text x="548" y="51" textAnchor="middle" fontSize="13" fill="var(--ink)">#5</text>
          <line x1="212" y1="64" x2="212" y2="130" stroke="var(--line)" strokeWidth="2" />
          <polyline points="207,126 212,136 217,126" fill="none" stroke="var(--line)" strokeWidth="2" strokeLinecap="round" />
          <line x1="296" y1="64" x2="296" y2="130" stroke="var(--line)" strokeWidth="2" />
          <polyline points="291,126 296,136 301,126" fill="none" stroke="var(--line)" strokeWidth="2" strokeLinecap="round" />
          <line x1="380" y1="64" x2="380" y2="96" stroke="var(--rose)" strokeWidth="2" strokeDasharray="4 4" />
          <text x="380" y="116" textAnchor="middle" fontSize="15" fontWeight="700" fill="var(--rose)">✕</text>
          <text x="396" y="104" fontSize="12" fill="var(--rose)">유실!</text>
          <line x1="464" y1="64" x2="464" y2="130" stroke="var(--line)" strokeWidth="2" />
          <polyline points="459,126 464,136 469,126" fill="none" stroke="var(--line)" strokeWidth="2" strokeLinecap="round" />
          <line x1="548" y1="64" x2="548" y2="130" stroke="var(--line)" strokeWidth="2" />
          <polyline points="543,126 548,136 553,126" fill="none" stroke="var(--line)" strokeWidth="2" strokeLinecap="round" />
          <text x="16" y="163" fontSize="13" fill="var(--muted)">도착</text>
          <rect x="180" y="140" width="64" height="36" rx="8" fill="var(--card)" stroke="var(--line)" />
          <text x="212" y="163" textAnchor="middle" fontSize="13" fill="var(--ink)">#1</text>
          <rect x="264" y="140" width="64" height="36" rx="8" fill="var(--card)" stroke="var(--line)" />
          <text x="296" y="163" textAnchor="middle" fontSize="13" fill="var(--ink)">#2</text>
          <rect x="348" y="140" width="64" height="36" rx="8" fill="none" stroke="var(--rose)" strokeDasharray="5 4" />
          <text x="380" y="163" textAnchor="middle" fontSize="13" fill="var(--rose)">비었음</text>
          <rect x="432" y="140" width="64" height="36" rx="8" fill="var(--card)" stroke="var(--line)" />
          <text x="464" y="163" textAnchor="middle" fontSize="13" fill="var(--ink)">#4</text>
          <rect x="516" y="140" width="64" height="36" rx="8" fill="var(--card)" stroke="var(--line)" />
          <text x="548" y="163" textAnchor="middle" fontSize="13" fill="var(--ink)">#5</text>
          <text x="200" y="207" textAnchor="middle" fontSize="12" fill="var(--muted)">받는 쪽 ACK: "#3 못 받았어요!"</text>
          <line x1="380" y1="180" x2="380" y2="224" stroke="var(--rose)" strokeWidth="2" />
          <polyline points="375,220 380,230 385,220" fill="none" stroke="var(--rose)" strokeWidth="2" strokeLinecap="round" />
          <text x="392" y="207" fontSize="12" fill="var(--rose)">#3만 재전송</text>
          <text x="16" y="257" fontSize="13" fill="var(--muted)">조립 완료</text>
          <rect x="180" y="234" width="64" height="36" rx="8" fill="var(--card)" stroke="var(--line)" />
          <text x="212" y="257" textAnchor="middle" fontSize="13" fill="var(--ink)">#1</text>
          <rect x="264" y="234" width="64" height="36" rx="8" fill="var(--card)" stroke="var(--line)" />
          <text x="296" y="257" textAnchor="middle" fontSize="13" fill="var(--ink)">#2</text>
          <rect x="348" y="234" width="64" height="36" rx="8" fill="var(--card)" stroke="var(--teal)" strokeWidth="2" />
          <text x="380" y="257" textAnchor="middle" fontSize="13" fontWeight="600" fill="var(--teal)">#3</text>
          <rect x="432" y="234" width="64" height="36" rx="8" fill="var(--card)" stroke="var(--line)" />
          <text x="464" y="257" textAnchor="middle" fontSize="13" fill="var(--ink)">#4</text>
          <rect x="516" y="234" width="64" height="36" rx="8" fill="var(--card)" stroke="var(--line)" />
          <text x="548" y="257" textAnchor="middle" fontSize="13" fill="var(--ink)">#5</text>
          <text x="380" y="296" textAnchor="middle" fontSize="13" fill="var(--teal)">늦게 온 #3을 제자리에 → 원본과 100% 동일</text>
        </svg>
        <p className="muted" style={{ fontSize: 12.5, textAlign: 'center', marginTop: 2 }}>그림: 유실된 #3만 골라 재전송하고, 번호 순서대로 제자리에 조립한다</p>
        <div className="tip">
          <b>기억할 한 줄</b> TCP의 신뢰성은 공짜가 아니에요. "확인하고, 기다리고, 다시 보내는"
          시간을 지불합니다. 이 비용을 못 견디는 서비스들이 다음 섹션의 주인공을 찾아가요.
        </div>
      </Section>

      <Section n={4} title="UDP는 왜 빠른가" sub="비결은 '안 하는 일이 많다'는 것">
        <p>
          UDP는 TCP가 하는 일을 거의 다 <strong>생략</strong>해요. 악수도 없고, 영수증도 없고,
          재전송도 없어요. 확성기 방송처럼 그냥 계속 내보낼 뿐이죠. 무책임해 보이지만,
          어떤 데이터에게는 이게 <strong>최고의 배려</strong>입니다.
        </p>
        <Code>{CODE_UDP}</Code>
        <p>
          생방송을 생각해 보세요. 0.5초 전 화면 조각이 유실됐다고 재전송을 기다리면,
          방송은 그만큼 계속 <strong>밀려요</strong>. 화면이 잠깐 뭉개져도 다음 장면으로
          넘어가는 게 시청자에게 낫죠. 게임도 같아요 — 0.1초 전 상대 위치를 되살려 봤자
          이미 과거입니다. <strong>"낡은 정보를 정확히 받기 vs 최신 정보를 빨리 받기"</strong>에서
          후자를 고른 서비스들이 UDP를 씁니다.
        </p>
        <div className="warn">
          <b>주의</b> "UDP = 항상 빠르고 좋음"이 아니에요. 유실을 감수할 수 없는 데이터
          (파일, 결제, 메시지)에 UDP를 쓰면 깨진 결과를 얻습니다. 속도는 <strong>신뢰성을
          포기한 대가</strong>로 얻은 것임을 잊지 마세요.
        </div>
      </Section>

      <Section n={5} title="포트 번호 총정리" sub="우리가 매일 두드리는 방 번호들">
        <p>
          "네트워크의 이해" 코스에서 <strong>IP는 건물 주소, 포트는 방 번호</strong>라고
          배웠죠. TCP·UDP 헤더에 이 방 번호가 적혀 있어서, 도착한 패킷이 어느 프로그램의
          문을 두드릴지 정해집니다. 유명한 서비스들은 방 번호가 <strong>전 세계 공통으로
          예약</strong>되어 있어요 — 그리고 그 목록이 곧 우리 회사 인프라 지도입니다.
        </p>
        <Code>{CODE_PORTS}</Code>
        <p>
          예를 들어 여러분이 EC2 서버에 <span className="icode">ssh</span>로 들어가면 22번,
          이 플랫폼에 접속하면 443번, 백엔드가 DB에 질의하면 5432번 문이 열려요.
          로컬에서 Spring Boot를 <span className="icode">./mvnw spring-boot:run</span>으로 띄우면
          "내 PC 건물의 8080호"에 세 들어 사는 셈이고, 그래서 브라우저에
          <span className="icode">localhost:8080</span>을 치는 거예요.
        </p>
        <div className="tip">
          <b>직접 확인해 보기 ①</b> 로컬에서 백엔드를 켜 둔 상태로 브라우저에
          <span className="icode">localhost:8080</span>을 쳐 보고, 백엔드를 끈 뒤 다시 쳐 보세요.
          꺼진 뒤엔 "연결할 수 없음"이 떠요 — <strong>그 방에 아무도 안 산다</strong>는 뜻이죠.
          같은 건물(내 PC)이라도 방(포트)마다 세입자(프로그램)가 따로라는 걸 몸으로 확인하는 겁니다.
        </div>
      </Section>

      <Section n={6} title="netstat 실습 — 내 PC의 연결 명단 열람" sub="지금 이 순간의 3-way 악수 결과들">
        <p>
          이론은 충분해요. 이제 내 PC가 <strong>지금 실제로 맺고 있는 TCP 연결들</strong>을
          직접 열어 봅시다. <span className="icode">netstat</span>은 "network statistics"의
          줄임말로, 연결 명단을 보여 주는 터미널 명령이에요.
        </p>
        <div className="tip">
          <b>직접 확인해 보기 ②</b> 브라우저로 우리 플랫폼(<span className="icode">edu.awesomedevapp.com</span>)을
          열어 둔 채, 터미널에서 아래 명령을 실행해 보세요. <span className="kbd">Win</span>+<span className="kbd">R</span> →
          <span className="icode">cmd</span> → 엔터로 터미널을 열 수 있어요.
        </div>
        <Code>{CODE_NETSTAT}</Code>
        <ol className="olist">
            <li>원격 주소가 <span className="icode">:443</span>인 줄을 찾아보세요 — 전부 HTTPS 연결이에요.</li>
            <li>로컬 주소의 5만 번대 포트에 주목 — 내 쪽 <strong>임시 포트</strong>가 자동 배정된 거예요.</li>
            <li><span className="icode">tasklist</span>로 PID의 정체를 밝혀 보세요. 대부분 브라우저일 거예요.</li>
            <li>브라우저를 전부 끄고 다시 실행 — <span className="icode">ESTABLISHED</span> 줄이 확 줄어드는 걸 관찰!</li>
          </ol>
        <p>
          여기서 <span className="icode">ESTABLISHED</span> 한 줄 한 줄이 섹션 2에서 배운
          3-way 악수가 <strong>성공적으로 끝난 흔적</strong>입니다. 참고로 UDP는 연결이라는
          개념이 없어서 이 명단에 '상태'가 안 떠요 — 명단 자체가 TCP의 철학을 보여 주는 셈이죠.
        </p>
      </Section>

      <Section n={7} title="토론: 왜 채팅은 TCP, 게임은 UDP인가" sub="프로토콜 선택은 결국 '유실돼도 되는가'라는 질문">
        <p>
          마지막 섹션은 정답 암기가 아니라 <strong>토론</strong>이에요. 두 상황을 놓고
          "이 데이터가 유실되면 무슨 일이 벌어지나?"를 따져 보면, 프로토콜 선택의
          기준이 스스로 보이기 시작합니다.
        </p>
        <Code>{CODE_DEBATE}</Code>
        <p>
          우리 플랫폼도 같은 기준으로 만들어졌어요. 로그인, 과제 제출, 게시글 저장 —
          전부 <strong>한 바이트도 잃으면 안 되는</strong> 데이터라서 HTTPS(TCP 위)로
          오갑니다. 여러분이 나중에 실시간 기능(화상 멘토링, 라이브 코딩 중계 같은)을
          설계하게 되면, 그때 비로소 UDP 계열을 꺼내 들 차례가 오는 거예요.
        </p>
        <div className="tip">
          <b>공부 팁</b> Q1~Q3에 대한 내 생각을 말로 정리해서 멘토나 동기에게 설명해 보세요.
          "게임인데 왜 이건 TCP지?"라고 <strong>반박당해 보는 것</strong>이 이 코스 최고의
          마무리 복습입니다.
        </div>
      </Section>

      <div className="step-card">
        <div className="step-body">
          <h3 style={{ marginBottom: 6 }}>📦 여기까지 왔다면</h3>
          <p className="muted">
            이제 데이터가 상자(패킷)로 쪼개지고, 세 번의 악수로 길을 열고, 잃어버리면
            다시 보내는 <strong>TCP</strong>와 — 그 모든 걸 생략하고 속도를 얻은
            <strong> UDP</strong>를 구분할 수 있어요. 그리고 22·80·443·5432·8080이라는
            방 번호가 우리 회사 어디에서 쓰이는지도요. 아직
            <Link to="/learn/network"><strong> 네트워크의 이해</strong></Link> 코스를 안 봤다면
            먼저 다녀오세요 — IP·DNS·HTTP가 이 코스의 앞 이야기입니다. 다 봤다면
            netstat 실습 결과를 캡처해서 멘토에게 공유하는 것으로 이번 코스 과제를 마무리하세요.
          </p>
        </div>
      </div>
    </div>
  );
}
