// 이 파일이 하는 일: "데이터 모델링 기초" 코스 — 테이블 설계를 '정리정돈'에 비유해
// ERD 읽는 법, 기본키/외래키, 1:N·N:M 관계, 정규화, 나쁜 설계의 냄새까지
// 7개 섹션으로 안내하는 정적 학습 페이지. 마지막은 "쪽지 기능" 설계 실습으로 마무리.
// 학습 포인트: API 호출이 없는 '내용 고정' 페이지다. 스타일은 global.css의
// 가이드 전용 클래스(step-card, code-block, tip 등)를 재사용한다 — 색을 여기서 하드코딩하지 않는다.
// 텍스트 다이어그램은 JSX 중괄호/백틱 충돌을 피하려고 파일 상단의 백틱 문자열 상수로 정의한다.

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

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

const CODE_MESSY_DESK = `설계 없이 데이터를 쌓으면 이런 일이 벌어져요:

메모장.txt
─────────────────────────────────────────────
김수습, 3반, 과제1 제출함, 점수 85
이수습 / 3반 / 과제1 아직 / 멘토가 박멘토님
김수습 과제2도 냈음 (점수는 나중에)
박수습(2반?) 과제1 90점 — 근데 위에 김수습이랑 같은 반 맞나?

→ "3반 학생 중 과제1 안 낸 사람?" 같은 간단한 질문에도
  파일 전체를 눈으로 뒤져야 해요. 데이터가 1만 줄이면?

잘 정리된 테이블
─────────────────────────────────────────────
users(사용자)      : 누가 있는지 한 번만 기록
assignment(과제)   : 어떤 과제가 있는지 한 번만 기록
submission(제출)   : "누가 어떤 과제를 냈다"는 사실만 기록

→ 같은 질문을 SQL 한 줄로 즉시 답할 수 있어요.`;

const CODE_ERD_OURS = `우리 학습 플랫폼의 핵심 ERD (관계도)

┌──────────────┐          ┌──────────────────┐
│    users     │          │    assignment    │
├──────────────┤          ├──────────────────┤
│ id (PK)      │          │ id (PK)          │
│ name         │          │ title            │
│ email        │          │ due_date         │
│ role         │          │ description      │
└──────┬───────┘          └────────┬─────────┘
       │ 1                         │ 1
       │                           │
       │ N                         │ N
       └───────►┌──────────────────┐◄──────┘
                │    submission    │
                ├──────────────────┤
                │ id (PK)          │
                │ user_id (FK)     │ → users.id 를 가리킴
                │ assignment_id(FK)│ → assignment.id 를 가리킴
                │ content          │
                │ submitted_at     │
                │ score            │
                └──────────────────┘

읽는 법: 선의 양 끝에 붙은 숫자가 관계예요.
"users 1명은 submission을 N개 가질 수 있다" (한 학생이 여러 번 제출)
"assignment 1개에 submission이 N개 달릴 수 있다" (한 과제에 여러 명이 제출)`;

const CODE_PK_FK = `기본키(PK)와 외래키(FK) — 학번과 "학번으로 가리키기"

users 테이블                     submission 테이블
──────────────────────          ─────────────────────────────
id │ name  │ email               id │ user_id │ content
───┼───────┼──────────          ────┼─────────┼───────────────
 1 │ 김수습 │ kim@...             10 │    1    │ "과제1 제출.."
 2 │ 이수습 │ lee@...             11 │    2    │ "저도 냈어요"
 3 │ 박수습 │ park@..             12 │    1    │ "과제2 제출.."
   ↑                                     ↑
   PK: 이 테이블 안에서                    FK: 다른 테이블의 PK를
   절대 겹치지 않는 번호                    "가리키는" 번호

submission에 이름 대신 user_id를 적는 이유:
- 김수습이 개명해도 users 한 곳만 고치면 끝
- 동명이인이 와도 번호가 다르니 절대 안 섞임
- 이름 오타("김수습" vs "김 수습")로 데이터가 갈라질 일이 없음`;

