mirim-app/frontend/public/docs/cs-curriculum.html
AWESOMEDEV 84144a1608 fix(security+a11y): 종합 감사(PMD+5관점, 29에이전트) 확정 12건 수정
[HIGH]
- 로그인 잠금 XFF 스푸핑 우회: X-Forwarded-For leftmost(위조 가능) → rightmost(Caddy가 붙인 실제 IP) 사용
- 멘토 기본 비밀번호 하드코딩 제거: env 미설정 시 SecureRandom 생성 후 로그 1회 출력.
  compose에 MENTOR_INITIAL_PASSWORD 추가
- 클릭 카드 키보드 접근 불가(학습문서 전체): Card에 role=button·tabIndex·Enter/Space·aria-label

[MEDIUM]
- CSV 수식 인젝션: =+-@ 로 시작하는 학생 자유입력 앞에 ' 붙여 엑셀 수식화 차단 (+회귀 테스트)
- 학습문서 17개 <html lang=ko> 골격 주입 (스크린리더 한국어 발음)
- 과제 제출 폼 label htmlFor/id 연결
- 상단 아이콘 링크(👤·🔑) aria-label + 이모지 aria-hidden
- 멘토 제출물 표 행 키보드 접근(role/tabIndex/Enter·Space)
- 배지 amber/teal 글자 대비 4.5:1 확보(테마별 --amber-text/--teal-text)

[LOW]
- 코드에디터 포커스 표시(:focus-within), 문제번호 색 대비(--muted), 카드 :focus-visible
- 폼 오류 메시지 role=alert (스크린리더 즉시 안내)

검증: 테스트 26개 통과, 운영에서 XFF 우회 차단(6회째 429)·카드 role/aria·문서 lang=ko 확인.
PMD 29건은 전부 저심각 스멜로 실질 결함 없음. 각 수정에 원리 학습 주석.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-17 13:38:30 +09:00

