// 이 파일이 하는 일: "Spring Boot 입문" 코스 — 스프링이 대신 해주는 일(DI)에서 출발해
// 어노테이션 읽는 법, Controller→Service→Repository 계층 여행, application.yml,
// JPA 맛보기, 그리고 우리 백엔드에 API 하나를 직접 추가하는 실습까지 7개 섹션으로 안내한다.
// 학습 포인트: API 호출이 없는 '내용 고정' 정적 페이지다. 스타일은 global.css의
// 가이드 전용 클래스(step-card, code-block, tip 등)를 재사용한다 — 색을 여기서 하드코딩하지 않는다.
// 자바 코드 예시는 JSX 중괄호/백틱 충돌을 피하려고 파일 상단의 백틱 문자열 상수로 정의한다.

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

// ── 코드 예시 · 텍스트 다이어그램 상수들 ──

const CODE_NO_SPRING = `// 스프링이 없다면 — 필요한 재료를 전부 '내가' 만들어야 해요.
public class AuthService {
    // DB 연결 만들고, 리포지토리 만들고, 암호화 도구 만들고...
    private final UserRepository userRepository =
            new UserRepository(new DataSource("jdbc:postgresql://...", "id", "pw"));
    private final PasswordEncoder encoder = new BCryptPasswordEncoder();
    // 재료가 하나 바뀌면? 이걸 만든 모든 파일을 고쳐야 합니다. 끔찍하죠.
}`;

const CODE_WITH_SPRING = `// 스프링이 있다면 — "필요해요"라고 선언만 하면 주방(컨테이너)이 가져다줘요.
@Service
public class AuthService {
    private final UserRepository userRepository;
    private final PasswordEncoder encoder;

    // 생성자에 적어 두면 스프링이 알아서 넣어(주입해) 줍니다.
    public AuthService(UserRepository userRepository, PasswordEncoder encoder) {
        this.userRepository = userRepository;
        this.encoder = encoder;
    }
}`;

const CODE_ANNOTATIONS = `우리 백엔드에서 매일 만나는 어노테이션 5총사

@RestController  "나는 요청을 받는 카운터 직원이에요. 응답은 JSON으로 드려요."
@Service         "나는 주방에서 실제 요리(비즈니스 로직)를 하는 요리사예요."
@Repository      "나는 창고(DB) 담당이에요. 재료를 꺼내오고 넣어요."
@Component       "특별한 역할은 없지만 나도 스프링이 관리해 주세요." (위 셋의 부모 격)
@Configuration   "나는 주방 설비 설치 담당 — 빈(Bean)을 직접 만들어 등록해요."

공통점: 클래스 위에 붙이면 스프링이 그 클래스를 '빈(Bean)'으로 만들어
컨테이너(주방)에 등록하고, 필요한 곳에 배달(주입)해 줍니다.`;

const CODE_CONSTRUCTOR_DI = `// 생성자 주입 — 우리 회사 표준 방식이에요.
@RestController
public class AuthController {
    private final AuthService authService;   // final! 한 번 받으면 안 바뀜

    public AuthController(AuthService authService) {  // 생성자가 하나면
        this.authService = authService;               // @Autowired 생략 가능
    }
}

// 필드에 @Autowired를 직접 붙이는 방식(필드 주입)도 돌아가긴 하지만,
// final을 못 쓰고 테스트하기 어려워서 요즘은 생성자 주입이 정석입니다.`;

const CODE_LAYER_TRIP = `로그인 요청 한 번의 여행 — POST /api/auth/login 이 도착하면:

[브라우저]
   │  POST /api/auth/login  { "email": "...", "password": "..." }
   ▼
① AuthController  (현관 카운터)
   │  "주문 받았어요!" — 요청 JSON을 DTO로 받아서 검사만 하고
   ▼     바로 주방에 넘깁니다. 카운터는 요리하지 않아요.
② AuthService     (주방)
   │  비밀번호 대조, 토큰 발급 같은 '진짜 일'은 전부 여기서.
   ▼     재료가 필요하면 창고 담당을 부릅니다.
③ UserRepository  (창고)
   │  SELECT * FROM users WHERE email = ?   ← DB에서 재료 꺼내오기
   ▼
[PostgreSQL]

응답은 이 길을 거꾸로: 창고 → 주방 → 카운터 → 200 OK + JSON.
각 층이 자기 일만 하니까, 문제가 생겨도 "어느 층이 범인인지" 금방 찾아요.`;