const CODE_PSQL_PEEK = `# 우리 개발 DB에 직접 들어가서 진짜 PK/FK를 눈으로 확인하기
# (로컬에서 Docker로 PostgreSQL을 띄워 뒀다면)

docker exec -it <postgres-컨테이너이름> psql -U <사용자명> -d <DB이름>

\\dt              -- 테이블 목록 보기
\\d submission    -- submission 테이블의 구조 보기

# 출력에서 이런 줄을 찾아보세요:
Indexes:
    "submission_pkey" PRIMARY KEY (id)        ← 기본키!
Foreign-key constraints:
    "..._user_id_fkey" FOREIGN KEY (user_id)
        REFERENCES users(id)                  ← 외래키!

# 나올 때는 \\q`;

const CODE_ONE_TO_N = `1:N — "하나가 여럿을 거느린다"

멘토 1명 ──── 수습 N명        (멘토 쪽엔 아무것도 안 적고,
과제 1개 ──── 제출 N개         '여럿' 쪽에 FK 한 칸만 추가!)

users
────────────────────────────
id │ name  │ role  │ mentor_id (FK, 자기 테이블을 가리켜도 OK!)
───┼───────┼───────┼──────────
 1 │ 박멘토 │ MENTOR│  (없음)
 2 │ 김수습 │ INTERN│    1     ← 박멘토가 담당
 3 │ 이수습 │ INTERN│    1     ← 박멘토가 담당

규칙: 1:N에서는 항상 N쪽(여럿 쪽)에 FK를 둔다.
멘토 테이블에 "담당수습1, 담당수습2, 담당수습3..." 칸을
늘려 가는 순간 설계가 무너집니다. (섹션 6에서 다시 만나요)`;

const CODE_N_TO_M = `N:M — "여럿과 여럿"은 중간 테이블이 필요해요

학생 여러 명 ↔ 스터디 여러 개
(한 학생이 여러 스터디에 들고, 한 스터디에 여러 학생이 든다)

FK 한 칸으로는 표현 불가! → 사이에 '다리' 테이블을 놓습니다.

users                study_member(중간 테이블)         study
──────────           ──────────────────────           ──────────
id │ name            id │ user_id │ study_id          id │ name
───┼──────           ───┼─────────┼─────────          ───┼──────
 2 │ 김수습            1 │    2    │    1               1 │ React반
 3 │ 이수습            2 │    2    │    2               2 │ DB반
                      3 │    3    │    1

읽는 법: study_member의 한 줄 = "가입했다"는 사실 하나.
김수습(2)은 React반(1)과 DB반(2) 둘 다,
이수습(3)은 React반(1)만.

사실 우리 submission도 정확히 이 패턴이에요!
users ↔ assignment 라는 N:M 관계의 중간 테이블이
submission이고, 거기에 content·score 같은
'관계 자체의 정보'가 얹혀 있는 것뿐입니다.`;

const CODE_NORMALIZE = `정규화 = "같은 정보를 두 번 적지 않기" 대작전

나쁜 예 — 제출 테이블에 전부 때려 넣기:
──────────────────────────────────────────────────
제출id │ 학생이름 │ 학생이메일  │ 과제제목    │ 과제마감일
──────┼─────────┼───────────┼───────────┼──────────
  10  │ 김수습   │ kim@...   │ 자기소개 API│ 07-20
  11  │ 이수습   │ lee@...   │ 자기소개 API│ 07-20
  12  │ 김수습   │ kim@...   │ ERD 그리기  │ 07-27

문제 1: 김수습의 이메일이 두 줄에 중복 → 한 줄만 고치면 데이터 모순
문제 2: 과제 마감일이 바뀌면? 그 과제의 제출 줄 전부를 찾아 고쳐야 함
문제 3: 아직 아무도 안 낸 새 과제는... 적을 곳이 없음!

정규화 후: users / assignment / submission 세 테이블로 분리
→ 각 사실은 딱 한 곳에만. 고칠 일이 생기면 한 줄만 고침.

교과서의 1·2·3차 정규형, 직관 버전:
1차: 한 칸에는 값 하나만 (칸 안에 목록 금지)
2차: 그 줄의 '주인공(PK)'과 상관없는 정보는 딴 데로
3차: 다른 칸을 통해 알 수 있는 정보는 또 적지 말기
     (과제제목을 알면 마감일은 assignment에서 찾으면 됨)`;

