// 이 파일이 하는 일: "안드로이드 앱의 구조" 코스 — 안드로이드가 무엇으로 이뤄지고
// 어떻게 도는지를, 학생이 이미 배운 React/JS 지식을 다리 삼아 7개 섹션으로 안내하는
// 정적 학습 페이지. 오픈소스·기기 다양성에서 출발해 Activity·Intent·생명주기·화면
// 만들기(XML vs Compose)·스튜디오/에뮬레이터·권한/Manifest, 그리고 "웹 개발자가
// 첫 안드로이드 앱으로 가는 길"까지 이어진다.
// 학습 포인트: API 호출이 없는 '내용 고정' 페이지다. 스타일은 global.css의 가이드 전용
// 클래스(step-card, code-block, tip, warn 등)를 재사용한다 — 색을 여기서 하드코딩하지 않는다.
// 예제 코드는 JSX 중괄호/백틱 충돌을 피하려고 파일 상단의 백틱 문자열 상수로 정의한다.
// 프레이밍: "2개월에 네이티브 전문가"가 아니라 "지형을 읽고 내 실력으로 앱까지 가는 길을 아는" 것.

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

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

const CODE_STACK = `안드로이드는 '층층이 쌓은 케이크'예요 (오픈소스 프로젝트 AOSP)

┌───────────────────────────────────────┐
│  앱들 (내 앱, 카카오톡, 크롬 ...)          │ ← 우리가 만드는 층
├───────────────────────────────────────┤
│  앱 프레임워크 (Activity, 알림, 화면 ...)  │ ← 미리 준비된 부품 상자
├───────────────────────────────────────┤
│  런타임(ART) + 시스템 라이브러리           │ ← 내 코드가 실제로 도는 곳
├───────────────────────────────────────┤
│  리눅스 커널 (드라이버, 메모리, 전원 ...)   │ ← 하드웨어와의 통역사
└───────────────────────────────────────┘

- 맨 아래 바탕이 '리눅스'예요. (리눅스 기초 코스에서 본 바로 그 커널!)
- 소스가 공개(AOSP)라 삼성·샤오미·구글이 각자 고쳐 씁니다
  → 화면 크기·OS 버전·제조사가 천차만별. "기기 파편화"라 불러요.
- 앱 언어는 Kotlin(구글이 미는 1순위) 또는 Java.
  우리 백엔드가 Java라, 중괄호·세미콜론·클래스 문법이 이미 눈에 익습니다.`;

const CODE_ACTIVITY = `// Activity = 화면 '한 장'. 앱은 액티비티 여러 장을 넘겨 보는 묶음이에요.
class MainActivity : AppCompatActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)   // 이 화면이 보여줄 레이아웃
    }
}

// Intent = 화면과 화면을 잇는 '심부름 쪽지' (어디로 갈지 + 무엇을 들고 갈지)
val intent = Intent(this, DetailActivity::class.java)
intent.putExtra("courseId", 42)   // 다음 화면에 데이터 전달
startActivity(intent)             // 상세 화면으로 이동!

// 웹으로 치면 <Link to="/course/42"> 와 비슷 — 화면 전환 + 파라미터 전달.
// Activity가 '방'이라면 Intent는 "이 방으로 가 주세요" 하고 내미는 쪽지예요.`;

const CODE_LIFECYCLE = `액티비티 생명주기 ↔ 웹 페이지, 나란히 놓고 보기

안드로이드 (Activity)              웹 (브라우저 탭/React 컴포넌트)
──────────────────────         ──────────────────────
onCreate()  최초 생성 · 1회        컴포넌트 mount / DOMContentLoaded
onStart()   화면에 보이기 시작       (탭이 보이기 시작)
onResume()  포커스 · 입력 받음       visibilitychange → visible
── 사용자와 상호작용 중 ──          ── 사용자와 상호작용 중 ──
onPause()   곧 가려짐 · 저장 시점     visibilitychange → hidden
onStop()    완전히 안 보임          (다른 탭으로 전환)
onDestroy() 메모리에서 제거         컴포넌트 unmount / beforeunload

핵심 차이: 웹은 대개 '열고 닫기'가 단순하지만, 안드로이드는 전화가 오고,
화면을 돌리고, 홈으로 나갔다 돌아오는 일이 잦아 onPause↔onResume이 수시로 오갑니다.
그래서 "onPause에서 저장하고 onResume에서 복구"가 앱의 기본 예절이에요.`;

