// 이 파일이 하는 일: "Swift 입문" 코스 — iOS(아이폰)를 움직이는 언어 Swift를,
// 이미 JavaScript/React를 배운 웹 개발자의 눈으로 읽어 내는 정적 학습 페이지.
// "지형부터 읽자"에서 출발해 let/var·타입, 옵셔널, 함수와 클로저, struct vs class,
// 프로토콜까지 7개 섹션으로, 네가 아는 JS/TS 지식을 다리 삼아 안내한다.
// 학습 포인트: API 호출이 없는 '내용 고정' 페이지다. 스타일은 global.css의
// 가이드 전용 클래스(step-card, code-block, tip 등)를 재사용한다 — 색을 여기서 하드코딩하지 않는다.
// 예제 코드는 JSX 중괄호/백틱 충돌을 피하려고 파일 상단의 백틱 문자열 상수로 정의한다.
// (우리 플랫폼엔 iOS 앱이 없다. 이 코스는 '앱까지 가는 길의 지도'를 손에 쥐는 것이 목표다.)

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

// ── 예제 코드 상수들 ──

const CODE_LANDSCAPE = `플랫폼마다 '공식 언어'가 다르다 — 문법보다 지형이 먼저

  웹 브라우저      →  JavaScript / TypeScript   ← 네가 지금 쓰는 것
  iOS (아이폰)     →  Swift        + SwiftUI / UIKit
  안드로이드        →  Kotlin / Java + Jetpack Compose
  양쪽 한 번에      →  React Native, Flutter     ← 바로 다음 코스!

Swift은 애플이 2014년에 내놓은 언어예요.
그전까지 iOS는 Objective-C라는, 대괄호가 잔뜩 붙는 옛날 언어를
썼는데, Swift은 '요즘 언어'의 편의(타입 추론·옵셔널·클로저)를
처음부터 담아 새로 설계됐습니다. 안전하고, 빠르고, 읽기 쉽게.

좋은 소식: 네가 아는 JS/TS 지식의 상당 부분이 그대로 옮겨져요.
낯선 부분이 이 코스의 주인공 — let/var, 옵셔널, 그리고 '값 타입'.`;

const CODE_LETVAR = `// let = 상수(바뀌지 않음),  var = 변수(바뀔 수 있음)
let name = "미림"        // JS의 const 와 같은 느낌
var age  = 18           // JS의 let  과 같은 느낌
age = 19                // OK
// name = "미마고"      // ❌ 컴파일 에러! let 은 재할당 불가

// 타입 추론: 위처럼 값을 주면 Swift가 타입을 알아서 안다.
// 명시하고 싶으면 콜론(:)으로 붙인다 — TypeScript 와 판박이.
let city: String  = "서울"
let score: Int    = 95
let ratio: Double = 3.14
let isMentor: Bool = false

// Swift는 타입에 엄격하다. 몰래 바꿔 주는 자동 형변환이 거의 없다.
let a = 3
let b = 2.0
// let c = a + b       // ❌ Int + Double 을 바로 못 더한다
let c = Double(a) + b  // ✅ 직접 변환해서 더한다  → 5.0

// 문자열에 값 끼우기(문자열 보간):
// JS는 백틱 문자열의 '달러+중괄호'였다면, Swift은 역슬래시+괄호.
print("이름 \\(name), 나이 \\(age)")   // 이름 미림, 나이 19`;