const CODE_YML = `# application.yml — 코드 밖에 두는 '설정 메모장'
server:
  port: 8080                       # 이 서버가 문을 여는 포트

spring:
  datasource:
    url: \${DB_URL:jdbc:postgresql://localhost:5432/mirim}
    username: \${DB_USER:mirim}
    password: \${DB_PASSWORD}      # 비밀번호는 기본값 없이 환경변수로만!
  jpa:
    hibernate:
      ddl-auto: update             # 엔티티 보고 테이블 자동 생성/수정

# \${환경변수:기본값} 문법이 핵심!
# 내 PC에선 기본값으로 돌고, 운영 EC2에선 환경변수가 덮어씁니다.
# 같은 코드로 어디서든 도는 비결이 이거예요.`;

const CODE_JPA = `// JPA — 메서드 '이름'이 곧 SQL이 되는 마법
public interface UserRepository extends JpaRepository<User, Long> {

    Optional<User> findByEmail(String email);
    // → SELECT * FROM users WHERE email = ?

    boolean existsByNickname(String nickname);
    // → SELECT COUNT(*) > 0 FROM users WHERE nickname = ?

    List<User> findByRoleOrderByCreatedAtDesc(String role);
    // → SELECT * FROM users WHERE role = ? ORDER BY created_at DESC
}
// 구현 코드가 한 줄도 없죠? 스프링이 메서드 이름을 '읽고'
// SQL을 대신 써 줍니다. 규칙: findBy + 필드명 + (조건/정렬)`;

const CODE_PRACTICE_API = `// 실습: 서버의 상태를 알려주는 초간단 API 만들기
// 위치: backend/src/main/java/.../web/HelloController.java (새 파일)

@RestController
public class HelloController {

    @GetMapping("/api/hello")
    public Map<String, String> hello() {
        return Map.of(
            "message", "안녕하세요, AWESOMEDEV 수습 여러분!",
            "from", "내가 만든 첫 스프링 API"
        );
    }
}

// 이게 전부예요. 서버 재시작 후 브라우저에서
// http://localhost:8080/api/hello 를 열어 보세요.
// JSON이 보이면 — 방금 백엔드 개발자가 된 겁니다.`;

const CODE_PRACTICE_NEXT = `한 단계 더 (STUDY 과제 연계) — 파라미터 받아 보기

@GetMapping("/api/hello/{name}")
public Map<String, String> helloName(@PathVariable String name) {
    return Map.of("message", name + "님, 환영합니다!");
}

// http://localhost:8080/api/hello/미림 으로 접속하면?
// URL의 '미림'이 name 변수로 들어옵니다.
// 도전 과제: @RequestParam으로 ?lang=en 을 받아서
// 영어 인사도 되게 만들어 보세요. 완성하면 Gitea에 커밋!`;

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

Q1. "의존성 주입(DI)"을 식당 주방 비유로 설명해 보세요.
    힌트: 요리사가 직접 장을 보러 가나요? (섹션 1)

Q2. @RestController와 @Service의 역할 차이는?
    힌트: 카운터 직원과 요리사 (섹션 2·3)

Q3. Controller에 비즈니스 로직을 쓰면 왜 안 좋을까요?
    힌트: 카운터에서 요리를 하면 주문은 누가 받죠? (섹션 3)

Q4. DB 비밀번호를 application.yml에 그대로 적으면 왜 위험할까요?
    힌트: 이 파일은 Git에 올라갑니다 (섹션 4)

Q5. findByEmailAndRole(String email, String role) 은
    어떤 SQL이 될까요? 직접 써 보세요. (섹션 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: 'application.yml' },
  { n: 5, label: 'JPA 한 입' },
  { n: 6, label: '실습: 첫 API' },
  { n: 7, label: '정리 퀴즈' },
];