const CODE_XML = `<!-- XML 레이아웃 — res/layout/activity_main.xml (명령형에 가까운 옛 방식) -->
<Button
    android:id="@+id/likeBtn"
    android:text="좋아요 0" />

// 코드에서 그 버튼을 '찾아서' 직접 손으로 바꿔 줌 (React 이전의 그 느낌!)
val btn = findViewById<Button>(R.id.likeBtn)
var count = 0
btn.setOnClickListener {
    count++
    btn.text = "좋아요 " + count   // 내가 일일이 화면을 수정한다
}`;

const CODE_COMPOSE = `// Jetpack Compose — 선언형 UI. 우리 React와 발상이 판박이예요!
@Composable
fun LikeButton() {
    var count by remember { mutableStateOf(0) }   // ← React의 useState 느낌

    Button(onClick = { count++ }) {               // 상태만 바꾸면
        Text("좋아요 " + count)                    // 화면은 알아서 다시 그려짐
    }
}

// React:  화면 = f(상태)      →  setCount(1) 하면 다시 렌더
// Compose: 화면 = f(상태)      →  count 바뀌면 '재구성(recomposition)'
// XML은 "글자를 찾아 바꿔"(명령형), Compose는 "상태가 이러면 이렇게 생겨야 해"(선언형).`;

const CODE_STUDIO = `안드로이드 스튜디오 = 앱 개발용 '통합 작업실' (IntelliJ 기반)

에디터           코드 작성·자동완성 (IntelliJ 코스에서 만진 그 IDE 계열!)
Gradle          빌드 도구 — 소스 코드를 설치 파일(APK / AAB)로 조립
에뮬레이터(AVD)   내 PC 안에 뜨는 '가짜 안드로이드 폰'
Logcat          앱이 뱉는 로그 창 (웹의 F12 콘솔에 해당)
Preview         화면을 실행 없이 눈으로 미리 확인

# 개발 한 바퀴
1) 에뮬레이터(가상 폰) 실행  또는  실제 폰 USB 연결 + 개발자 옵션 켜기
2) ▶ Run  →  Gradle 빌드  →  폰/에뮬에 설치  →  앱 실행
3) Logcat으로 로그 보며 고치고 다시 Run (웹의 '저장 → 새로고침'과 닮은 리듬)

# adb — 폰과 대화하는 명령줄 도구 (터미널 코스의 CLI 감각 그대로)
adb devices            # 연결된 기기 목록 보기
adb install app.apk    # 앱 설치
adb logcat             # 로그 실시간으로 흘려보기`;

const CODE_MANIFEST = `<!-- AndroidManifest.xml — 앱의 '주민등록증 + 권한 신청서' -->
<manifest ...>

    <!-- 이 앱이 쓰겠다고 '선언'하는 권한들 -->
    <uses-permission android:name="android.permission.INTERNET" />
    <uses-permission android:name="android.permission.CAMERA" />

    <application android:label="미림앱" android:icon="@mipmap/ic_launcher">
        <!-- 앱을 켜면 처음 뜨는 화면(런처 액티비티)을 지정 -->
        <activity android:name=".MainActivity">
            <intent-filter>
                <action   android:name="android.intent.action.MAIN" />
                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
    </application>
</manifest>`;

const CODE_RUNTIME_PERM = `// 위험 권한(카메라·위치·연락처 등)은 '선언'만으론 부족!
// 안드로이드 6.0(API 23)부터는 실행 중에 사용자에게 직접 물어봐야 해요.
if (checkSelfPermission(Manifest.permission.CAMERA) != PERMISSION_GRANTED) {
    requestPermissions(arrayOf(Manifest.permission.CAMERA), REQ_CAMERA)
    // → 화면에 "이 앱이 카메라에 접근하도록 허용하시겠어요?" 팝업이 뜸
}

// INTERNET 같은 '일반 권한'은 설치 시 자동 허용, 팝업 없음.
// CAMERA·위치 같은 '위험 권한'만 실행 중에 물어봐요. 최소한만 신청하는 게 예의!`;