const CODE_OPTIONAL = `// 옵셔널 = "값이 없을 수도 있음(nil)"을 타입에 대놓고 표시
var nickname: String? = "미리내"   // String? = String 이거나 nil
nickname = nil                    // 언제든 '없음'이 될 수 있다

// 왜 이런 게 있나? JS의 악명 높은 런타임 버그:
//   Cannot read properties of null (reading 'count')
// 실행 도중에 '펑' 터진다. Swift은 이 위험을 컴파일 단계에서 막는다.
// nil 가능성이 있으면 반드시 물음표(?)로 표시하도록 강제하기 때문.

// ── 옵셔널을 안전하게 여는 방법 ──
// 1) if let : 값이 있으면 그 안으로 들어가 꺼내 쓴다
if let n = nickname {
    print("반가워, \\(n)")     // 이 안에서 n 은 순수 String (nil 아님)
} else {
    print("닉네임이 없어요")
}

// 2) guard let : 없으면 일찍 탈출, 있으면 아래로 쭉 (함수에서 애용)
func greet(_ name: String?) {
    guard let name = name else { return }
    print("안녕, \\(name)")     // 여기부턴 name 이 안전하게 String
}

// 3) ?? (nil 병합) : 없으면 기본값 — JS에도 있는 바로 그 ??
let shown = nickname ?? "손님"

// 4) ?. (옵셔널 체이닝) : 있으면 잇고, 없으면 통째로 nil — JS와 동일
let len = nickname?.count       // 타입은 Int? (nil일 수 있음)

// ⚠ 강제 언래핑 nickname!  — "무조건 값 있어!"라는 단언.
//    틀리면 앱이 그 자리에서 크래시. 입문 땐 되도록 피하자.`;

const CODE_FUNC_CLOSURE = `// 함수 — func 이름(인자: 타입) -> 반환타입
func add(_ a: Int, _ b: Int) -> Int {
    return a + b
}
add(3, 4)   // 7

// Swift 특징: '인자 라벨'. 호출할 때 이름을 붙여 문장처럼 읽히게 한다.
func power(base: Int, to exponent: Int) -> Int { /* ... */ }
power(base: 2, to: 10)      // "base 2, to 10" — 읽기 쉬움

// 클로저 = 이름 없는 함수 덩어리 (JS의 화살표 함수와 사촌지간)
//   JS:    const double = (x) => x * 2
//   Swift: let double = { (x: Int) -> Int in x * 2 }
let double = { (x: Int) -> Int in x * 2 }
double(21)   // 42

// 진짜 힘은 '함수에 함수를 넘길 때' 나온다 — map / filter
let nums = [1, 2, 3, 4]
let evens   = nums.filter { $0 % 2 == 0 }   // [2, 4]
let squared = nums.map    { $0 * $0 }       // [1, 4, 9, 16]

// $0 = 첫 번째 인자의 축약형. { n in n * n } 을 짧게 쓴 것.
// 중괄호가 마지막 인자면 소괄호 밖으로 빼는 '트레일링 클로저' 문법.
// React에서 배열.map()으로 목록을 그렸던 그 감각, 여기서도 그대로다.`;

const CODE_STRUCT_CLASS = `// struct = 값 타입(복사됨),  class = 참조 타입(공유됨) — 이게 최대 차이!

struct PointS { var x: Int; var y: Int }   // 멤버와이즈 초기화 공짜
class  PointC {
    var x: Int; var y: Int
    init(x: Int, y: Int) { self.x = x; self.y = y }   // 직접 써 줘야 함
}

// ── 값 타입: 대입하면 '복사본'이 생긴다 ──
var s1 = PointS(x: 1, y: 1)
var s2 = s1        // 통째로 복사
s2.x = 99
print(s1.x)        // 1   ← s1 은 그대로! (s1, s2 는 남남)

// ── 참조 타입: 대입하면 '같은 것'을 가리킨다 ──
let c1 = PointC(x: 1, y: 1)
let c2 = c1        // 같은 객체를 가리킴
c2.x = 99
print(c1.x)        // 99  ← c1 도 바뀐다! (c1, c2 는 한 몸)

// JS의 객체({})와 배열은 전부 참조 타입 — 위 class 쪽과 같은 동작.
// Swift은 struct(값)를 '기본'으로 권한다. 예상 못한 공유 버그가 줄어서다.
// SwiftUI의 화면 조각(View)도 전부 struct 로 만든다.`;