475 lines
28 KiB
HTML
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<!doctype html>
<html lang="ko">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>CS 기본기 4주 커리큘럼</title>
<style>
:root {
--paper: #FAFBFD; --card: #FFFFFF; --ink: #101A28; --ink-soft: #46536A;
--ink-faint: #7B8798; --line: #E4E8F0; --line-soft: #EFF2F7;
--primary: #2159C5; --primary-soft: #E5EDFB; --primary-deep: #163F8F;
--amber: #B9772A; --amber-soft: #F6EBDA; --amber-line: #E4C79A;
--blue: #0E8C86; --blue-soft: #E0F1EF;
--code-bg: #F1F4F9;
--shadow: 0 1px 2px rgba(16,26,40,.05), 0 8px 24px -12px rgba(16,26,40,.16);
--radius: 14px;
}
@media (prefers-color-scheme: dark) {
:root {
--paper: #0B1017; --card: #131A24; --ink: #E8EDF4; --ink-soft: #A4B0C0;
--ink-faint: #74808F; --line: #263140; --line-soft: #1C242F;
--primary: #6AA0F0; --primary-soft: #172A44; --primary-deep: #AECBF8;
--amber: #DBA25C; --amber-soft: #2C2318; --amber-line: #4A3B23;
--blue: #4FC7BE; --blue-soft: #14302E;
--code-bg: #161E28;
--shadow: 0 1px 2px rgba(0,0,0,.35), 0 10px 30px -14px rgba(0,0,0,.65);
}
}
:root[data-theme="light"] {
--paper: #FAFBFD; --card: #FFFFFF; --ink: #101A28; --ink-soft: #46536A;
--ink-faint: #7B8798; --line: #E4E8F0; --line-soft: #EFF2F7;
--primary: #2159C5; --primary-soft: #E5EDFB; --primary-deep: #163F8F;
--amber: #B9772A; --amber-soft: #F6EBDA; --amber-line: #E4C79A;
--blue: #0E8C86; --blue-soft: #E0F1EF; --code-bg: #F1F4F9;
--shadow: 0 1px 2px rgba(16,26,40,.05), 0 8px 24px -12px rgba(16,26,40,.16);
}
:root[data-theme="dark"] {
--paper: #0B1017; --card: #131A24; --ink: #E8EDF4; --ink-soft: #A4B0C0;
--ink-faint: #74808F; --line: #263140; --line-soft: #1C242F;
--primary: #6AA0F0; --primary-soft: #172A44; --primary-deep: #AECBF8;
--amber: #DBA25C; --amber-soft: #2C2318; --amber-line: #4A3B23;
--blue: #4FC7BE; --blue-soft: #14302E; --code-bg: #161E28;
--shadow: 0 1px 2px rgba(0,0,0,.35), 0 10px 30px -14px rgba(0,0,0,.65);
}
* { box-sizing: border-box; }
html { -webkit-text-size-adjust: 100%; scroll-behavior: smooth; }
body {
margin: 0; background: var(--paper); color: var(--ink);
font-family: "Pretendard", "Apple SD Gothic Neo", "Malgun Gothic", "Noto Sans KR", system-ui, sans-serif;
line-height: 1.72; -webkit-font-smoothing: antialiased; letter-spacing: -0.01em;
}
.wrap { max-width: 860px; margin: 0 auto; padding: clamp(20px, 4vw, 48px); }
.eyebrow { font-size: 12px; font-weight: 700; letter-spacing: 0.14em; text-transform: uppercase; color: var(--amber); display: flex; align-items: center; gap: 10px; }
.eyebrow::before { content: ""; width: 22px; height: 2px; background: var(--amber); border-radius: 2px; }
.eyebrow.green { color: var(--primary); } .eyebrow.green::before { background: var(--primary); }
.eyebrow.blue { color: var(--blue); } .eyebrow.blue::before { background: var(--blue); }
/* Masthead */
header.mast {
border: 1px solid var(--line); border-radius: var(--radius);
background: radial-gradient(120% 140% at 0% 0%, var(--amber-soft) 0%, transparent 55%), var(--card);
box-shadow: var(--shadow); padding: clamp(26px, 4vw, 42px);
}
.wordmark { font-size: 13px; font-weight: 800; letter-spacing: 0.22em; text-transform: uppercase; color: var(--ink-soft); }
.wordmark b { color: var(--amber); }
header.mast h1 { font-size: clamp(28px, 5.6vw, 42px); line-height: 1.14; margin: 16px 0 0; font-weight: 800; letter-spacing: -0.03em; text-wrap: balance; }
header.mast .lede { margin: 16px 0 0; font-size: clamp(15px, 2.4vw, 17px); color: var(--ink-soft); max-width: 56ch; }
.mast-meta { margin-top: 24px; display: flex; flex-wrap: wrap; gap: 10px; }
.chip { font-size: 13px; font-weight: 600; color: var(--ink-soft); background: var(--paper); border: 1px solid var(--line); padding: 6px 12px; border-radius: 999px; display: inline-flex; align-items: center; gap: 7px; }
.chip .dot { width: 7px; height: 7px; border-radius: 50%; background: var(--amber); }
section { margin-top: clamp(34px, 6vw, 52px); scroll-margin-top: 20px; }
section > h2 { font-size: clamp(21px, 3.6vw, 27px); font-weight: 800; letter-spacing: -0.025em; margin: 14px 0 0; text-wrap: balance; }
section > .sub { color: var(--ink-soft); margin: 9px 0 0; font-size: 15.5px; max-width: 62ch; }
.card { background: var(--card); border: 1px solid var(--line); border-radius: var(--radius); box-shadow: var(--shadow); padding: clamp(20px, 3vw, 28px); }
.mt { margin-top: 18px; } .mt-s { margin-top: 12px; }
p { margin: 0; } strong { font-weight: 700; }
/* How-we-run ops box */
.ops { display: grid; grid-template-columns: repeat(auto-fit, minmax(180px,1fr)); gap: 0; }
.ops .o { padding: 6px 18px; border-left: 3px solid var(--amber); }
.ops .o:first-child { padding-left: 0; border-left: 0; }
.ops .o .k { font-size: 12px; font-weight: 700; letter-spacing: 0.06em; text-transform: uppercase; color: var(--amber); }
.ops .o .v { margin-top: 5px; font-size: 14.5px; color: var(--ink); }
.ops .o .v b { font-weight: 700; }
@media (max-width:560px){ .ops .o { border-left: 0; border-top: 1px solid var(--line-soft); padding: 12px 0; } .ops .o:first-child { border-top:0; } }
/* Week block */
.week-head { display: grid; grid-template-columns: auto 1fr; gap: 18px; align-items: center; margin-bottom: 4px; }
.week-badge { width: 62px; height: 62px; border-radius: 15px; background: var(--primary); color: #fff; display: grid; place-items: center; text-align: center; line-height: 1.05; box-shadow: var(--shadow); }
.week-badge .w { font-size: 11px; font-weight: 700; letter-spacing: 0.1em; opacity: .85; }
.week-badge .n { font-size: 24px; font-weight: 800; font-variant-numeric: tabular-nums; }
@media (prefers-color-scheme: dark){ .week-badge { color: #0E1512; } }
:root[data-theme="dark"] .week-badge { color: #0E1512; }
.w2 .week-badge { background: var(--amber); }
.w3 .week-badge { background: var(--blue); }
.w4 .week-badge { background: var(--primary-deep); }
.week-head h3 { margin: 0; font-size: clamp(19px,3.2vw,23px); font-weight: 800; letter-spacing: -0.02em; }
.week-head .goal { margin-top: 3px; color: var(--ink-soft); font-size: 14.5px; }
/* Daily rows */
.days { display: grid; gap: 0; margin-top: 6px; }
.day { display: grid; grid-template-columns: 66px 1fr; gap: 18px; padding: 18px 0; border-top: 1px solid var(--line-soft); }
.day:first-child { border-top: 0; }
.day .badge { font-size: 12px; font-weight: 800; letter-spacing: 0.03em; color: var(--primary); background: var(--primary-soft); border-radius: 8px; padding: 8px 4px; text-align: center; height: fit-content; white-space: nowrap; }
.w2 .day .badge { color: var(--amber); background: var(--amber-soft); }
.w3 .day .badge { color: var(--blue); background: var(--blue-soft); }
.w4 .day .badge { color: var(--primary-deep); background: var(--primary-soft); }
.day h4 { margin: 2px 0 0; font-size: 16px; font-weight: 800; letter-spacing: -0.01em; }
.meta { margin-top: 10px; display: grid; gap: 7px; }
.meta .m { display: grid; grid-template-columns: 74px 1fr; gap: 12px; font-size: 14px; align-items: start; }
.meta .m .lab { font-size: 11px; font-weight: 700; letter-spacing: 0.04em; text-transform: uppercase; padding-top: 3px; }
.meta .m.prac .lab { color: var(--amber); }
.meta .m.link .lab { color: var(--primary); }
.meta .m .txt { color: var(--ink-soft); }
.meta .m .txt b { color: var(--ink); font-weight: 600; }
code { font-family: "SF Mono","Cascadia Code","Consolas",ui-monospace,monospace; font-size: 0.9em; background: var(--code-bg); padding: 1px 6px; border-radius: 5px; letter-spacing: 0; }
.friday { background: var(--primary-soft); border-radius: 10px; padding: 4px 12px; }
.w2 .friday { background: var(--amber-soft); } .w3 .friday { background: var(--blue-soft); }
/* Designer track */
.dz { border: 1px dashed var(--blue); background: var(--blue-soft); border-radius: 12px; padding: 18px 20px; }
.dz .h { font-weight: 800; color: var(--blue); font-size: 14px; display: flex; align-items: center; gap: 8px; }
.dz p { color: var(--ink-soft); font-size: 14px; margin-top: 8px; }
.dz b { color: var(--ink); }
/* Check / assessment */
.assess { display: grid; gap: 12px; }
.assess .a { display: grid; grid-template-columns: 82px 1fr; gap: 16px; padding: 14px 0; border-top: 1px solid var(--line-soft); align-items: start; }
.assess .a:first-child { border-top: 0; }
.assess .a .wk { font-weight: 800; color: var(--primary); font-variant-numeric: tabular-nums; font-size: 14px; }
.assess .a .txt { font-size: 14.5px; color: var(--ink-soft); } .assess .a .txt b { color: var(--ink); font-weight: 600; }
.callout { margin-top:18px; border: 1px solid var(--amber-line); border-radius: var(--radius); background: var(--amber-soft); padding: 20px 24px; }
.callout h3 { margin: 0 0 6px; font-size: 16px; font-weight: 800; color: var(--ink); }
.callout p { color: var(--ink-soft); font-size: 14.5px; }
footer { margin-top: 48px; padding-top: 22px; border-top: 1px solid var(--line); color: var(--ink-faint); font-size: 13px; display: flex; justify-content: space-between; flex-wrap: wrap; gap: 8px; }
@media (max-width: 560px) {
.day { grid-template-columns: 56px 1fr; gap: 12px; }
.meta .m { grid-template-columns: 60px 1fr; gap: 8px; }
.assess .a { grid-template-columns: 64px 1fr; }
}
@media print { body{background:#fff;} .card,header.mast,.week-badge{box-shadow:none;} section{break-inside:avoid;} }
</style>
</head>
<body>
<div class="wrap">
<header class="mast">
<div class="wordmark"><b>AWESOMEDEV</b> · 수습 교육 · Layer&nbsp;B</div>
<h1>컴퓨터 기본기<br>4주 커리큘럼</h1>
<p class="lede">개발 수습생 3명이 <strong>매일 아침 1시간</strong>씩, 4주 동안 컴퓨터의 뼈대를 잡는 과정이에요. 도구 사용법이 아니라 <strong>"컴퓨터가 어떻게 돌아가는가"</strong>를 배웁니다. 모든 주제는 마지막에 <strong>우리 회사 시스템</strong>으로 연결돼요.</p>
<div class="mast-meta">
<span class="chip"><span class="dot"></span>매일 아침 09:3010:30 · 20일</span>
<span class="chip"><span class="dot"></span>강의 20분 + 실습 40분</span>
</div>
</header>
<!-- How we run -->
<section id="how">
<div class="eyebrow">운영 방식</div>
<h2>이렇게 진행해요</h2>
<p class="sub">지루한 이론 통독은 안 해요. 짧게 배우고, 바로 손으로 확인하고, 우리 것에 붙입니다.</p>
<div class="card mt">
<div class="ops">
<div class="o"><div class="k">시간</div><div class="v"><b>매일 아침 1시간.</b> 하루를 가볍게 여는 루틴으로.</div></div>
<div class="o"><div class="k">구성</div><div class="v">강의 20분 → <b>실습 40분.</b> 듣기보다 해보기 위주.</div></div>
<div class="o"><div class="k">실습 언어</div><div class="v"><b>JavaScript</b>(React에서 쓰는 언어)로 개념 확인. 잡히면 <b>Java</b>(Spring Boot)로도 확인.</div></div>
<div class="o"><div class="k">마무리</div><div class="v">매일 <b>3줄 회고</b>, 금요일 <b>미니 퀴즈</b>로 이해도 확인.</div></div>
</div>
</div>
<div class="callout">
<h3>💡 멘토를 위한 한 가지 원칙</h3>
<p>모든 개념 끝에 꼭 <b>"그래서 우리 회사에선?"</b>을 붙여주세요. 학생이 배운 걸 우리 실제 스택(<b>React 웹 · Spring Boot · 클라우드 · React Native · Flutter</b>)에서 직접 보면, 죽은 지식이 살아 있는 이해가 됩니다.</p>
</div>
</section>
<!-- WEEK 1 -->
<section id="w1" class="w1">
<div class="eyebrow green">Week 1</div>
<div class="card mt">
<div class="week-head">
<div class="week-badge"><span class="w">WEEK</span><span class="n">1</span></div>
<div>
<h3>컴퓨터 구조 — 컴퓨터는 결국 뭘 하는 기계인가</h3>
<div class="goal">데이터가 0과 1로 저장되고, 부품들이 어떻게 협력해 프로그램을 실행하는지 이해해요.</div>
</div>
</div>
<div class="days">
<div class="day">
<div class="badge">1일차<br></div>
<div>
<h4>2진수 · 비트 · 바이트 — 모든 건 0과 1</h4>
<div class="meta">
<div class="m prac"><span class="lab">실습</span><span class="txt">10진수 ↔ 2진수 손으로 변환. 글자가 숫자로 바뀌는 것 보기(ASCII), <b>색이 숫자로</b>: <code>#15715A</code> 가 곧 RGB 숫자라는 것 확인.</span></div>
<div class="m link"><span class="lab">연결</span><span class="txt">디자이너가 쓰는 색상 코드도, 사진 한 장도 전부 숫자 덩어리예요.</span></div>
</div>
</div>
</div>
<div class="day">
<div class="badge">2일차<br></div>
<div>
<h4>CPU · 메모리(RAM) · 저장장치 · 입출력</h4>
<div class="meta">
<div class="m prac"><span class="lab">실습</span><span class="txt">내 PC <b>작업 관리자</b>로 CPU·메모리 사용량 관찰. 비유로 정리: 책상=RAM(작업 공간), 책장=디스크(보관).</span></div>
<div class="m link"><span class="lab">연결</span><span class="txt">우리가 서비스를 올리는 <b>클라우드 서버</b>도 똑같은 부품 구성. 사양(vCPU·RAM)이 뭘 뜻하는지 함께 확인.</span></div>
</div>
</div>
</div>
<div class="day">
<div class="badge">3일차<br></div>
<div>
<h4>프로그램이 실행되면 벌어지는 일</h4>
<div class="meta">
<div class="m prac"><span class="lab">실습</span><span class="txt">소스코드 → 실행 과정 따라가기. 간단한 <b>JavaScript(Node)</b> 프로그램을 돌리며 <b>프로세스</b>가 메모리에 올라가는 것 관찰.</span></div>
<div class="m link"><span class="lab">연결</span><span class="txt">우리가 만드는 <b>Spring Boot 서버 앱</b>도 이렇게 하나의 프로세스로 떠서 돌아가요.</span></div>
</div>
</div>
</div>
<div class="day">
<div class="badge">4일차<br></div>
<div>
<h4>네트워크 기초 — 컴퓨터끼리 대화하는 법</h4>
<div class="meta">
<div class="m prac"><span class="lab">실습</span><span class="txt">브라우저 <b>개발자도구 → Network 탭</b>으로 우리 사이트가 서버에 보내는 요청/응답 직접 보기. IP·포트·HTTP 개념.</span></div>
<div class="m link"><span class="lab">연결</span><span class="txt">우리 <b>React 웹</b><b>REST API</b><b>Spring Boot 서버</b>에 요청을 보내는 흐름을 눈으로 확인.</span></div>
</div>
</div>
</div>
<div class="day">
<div class="badge">5일차<br></div>
<div>
<h4 class="friday">정리 &amp; 미니 퀴즈 &amp; 우리 시스템 세미나</h4>
<div class="meta">
<div class="m prac"><span class="lab">확인</span><span class="txt">한 주 개념 퀴즈(10문항). "왜 메모리가 부족하면 서버가 느려지나?"를 스스로 설명해보기.</span></div>
</div>
</div>
</div>
</div>
<div class="dz" style="margin-top:16px;">
<div class="h">🎨 디자이너 대체 트랙 (같은 시간)</div>
<p><b>디자인 기본기 ①</b> — 색(색상·명도·채도, RGB/HEX), 타이포그래피 기초. + 컴퓨터가 색·이미지를 숫자로 다루는 원리는 개발자와 함께 들어요(협업 기반).</p>
</div>
</div>
</section>
<!-- WEEK 2 -->
<section id="w2" class="w2">
<div class="eyebrow">Week 2</div>
<div class="card mt">
<div class="week-head">
<div class="week-badge"><span class="w">WEEK</span><span class="n">2</span></div>
<div>
<h3>자료구조 — 데이터를 어떻게 담는가</h3>
<div class="goal">상황마다 왜 다른 그릇(구조)을 쓰는지 감을 잡고, 직접 만들어봐요.</div>
</div>
</div>
<div class="days">
<div class="day">
<div class="badge">6일차<br></div>
<div>
<h4>배열 · 리스트 — 순서대로 담기</h4>
<div class="meta">
<div class="m prac"><span class="lab">실습</span><span class="txt">JavaScript 배열로 <b>할 일 목록·상품 목록</b> 만들기 — 추가·삭제·인덱스로 꺼내기.</span></div>
<div class="m link"><span class="lab">연결</span><span class="txt">화면에 목록을 뿌리는 모든 기능(<b>React의 리스트 렌더링</b>)이 결국 이 목록 데이터예요.</span></div>
</div>
</div>
</div>
<div class="day">
<div class="badge">7일차<br></div>
<div>
<h4>스택 · 큐 — 쌓기(LIFO)와 줄서기(FIFO)</h4>
<div class="meta">
<div class="m prac"><span class="lab">실습</span><span class="txt">스택·큐를 <b>직접 구현</b>. 스택=실행취소(Undo), 큐=먼저 온 순서대로 처리.</span></div>
<div class="m link"><span class="lab">연결</span><span class="txt">알림·이벤트를 <b>들어온 순서대로 처리</b>하는 큐(Kafka) 개념의 씨앗.</span></div>
</div>
</div>
</div>
<div class="day">
<div class="badge">8일차<br></div>
<div>
<h4>해시 (맵 · 객체) — 열쇠로 한 번에 찾기</h4>
<div class="meta">
<div class="m prac"><span class="lab">실습</span><span class="txt">JavaScript 객체(Map)로 <b>아이디 → 사용자 정보</b> 캐시 흉내내기. 목록을 뒤지는 것 vs 바로 찾는 것 속도 비교.</span></div>
<div class="m link"><span class="lab">연결</span><span class="txt">자주 쓰는 데이터를 빠르게 꺼내는 <b>캐시(Redis)가 왜 빠른가 = 해시</b> 덕분. 이 순간을 크게 강조!</span></div>
</div>
</div>
</div>
<div class="day">
<div class="badge">9일차<br></div>
<div>
<h4>트리 — 계층으로 담기</h4>
<div class="meta">
<div class="m prac"><span class="lab">실습</span><span class="txt">폴더 구조·<b>JSON</b>을 트리로 그려보기. 부모-자식 관계 이해.</span></div>
<div class="m link"><span class="lab">연결</span><span class="txt">웹 화면의 <b>HTML(DOM) 트리</b>, 서버가 주는 JSON 응답이 다 트리 구조.</span></div>
</div>
</div>
</div>
<div class="day">
<div class="badge">10일차<br></div>
<div>
<h4 class="friday">시간복잡도 맛보기 &amp; 미니 퀴즈</h4>
<div class="meta">
<div class="m prac"><span class="lab">확인</span><span class="txt">"왜 상황마다 다른 구조를 쓰나" = 빠른 것/순서 지키는 것의 차이. Big-O 감각만 가볍게. 퀴즈 10문항.</span></div>
</div>
</div>
</div>
</div>
<div class="dz" style="margin-top:16px;">
<div class="h">🎨 디자이너 대체 트랙 (같은 시간)</div>
<p><b>디자인 기본기 ②</b> — 레이아웃·<b>그리드</b>·여백·정렬 원칙. 트리 개념은 함께 들어요(화면이 컴포넌트 트리로 구성된다는 이해 = 개발 협업의 핵심).</p>
</div>
</div>
</section>
<!-- WEEK 3 -->
<section id="w3" class="w3">
<div class="eyebrow blue">Week 3</div>
<div class="card mt">
<div class="week-head">
<div class="week-badge"><span class="w">WEEK</span><span class="n">3</span></div>
<div>
<h3>프로그램의 변화 — 지금 우리가 쓰는 것이 어디서 왔나</h3>
<div class="goal">언어와 소프트웨어가 어떻게 진화해 왔는지 큰 지도를 그리고, 우리 스택의 위치를 찾아요.</div>
</div>
</div>
<div class="days">
<div class="day">
<div class="badge">11일차<br></div>
<div>
<h4>언어의 진화 — 기계어에서 사람 말까지</h4>
<div class="meta">
<div class="m prac"><span class="lab">실습</span><span class="txt">같은 동작을 <b>저수준 vs 고수준</b>으로 비교. "왜 점점 사람 말에 가까워졌나" 이야기 나누기.</span></div>
<div class="m link"><span class="lab">연결</span><span class="txt">우리가 Java·JavaScript 같은 고급 언어를 쓰는 이유.</span></div>
</div>
</div>
</div>
<div class="day">
<div class="badge">12일차<br></div>
<div>
<h4>프로그래밍 패러다임 — 절차 → 객체 → 함수</h4>
<div class="meta">
<div class="m prac"><span class="lab">실습</span><span class="txt">같은 문제를 <b>절차지향 vs 객체지향</b>으로 각각 짜보고 차이 느끼기.</span></div>
<div class="m link"><span class="lab">연결</span><span class="txt">우리 백엔드(Java)가 <b>객체지향</b>인 이유, 프론트에 함수형 요소가 섞인 이유.</span></div>
</div>
</div>
</div>
<div class="day">
<div class="badge">13일차<br></div>
<div>
<h4>웹의 등장 — 클라이언트와 서버로 나뉘다</h4>
<div class="meta">
<div class="m prac"><span class="lab">실습</span><span class="txt">혼자 도는 프로그램 → 웹으로. <b>프론트엔드 / 백엔드</b>가 나뉜 이유와 역할 분담 정리.</span></div>
<div class="m link"><span class="lab">연결</span><span class="txt">우리 <b>React 웹(프론트)</b><b>Spring Boot(백엔드)</b>가 딱 이 구도. 4일차 Network 탭과 이어짐.</span></div>
</div>
</div>
</div>
<div class="day">
<div class="badge">14일차<br></div>
<div>
<h4>아키텍처의 진화 — 모놀리식 → MSA → 클라우드 → AI</h4>
<div class="meta">
<div class="m prac"><span class="lab">실습</span><span class="txt">하나로 뭉친 프로그램 vs 잘게 나눈 <b>마이크로서비스</b>의 장단점 토론.</span></div>
<div class="m link"><span class="lab">연결</span><span class="txt">우리가 <b>웹(React) · 앱(React Native·Flutter) · 서버(Spring Boot)</b>를 나눠 만들고 <b>클라우드</b>에 올리는 방식이 바로 이 진화의 결과.</span></div>
</div>
</div>
</div>
<div class="day">
<div class="badge">15일차<br></div>
<div>
<h4 class="friday">우리 서비스 구성도 그려보기 &amp; 미니 퀴즈</h4>
<div class="meta">
<div class="m prac"><span class="lab">확인</span><span class="txt">배운 흐름으로 우리 시스템 구성도를 <b>직접 그려보기</b>. 퀴즈 10문항.</span></div>
</div>
</div>
</div>
</div>
<div class="dz" style="margin-top:16px;">
<div class="h">🎨 디자이너 대체 트랙 (같은 시간)</div>
<p><b>디자인 시스템 &amp; 핸드오프</b> — 컴포넌트·재사용 개념, 개발자에게 넘기는 스펙(간격·상태·인터랙션) 작성법. 웹의 프론트/백 구분은 함께 들어요.</p>
</div>
</div>
</section>
<!-- WEEK 4 -->
<section id="w4" class="w4">
<div class="eyebrow green">Week 4</div>
<div class="card mt">
<div class="week-head">
<div class="week-badge"><span class="w">WEEK</span><span class="n">4</span></div>
<div>
<h3>통합 · 복습 · 발표 — 배운 걸 내 말로</h3>
<div class="goal">3주간 배운 조각들을 하나로 잇고, "내가 이해한 것"을 발표로 증명해요.</div>
</div>
</div>
<div class="days">
<div class="day">
<div class="badge">1617일차<br>월·화</div>
<div>
<h4>한 요청의 여행 — 클릭에서 응답까지 따라가기</h4>
<div class="meta">
<div class="m prac"><span class="lab">실습</span><span class="txt">화면에서 버튼 하나 눌렀을 때: <b>React 웹/앱 → REST API → Spring Boot 서버 → DB → 응답</b>까지 전 과정을 추적하고 그림으로 정리.</span></div>
<div class="m link"><span class="lab">연결</span><span class="txt">1~3주 개념(네트워크·자료구조·아키텍처)이 여기서 전부 만나요.</span></div>
</div>
</div>
</div>
<div class="day">
<div class="badge">18일차<br></div>
<div>
<h4>발표 주제 정하고 깊게 파기</h4>
<div class="meta">
<div class="m prac"><span class="lab">실습</span><span class="txt">각자 가장 흥미로웠던 주제 하나 선택(예: "캐시는 왜 빠른가", "React와 서버는 어떻게 대화하나", "웹과 앱은 뭐가 다른가") — 자료 조사.</span></div>
</div>
</div>
</div>
<div class="day">
<div class="badge">19일차<br></div>
<div>
<h4>발표 자료 만들기</h4>
<div class="meta">
<div class="m prac"><span class="lab">실습</span><span class="txt">10분 분량 슬라이드 작성. <b>어려운 말 없이, 내 말로</b> 설명하는 걸 목표로. (멘토가 1:1 코칭)</span></div>
</div>
</div>
</div>
<div class="day">
<div class="badge">20일차<br></div>
<div>
<h4 class="friday">미니 발표회 🎤 — Layer B의 졸업식</h4>
<div class="meta">
<div class="m prac"><span class="lab">발표</span><span class="txt">한 사람당 10분 "내가 이해한 컴퓨터 / 우리 시스템". 팀 앞에서 발표하고 질문받기.</span></div>
<div class="m link"><span class="lab">평가</span><span class="txt">이 발표가 <b>기본기 이해도의 핵심 평가 포인트</b>. (아래 평가 방법 참고)</span></div>
</div>
</div>
</div>
</div>
<div class="dz" style="margin-top:16px;">
<div class="h">🎨 디자이너 대체 트랙 (같은 시간)</div>
<p>디자이너도 함께 요청 흐름을 따라가고(협업 이해), 발표는 <b>"내가 다시 디자인한다면"</b> 주제로 — 우리가 다루는 서비스 화면 하나를 골라 개선안을 발표해요.</p>
</div>
</div>
</section>
<!-- Assessment -->
<section id="assess">
<div class="eyebrow green">이해도 확인</div>
<h2>어떻게 평가하나</h2>
<p class="sub">시험 점수가 목적이 아니에요. <strong>"이해했는지, 그리고 내 말로 설명할 수 있는지"</strong>를 봅니다.</p>
<div class="card mt assess">
<div class="a"><div class="wk">매일</div><div class="txt"><b>3줄 회고</b> — 오늘 배운 것 / 이해 안 된 것 / 궁금한 것. 이해가 막힌 지점을 멘토가 바로 캐치.</div></div>
<div class="a"><div class="wk">매주 금</div><div class="txt"><b>미니 퀴즈 10문항</b> — 맞고 틀림보다, 틀린 개념을 다음 주에 보완하는 용도.</div></div>
<div class="a"><div class="wk">4주차</div><div class="txt"><b>미니 발표 (가장 중요)</b> — 어려운 용어 없이 자기 말로 설명하면 진짜 이해한 것. 암기가 아니라 이해를 봐요.</div></div>
<div class="a"><div class="wk">상시</div><div class="txt"><b>"그래서 우리 회사에선?" 대답</b> — 배운 개념을 우리 실제 개발(React·Spring Boot·앱·클라우드)에 연결해 말할 수 있는지가 최종 목표.</div></div>
</div>
<div class="callout">
<h3>⚠️ 눈높이 주의</h3>
<p>고교생에게 Big-O 증명이나 CPU 파이프라인 같은 <b>깊은 이론은 목표가 아니에요.</b> "왜 이렇게 만들어졌고, 우리 시스템의 어디에 있는가"라는 <b>큰 그림과 직관</b>을 잡는 게 이 4주의 목적입니다. 못 따라오면 속도를 늦춰도 괜찮아요.</p>
</div>
</section>
<footer>
<span>AWESOMEDEV · 수습 교육 · Layer B 커리큘럼</span>
<span>2026 · 수습 가이드와 함께 사용</span>
</footer>
</div>
</body>
</html>