const CODE_PATH = `웹 개발자가 안드로이드로 가는 세 갈래 길

A. React Native / Expo   ← 지금 실력에서 가장 가까운 다리
   · 언어: JavaScript/TypeScript + React (이미 배운 것!)
   · 화면: <View> <Text> 같은 React 컴포넌트로 iOS·안드 동시에
   · 한 코드로 두 OS. '웹 지식 재사용'이 최대 강점.

B. Kotlin + Jetpack Compose   ← 정통 네이티브, 성능·기기기능 최대
   · 선언형 UI라 "화면 = f(상태)" React 감각이 그대로 통함
   · 카메라·센서·알림 등 안드로이드의 모든 기능에 직접 접근. 구글의 정공법.

C. WebView / PWA(하이브리드)   ← 기존 웹을 '앱 껍데기'에 담기
   · 만든 웹을 앱처럼 포장. 시작은 빠르지만 네이티브 느낌·성능은 제한적.

우리 상황에 맞는 현실 판단
  · 백엔드는 그대로! 앱은 우리 Spring API(/api/...)를 부르는 '또 다른 손님'일 뿐.
    화면 기술만 바뀌고, 서버는 웹이든 앱이든 똑같이 JSON으로 응답해요.
  · 2개월 만에 '네이티브 전문가'는 무리 — 목표는 '지형 읽기'.
    Compose로 화면 하나 만들고, 그 화면에서 API 한 번 호출까지가 현실적인 첫 봉우리.`;

// ── 이 페이지 안에서만 쓰는 작은 부품들 ──
// 학습 포인트: 같은 모양이 반복되면 컴포넌트로 뽑는다. props(n·title·sub)만 바꿔 재사용.
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: '구성요소·Intent' },
  { n: 3, label: '생명주기' },
  { n: 4, label: '화면 만들기' },
  { n: 5, label: '스튜디오·에뮬' },
  { n: 6, label: '권한·Manifest' },
  { n: 7, label: '첫 앱으로 가는 길' },
];