const CODE_BAD_SMELLS = `나쁜 설계의 냄새 3가지 — 보이면 일단 의심!

냄새 1: 한 칸에 여러 값
  tags = "react,db,docker"        ← 쉼표로 구겨 넣기
  → "docker 태그 단 글 검색"이 지옥이 됨. 별도 테이블로!

냄새 2: 번호 붙은 칸의 행진
  phone1, phone2, phone3          ← 4번째 전화번호는?
  담당수습1, 담당수습2, ...        ← 1:N을 억지로 가로로 편 것
  → 세로로(줄을 늘려서) 담아야 할 걸 가로로 담은 신호

냄새 3: 복붙된 정보
  모든 제출 줄마다 학생 이메일이 통째로 복사돼 있다
  → 정규화 필요 신호 (섹션 5의 문제 그대로)

공통 처방: "이 정보의 주인 테이블은 어디지?"를 묻고,
주인 테이블에 한 번만 적은 뒤 FK로 가리키기.`;

const CODE_PRACTICE = `실습 미션: "쪽지 기능" 테이블 설계하기

요구사항 (우리 플랫폼에 진짜 있으면 좋을 기능이죠?)
- 사용자가 다른 사용자에게 쪽지를 보낼 수 있다
- 쪽지에는 제목·내용·보낸 시각이 있다
- 받는 사람은 읽음/안읽음을 구분할 수 있다
- 나중에 "내가 보낸 쪽지함 / 받은 쪽지함"을 만들 예정

스스로에게 던질 질문 (설계 순서 그대로):
1. 어떤 '사실'들을 저장해야 하지? → 명사를 뽑아 보기
2. 테이블은 몇 개 필요할까? 새로 만들 건 뭐고,
   이미 있는 users를 어떻게 재사용할까?
3. 보낸 사람과 받는 사람 — FK가 몇 개 필요하지?
   둘 다 users를 가리켜도 되나? (힌트: 됩니다!)
4. 읽음 여부는 어느 테이블의 어느 칸에?
5. 관계는 1:N일까 N:M일까? 한 쪽지를 여러 명에게
   보내는 '단체 쪽지'까지 지원한다면 뭐가 달라질까?

제출물: 종이나 그림판에 그린 ERD 한 장
(섹션 2의 그림처럼 — 테이블 상자, PK/FK 표시, 관계선과 1/N)`;

// ── 이 페이지 안에서만 쓰는 작은 부품들 ──
// 학습 포인트: 같은 모양이 반복되면 컴포넌트로 뽑는다. 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: 'ERD 읽기' },
  { n: 3, label: '기본키·외래키' },
  { n: 4, label: '1:N과 N:M' },
  { n: 5, label: '정규화' },
  { n: 6, label: '나쁜 설계의 냄새' },
  { n: 7, label: '실습: 쪽지 기능' },
];