const CODE_PROTOCOL = `// 프로토콜 = "이런 기능을 갖춰야 한다"는 약속(계약).
// TypeScript의 interface, Java의 interface와 똑같은 자리.

protocol Greetable {
    var name: String { get }      // 이 프로퍼티를 가져야 하고
    func greet() -> String        // 이 함수를 구현해야 한다
}

// 채택(conform): 콜론 뒤에 프로토콜 이름을 적는다
struct Student: Greetable {
    let name: String
    func greet() -> String { "안녕, 나는 \\(name)" }
}

class Robot: Greetable {
    let name: String
    init(name: String) { self.name = name }
    func greet() -> String { "삐빅, \\(name) 가동" }
}

// 핵심: 타입이 struct든 class든, Greetable을 지키기만 하면
// 같은 자리에 바꿔 낄 수 있다 (다형성).
let crew: [Greetable] = [Student(name: "미림"), Robot(name: "T-800")]
for member in crew { print(member.greet()) }

// Swift 문화의 큰 축이 '프로토콜 지향(POP)' — 상속(is-a)보다
// "무엇을 할 수 있는가(can-do)"로 조립하는 사고방식이다.`;

const CODE_ROSETTA = `같은 개념, 다른 표기 — '번역표'로 머릿속에 얹기

 개념              JavaScript / TS       Swift
 ───────────────  ──────────────────   ──────────────────
 불변 / 가변       const / let          let / var
 타입 명시         let x: number        let x: Int
 없음(빈 값)       null / undefined     nil
 널 가능 표시      x: string | null     x: String?
 기본값 대체       x ?? "기본"          x ?? "기본"    (동일!)
 안전한 접근       obj?.prop            obj?.prop      (동일!)
 익명 함수         (x) => x * 2         { x in x * 2 }
 배열 변환         arr.map(f)           arr.map(f)     (거의 동일)
 인터페이스        interface            protocol
 객체(참조 공유)   {} · class           class
 값 타입(복사)      ―                    struct  ← Swift의 개성

읽는 법: 왼쪽(네가 아는 것)을 다리 삼아 오른쪽으로 건너가라.
정말 새로 익힐 건 맨 아래 두 줄 — '옵셔널'과 '값 타입 struct'뿐이다.`;

// ── 이 페이지 안에서만 쓰는 작은 부품들 ──
// 학습 포인트: 같은 모양이 반복되면 컴포넌트로 뽑는다. 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: '왜 Swift인가' },
  { n: 2, label: 'let / var' },
  { n: 3, label: '옵셔널' },
  { n: 4, label: '함수·클로저' },
  { n: 5, label: 'struct vs class' },
  { n: 6, label: '프로토콜' },
  { n: 7, label: '요약' },
];