export default function SpringIntroPage() {
  return (
    <div>
      {/* 히어로: 이 코스가 어디서 출발해 어디까지 가는지 */}
      <div className="hero">
        <div className="eyebrow">Course · 소프트웨어</div>
        <h1>Spring Boot 입문<br />— 우리 백엔드가 돌아가는 원리</h1>
        <p>
          자바 코드 몇 줄이 어떻게 로그인·회원가입 같은 서비스가 되는지, 우리 플랫폼의
          백엔드를 직접 열어 보며 배웁니다. 마지막 섹션에선 진짜로 <strong>내 손으로 API
          하나를 추가</strong>해 봐요 — 읽기만 하는 코스가 아닙니다.
        </p>
        <div className="chip-row">
          <span className="chip">예상 소요 90분</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="스프링이 해주는 일 — 객체 조립(DI)" sub="요리사는 요리만, 장보기는 주방이">
        <p>
          식당 주방을 상상해 보세요. 요리사가 요리할 때마다 직접 마트에 가서 재료를 사 오고,
          칼을 벼리고, 가스까지 설치해야 한다면? 요리할 시간이 없겠죠. 좋은 주방은
          <strong> 요리사가 "재료 주세요" 하면 필요한 게 손에 들어오는</strong> 곳이에요.
        </p>
        <p>
          코드도 똑같아요. 객체가 일하려면 다른 객체(재료)가 필요한데, 그걸 매번 직접
          <span className="icode">new</span>로 만들면 이렇게 됩니다.
        </p>
        <Code>{CODE_NO_SPRING}</Code>
        <p>
          스프링은 이 "장보기"를 통째로 대신해 줘요. 앱이 켜질 때 필요한 객체들을 미리 만들어
          <strong> 컨테이너</strong>(주방 창고)에 보관해 두고, "이거 필요해요"라고 선언한 곳에
          <strong> 알아서 넣어 줍니다</strong>. 이게 <strong>의존성 주입</strong>(DI,
          Dependency Injection)이에요. 이름은 어렵지만 뜻은 "필요한 재료를 주방이 가져다준다",
          그게 전부입니다.
        </p>
        <svg className="diagram" viewBox="0 0 640 280" xmlns="http://www.w3.org/2000/svg" role="img" aria-label="스프링 컨테이너가 보관하던 빈들을 AuthService의 생성자로 주입해 주는 의존성 주입 개념도">
          <rect x="20" y="70" width="250" height="170" rx="8" fill="none" stroke="var(--line)" strokeWidth="1.5" strokeDasharray="6 5" />
          <text x="145" y="92" textAnchor="middle" fontSize="13" fontWeight="600" fill="var(--ink)">스프링 컨테이너 (주방)</text>
          <rect x="40" y="100" width="210" height="34" rx="8" fill="var(--card)" stroke="var(--amber)" strokeWidth="1.5" />
          <text x="145" y="121" textAnchor="middle" fontSize="12.5" fill="var(--ink)">UserRepository 빈</text>
          <rect x="40" y="160" width="210" height="34" rx="8" fill="var(--card)" stroke="var(--teal)" strokeWidth="1.5" />
          <text x="145" y="181" textAnchor="middle" fontSize="12.5" fill="var(--ink)">PasswordEncoder 빈</text>
          <line x1="254" y1="117" x2="384" y2="117" stroke="var(--primary)" strokeWidth="2" />
          <path d="M 394 117 l -9 -5 l 0 10 z" fill="var(--primary)" />
          <line x1="254" y1="177" x2="384" y2="177" stroke="var(--primary)" strokeWidth="2" />
          <path d="M 394 177 l -9 -5 l 0 10 z" fill="var(--primary)" />
          <text x="324" y="150" textAnchor="middle" fontSize="12" fill="var(--muted)">주입 (자동 배달)</text>
          <rect x="400" y="70" width="215" height="170" rx="8" fill="var(--card)" stroke="var(--primary)" strokeWidth="1.5" />
          <text x="507" y="95" textAnchor="middle" fontSize="13" fontWeight="600" fill="var(--ink)">AuthService (요리사)</text>
          <rect x="418" y="103" width="180" height="30" rx="8" fill="none" stroke="var(--line)" strokeWidth="1.5" />
          <text x="508" y="122" textAnchor="middle" fontSize="12" fill="var(--muted)">필요: userRepository</text>
          <rect x="418" y="162" width="180" height="30" rx="8" fill="none" stroke="var(--line)" strokeWidth="1.5" />
          <text x="508" y="181" textAnchor="middle" fontSize="12" fill="var(--muted)">필요: encoder</text>
          <text x="507" y="262" textAnchor="middle" fontSize="12" fill="var(--muted)">new 없이 생성자에 선언만 하면 채워져요</text>
        </svg>
        <p className="muted" style={{ fontSize: 12.5, textAlign: 'center', marginTop: 2 }}>그림: 컨테이너(주방)가 미리 만들어 둔 빈을 필요하다고 선언한 곳에 넣어 주는 의존성 주입</p>
        <Code>{CODE_WITH_SPRING}</Code>
        <div className="tip">
          <b>왜 이게 좋은가요?</b> 재료(예: DB 연결 방식)가 바뀌어도 주방 설정 한 곳만 고치면
          돼요. 요리사(각 클래스)들은 코드 한 줄 안 바꿔도 됩니다. 부품을 갈아 끼우기 쉬운
          코드 — 이게 스프링이 20년 넘게 살아남은 이유예요.
        </div>
      </Section>

      <Section n={2} title="어노테이션 읽기" sub="@ 붙은 한 줄이 스프링에게 보내는 쪽지">
        <p>
          스프링 코드를 처음 열면 <span className="icode">@</span>로 시작하는 단어가 잔뜩
          보여요. 겁먹지 마세요 — 어노테이션은 <strong>스프링에게 보내는 짧은 쪽지</strong>일
          뿐입니다. "이 클래스는 이런 역할이니 이렇게 관리해 주세요"라는 메모예요.
        </p>
        <Code>{CODE_ANNOTATIONS}</Code>
        <p>
          그리고 재료를 받는 방법, 즉 주입 방식 중에서 우리는 <strong>생성자 주입</strong>을
          씁니다. 생성자의 파라미터에 필요한 것을 적어 두면 스프링이 객체를 만들 때 채워 줘요.
        </p>
        <Code>{CODE_CONSTRUCTOR_DI}</Code>
        <div className="tip">
          <b>직접 확인해 보기</b> 우리 백엔드 저장소(edu.awesomedevapp.com:3000의 Gitea)에서
          <span className="icode"> AuthController.java</span>를 열어 보세요. 클래스 위의
          <span className="icode"> @RestController</span>, 생성자에서 받는
          <span className="icode"> final</span> 필드들 — 방금 배운 모양 그대로인지 눈으로
          확인해 보세요. "읽을 수 있는 코드"가 하나 생기는 순간입니다.
        </div>
      </Section>

      <Section n={3} title="계층 구조 여행 — Controller → Service → Repository" sub="로그인 요청 하나를 끝까지 따라가기">
        <p>
          백엔드는 층이 나뉜 식당이에요. <strong>카운터(Controller)</strong>는 주문만 받고,
          <strong> 주방(Service)</strong>은 요리만 하고, <strong>창고(Repository)</strong>는
          재료 관리만 합니다. 여러분이 우리 플랫폼에 로그인하는 순간, 요청은 이 세 층을
          차례로 여행해요.
        </p>
        <Code>{CODE_LAYER_TRIP}</Code>
        <p>
          핵심은 <strong>각 층이 자기 일만 한다</strong>는 것. 카운터가 요리까지 하면 주문이
          밀리고, 요리사가 창고 정리까지 하면 음식이 늦어요. 코드도 같습니다 — Controller에
          비즈니스 로직을 쓰기 시작하면, 나중에 "로그인 규칙만 바꾸고 싶은데" 할 때 어디를
          고쳐야 할지 아무도 몰라요.
        </p>
        <svg className="diagram" viewBox="0 0 640 240" xmlns="http://www.w3.org/2000/svg" role="img" aria-label="로그인 요청이 브라우저에서 Controller, Service, Repository를 거쳐 PostgreSQL까지 갔다가 같은 길로 되돌아오는 계층 구조도">
          <line x1="90" y1="50" x2="128" y2="50" stroke="var(--primary)" strokeWidth="2" />
          <path d="M 136 50 l -9 -5 l 0 10 z" fill="var(--primary)" />
          <text x="144" y="54" fontSize="12" fill="var(--muted)">요청 (POST /api/auth/login)</text>
          <path d="M 372 50 l 9 -5 l 0 10 z" fill="var(--muted)" />
          <line x1="380" y1="50" x2="418" y2="50" stroke="var(--muted)" strokeWidth="2" strokeDasharray="4 4" />
          <text x="426" y="54" fontSize="12" fill="var(--muted)">응답 (200 OK + JSON)</text>
          <rect x="10" y="110" width="96" height="64" rx="8" fill="var(--card)" stroke="var(--line)" strokeWidth="1.5" />
          <text x="58" y="136" textAnchor="middle" fontSize="13" fontWeight="600" fill="var(--ink)">브라우저</text>
          <text x="58" y="155" textAnchor="middle" fontSize="12" fill="var(--muted)">요청 출발점</text>
          <rect x="141" y="110" width="96" height="64" rx="8" fill="var(--card)" stroke="var(--primary)" strokeWidth="1.5" />
          <text x="189" y="136" textAnchor="middle" fontSize="13" fontWeight="600" fill="var(--ink)">① Controller</text>
          <text x="189" y="155" textAnchor="middle" fontSize="12" fill="var(--muted)">현관 카운터</text>
          <rect x="272" y="110" width="96" height="64" rx="8" fill="var(--card)" stroke="var(--teal)" strokeWidth="1.5" />
          <text x="320" y="136" textAnchor="middle" fontSize="13" fontWeight="600" fill="var(--ink)">② Service</text>
          <text x="320" y="155" textAnchor="middle" fontSize="12" fill="var(--muted)">주방 · 진짜 일</text>
          <rect x="403" y="110" width="96" height="64" rx="8" fill="var(--card)" stroke="var(--amber)" strokeWidth="1.5" />
          <text x="451" y="136" textAnchor="middle" fontSize="13" fontWeight="600" fill="var(--ink)">③ Repository</text>
          <text x="451" y="155" textAnchor="middle" fontSize="12" fill="var(--muted)">창고 · SQL</text>
          <rect x="534" y="110" width="96" height="64" rx="8" fill="var(--card)" stroke="var(--line)" strokeWidth="1.5" />
          <text x="582" y="136" textAnchor="middle" fontSize="13" fontWeight="600" fill="var(--ink)">PostgreSQL</text>
          <text x="582" y="155" textAnchor="middle" fontSize="12" fill="var(--muted)">데이터의 집</text>
          <line x1="109" y1="126" x2="128" y2="126" stroke="var(--primary)" strokeWidth="2" />
          <path d="M 138 126 l -9 -5 l 0 10 z" fill="var(--primary)" />
          <line x1="240" y1="126" x2="259" y2="126" stroke="var(--primary)" strokeWidth="2" />
          <path d="M 269 126 l -9 -5 l 0 10 z" fill="var(--primary)" />
          <line x1="371" y1="126" x2="390" y2="126" stroke="var(--primary)" strokeWidth="2" />
          <path d="M 400 126 l -9 -5 l 0 10 z" fill="var(--primary)" />
          <line x1="502" y1="126" x2="521" y2="126" stroke="var(--primary)" strokeWidth="2" />
          <path d="M 531 126 l -9 -5 l 0 10 z" fill="var(--primary)" />
          <path d="M 109 158 l 9 -5 l 0 10 z" fill="var(--muted)" />
          <line x1="119" y1="158" x2="136" y2="158" stroke="var(--muted)" strokeWidth="2" strokeDasharray="4 4" />
          <path d="M 240 158 l 9 -5 l 0 10 z" fill="var(--muted)" />
          <line x1="250" y1="158" x2="267" y2="158" stroke="var(--muted)" strokeWidth="2" strokeDasharray="4 4" />
          <path d="M 371 158 l 9 -5 l 0 10 z" fill="var(--muted)" />
          <line x1="381" y1="158" x2="398" y2="158" stroke="var(--muted)" strokeWidth="2" strokeDasharray="4 4" />
          <path d="M 502 158 l 9 -5 l 0 10 z" fill="var(--muted)" />
          <line x1="512" y1="158" x2="529" y2="158" stroke="var(--muted)" strokeWidth="2" strokeDasharray="4 4" />
          <text x="320" y="210" textAnchor="middle" fontSize="12" fill="var(--muted)">요청은 세 층을 차례로 지나고, 응답은 같은 길을 거꾸로 돌아옵니다</text>
        </svg>
        <p className="muted" style={{ fontSize: 12.5, textAlign: 'center', marginTop: 2 }}>그림: 로그인 요청 한 번이 카운터 → 주방 → 창고를 지나 DB까지 갔다가 되돌아오는 길</p>
        <div className="warn">
          <b>수습 단골 실수</b> — Controller에서 Repository를 바로 부르는 코드.
          당장은 돌아가지만, 검증·로그 같은 "주방에서 할 일"이 카운터에 쌓이기 시작해요.
          Controller → Service → Repository, 한 방향으로만 흐르게 유지하세요.
        </div>
      </Section>

      <Section n={4} title="application.yml — 설정은 코드 밖으로" sub="같은 코드가 내 PC에서도, 서울 EC2에서도 도는 비결">
        <p>
          DB 주소, 포트 번호, 비밀번호… 이런 값을 자바 코드에 직접 적으면 환경이 바뀔 때마다
          코드를 고쳐야 해요. 그래서 스프링은 설정을 <strong>application.yml</strong>이라는
          별도 파일에 몰아둡니다. 요리 레시피(코드)와 "오늘의 가스 밸브 위치"(설정)를 분리하는
          거예요.
        </p>
        <Code>{CODE_YML}</Code>
        <p>
          <span className="icode">{'${DB_URL:기본값}'}</span> 문법을 눈여겨보세요.
          <strong> 환경변수가 있으면 그걸 쓰고, 없으면 기본값</strong>이라는 뜻이에요. 덕분에
          내 PC에선 로컬 PostgreSQL, 운영 서울 EC2에선 진짜 DB로 — 코드 수정 없이 환경변수만
          바꿔 배포합니다. 우리 Docker 배포가 정확히 이 원리로 굴러가요.
        </p>
        <div className="warn">
          <b>절대 규칙</b> — 진짜 비밀번호·키는 yml에 기본값으로 적어서 Git에 올리지 마세요.
          Git 이력은 지워지지 않아요. 비밀값은 환경변수(.env)로만, 이건 회사 보안 규칙이기도
          합니다.
        </div>
      </Section>

      <Section n={5} title="JPA 한 입 — 메서드 이름이 SQL로" sub="구현 없이 인터페이스만 썼는데 DB가 조회되는 이유">
        <p>
          창고(Repository) 층에서 SQL을 매번 손으로 쓰면 지루하고 실수도 잦아요.
          <strong> JPA</strong>는 자바 객체와 DB 테이블을 이어 주는 통역사예요. 그중 제일
          신기한 기능이 이겁니다 — <strong>메서드 이름만 규칙대로 지으면, 스프링이 이름을 읽고
          SQL을 대신 써 줘요.</strong>
        </p>
        <Code>{CODE_JPA}</Code>
        <p>
          <span className="icode">findBy</span> 뒤에 필드명을 붙이면 WHERE 조건이 되고,
          <span className="icode"> And</span>·<span className="icode">OrderBy</span> 같은
          단어로 조건을 이어 붙일 수 있어요. 물론 복잡한 쿼리는 직접 SQL을 쓰기도 하지만,
          단순 조회의 8할은 이 "이름 짓기"로 끝납니다.
        </p>
        <div className="tip">
          <b>주의할 점 하나</b> — 편한 만큼, JPA가 뒤에서 <strong>어떤 SQL을 만드는지</strong>
          모르면 느린 코드를 쓰게 돼요. 로그에 SQL을 찍어 보는 습관
          (<span className="icode">show-sql: true</span>)을 들이면, 편리함과 이해를 둘 다
          가져갈 수 있습니다.
        </div>
      </Section>

      <Section n={6} title="실습 — 우리 백엔드에 첫 API 추가하기" sub="읽었으면 이제 쓸 차례 (STUDY 과제 연계)">
        <p>
          지금까지 배운 걸 전부 씁니다. 컨트롤러 파일 하나를 새로 만들어서, 브라우저로 접속하면
          JSON 인사말이 돌아오는 API를 여는 거예요. 코드는 딱 이만큼입니다.
        </p>
        <Code>{CODE_PRACTICE_API}</Code>
        <div className="tip">
          <b>직접 확인해 보기</b> 백엔드 프로젝트를 열고 위 파일을 만든 뒤 서버를 실행하세요.
          브라우저에서 <span className="icode">localhost:8080/api/hello</span>를 열어 JSON이
          보이면 성공! 그다음 <span className="kbd">F12</span> → <span className="kbd">Network</span>
          탭에서 방금 요청의 <strong>Status 200</strong>과 응답 본문을 확인해 보세요.
          네트워크 코스에서 배운 "요청과 응답"을 이번엔 <strong>내가 만든 서버</strong>로 보는
          거예요.
        </div>
        <p>여기까지 됐다면, 한 걸음 더 나가 봅시다.</p>
        <Code>{CODE_PRACTICE_NEXT}</Code>
        <p>실습이 막힐 때 점검 순서는 이렇게 해요.</p>
        <ol className="olist">
          <li>서버가 켜져 있나요? 터미널에 에러 없이 <span className="icode">Started ...</span> 로그가 떴는지 확인.</li>
          <li>404가 나오면 — URL 오타이거나 <span className="icode">@GetMapping</span> 경로가 다른 거예요.</li>
          <li>500이 나오면 — 서버 터미널의 에러 로그를 <strong>위에서부터</strong> 읽으세요. 첫 줄에 답이 있어요.</li>
          <li>그래도 막히면 멘토에게 — 단, "안 돼요" 말고 <strong>"뭘 했고, 뭘 기대했고, 뭐가 나왔는지"</strong> 세 가지를 들고 가세요.</li>
        </ol>
      </Section>

      <Section n={7} title="정리 퀴즈 — 셀프 체크 5문항" sub="설명할 수 있어야 아는 것">
        <Code>{CODE_QUIZ}</Code>
        <div className="tip">
          <b>공부 팁</b> 퀴즈보다 좋은 복습은 <strong>우리 실제 코드 읽기</strong>예요.
          Gitea에서 백엔드 저장소를 열고, 아무 Controller나 골라 오늘 배운 어노테이션과
          계층 흐름을 찾아보세요. 교과서 예제가 아니라 <strong>지금 돌아가는 서비스</strong>가
          우리 교재입니다.
        </div>
      </Section>

      <div className="step-card">
        <div className="step-body">
          <h3 style={{ marginBottom: 6 }}>🌱 여기까지 왔다면</h3>
          <p className="muted">
            이제 스프링이 객체를 조립해 주는 원리(DI), 어노테이션 읽는 법, 요청이 세 층을
            여행하는 길, 설정과 JPA까지 — 우리 백엔드의 뼈대를 전부 훑었어요. 심지어 API도
            하나 만들었죠. 다음은 그 데이터가 잠드는 곳 —{' '}
            <Link to="/learn/sql"><strong>데이터베이스 기초</strong></Link> 코스에서
            PostgreSQL과 테이블 설계를 이어서 배우고, 실습에서 만든 API는{' '}
            <Link to="/assignments"><strong>STUDY 과제</strong></Link>로 제출해 멘토 리뷰를 받아
            보세요.
          </p>
        </div>
      </div>
    </div>
  );
}