export default function DataModelingPage() {
  return (
    <div>
      {/* 히어로: 이 코스가 어디서 출발해 어디까지 가는지 */}
      <div className="hero">
        <div className="eyebrow">Course · 서버와 데이터</div>
        <h1>데이터 모델링 기초<br />— 테이블을 잘 짜면 코드가 편해진다</h1>
        <p>
          데이터베이스 테이블 설계는 이사 갈 집의 <strong>수납장을 미리 짜는 일</strong>이에요.
          지금 여러분이 쓰는 이 학습 플랫폼의 진짜 테이블(users·assignment·submission)을
          교재 삼아, 관계도를 읽고 직접 설계까지 해 봅니다.
        </p>
        <div className="chip-row">
          <span className="chip">예상 소요 70분</span>
          <span className="chip">직접 확인해 보기 3개</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> 서랍 전체를 뒤집어야 하죠.
          데이터도 똑같아요. 설계 없이 쌓은 데이터는 넣기는 쉬워도 꺼내기가 고통입니다.
        </p>
        <Code>{CODE_MESSY_DESK}</Code>
        <p>
          <strong>데이터 모델링</strong>은 데이터를 넣기 전에 "어떤 서랍(테이블)을 만들고,
          각 서랍에 어떤 칸(컬럼)을 둘까"를 정하는 일이에요. 우리 플랫폼의 백엔드
          (<strong>Spring Boot</strong>)가 다루는 모든 데이터도 <strong>PostgreSQL</strong>의
          테이블 설계 위에 서 있습니다. 설계가 좋으면 코드가 짧아지고, 설계가 나쁘면
          코드가 그 나쁨을 평생 뒤치다꺼리하게 돼요.
        </p>
        <div className="tip">
          <b>미리 보는 핵심 문장</b> 이 코스 전체를 한 줄로 줄이면 이거예요 —
          <strong> "같은 사실은 딱 한 곳에만 적고, 필요한 곳에서는 번호(FK)로 가리킨다."</strong>
          섹션 7까지 가면 이 문장이 완전히 내 것이 됩니다.
        </div>
      </Section>

      <Section n={2} title="ERD 읽고 그리기" sub="우리 플랫폼의 진짜 관계도로 배우기">
        <p>
          <strong>ERD</strong>(Entity-Relationship Diagram)는 테이블들의 <strong>지도</strong>예요.
          상자 하나가 테이블 하나, 상자를 잇는 선이 <strong>관계</strong>입니다.
          멀리 갈 것 없이, 지금 여러분이 과제를 제출할 때마다 실제로 움직이는
          우리 플랫폼의 핵심 세 테이블을 볼게요.
        </p>
        <Code>{CODE_ERD_OURS}</Code>
        <p>
          ERD를 읽는 순서는 이래요. <strong>① 상자 이름</strong>부터 —
          "아, users랑 assignment랑 submission이 있구나."
          <strong> ② 선의 방향과 숫자</strong> — "학생 하나에 제출이 여러 개 달리는구나."
          <strong> ③ FK 칸</strong> — "submission이 user_id로 users를 가리키는구나."
          이 세 단계면 처음 보는 프로젝트의 DB도 30분 안에 파악할 수 있어요.
          실제로 실무 개발자가 새 팀에 합류하면 <strong>제일 먼저 찾는 문서가 ERD</strong>입니다.
        </p>
        <svg className="diagram" viewBox="0 0 640 360" xmlns="http://www.w3.org/2000/svg" role="img" aria-label="users, assignment, submission 세 테이블의 ERD. users와 submission, assignment와 submission이 각각 1대N 관계로 연결된다">
          <rect x="40" y="30" width="170" height="120" rx="8" fill="var(--card)" stroke="var(--line)" />
          <text x="125" y="52" textAnchor="middle" fontSize="14" fontWeight="600" fill="var(--ink)">users</text>
          <line x1="40" y1="62" x2="210" y2="62" stroke="var(--line)" />
          <text x="54" y="82" fontSize="12.5" fontWeight="600" fill="var(--primary)">id (PK)</text>
          <text x="54" y="100" fontSize="12.5" fill="var(--ink)">name</text>
          <text x="54" y="118" fontSize="12.5" fill="var(--ink)">email</text>
          <text x="54" y="136" fontSize="12.5" fill="var(--ink)">role</text>
          <rect x="430" y="30" width="170" height="120" rx="8" fill="var(--card)" stroke="var(--line)" />
          <text x="515" y="52" textAnchor="middle" fontSize="14" fontWeight="600" fill="var(--ink)">assignment</text>
          <line x1="430" y1="62" x2="600" y2="62" stroke="var(--line)" />
          <text x="444" y="82" fontSize="12.5" fontWeight="600" fill="var(--primary)">id (PK)</text>
          <text x="444" y="100" fontSize="12.5" fill="var(--ink)">title</text>
          <text x="444" y="118" fontSize="12.5" fill="var(--ink)">due_date</text>
          <text x="444" y="136" fontSize="12.5" fill="var(--ink)">description</text>
          <rect x="225" y="200" width="200" height="140" rx="8" fill="var(--card)" stroke="var(--line)" />
          <text x="325" y="222" textAnchor="middle" fontSize="14" fontWeight="600" fill="var(--ink)">submission</text>
          <line x1="225" y1="232" x2="425" y2="232" stroke="var(--line)" />
          <text x="239" y="252" fontSize="12.5" fontWeight="600" fill="var(--primary)">id (PK)</text>
          <text x="239" y="270" fontSize="12.5" fill="var(--teal)">user_id (FK)</text>
          <text x="239" y="288" fontSize="12.5" fill="var(--teal)">assignment_id (FK)</text>
          <text x="239" y="306" fontSize="12.5" fill="var(--ink)">content · submitted_at</text>
          <text x="239" y="324" fontSize="12.5" fill="var(--ink)">score</text>
          <polyline points="125,150 125,265 207,265" fill="none" stroke="var(--muted)" strokeWidth="1.5" />
          <line x1="117" y1="172" x2="133" y2="172" stroke="var(--muted)" strokeWidth="1.5" />
          <text x="140" y="176" fontSize="12" fontWeight="600" fill="var(--muted)">1</text>
          <line x1="207" y1="265" x2="225" y2="257" stroke="var(--muted)" strokeWidth="1.5" />
          <line x1="207" y1="265" x2="225" y2="265" stroke="var(--muted)" strokeWidth="1.5" />
          <line x1="207" y1="265" x2="225" y2="273" stroke="var(--muted)" strokeWidth="1.5" />
          <text x="192" y="257" textAnchor="middle" fontSize="12" fontWeight="600" fill="var(--muted)">N</text>
          <polyline points="515,150 515,283 443,283" fill="none" stroke="var(--muted)" strokeWidth="1.5" />
          <line x1="507" y1="172" x2="523" y2="172" stroke="var(--muted)" strokeWidth="1.5" />
          <text x="528" y="176" fontSize="12" fontWeight="600" fill="var(--muted)">1</text>
          <line x1="443" y1="283" x2="425" y2="275" stroke="var(--muted)" strokeWidth="1.5" />
          <line x1="443" y1="283" x2="425" y2="283" stroke="var(--muted)" strokeWidth="1.5" />
          <line x1="443" y1="283" x2="425" y2="291" stroke="var(--muted)" strokeWidth="1.5" />
          <text x="458" y="275" textAnchor="middle" fontSize="12" fontWeight="600" fill="var(--muted)">N</text>
        </svg>
        <p className="muted" style={{ fontSize: 12.5, textAlign: 'center', marginTop: 2 }}>그림: 우리 플랫폼 핵심 ERD — 까치발(세 갈래)이 붙은 쪽이 N, 한 줄 눈금이 1</p>
        <div className="tip">
          <b>직접 확인해 보기 ①</b> 종이에 위 ERD를 <strong>안 보고</strong> 다시 그려 보세요.
          상자 3개, PK/FK 표시, 관계선의 1과 N까지. 그리고 원본과 비교 —
          빠뜨린 게 있다면 그게 아직 이해가 덜 된 부분이에요. 지도는 그려 봐야 외워집니다.
        </div>
      </Section>

      <Section n={3} title="기본키(PK)와 외래키(FK)" sub="학번, 그리고 '학번으로 가리키기'">
        <p>
          <strong>기본키(Primary Key)</strong>는 학번이에요. 이름은 동명이인이 있을 수 있지만,
          학번은 학교 안에서 절대 겹치지 않죠. 테이블의 모든 줄(행)은 PK 하나로
          유일하게 찍어낼 수 있어야 합니다. 보통 <span className="icode">id</span>라는
          자동 증가 숫자를 씁니다.
        </p>
        <p>
          <strong>외래키(Foreign Key)</strong>는 "다른 반 친구를 부를 때 학번으로 부르기"예요.
          submission 테이블이 학생 정보를 통째로 복사해 오는 대신,
          <span className="icode">user_id</span> 한 칸에 <strong>users의 학번(PK)만</strong> 적어 두는 거죠.
        </p>
        <Code>{CODE_PK_FK}</Code>
        <div className="warn">
          <b>이메일을 PK로 쓰면 안 될까요?</b> 유일하긴 하죠. 하지만 이메일은
          <strong> 바뀔 수 있는 값</strong>이에요. PK가 바뀌면 그걸 가리키던 모든 FK가
          함께 흔들립니다. 그래서 PK는 의미 없는 번호(<span className="icode">id</span>)로 두고,
          이메일 같은 건 "중복 금지" 제약만 거는 게 정석이에요. 학번을 두고
          "이름+생일"로 학생을 식별하지 않는 것과 같은 이유입니다.
        </div>
        <div className="tip">
          <b>직접 확인해 보기 ②</b> 로컬에서 Docker로 개발 DB를 띄워 뒀다면,
          psql로 접속해 우리 테이블의 PK/FK를 눈으로 직접 확인할 수 있어요.
          컨테이너 이름은 <span className="icode">docker ps</span>로 먼저 찾으세요.
        </div>
        <Code>{CODE_PSQL_PEEK}</Code>
      </Section>

      <Section n={4} title="1:N과 N:M" sub="관계의 두 가지 얼굴, 그리고 중간 테이블이라는 다리">
        <p>
          테이블 사이의 관계는 대부분 두 종류로 정리돼요. 먼저 <strong>1:N</strong> —
          "하나가 여럿을 거느리는" 관계입니다. 멘토 한 명이 수습 여러 명을 담당하고,
          과제 하나에 제출이 여러 개 달리죠.
        </p>
        <Code>{CODE_ONE_TO_N}</Code>
        <p>
          그런데 <strong>양쪽 다 여럿</strong>이면 어떡할까요? 한 학생이 여러 스터디에 들고,
          한 스터디에도 여러 학생이 드는 <strong>N:M</strong> 관계요. 이때는 FK 한 칸으로는
          부족해서, 두 테이블 사이에 <strong>다리(중간 테이블)</strong>를 놓습니다.
        </p>
        <Code>{CODE_N_TO_M}</Code>
        <p>
          마지막 줄이 이 섹션의 반전 포인트예요 — 섹션 2에서 본 <strong>submission이
          바로 중간 테이블</strong>이었다는 것. "학생과 과제 사이의 N:M 다리"에
          제출 내용과 점수라는 정보가 얹힌 형태죠. N:M을 발견하면
          "중간 테이블 + 거기에 얹을 정보가 있나?"를 묻는 습관을 들이세요.
        </p>
        <svg className="diagram" viewBox="0 0 640 240" xmlns="http://www.w3.org/2000/svg" role="img" aria-label="N대M 관계 분해도. users와 study는 직접 연결할 수 없고, 중간 테이블 study_member가 두 개의 1대N 관계로 다리를 놓는다">
          <text x="325" y="40" textAnchor="middle" fontSize="12.5" fontWeight="600" fill="var(--rose)">FK 한 칸으로 직접 연결은 불가 (N:M)</text>
          <line x1="105" y1="55" x2="305" y2="55" stroke="var(--rose)" strokeDasharray="5 4" />
          <line x1="345" y1="55" x2="545" y2="55" stroke="var(--rose)" strokeDasharray="5 4" />
          <line x1="105" y1="55" x2="105" y2="70" stroke="var(--rose)" strokeDasharray="5 4" />
          <line x1="545" y1="55" x2="545" y2="70" stroke="var(--rose)" strokeDasharray="5 4" />
          <line x1="317" y1="48" x2="333" y2="62" stroke="var(--rose)" strokeWidth="1.5" />
          <line x1="333" y1="48" x2="317" y2="62" stroke="var(--rose)" strokeWidth="1.5" />
          <rect x="30" y="70" width="150" height="100" rx="8" fill="var(--card)" stroke="var(--line)" />
          <text x="105" y="92" textAnchor="middle" fontSize="14" fontWeight="600" fill="var(--ink)">users</text>
          <line x1="30" y1="100" x2="180" y2="100" stroke="var(--line)" />
          <text x="44" y="120" fontSize="12.5" fontWeight="600" fill="var(--primary)">id (PK)</text>
          <text x="44" y="140" fontSize="12.5" fill="var(--ink)">name</text>
          <rect x="245" y="60" width="170" height="120" rx="8" fill="var(--card)" stroke="var(--primary)" />
          <text x="330" y="82" textAnchor="middle" fontSize="14" fontWeight="600" fill="var(--primary)">study_member</text>
          <line x1="245" y1="90" x2="415" y2="90" stroke="var(--line)" />
          <text x="259" y="110" fontSize="12.5" fontWeight="600" fill="var(--primary)">id (PK)</text>
          <text x="259" y="128" fontSize="12.5" fill="var(--teal)">user_id (FK)</text>
          <text x="259" y="146" fontSize="12.5" fill="var(--teal)">study_id (FK)</text>
          <text x="330" y="170" textAnchor="middle" fontSize="12" fill="var(--muted)">한 줄 = 가입 사실 하나</text>
          <rect x="470" y="70" width="150" height="100" rx="8" fill="var(--card)" stroke="var(--line)" />
          <text x="545" y="92" textAnchor="middle" fontSize="14" fontWeight="600" fill="var(--ink)">study</text>
          <line x1="470" y1="100" x2="620" y2="100" stroke="var(--line)" />
          <text x="484" y="120" fontSize="12.5" fontWeight="600" fill="var(--primary)">id (PK)</text>
          <text x="484" y="140" fontSize="12.5" fill="var(--ink)">name</text>
          <line x1="180" y1="125" x2="227" y2="125" stroke="var(--muted)" strokeWidth="1.5" />
          <line x1="192" y1="117" x2="192" y2="133" stroke="var(--muted)" strokeWidth="1.5" />
          <text x="192" y="110" textAnchor="middle" fontSize="12" fontWeight="600" fill="var(--muted)">1</text>
          <line x1="227" y1="125" x2="245" y2="117" stroke="var(--muted)" strokeWidth="1.5" />
          <line x1="227" y1="125" x2="245" y2="125" stroke="var(--muted)" strokeWidth="1.5" />
          <line x1="227" y1="125" x2="245" y2="133" stroke="var(--muted)" strokeWidth="1.5" />
          <text x="232" y="110" textAnchor="middle" fontSize="12" fontWeight="600" fill="var(--muted)">N</text>
          <line x1="433" y1="125" x2="470" y2="125" stroke="var(--muted)" strokeWidth="1.5" />
          <line x1="452" y1="117" x2="452" y2="133" stroke="var(--muted)" strokeWidth="1.5" />
          <text x="452" y="110" textAnchor="middle" fontSize="12" fontWeight="600" fill="var(--muted)">1</text>
          <line x1="433" y1="125" x2="415" y2="117" stroke="var(--muted)" strokeWidth="1.5" />
          <line x1="433" y1="125" x2="415" y2="125" stroke="var(--muted)" strokeWidth="1.5" />
          <line x1="433" y1="125" x2="415" y2="133" stroke="var(--muted)" strokeWidth="1.5" />
          <text x="428" y="110" textAnchor="middle" fontSize="12" fontWeight="600" fill="var(--muted)">N</text>
          <text x="325" y="212" textAnchor="middle" fontSize="12" fill="var(--muted)">N:M = 중간 테이블을 사이에 둔 1:N 두 개 — submission도 같은 패턴</text>
        </svg>
        <p className="muted" style={{ fontSize: 12.5, textAlign: 'center', marginTop: 2 }}>그림: N:M 관계는 중간 테이블(다리)로 분해된다 — 까치발 두 개가 모두 중간 테이블을 향한다</p>
      </Section>

      <Section n={5} title="정규화 — 중복 제거 대작전" sub="같은 사실을 두 번 적으면 언젠가 모순이 생긴다">
        <p>
          <strong>정규화</strong>(Normalization)라는 무서운 단어의 정체는 사실 단순해요 —
          <strong> "같은 정보를 여러 곳에 복사해 두지 말자"</strong>입니다.
          연락처를 폰에도 적고 다이어리에도 적고 포스트잇에도 적으면,
          친구가 번호를 바꿨을 때 셋 중 하나는 꼭 옛날 번호로 남죠. 그게 데이터 모순이에요.
        </p>
        <Code>{CODE_NORMALIZE}</Code>
        <p>
          1·2·3차 정규형의 엄밀한 정의는 나중에 필요할 때 찾아봐도 충분해요.
          지금 단계에서는 위의 <strong>직관 버전 세 줄</strong>과,
          "중복이 보이면 테이블을 쪼개고 FK로 가리킨다"는 감각이면 실무 설계의 90%를 커버합니다.
        </p>
        <div className="warn">
          <b>그럼 무조건 잘게 쪼갤수록 좋은가요?</b> 아니에요. 너무 쪼개면 데이터를
          읽을 때마다 여러 테이블을 이어 붙여야(JOIN) 해서 느려질 수 있어요.
          그래서 실무에서는 일부러 약간의 중복을 허용하기도 합니다(비정규화).
          다만 그건 <strong>정규화를 할 줄 아는 사람이 이유를 갖고 어기는 것</strong> —
          기본기는 언제나 "중복 없이"입니다.
        </div>
      </Section>

      <Section n={6} title="나쁜 설계의 냄새" sub="코드 리뷰처럼, 설계에도 '냄새'가 있다">
        <p>
          경험 많은 개발자는 테이블 구조만 슥 봐도 "여기 냄새 나는데?" 하고 알아챕니다.
          대표적인 냄새 세 가지를 익혀 두면, 여러분도 설계 리뷰에서 한마디 얹을 수 있어요.
        </p>
        <Code>{CODE_BAD_SMELLS}</Code>
        <p>
          특히 <strong>냄새 1(한 칸에 여러 값)</strong>이 제일 유혹적이에요.
          "태그쯤이야 쉼표로 이어 붙이면 되지" 싶지만, 그 순간부터 검색·수정·삭제가
          전부 문자열 곡예가 됩니다. 한 칸엔 값 하나 — 목록이 필요하면 줄을 늘리거나
          테이블을 새로 만드세요. 서랍 한 칸에 양말 뭉치를 테이프로 감아 넣지 않는 것처럼요.
        </p>
        <div className="tip">
          <b>연습 문제</b> 다음 설계의 냄새를 맡아 보세요 —
          <span className="icode">study(id, name, member_names)</span>에서
          <span className="icode">member_names = "김수습,이수습"</span>.
          냄새가 몇 번인지, 어떻게 고칠지 말로 설명해 보세요.
          (힌트: 섹션 4에서 정답 구조를 이미 봤어요!)
        </div>
      </Section>

      <Section n={7} title="실습: '쪽지 기능' 테이블 설계" sub="배운 걸 전부 꺼내 쓰는 진짜 설계 한 판">
        <p>
          이제 여러분 차례입니다. 우리 플랫폼에 <strong>쪽지 기능</strong>을 추가한다고
          가정하고, 필요한 테이블을 직접 설계해 보세요. 정답이 하나로 정해진 문제가
          아니에요 — <strong>왜 그렇게 설계했는지 설명할 수 있느냐</strong>가 핵심입니다.
        </p>
        <Code>{CODE_PRACTICE}</Code>
        <div className="tip">
          <b>직접 확인해 보기 ③ — 멘토 리뷰 받기</b> 완성한 ERD를 들고 멘토에게
          설계 리뷰를 요청하세요. 리뷰 때 이 세 가지를 <strong>내가 먼저</strong> 설명하면
          훨씬 깊은 피드백을 받을 수 있어요: ① 각 FK가 무엇을 가리키는지
          ② 관계가 1:N인지 N:M인지와 그 근거 ③ 중복 저장한 정보가 없는지 스스로 점검한 결과.
          실무의 설계 리뷰도 정확히 이 순서로 흘러갑니다.
        </div>
        <div className="warn">
          <b>흔한 함정 미리보기</b> "보낸사람이름" 칸을 만들고 싶어지면 섹션 3을,
          "받는사람1, 받는사람2" 칸이 떠오르면 섹션 6의 냄새 2를 다시 읽어 보세요.
          단체 쪽지(한 쪽지 → 여러 수신자)는 N:M — 섹션 4의 중간 테이블이 답입니다.
        </div>
      </Section>

      <div className="step-card">
        <div className="step-body">
          <h3 style={{ marginBottom: 6 }}>🗂️ 여기까지 왔다면</h3>
          <p className="muted">
            이제 여러분은 <strong>ERD를 읽고</strong>, PK/FK로 <strong>테이블을 잇고</strong>,
            중복을 보면 <strong>쪼개서 가리키는</strong> 사람이 됐어요. 설계한 테이블을
            실제로 만들고 데이터를 꺼내는 언어가 궁금하다면{' '}
            <Link to="/learn/sql"><strong>SQL 첫걸음</strong></Link> 코스로,
            그 테이블을 백엔드 코드와 연결하는 법이 궁금하다면{' '}
            <Link to="/learn/spring-intro"><strong>Spring Boot 백엔드 입문</strong></Link>으로
            이어 가세요. 쪽지 기능 ERD는 멘토 리뷰 후 과제 게시판에 제출하는 것도 잊지 말고요!
          </p>
        </div>
      </div>
    </div>
  );
}