export default function AndroidBasicsPage() {
  return (
    <div>
      {/* 히어로: 이 코스가 어디서 출발해 어디까지 가는지 */}
      <div className="hero">
        <div className="eyebrow">Course · 앱 개발</div>
        <h1>안드로이드 앱의 구조<br />— 웹 개발자가 보는 모바일</h1>
        <p>
          우리 회사 스택은 React 프론트 + Spring Boot 백엔드예요. 그런데 스마트폰 앱은
          어떻게 다를까요? 이 코스는 <strong>이미 배운 React/JS 지식을 다리 삼아</strong>{' '}
          안드로이드가 무엇으로 이뤄지고 어떻게 도는지를 읽습니다. 목표는 "2개월에 네이티브
          전문가"가 아니라 <strong>지형을 읽고, 내 실력으로 앱까지 가는 길을 아는 것</strong>이에요.
        </p>
        <div className="chip-row">
          <span className="chip">예상 소요 70분</span>
          <span className="chip">둘러보기 실습 2개</span>
          <span className="chip">선수 지식: React·HTTP 기초</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>예요. 정식 이름은{' '}
          <span className="icode">AOSP</span>(Android Open Source Project). 바탕에{' '}
          <strong>리눅스 커널</strong>이 깔려 있고 — 그래서 리눅스 코스에서 배운 프로세스·파일·권한
          개념이 여기서도 통합니다 — 그 위에 앱을 위한 부품들이 층층이 쌓여 있습니다.
        </p>
        <Code>{CODE_STACK}</Code>
        <p>
          소스가 공개돼 있다 보니 삼성·샤오미·구글 폰이 저마다 조금씩 다르고, 화면 크기와 OS
          버전도 제각각이에요. 이걸 <strong>기기 파편화(fragmentation)</strong>라고 부릅니다.
          웹에서 "크롬·사파리·모바일 화면을 다 신경 써야 하는" 상황과 똑같은 고민이, 앱에서는
          한층 더 크게 나타나는 셈이죠.
        </p>
        <div className="tip">
          <b>이미 아는 것과 잇기</b> 앱 언어는 <span className="icode">Kotlin</span>(구글 권장)
          또는 <span className="icode">Java</span>예요. 우리 백엔드가 Java라 클래스·중괄호·타입
          같은 뼈대가 낯설지 않습니다. Kotlin은 Java와 100% 함께 쓸 수 있는 "더 간결해진 사촌"
          정도로 생각하면 시작이 편해요.
        </div>
      </Section>

      <Section n={2} title="앱의 구성요소와 Intent" sub="Activity = 화면 한 장, Intent = 화면 사이의 쪽지">
        <p>
          안드로이드 앱은 하나의 거대한 프로그램이 아니라 <strong>정해진 부품(컴포넌트)들의
          조합</strong>이에요. 대표 부품이 넷인데 — <strong>Activity</strong>(화면),{' '}
          <strong>Service</strong>(백그라운드 작업, 예: 음악 재생),{' '}
          <strong>BroadcastReceiver</strong>(시스템 알림 수신, 예: 배터리 부족),{' '}
          <strong>ContentProvider</strong>(앱끼리 데이터 공유) — 그중 초보가 가장 먼저,
          가장 많이 만지는 게 <strong>Activity</strong>입니다.
        </p>
        <p>
          <strong>Activity는 "화면 한 장"</strong>이에요. 로그인 화면, 코스 목록 화면, 상세
          화면 — 각각이 액티비티 하나라고 보면 됩니다. 우리 React 앱에서{' '}
          <span className="icode">pages/</span> 폴더의 페이지 컴포넌트 하나하나가 화면 한 장이었죠?
          거의 그 대응이에요.
        </p>
        <Code>{CODE_ACTIVITY}</Code>
        <p>
          화면과 화면을 잇는 <strong>Intent</strong>는 "이 화면으로 가 주세요"라고 시스템에
          내미는 <strong>쪽지</strong>입니다. 어디로 갈지(대상)와 무엇을 들고 갈지(데이터)를
          담아 <span className="icode">startActivity()</span>로 보내죠. 웹으로 치면{' '}
          <span className="icode">&lt;Link to="/course/42" /&gt;</span>로 페이지를 옮기며
          파라미터를 넘기는 것과 같은 역할이에요.
        </p>
        <div className="tip">
          <b>한 문장 요약</b> "앱 = 액티비티(화면)들의 묶음, 이동은 Intent(쪽지)로."
          이 한 줄만 쥐고 있어도 안드로이드 코드의 절반은 길을 잃지 않아요.
        </div>
      </Section>

      <Section n={3} title="액티비티 생명주기" sub="화면은 태어나고, 가려지고, 사라진다 — 웹 페이지와 비교">
        <p>
          웹 페이지는 열리고(load) 닫히죠(unload). 액티비티도 비슷하게{' '}
          <strong>태어나서(onCreate) 보이고(onResume) 가려졌다(onPause) 사라지는(onDestroy)</strong>{' '}
          일생을 삽니다. 안드로이드는 이 각 순간마다 정해진 함수(콜백)를 자동으로 불러 줘요.
          우리는 "그 순간에 무엇을 할지"만 채워 넣으면 됩니다.
        </p>
        <Code>{CODE_LIFECYCLE}</Code>
        <svg className="diagram" viewBox="0 0 640 440" xmlns="http://www.w3.org/2000/svg" role="img" aria-label="액티비티 생명주기 사다리: onCreate에서 onStart, onResume을 거쳐 사용자와 상호작용하는 활성 상태로 갔다가 onPause, onStop, onDestroy로 내려온다. onStop에서 화면으로 돌아오면 onRestart를 거쳐 다시 onStart로 올라간다.">
          {/* 세로 연결선 + 화살표 (아래로 흐름) */}
          <line x1="320" y1="54" x2="320" y2="74" stroke="var(--line)" strokeWidth="2" />
          <path d="M320 80 L314 68 L326 68 Z" fill="var(--line)" />
          <line x1="320" y1="114" x2="320" y2="134" stroke="var(--line)" strokeWidth="2" />
          <path d="M320 140 L314 128 L326 128 Z" fill="var(--line)" />
          <line x1="320" y1="174" x2="320" y2="194" stroke="var(--line)" strokeWidth="2" />
          <path d="M320 200 L314 188 L326 188 Z" fill="var(--line)" />
          <line x1="320" y1="234" x2="320" y2="254" stroke="var(--line)" strokeWidth="2" />
          <path d="M320 260 L314 248 L326 248 Z" fill="var(--line)" />
          <line x1="320" y1="294" x2="320" y2="314" stroke="var(--line)" strokeWidth="2" />
          <path d="M320 320 L314 308 L326 308 Z" fill="var(--line)" />
          <line x1="320" y1="354" x2="320" y2="374" stroke="var(--line)" strokeWidth="2" />
          <path d="M320 380 L314 368 L326 368 Z" fill="var(--line)" />
          {/* onRestart 되돌이 경로 (onStop → onStart) */}
          <polyline points="220,337 150,337 150,97 218,97" fill="none" stroke="var(--rose)" strokeWidth="2" strokeDasharray="5 4" />
          <path d="M226 97 L214 91 L214 103 Z" fill="var(--rose)" />
          <text x="144" y="213" textAnchor="middle" fontSize="12" fill="var(--rose)" transform="rotate(-90 144 213)">다시 화면으로 → onRestart()</text>
          {/* 상태 박스들 */}
          <rect x="220" y="20" width="200" height="34" rx="8" fill="var(--card)" stroke="var(--primary)" strokeWidth="2" />
          <text x="320" y="42" textAnchor="middle" fontSize="13" fontWeight="600" fill="var(--ink)">onCreate()</text>
          <text x="440" y="42" textAnchor="start" fontSize="12" fill="var(--muted)">레이아웃 붙이기 · 1회만</text>
          <rect x="220" y="80" width="200" height="34" rx="8" fill="var(--card)" stroke="var(--line)" />
          <text x="320" y="102" textAnchor="middle" fontSize="13" fill="var(--ink)">onStart()</text>
          <text x="440" y="102" textAnchor="start" fontSize="12" fill="var(--muted)">화면에 보이기 시작</text>
          <rect x="220" y="140" width="200" height="34" rx="8" fill="var(--card)" stroke="var(--line)" />
          <text x="320" y="162" textAnchor="middle" fontSize="13" fill="var(--ink)">onResume()</text>
          <text x="440" y="162" textAnchor="start" fontSize="12" fill="var(--muted)">터치 입력 받음</text>
          <rect x="220" y="200" width="200" height="34" rx="8" fill="var(--card)" stroke="var(--teal)" strokeWidth="2" />
          <text x="320" y="222" textAnchor="middle" fontSize="13" fontWeight="600" fill="var(--ink)">화면 활성 · 사용 중</text>
          <text x="440" y="222" textAnchor="start" fontSize="12" fill="var(--muted)">사용자와 대화 중</text>
          <rect x="220" y="260" width="200" height="34" rx="8" fill="var(--card)" stroke="var(--amber)" strokeWidth="2" />
          <text x="320" y="282" textAnchor="middle" fontSize="13" fill="var(--ink)">onPause()</text>
          <text x="440" y="282" textAnchor="start" fontSize="12" fill="var(--muted)">곧 가려짐 · 저장 시점</text>
          <rect x="220" y="320" width="200" height="34" rx="8" fill="var(--card)" stroke="var(--line)" />
          <text x="320" y="342" textAnchor="middle" fontSize="13" fill="var(--ink)">onStop()</text>
          <text x="440" y="342" textAnchor="start" fontSize="12" fill="var(--muted)">완전히 안 보임</text>
          <rect x="220" y="380" width="200" height="34" rx="8" fill="var(--card)" stroke="var(--rose)" strokeWidth="2" />
          <text x="320" y="402" textAnchor="middle" fontSize="13" fill="var(--ink)">onDestroy()</text>
          <text x="440" y="402" textAnchor="start" fontSize="12" fill="var(--muted)">메모리에서 정리</text>
        </svg>
        <p className="muted" style={{ fontSize: 12.5, textAlign: 'center', marginTop: 2 }}>그림: 액티비티 생명주기 사다리 — 생성(onCreate)에서 활성으로 올랐다 소멸(onDestroy)로 내려오고, 화면으로 돌아오면 onRestart로 되돌아 올라간다</p>
        <div className="warn">
          <b>초보 함정: 화면 회전</b> 폰을 가로로 돌리면 안드로이드는 액티비티를{' '}
          <span className="icode">onDestroy()</span> 후 <span className="icode">onCreate()</span>로
          <strong> 통째로 다시 만들어요</strong>. 그래서 변수에만 담아 둔 값은 회전하는 순간
          사라집니다. "화면이 언제든 재생성될 수 있다"는 전제 위에서, 중요한 값은 저장해 두는
          습관이 필요해요 — React에서 새로고침하면 state가 초기화되던 것과 같은 결이에요.
        </div>
      </Section>

      <Section n={4} title="화면 만들기 — XML vs Jetpack Compose" sub="명령형 옛 방식과, React를 닮은 선언형 새 방식">
        <p>
          화면을 그리는 방식은 크게 둘이에요. 오래된 방식은{' '}
          <strong>XML 레이아웃</strong> — <span className="icode">res/layout/</span> 폴더에 화면
          구조를 XML로 적고, 코드에서 <span className="icode">findViewById</span>로 그 요소를
          '찾아서' 손으로 바꾸는 <strong>명령형</strong> 스타일입니다. HTML을 만들어 두고
          순수 자바스크립트로 <span className="icode">document.getElementById</span> 해서 글자를
          바꾸던, 딱 그 느낌이죠.
        </p>
        <Code>{CODE_XML}</Code>
        <p>
          요즘 구글이 미는 새 방식은 <strong>Jetpack Compose</strong>예요. Kotlin 함수 하나가
          화면 조각이 되고(<span className="icode">@Composable</span>), <strong>상태가 바뀌면 그
          부분이 자동으로 다시 그려집니다.</strong> 어디서 많이 본 발상이죠? 맞아요 —{' '}
          <strong>우리 React의 "화면 = 상태의 함수"와 똑같습니다.</strong>
        </p>
        <Code>{CODE_COMPOSE}</Code>
        <div className="tip">
          <b>React를 배운 게 그대로 무기</b> Compose의{' '}
          <span className="icode">remember {'{ mutableStateOf(0) }'}</span>는 React의{' '}
          <span className="icode">useState(0)</span>, "상태 변경 → 재구성(recomposition)"은
          "state 변경 → 재렌더"에 대응해요. 문법(Kotlin)만 새로 익히면, <strong>사고방식은
          이미 배운 것</strong>입니다. 그래서 웹 프론트를 해 본 사람이 Compose에 특히 빨리 붙어요.
        </div>
      </Section>

      <Section n={5} title="안드로이드 스튜디오와 에뮬레이터" sub="앱을 만들고 돌려 보는 작업실">
        <p>
          앱 개발의 공식 도구는 <strong>안드로이드 스튜디오</strong>예요. 우리가 IntelliJ 코스에서
          만진 그 IDE와 뿌리가 같아서(둘 다 IntelliJ 기반) 단축키와 화면이 익숙할 겁니다. 여기에
          빌드 도구 <span className="icode">Gradle</span>, 가상 폰을 띄우는{' '}
          <strong>에뮬레이터(AVD)</strong>, 로그 창 <span className="icode">Logcat</span>이 한
          몸으로 붙어 있어요.
        </p>
        <Code>{CODE_STUDIO}</Code>
        <p>
          여기서 <span className="icode">Logcat</span>은 웹의 <span className="kbd">F12</span>{' '}
          콘솔에, <strong>▶ Run → 빌드 → 설치 → 실행</strong>의 반복은 웹의 "저장 → 새로고침"에
          해당해요. 도구 이름만 다를 뿐, "고치고 → 돌려 보고 → 로그로 확인"하는 개발 리듬은
          웹과 똑같습니다. 명령줄로 폰을 다루는 <span className="icode">adb</span>는 터미널 코스에서
          익힌 CLI 감각이 그대로 이어지고요.
        </p>
        <div className="tip">
          <b>에뮬레이터가 무겁다면</b> 가상 폰은 PC 자원을 꽤 먹어요. 노트북이 버거우면{' '}
          <strong>실제 안드로이드 폰을 USB로 연결</strong>하고 설정에서 "개발자 옵션 → USB
          디버깅"을 켜면, 진짜 기기에서 더 빠르고 정확하게 테스트할 수 있습니다. 실제 기기의
          터치감·성능은 에뮬로는 100% 재현되지 않으니, 마무리 점검은 실기기가 정석이에요.
        </div>
      </Section>

      <Section n={6} title="권한과 AndroidManifest" sub="앱의 신분증이자 권한 신청서 — 그리고 최소 권한의 예의">
        <p>
          앱 폴더에는 <span className="icode">AndroidManifest.xml</span>이라는 특별한 파일이 딱
          하나 있어요. 여기에 <strong>이 앱이 어떤 화면을 갖고, 어떤 권한을 쓰며, 처음 켜면 어느
          화면이 뜨는지</strong>를 선언합니다. 시스템은 앱을 설치할 때 이 파일부터 읽어요 —
          말하자면 앱의 <strong>주민등록증 겸 권한 신청서</strong>죠.
        </p>
        <Code>{CODE_MANIFEST}</Code>
        <p>
          권한에는 결이 두 가지 있어요. <span className="icode">INTERNET</span> 같은{' '}
          <strong>일반 권한</strong>은 설치할 때 조용히 허용되지만, 카메라·위치·연락처 같은{' '}
          <strong>위험 권한</strong>은 안드로이드 6.0(API 23)부터 <strong>실행 중에 사용자에게
          팝업으로 직접 물어봐야</strong> 합니다. 매니페스트에 적는 것은 "신청"일 뿐, 실제 허락은
          사용자가 그 순간에 주는 거예요.
        </p>
        <Code>{CODE_RUNTIME_PERM}</Code>
        <div className="warn">
          <b>최소 권한의 원칙</b> "혹시 몰라서" 권한을 잔뜩 신청하면, 사용자는 불안해서 앱을
          지우고 스토어 심사에서도 감점돼요. 방화벽 코스에서 배운 <strong>"필요한 것만
          열어라"</strong>는 원칙이 앱 권한에도 그대로 적용됩니다 — 정말 쓰는 기능의 권한만,
          쓰는 그 순간에 요청하세요.
        </div>
      </Section>

      <Section n={7} title="웹 개발자의 첫 안드로이드 앱으로 가는 길" sub="지형을 읽었으니, 이제 현실적인 첫 봉우리를 고른다">
        <p>
          여기까지 왔다면 안드로이드의 <strong>지형도</strong>가 머릿속에 그려졌을 거예요 —
          층층 구조, 화면(Activity)과 이동(Intent), 생명주기, 화면 그리기(XML/Compose), 작업실,
          권한. 이제 남은 건 "그래서 나는 어디로 첫발을 뗄까"입니다. 웹을 해 본 사람에게는 길이
          세 갈래 있어요.
        </p>
        <Code>{CODE_PATH}</Code>
        <p>
          가장 중요한 사실 하나. <strong>앱을 만든다고 백엔드를 새로 짜지 않습니다.</strong>{' '}
          우리 Spring API(<span className="icode">/api/...</span>)는 웹 브라우저든 안드로이드
          앱이든 가리지 않고 똑같이 JSON으로 응답해요. 앱은 그저 <strong>같은 서버를 부르는 또
          다른 손님</strong>일 뿐이죠. 그래서 여러분이 배운 HTTP·JSON·API 지식이 앱에서도 100%
          재사용됩니다.
        </p>
        <div className="tip">
          <b>현실적인 첫 목표</b> "네이티브 앱 전문가"를 두 달 만에 되겠다는 건 무리이고, 그럴
          필요도 없어요. 대신 <strong>Compose로 화면 하나를 만들고, 그 화면에서 우리 API를 한 번
          호출해 목록을 띄우는 것</strong> — 딱 여기까지가 지금 실력으로 오를 수 있는 정직한 첫
          봉우리입니다. React에서 <span className="icode">useEffect</span>로 데이터를 불러오던 그
          경험이, Compose에서도 거의 같은 모양으로 반복돼요.
        </div>
      </Section>

      <div className="step-card">
        <div className="step-body">
          <h3 style={{ marginBottom: 6 }}>📱 여기까지 왔다면</h3>
          <p className="muted">
            이제 안드로이드를 "낯선 딴 세상"이 아니라 <strong>이미 아는 개념의 다른 표현</strong>으로
            읽을 수 있게 됐어요 — 화면 한 장은 Activity, 페이지 이동은 Intent, 컴포넌트 생명주기는
            액티비티 생명주기, "화면 = 상태의 함수"는 Jetpack Compose로. 다음은 그 화면을 실제로
            쓰는 언어를 배울 차례예요.{' '}
            <Link to="/learn/kotlin-intro"><strong>Kotlin 입문</strong></Link> 코스에서, 우리
            백엔드 Java와 사촌지간인 이 언어의 문법을 손에 익히고 첫 Compose 화면으로 한 걸음 더
            나아가 봅시다.
          </p>
        </div>
      </div>
    </div>
  );
}