export default function SwiftIntroPage() {
  return (
    <div>
      {/* 히어로: 웹 개발자의 눈으로 iOS의 언어를 읽는다 */}
      <div className="hero">
        <div className="eyebrow">Course · 앱 개발</div>
        <h1>Swift 입문<br />— iOS를 움직이는 언어</h1>
        <p>
          우리 회사의 화면은 웹(React)이에요. 아이폰 앱은 또 다른 대륙이고, 그 대륙의
          공식 언어가 <strong>Swift</strong>입니다. 2개월 만에 네이티브 앱 전문가가 되자는
          게 아니라 — <strong>이미 아는 JavaScript를 다리 삼아</strong> Swift의 지형을 읽고,
          "여기서 앱까지 어떻게 건너가는지" 그 지도를 손에 쥐는 게 목표예요.
        </p>
        <div className="chip-row">
          <span className="chip">예상 소요 70분</span>
          <span className="chip">실습: 문법 손코딩</span>
          <span className="chip">선수 지식: JS·React 기초</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="왜 Swift인가" sub="문법보다 지형이 먼저다">
        <p>
          프로그래밍 언어는 하나가 아니에요. <strong>플랫폼마다 '공식 언어'가 다릅니다.</strong>{' '}
          웹 브라우저는 자바스크립트, 안드로이드는 주로 Kotlin, 그리고{' '}
          <strong>아이폰(iOS)은 Swift</strong>. 우리가 매일 만지는 건 웹(React)이지만,
          "앱은 어떻게 만들지?"라는 질문에 답하려면 이 지형도부터 머릿속에 그려야 해요.
        </p>
        <Code>{CODE_LANDSCAPE}</Code>
        <p>
          Swift은 애플이 만든 <strong>비교적 최신 언어</strong>라, 네가 이미 아는 요즘 문법들(타입
          추론, <span className="icode">?.</span>, <span className="icode">??</span>, 화살표
          함수 같은 클로저)이 곳곳에 그대로 있어요. 그래서 이 코스는 "처음부터"가 아니라{' '}
          <strong>"JS와 뭐가 같고 뭐가 다른가"</strong>로 진행합니다.
        </p>
        <p>
          참고로 실제 iOS 앱은 애플의 개발 도구 <span className="icode">Xcode</span>(맥 전용)에서
          만들고, 거기서 <span className="kbd">⌘</span>+<span className="kbd">R</span>을 누르면
          아이폰 시뮬레이터로 앱이 실행돼요. 다만 이 코스는 <strong>도구가 아니라 언어 자체</strong>에
          집중합니다 — 문법의 눈을 먼저 갖추면, 도구는 그다음에 붙이면 되니까요.
        </p>
        <div className="tip">
          <b>미리 보는 큰 그림</b> 이 코스에서 정말 새로 배울 건 딱 두 개예요 —{' '}
          <strong>옵셔널</strong>(섹션 3)과 <strong>값 타입 struct</strong>(섹션 5).
          나머지는 아는 개념에 새 옷을 입히는 정도랍니다.
        </div>
      </Section>

      <Section n={2} title="변수 let / var 와 타입" sub="const/let 이 거의 그대로 옮겨온다">
        <p>
          Swift에서 값에 이름을 붙이는 방법은 둘이에요. <span className="icode">let</span>은{' '}
          <strong>상수</strong>(한 번 정하면 안 바뀜), <span className="icode">var</span>는{' '}
          <strong>변수</strong>(바뀔 수 있음). JS를 했다면 <span className="icode">const</span>와{' '}
          <span className="icode">let</span>이 그대로 이사 온 거라고 보면 돼요. 이름이 살짝
          헷갈리는데, <strong>JS의 <span className="icode">let</span> ≈ Swift의{' '}
          <span className="icode">var</span></strong>라는 점만 주의!
        </p>
        <Code>{CODE_LETVAR}</Code>
        <p>
          타입을 콜론으로 붙이는 <span className="icode">let score: Int = 95</span> 문법은
          TypeScript와 판박이예요. 값만 주면 Swift가 타입을 알아서 <strong>추론</strong>하지만,
          한 가지 크게 다른 점은 <strong>자동 형변환을 거의 안 해 준다</strong>는 것. JS는{' '}
          <span className="icode">3 + "2"</span>를 슬그머니 <span className="icode">"32"</span>로
          만들지만, Swift는 "타입 다른 걸 왜 섞어?"라며 컴파일 단계에서 딱 막아요.
        </p>
        <div className="tip">
          <b>습관 하나</b> 특별한 이유가 없으면 일단 <span className="icode">let</span>부터
          쓰세요. "이건 나중에 바꿔야 해"라는 확신이 설 때만 <span className="icode">var</span>로.
          바뀌지 않는 값을 상수로 못 박아 두면, 실수로 값이 변하는 버그 자체가 원천 봉쇄됩니다.
        </div>
      </Section>

      <Section n={3} title="옵셔널(Optional)" sub="nil 안전 — Kotlin의 그것과 형제다">
        <p>
          여기가 첫 번째 진짜 새로운 개념이에요. <strong>옵셔널</strong>은 "이 값은{' '}
          <span className="icode">nil</span>(비어 있음)일 수도 있다"는 사실을{' '}
          <strong>타입에 대놓고 표시</strong>하는 장치입니다. 타입 뒤에 물음표를 붙여{' '}
          <span className="icode">String?</span>이라고 쓰면 "String 이거나, 아니면 nil"이라는
          뜻이에요.
        </p>
        <Code>{CODE_OPTIONAL}</Code>
        <p>
          왜 이렇게까지 할까요? JS에서 <span className="icode">null</span>인 값의 속성을
          읽다가 앱이 <strong>실행 도중에 터지는</strong> 경험, 다들 한 번쯤 하죠. Swift은 그
          위험을 <strong>실행 전(컴파일 단계)에</strong> 잡아요. nil이 될 수 있는 값은 반드시{' '}
          <span className="icode">?</span>로 표시하고, 쓸 땐 반드시 <strong>안전하게 열도록</strong>{' '}
          강제하니까요. <span className="icode">if let</span>, <span className="icode">guard let</span>,{' '}
          <span className="icode">??</span>, <span className="icode">?.</span> — 이 네 가지가 여는 열쇠입니다.
        </p>
        <svg className="diagram" viewBox="0 0 640 240" xmlns="http://www.w3.org/2000/svg" role="img" aria-label="옵셔널 String 물음표는 값이거나 nil이다. if let, guard, nil 병합 물음표물음표, 옵셔널 체이닝 같은 방법으로 열면 안전하지만, 느낌표로 강제 언래핑하면 nil일 때 앱이 크래시한다">
          <rect x="46" y="90" width="150" height="58" rx="10" fill="var(--card)" stroke="var(--primary)" strokeWidth="2" />
          <text x="121" y="115" textAnchor="middle" fontSize="15" fontWeight="600" fill="var(--ink)">String?</text>
          <text x="121" y="136" textAnchor="middle" fontSize="12" fill="var(--muted)">값 또는 nil</text>
          <line x1="196" y1="106" x2="356" y2="62" stroke="var(--teal)" strokeWidth="2" />
          <path d="M362 59 L349 58 L354 70 Z" fill="var(--teal)" />
          <rect x="362" y="38" width="236" height="54" rx="10" fill="var(--card)" stroke="var(--teal)" strokeWidth="2" />
          <text x="480" y="61" textAnchor="middle" fontSize="13" fill="var(--ink)">if let · guard · ?? · ?.</text>
          <text x="480" y="80" textAnchor="middle" fontSize="12" fill="var(--muted)">안전하게 값 꺼내기 ✔</text>
          <line x1="196" y1="132" x2="356" y2="176" stroke="var(--rose)" strokeWidth="2" />
          <path d="M362 179 L349 180 L354 168 Z" fill="var(--rose)" />
          <rect x="362" y="150" width="236" height="54" rx="10" fill="var(--card)" stroke="var(--rose)" strokeWidth="2" />
          <text x="480" y="173" textAnchor="middle" fontSize="13" fill="var(--ink)">강제 언래핑  nickname!</text>
          <text x="480" y="192" textAnchor="middle" fontSize="12" fill="var(--muted)">nil이면 앱 크래시 ✘</text>
        </svg>
        <p className="muted" style={{ fontSize: 12.5, textAlign: 'center', marginTop: 2 }}>그림: 같은 옵셔널이라도 안전하게 열면(위·teal) 무사하고, 강제로 열면(아래·rose) nil일 때 앱이 멈춘다</p>
        <div className="tip">
          <b>Kotlin 아는 사람에게</b> 안드로이드의 Kotlin도 똑같은 널 안정성을 가져요.
          거의 1:1로 대응됩니다 — 널 가능 타입 <span className="icode">String?</span>(양쪽 동일),
          안전한 접근 <span className="icode">?.</span>(동일), 기본값은 Kotlin{' '}
          <span className="icode">?:</span>(엘비스) ↔ Swift <span className="icode">??</span>,
          그리고 위험한 강제는 Kotlin <span className="icode">!!</span> ↔ Swift{' '}
          <span className="icode">!</span>. 이름만 다른 같은 안전벨트예요.
        </div>
        <div className="warn">
          <b>느낌표(!)를 조심</b> 강제 언래핑 <span className="icode">nickname!</span>은 "여긴
          절대 nil 아냐!"라고 개발자가 책임지는 선언이에요. 그 약속이 틀리는 순간 앱이 그
          자리에서 죽습니다. 입문 단계에선 <span className="icode">if let</span>·
          <span className="icode">??</span>로 도는 습관을 먼저 들이세요.
        </div>
      </Section>

      <Section n={4} title="함수와 클로저" sub="화살표 함수를 아는 너에게">
        <p>
          함수는 <span className="icode">func 이름(인자: 타입) -&gt; 반환타입</span> 꼴이에요.
          JS와 다른 재미난 점은 <strong>'인자 라벨'</strong> — 호출할 때 인자에 이름을 붙여{' '}
          <span className="icode">power(base: 2, to: 10)</span>처럼 <strong>문장처럼 읽히게</strong>{' '}
          만듭니다. 순서를 헷갈릴 일이 줄죠.
        </p>
        <Code>{CODE_FUNC_CLOSURE}</Code>
        <p>
          <strong>클로저(closure)</strong>는 이름 없는 함수 덩어리예요. 네가 React에서 매일 쓰던{' '}
          <span className="icode">(x) =&gt; x * 2</span> 화살표 함수의 사촌이라고 보면 됩니다.
          진가는 <span className="icode">.map()</span>·<span className="icode">.filter()</span>처럼{' '}
          <strong>함수에 함수를 넘길 때</strong> 나와요. React에서 배열을{' '}
          <span className="icode">.map()</span>으로 목록 UI로 바꿨던 그 감각이, Swift에서도
          거의 똑같이 통합니다.
        </p>
        <div className="tip">
          <b>$0 이 뭐죠?</b> <span className="icode">nums.map {'{ $0 * $0 }'}</span>에서{' '}
          <span className="icode">$0</span>은 "첫 번째 인자"의 축약이에요.{' '}
          <span className="icode">{'{ n in n * n }'}</span>이라고 이름 붙여 쓴 것을 짧게
          줄인 것뿐. 그리고 클로저가 마지막 인자면 소괄호 밖으로 빼서 뒤에 붙이는{' '}
          <strong>트레일링 클로저</strong> 문법이라, 괄호가 사라져 더 짧아 보이는 거예요.
        </div>
      </Section>

      <Section n={5} title="구조체(struct) vs 클래스(class)" sub="복사되는 값 vs 공유되는 참조">
        <p>
          Swift엔 데이터를 담는 그릇이 둘 있어요 — <span className="icode">struct</span>와{' '}
          <span className="icode">class</span>. 문법은 비슷해 보이지만 <strong>결정적으로 다른
          한 가지</strong>가 있습니다. <strong>struct는 값 타입(대입하면 복사됨)</strong>,{' '}
          <strong>class는 참조 타입(대입하면 같은 것을 공유함)</strong>이에요.
        </p>
        <Code>{CODE_STRUCT_CLASS}</Code>
        <p>
          JS만 하던 사람에겐 <strong>struct의 '복사' 동작이 낯설어요.</strong> JS에서 객체를
          다른 변수에 넣으면 둘은 <strong>같은 객체</strong>를 가리켜서(참조), 한쪽을 고치면
          다른 쪽도 바뀌었죠 — 그게 바로 Swift의 <span className="icode">class</span>와 같은
          동작입니다. 반면 <span className="icode">struct</span>는 대입하는 순간 <strong>각자
          독립된 복사본</strong>이 돼서, 서로 영향을 주지 않아요.
        </p>
        <svg className="diagram" viewBox="0 0 640 220" xmlns="http://www.w3.org/2000/svg" role="img" aria-label="struct 값 타입은 s1과 s2가 각자 다른 상자를 가져 s2를 바꿔도 s1은 그대로다. class 참조 타입은 c1과 c2가 같은 상자 하나를 가리켜 c2를 바꾸면 c1도 함께 바뀐다">
          <text x="165" y="26" textAnchor="middle" fontSize="14" fontWeight="600" fill="var(--ink)">struct — 값 타입 (복사)</text>
          <rect x="70" y="46" width="80" height="34" rx="8" fill="var(--card)" stroke="var(--teal)" strokeWidth="2" />
          <text x="110" y="68" textAnchor="middle" fontSize="13" fill="var(--ink)">s1</text>
          <rect x="180" y="46" width="80" height="34" rx="8" fill="var(--card)" stroke="var(--teal)" strokeWidth="2" />
          <text x="220" y="68" textAnchor="middle" fontSize="13" fill="var(--ink)">s2</text>
          <line x1="110" y1="80" x2="110" y2="112" stroke="var(--line)" strokeWidth="2" />
          <path d="M110 120 L104 108 L116 108 Z" fill="var(--line)" />
          <line x1="220" y1="80" x2="220" y2="112" stroke="var(--line)" strokeWidth="2" />
          <path d="M220 120 L214 108 L226 108 Z" fill="var(--line)" />
          <rect x="66" y="120" width="88" height="40" rx="8" fill="var(--card)" stroke="var(--line)" />
          <text x="110" y="145" textAnchor="middle" fontSize="13" fill="var(--ink)">x = 1</text>
          <rect x="176" y="120" width="88" height="40" rx="8" fill="var(--card)" stroke="var(--line)" />
          <text x="220" y="145" textAnchor="middle" fontSize="13" fill="var(--ink)">x = 99</text>
          <text x="165" y="188" textAnchor="middle" fontSize="12" fill="var(--muted)">각자 다른 상자 — s2를 바꿔도 s1.x 는 1</text>
          <line x1="320" y1="36" x2="320" y2="196" stroke="var(--line)" strokeWidth="1" strokeDasharray="4 4" />
          <text x="475" y="26" textAnchor="middle" fontSize="14" fontWeight="600" fill="var(--ink)">class — 참조 타입 (공유)</text>
          <rect x="392" y="46" width="80" height="34" rx="8" fill="var(--card)" stroke="var(--amber)" strokeWidth="2" />
          <text x="432" y="68" textAnchor="middle" fontSize="13" fill="var(--ink)">c1</text>
          <rect x="490" y="46" width="80" height="34" rx="8" fill="var(--card)" stroke="var(--amber)" strokeWidth="2" />
          <text x="530" y="68" textAnchor="middle" fontSize="13" fill="var(--ink)">c2</text>
          <line x1="432" y1="80" x2="462" y2="112" stroke="var(--line)" strokeWidth="2" />
          <path d="M468 118 L455 116 L462 106 Z" fill="var(--line)" />
          <line x1="530" y1="80" x2="500" y2="112" stroke="var(--line)" strokeWidth="2" />
          <path d="M494 118 L500 106 L507 116 Z" fill="var(--line)" />
          <rect x="435" y="120" width="94" height="40" rx="8" fill="var(--card)" stroke="var(--amber)" strokeWidth="2" />
          <text x="482" y="145" textAnchor="middle" fontSize="13" fill="var(--ink)">x = 99</text>
          <text x="475" y="188" textAnchor="middle" fontSize="12" fill="var(--muted)">같은 상자 하나 — c2를 바꾸면 c1.x 도 99</text>
        </svg>
        <p className="muted" style={{ fontSize: 12.5, textAlign: 'center', marginTop: 2 }}>그림: struct는 대입 때 복사돼 서로 남남, class는 같은 상자를 가리켜 한 몸으로 움직인다</p>
        <div className="tip">
          <b>고를 때 기준</b> Swift 문화는 <strong>일단 struct</strong>를 권해요. 복사되니까
          "저쪽에서 몰래 바꿔 놨네?" 하는 공유 버그가 줄거든요. 상속이 꼭 필요하거나, 여러
          곳이 하나의 상태를 <strong>일부러 공유</strong>해야 할 때만 class. 참고로 SwiftUI의
          화면 조각(<span className="icode">View</span>)은 전부 struct랍니다.
        </div>
      </Section>

      <Section n={6} title="프로토콜 맛보기" sub="interface 자리에 앉는 '계약'">
        <p>
          <strong>프로토콜(protocol)</strong>은 "이런 프로퍼티와 기능을 갖춰야 한다"고 정해
          두는 <strong>약속(계약)</strong>이에요. TypeScript의 <span className="icode">interface</span>,
          Java의 <span className="icode">interface</span>와 정확히 같은 자리에 앉습니다. 무엇을
          할지만 정하고, 어떻게 할지는 <strong>채택하는 쪽</strong>이 채워 넣어요.
        </p>
        <Code>{CODE_PROTOCOL}</Code>
        <p>
          멋진 점은 <strong>struct든 class든 상관없이</strong> 같은 프로토콜을 지키기만 하면
          같은 자리에 바꿔 낄 수 있다는 거예요(다형성). 위 예제에서{' '}
          <span className="icode">Student</span>(struct)와 <span className="icode">Robot</span>(class)이
          한 배열에 나란히 들어가 똑같이 <span className="icode">greet()</span>로 불리죠. Swift은
          이렇게 <strong>"무엇을 할 수 있는가"로 조립</strong>하는 방식을 특히 좋아해서,{' '}
          <strong>프로토콜 지향 프로그래밍(POP)</strong>이라는 이름까지 붙어 있어요.
        </p>
        <div className="tip">
          <b>TS의 interface를 떠올려요</b> 우리 <span className="icode">admin-web</span> 같은
          TypeScript 코드에서 <span className="icode">interface Props {'{ ... }'}</span>로 "이
          컴포넌트가 받을 값의 모양"을 정했던 그 감각 그대로예요. 프로토콜은 거기에 "가져야 할
          동작(함수)"까지 담을 수 있는, 조금 더 힘센 계약서라고 보면 됩니다.
        </div>
      </Section>

      <Section n={7} title="다른 언어 아는 사람을 위한 요약" sub="번역표 한 장으로 정리">
        <p>
          긴 설명을 한 장으로 압축해 볼게요. 아래 <strong>번역표</strong>는 네가 이미 아는{' '}
          JS/TS 표현을 왼쪽에, 대응하는 Swift 표현을 오른쪽에 둔 거예요. 새 언어를 "처음부터"
          외우지 말고, <strong>아는 것에서 다리를 놓아</strong> 건너가세요.
        </p>
        <Code>{CODE_ROSETTA}</Code>
        <p>
          보다시피 대부분은 <strong>표기만 다른 같은 개념</strong>이에요.{' '}
          <span className="icode">??</span>와 <span className="icode">?.</span>는 아예 똑같고,{' '}
          <span className="icode">.map()</span>도 거의 그대로죠. 정말 새로 몸에 익힐 건 딱
          두 줄 — <strong>옵셔널(값이 없을 수 있음을 타입으로 표현)</strong>과{' '}
          <strong>값 타입 struct(대입하면 복사)</strong>. 이 둘만 손에 익으면 Swift 코드가
          '읽히기' 시작합니다.
        </p>
        <div className="warn">
          <b>과욕은 금물</b> 이 코스는 "2개월에 iOS 앱 전문가"를 약속하지 않아요. 그건 거짓말이니까요.
          목표는 <strong>지형을 읽는 것</strong> — Swift 코드를 봤을 때 겁먹지 않고, "아, 이건
          옵셔널이고 저건 클로저구나" 알아보는 눈. 그 눈이 있으면, 앱까지 가는 길은 네 실력으로
          차근차근 이어 갈 수 있어요.
        </div>
        <div className="tip">
          <b>손으로 굳히기</b> 온라인 Swift 놀이터(<span className="icode">Swift Playgrounds</span>나
          웹 기반 <span className="icode">play.swift.org</span>)에 위 예제를 그대로 쳐 보세요.{' '}
          <span className="icode">let</span>을 재할당해서 에러를 직접 보고,{' '}
          <span className="icode">struct</span>를 복사해 한쪽만 바뀌는 걸 눈으로 확인 —
          '읽어서 아는 것'과 '쳐 봐서 아는 것'은 전혀 다르답니다.
        </div>
      </Section>

      <div className="step-card">
        <div className="step-body">
          <h3 style={{ marginBottom: 6 }}>🍎 여기까지 왔다면</h3>
          <p className="muted">
            이제 Swift 코드를 만나도 <strong>let/var·옵셔널·클로저·struct·프로토콜</strong>이라는
            다섯 단어로 지형을 읽을 수 있게 됐어요. 그런데 아이폰 앱을 만들려고 Swift를,
            안드로이드 앱을 만들려고 Kotlin을 <strong>따로</strong> 배워야 한다면 좀 억울하죠?
            바로 그 지점에서 <strong>네가 이미 아는 React</strong>로 iOS·안드로이드 앱을 한 번에
            만드는 길이 열립니다 —{' '}
            <Link to="/learn/react-native"><strong>React Native</strong></Link> 코스에서, 오늘 읽은
            네이티브의 지형 위에 네 실력으로 다리를 놓아 보세요.
          </p>
        </div>
      </div>
    </div>
  );
}
