Files
sam-manage/resources/views/academy/frontend-dev.blade.php
김보곤 aa9d9aef49 feat: [academy] 프론트엔드 개발 백과사전 추가
- 10개 섹션: HTML/CSS/JS, 프레임워크, 반응형, 브라우저, API, 도구, 성능
- purple 테마, 기존 아카데미 패턴 동일 적용
- 전문용어 툴팁 26개 추가 (frontend-dev 도메인)
2026-02-23 10:31:41 +09:00

1347 lines
93 KiB
PHP

@extends('layouts.app')
@section('title', '프론트엔드 개발 백과사전')
@push('styles')
<style>
/* 이미지 기본 스타일 */
.academy-img-hover {
transition: box-shadow 0.2s ease;
}
.academy-img-hover:hover {
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);
}
.academy-img-wrap {
overflow: hidden;
border-radius: 0.75rem;
}
/* hover 프리뷰 오버레이 */
#hover-preview {
display: none;
position: fixed;
inset: 0;
z-index: 45;
align-items: center;
justify-content: center;
background: rgba(0, 0, 0, 0.6);
backdrop-filter: blur(3px);
pointer-events: none;
}
#hover-preview.is-active {
display: flex;
pointer-events: none;
}
#hover-preview img {
max-height: 80vh;
max-width: 85vw;
border-radius: 0.75rem;
box-shadow: 0 25px 60px rgba(0, 0, 0, 0.5);
opacity: 0;
transform: scale(0.3);
transition: opacity 0.25s ease, transform 0.25s ease;
}
#hover-preview.is-active img {
opacity: 1;
transform: scale(1);
}
#hover-preview .hover-caption {
position: absolute;
bottom: 2rem;
left: 50%;
transform: translateX(-50%);
color: rgba(255,255,255,0.85);
font-size: 0.8rem;
background: rgba(0,0,0,0.5);
padding: 0.4rem 1rem;
border-radius: 2rem;
white-space: nowrap;
opacity: 0;
transition: opacity 0.3s ease 0.15s;
}
#hover-preview.is-active .hover-caption {
opacity: 1;
}
/* 클릭 라이트박스 */
#lightbox {
display: none;
position: fixed;
inset: 0;
z-index: 50;
align-items: center;
justify-content: center;
background: rgba(0, 0, 0, 0.9);
backdrop-filter: blur(4px);
}
#lightbox.is-open {
display: flex;
}
#lightbox img {
max-height: 90vh;
max-width: 90vw;
border-radius: 0.5rem;
box-shadow: 0 25px 50px rgba(0, 0, 0, 0.5);
}
/* 코드 블록 스타일 */
.code-block {
background: #1e1e2e;
color: #a6e3a1;
border-radius: 0.75rem;
padding: 1rem 1.25rem;
font-family: 'Courier New', Courier, monospace;
font-size: 0.75rem;
line-height: 1.6;
overflow-x: auto;
white-space: pre;
}
.code-block .code-comment { color: #6c7086; }
.code-block .code-tag { color: #89b4fa; }
.code-block .code-attr { color: #f9e2af; }
.code-block .code-string { color: #a6e3a1; }
.code-block .code-keyword { color: #cba6f7; }
.code-block .code-func { color: #89dceb; }
.code-block .code-number { color: #fab387; }
</style>
@endpush
@section('content')
<div class="max-w-6xl mx-auto">
<!-- 히어로 배너 -->
<div class="rounded-2xl overflow-hidden mb-8 shadow-lg" style="background: linear-gradient(135deg, #2e1065 0%, #0f172a 100%);">
<div class="flex items-center" style="flex-wrap: wrap;">
<div style="flex: 1 1 300px; padding: 2rem 2.5rem;">
<div class="flex items-center gap-2 text-sm mb-2" style="color: #c4b5fd;">
<span>아카데미</span>
<svg class="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 5l7 7-7 7" /></svg>
<span style="color: #ffffff;">프론트엔드 개발</span>
</div>
<h1 class="text-3xl font-bold mb-2" style="color: #ffffff;">프론트엔드 개발 백과사전</h1>
<p class="text-sm" style="color: #cbd5e1;">HTML, CSS, JavaScript부터 프레임워크, 성능 최적화까지 비개발자도 이해하는 프론트엔드 가이드</p>
</div>
<div class="shrink-0" style="width: 240px; padding: 1.5rem;">
<div class="overflow-hidden rounded-xl flex items-center justify-center" style="background: rgba(139,92,246,0.15); height: 160px;">
<svg style="width: 120px; height: 120px;" viewBox="0 0 120 120" fill="none" xmlns="http://www.w3.org/2000/svg">
<rect x="15" y="20" width="90" height="65" rx="6" stroke="#c4b5fd" stroke-width="2.5" fill="none"/>
<rect x="25" y="30" width="35" height="8" rx="2" fill="#a78bfa" opacity="0.6"/>
<rect x="25" y="42" width="55" height="5" rx="1.5" fill="#7c3aed" opacity="0.4"/>
<rect x="25" y="50" width="45" height="5" rx="1.5" fill="#7c3aed" opacity="0.3"/>
<rect x="25" y="58" width="50" height="5" rx="1.5" fill="#7c3aed" opacity="0.2"/>
<rect x="65" y="30" width="18" height="18" rx="3" fill="#8b5cf6" opacity="0.5"/>
<line x1="15" y1="72" x2="105" y2="72" stroke="#c4b5fd" stroke-width="1.5"/>
<circle cx="60" cy="78" r="2.5" fill="#c4b5fd"/>
<rect x="40" y="85" width="40" height="4" rx="2" fill="#c4b5fd" opacity="0.5"/>
<text x="60" y="105" text-anchor="middle" fill="#c4b5fd" font-size="10" font-family="monospace">&lt;/&gt;</text>
</svg>
</div>
</div>
</div>
</div>
<div class="flex gap-8">
<!-- 좌측 고정 목차 (TOC) -->
<nav class="hidden lg:block shrink-0" style="width: 220px;">
<div class="sticky top-24">
<div class="bg-purple-50 border border-purple-200 rounded-xl p-5">
<h2 class="font-semibold text-purple-800 mb-3 flex items-center gap-2 text-sm">
<svg class="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M4 6h16M4 10h16M4 14h16M4 18h16" /></svg>
목차
</h2>
<div class="space-y-0.5 text-xs">
<a href="#what-is-frontend" class="block text-purple-700 hover:text-purple-900 py-1 font-medium">1. 프론트엔드란?</a>
<a href="#frontend-vs-backend" class="block text-purple-600 hover:text-purple-800 py-0.5 pl-3">프론트 vs 백엔드</a>
<a href="#web-trio" class="block text-purple-600 hover:text-purple-800 py-0.5 pl-3">웹의 3요소</a>
<a href="#html" class="block text-purple-700 hover:text-purple-900 py-1 font-medium mt-2">2. HTML</a>
<a href="#html-tags" class="block text-purple-600 hover:text-purple-800 py-0.5 pl-3">태그와 구조</a>
<a href="#html-semantic" class="block text-purple-600 hover:text-purple-800 py-0.5 pl-3">시맨틱 태그</a>
<a href="#css" class="block text-purple-700 hover:text-purple-900 py-1 font-medium mt-2">3. CSS</a>
<a href="#css-selector" class="block text-purple-600 hover:text-purple-800 py-0.5 pl-3">선택자와 박스모델</a>
<a href="#css-layout" class="block text-purple-600 hover:text-purple-800 py-0.5 pl-3">Flexbox와 Grid</a>
<a href="#javascript" class="block text-purple-700 hover:text-purple-900 py-1 font-medium mt-2">4. JavaScript</a>
<a href="#js-basics" class="block text-purple-600 hover:text-purple-800 py-0.5 pl-3">변수와 함수</a>
<a href="#js-dom" class="block text-purple-600 hover:text-purple-800 py-0.5 pl-3">DOM 조작</a>
<a href="#frameworks" class="block text-purple-700 hover:text-purple-900 py-1 font-medium mt-2">5. 프레임워크</a>
<a href="#fw-compare" class="block text-purple-600 hover:text-purple-800 py-0.5 pl-3">React vs Vue</a>
<a href="#fw-sam" class="block text-purple-600 hover:text-purple-800 py-0.5 pl-3">SAM의 선택</a>
<a href="#responsive" class="block text-purple-700 hover:text-purple-900 py-1 font-medium mt-2">6. 반응형 디자인</a>
<a href="#rwd-breakpoint" class="block text-purple-600 hover:text-purple-800 py-0.5 pl-3">브레이크포인트</a>
<a href="#browser" class="block text-purple-700 hover:text-purple-900 py-1 font-medium mt-2">7. 브라우저 동작</a>
<a href="#browser-render" class="block text-purple-600 hover:text-purple-800 py-0.5 pl-3">렌더링 과정</a>
<a href="#api-integration" class="block text-purple-700 hover:text-purple-900 py-1 font-medium mt-2">8. API 연동</a>
<a href="#api-http" class="block text-purple-600 hover:text-purple-800 py-0.5 pl-3">HTTP 메서드</a>
<a href="#tooling" class="block text-purple-700 hover:text-purple-900 py-1 font-medium mt-2">9. 개발 도구</a>
<a href="#tool-workflow" class="block text-purple-600 hover:text-purple-800 py-0.5 pl-3">워크플로우</a>
<a href="#performance" class="block text-purple-700 hover:text-purple-900 py-1 font-medium mt-2">10. 성능 최적화</a>
<a href="#perf-vitals" class="block text-purple-600 hover:text-purple-800 py-0.5 pl-3">Core Web Vitals</a>
</div>
</div>
</div>
</nav>
<!-- 우측 콘텐츠 -->
<div class="flex-1 min-w-0 space-y-10">
<!-- 모바일 목차 -->
<div class="lg:hidden bg-purple-50 border border-purple-200 rounded-xl p-4 mb-6">
<details>
<summary class="font-semibold text-purple-800 text-sm cursor-pointer flex items-center gap-2">
<svg class="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M4 6h16M4 10h16M4 14h16M4 18h16" /></svg>
목차 보기
</summary>
<nav class="mt-3 space-y-1 text-sm">
<a href="#what-is-frontend" class="block text-purple-700 hover:text-purple-900 py-1">1. 프론트엔드란?</a>
<a href="#html" class="block text-purple-700 hover:text-purple-900 py-1">2. HTML 웹의 뼈대</a>
<a href="#css" class="block text-purple-700 hover:text-purple-900 py-1">3. CSS 웹의 </a>
<a href="#javascript" class="block text-purple-700 hover:text-purple-900 py-1">4. JavaScript 웹의 두뇌</a>
<a href="#frameworks" class="block text-purple-700 hover:text-purple-900 py-1">5. 프레임워크와 라이브러리</a>
<a href="#responsive" class="block text-purple-700 hover:text-purple-900 py-1">6. 반응형 디자인</a>
<a href="#browser" class="block text-purple-700 hover:text-purple-900 py-1">7. 브라우저 동작 원리</a>
<a href="#api-integration" class="block text-purple-700 hover:text-purple-900 py-1">8. API 연동</a>
<a href="#tooling" class="block text-purple-700 hover:text-purple-900 py-1">9. 개발 도구와 워크플로우</a>
<a href="#performance" class="block text-purple-700 hover:text-purple-900 py-1">10. 성능 최적화</a>
</nav>
</details>
</div>
{{-- ============================================================ --}}
{{-- 1. 프론트엔드란? --}}
{{-- ============================================================ --}}
<section id="what-is-frontend" class="scroll-mt-20">
<div class="bg-white rounded-xl shadow-sm border border-gray-100 p-6">
<h2 class="text-xl font-bold text-gray-800 mb-6 flex items-center gap-3">
<span class="w-8 h-8 bg-purple-500 text-white rounded-lg flex items-center justify-center text-sm font-bold">1</span>
프론트엔드란?
</h2>
<!-- 1-1. 프론트엔드 vs 백엔드 -->
<div id="frontend-vs-backend" class="scroll-mt-20 mb-8">
<h3 class="text-lg font-semibold text-gray-800 mb-3 flex items-center gap-2">
<span class="w-2 h-2 bg-purple-400 rounded-full"></span>
프론트엔드 vs 백엔드
</h3>
<div class="bg-purple-50 rounded-lg p-5 border border-purple-100 mb-4">
<p class="text-sm text-purple-900 leading-relaxed">
<strong>프론트엔드(Front-end)</strong> 사용자가 직접 보고, 클릭하고, 입력하는 화면 전체를 말한다.
브라우저에 표시되는 버튼, 메뉴, 입력창, , 이미지 눈에 보이는 모든 것이 프론트엔드의 영역이다.
</p>
</div>
<div class="bg-amber-50 rounded-lg p-4 border border-amber-100 mb-4">
<p class="font-semibold text-amber-800 mb-2">비유: 식당의 홀과 주방</p>
<p class="text-xs text-amber-900 leading-relaxed">
프론트엔드는 <strong>식당의 </strong>이다. 손님이 메뉴판을 보고, 주문하고, 음식을 받는 공간이다.
백엔드는 <strong>주방</strong>이다. 손님은 보지 못하지만, 주문을 받아 요리하고 결과를 내보내는 곳이다.
홀이 예쁘고 편해야 손님이 만족하듯, 프론트엔드가 만들어져야 사용자가 편하게 시스템을 있다.
</p>
</div>
<div class="grid grid-cols-1 md:grid-cols-2 gap-3 text-xs">
<div class="bg-purple-50 rounded-lg p-4 border border-purple-200 text-center">
<div class="mb-2">
<svg class="w-8 h-8 mx-auto text-purple-500" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9.75 17L9 20l-1 1h8l-1-1-.75-3M3 13h18M5 17h14a2 2 0 002-2V5a2 2 0 00-2-2H5a2 2 0 00-2 2v10a2 2 0 002 2z" /></svg>
</div>
<p class="font-bold text-purple-800 mb-1">프론트엔드 ()</p>
<p class="text-purple-700">사용자가 보는 화면<br>HTML, CSS, JavaScript<br>버튼, , 메뉴, 테이블</p>
</div>
<div class="bg-gray-50 rounded-lg p-4 border text-center">
<div class="mb-2">
<svg class="w-8 h-8 mx-auto text-gray-500" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M5 12h14M5 12a2 2 0 01-2-2V6a2 2 0 012-2h14a2 2 0 012 2v4a2 2 0 01-2 2M5 12a2 2 0 00-2 2v4a2 2 0 002 2h14a2 2 0 002-2v-4a2 2 0 00-2-2" /></svg>
</div>
<p class="font-bold text-gray-800 mb-1">백엔드 (주방)</p>
<p class="text-gray-600">서버에서 처리하는 로직<br>PHP, Python, Java<br>데이터 저장, 인증, 계산</p>
</div>
</div>
</div>
<!-- 1-2. 웹의 3요소 -->
<div id="web-trio" class="scroll-mt-20 mb-4">
<h3 class="text-lg font-semibold text-gray-800 mb-3 flex items-center gap-2">
<span class="w-2 h-2 bg-purple-400 rounded-full"></span>
웹의 3요소
</h3>
<p class="text-sm text-gray-700 mb-4">
프론트엔드는 가지 기술로 구성된다. 셋은 항상 함께 작동한다.
</p>
<div class="grid grid-cols-1 md:grid-cols-3 gap-3 text-xs mb-4">
<div class="bg-orange-50 rounded-lg p-4 border border-orange-200 text-center">
<div class="mb-2">
<svg class="w-8 h-8 mx-auto text-orange-500" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M19 11H5m14 0a2 2 0 012 2v6a2 2 0 01-2 2H5a2 2 0 01-2-2v-6a2 2 0 012-2m14 0V9a2 2 0 00-2-2M5 11V9a2 2 0 012-2m0 0V5a2 2 0 012-2h6a2 2 0 012 2v2M7 7h10" /></svg>
</div>
<p class="font-bold text-orange-800 mb-1">HTML (구조)</p>
<p class="text-orange-700">건물의 뼈대<br>, 거실, 주방의 위치를 정한다</p>
</div>
<div class="bg-blue-50 rounded-lg p-4 border border-blue-200 text-center">
<div class="mb-2">
<svg class="w-8 h-8 mx-auto text-blue-500" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M7 21a4 4 0 01-4-4V5a2 2 0 012-2h4a2 2 0 012 2v12a4 4 0 01-4 4zm0 0h12a2 2 0 002-2v-4a2 2 0 00-2-2h-2.343M11 7.343l1.657-1.657a2 2 0 012.828 0l2.829 2.829a2 2 0 010 2.828l-8.486 8.485M7 17h.01" /></svg>
</div>
<p class="font-bold text-blue-800 mb-1">CSS (디자인)</p>
<p class="text-blue-700">인테리어<br>벽지, 가구 배치, 조명을 결정한다</p>
</div>
<div class="bg-yellow-50 rounded-lg p-4 border border-yellow-200 text-center">
<div class="mb-2">
<svg class="w-8 h-8 mx-auto text-yellow-600" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M13 10V3L4 14h7v7l9-11h-7z" /></svg>
</div>
<p class="font-bold text-yellow-800 mb-1">JavaScript (동작)</p>
<p class="text-yellow-700">전기 배선<br>스위치를 누르면 조명이 켜진다</p>
</div>
</div>
<div class="bg-purple-50 rounded-lg p-4 border border-purple-100">
<p class="text-xs text-purple-800 leading-relaxed">
<strong>SAM 시스템의 프론트엔드:</strong>
SAM도 프론트엔드와 백엔드로 분리되어 있다. MNG(관리자 ) Blade + HTMX로, React 앱은 Next.js로 화면을 구성하고,
API 서버(Laravel) 데이터를 처리한다.
</p>
</div>
</div>
</div>
</section>
{{-- ============================================================ --}}
{{-- 2. HTML 웹의 뼈대 --}}
{{-- ============================================================ --}}
<section id="html" class="scroll-mt-20">
<div class="bg-white rounded-xl shadow-sm border border-gray-100 p-6">
<h2 class="text-xl font-bold text-gray-800 mb-6 flex items-center gap-3">
<span class="w-8 h-8 bg-purple-500 text-white rounded-lg flex items-center justify-center text-sm font-bold">2</span>
HTML 웹의 뼈대
</h2>
<!-- 2-1. 태그와 구조 -->
<div id="html-tags" class="scroll-mt-20 mb-8">
<h3 class="text-lg font-semibold text-gray-800 mb-3 flex items-center gap-2">
<span class="w-2 h-2 bg-purple-400 rounded-full"></span>
태그와 구조
</h3>
<div class="bg-amber-50 rounded-lg p-4 border border-amber-100 mb-4">
<p class="font-semibold text-amber-800 mb-2">비유: 건물의 설계도</p>
<p class="text-xs text-amber-900 leading-relaxed">
HTML은 <strong>건물의 설계도</strong> 같다. 여기는 거실, 저기는 주방, 위층은 침실 이렇게 공간의 위치와 구조를 정한다.
HTML 태그가 바로 역할을 한다. <code>&lt;div&gt;</code> , <code>&lt;p&gt;</code> 메모지, <code>&lt;img&gt;</code> 액자다.
</p>
</div>
<p class="text-sm text-gray-700 mb-3">
HTML(HyperText Markup Language) 페이지의 구조를 정의하는 마크업 언어다.
모든 페이지는 HTML 태그로 구성된다.
</p>
<div class="code-block mb-4"><span class="code-comment">&lt;!-- HTML 기본 구조 --&gt;</span>
<span class="code-tag">&lt;html&gt;</span>
<span class="code-tag">&lt;head&gt;</span>
<span class="code-tag">&lt;title&gt;</span>페이지 제목<span class="code-tag">&lt;/title&gt;</span>
<span class="code-tag">&lt;/head&gt;</span>
<span class="code-tag">&lt;body&gt;</span>
<span class="code-tag">&lt;h1&gt;</span>안녕하세요<span class="code-tag">&lt;/h1&gt;</span>
<span class="code-tag">&lt;p&gt;</span> 번째 문단입니다.<span class="code-tag">&lt;/p&gt;</span>
<span class="code-tag">&lt;button&gt;</span>클릭<span class="code-tag">&lt;/button&gt;</span>
<span class="code-tag">&lt;/body&gt;</span>
<span class="code-tag">&lt;/html&gt;</span></div>
<div class="overflow-x-auto">
<table class="w-full text-sm border-collapse">
<thead>
<tr class="border-b-2 border-gray-200 bg-gray-50">
<th class="text-left py-2 px-3 font-medium text-gray-600">태그</th>
<th class="text-left py-2 px-3 font-medium text-gray-600">비유</th>
<th class="text-left py-2 px-3 font-medium text-gray-600">역할</th>
</tr>
</thead>
<tbody class="text-xs text-gray-700">
<tr class="border-b border-gray-100">
<td class="py-2 px-3 font-mono">&lt;div&gt;</td>
<td class="py-2 px-3"> </td>
<td class="py-2 px-3">영역을 나누는 범용 컨테이너</td>
</tr>
<tr class="border-b border-gray-100">
<td class="py-2 px-3 font-mono">&lt;p&gt;</td>
<td class="py-2 px-3">메모지</td>
<td class="py-2 px-3">문단(paragraph)</td>
</tr>
<tr class="border-b border-gray-100">
<td class="py-2 px-3 font-mono">&lt;h1&gt;~&lt;h6&gt;</td>
<td class="py-2 px-3">간판(크기순)</td>
<td class="py-2 px-3">제목(heading), h1이 가장 </td>
</tr>
<tr class="border-b border-gray-100">
<td class="py-2 px-3 font-mono">&lt;a&gt;</td>
<td class="py-2 px-3"> (다른 방으로)</td>
<td class="py-2 px-3">링크(anchor)</td>
</tr>
<tr class="border-b border-gray-100">
<td class="py-2 px-3 font-mono">&lt;img&gt;</td>
<td class="py-2 px-3">액자</td>
<td class="py-2 px-3">이미지 표시</td>
</tr>
<tr class="border-b border-gray-100">
<td class="py-2 px-3 font-mono">&lt;form&gt;</td>
<td class="py-2 px-3">주문서</td>
<td class="py-2 px-3">사용자 입력 양식</td>
</tr>
<tr class="border-b border-gray-100">
<td class="py-2 px-3 font-mono">&lt;table&gt;</td>
<td class="py-2 px-3">엑셀 </td>
<td class="py-2 px-3"> 형식 데이터</td>
</tr>
<tr class="border-b border-gray-100">
<td class="py-2 px-3 font-mono">&lt;ul&gt; / &lt;li&gt;</td>
<td class="py-2 px-3">목록 메모</td>
<td class="py-2 px-3">순서 없는 목록</td>
</tr>
<tr class="border-b border-gray-100">
<td class="py-2 px-3 font-mono">&lt;button&gt;</td>
<td class="py-2 px-3">누름 버튼</td>
<td class="py-2 px-3">클릭 가능한 버튼</td>
</tr>
<tr>
<td class="py-2 px-3 font-mono">&lt;input&gt;</td>
<td class="py-2 px-3"> </td>
<td class="py-2 px-3">텍스트 입력 필드</td>
</tr>
</tbody>
</table>
</div>
</div>
<!-- 2-2. 시맨틱 태그 -->
<div id="html-semantic" class="scroll-mt-20 mb-4">
<h3 class="text-lg font-semibold text-gray-800 mb-3 flex items-center gap-2">
<span class="w-2 h-2 bg-purple-400 rounded-full"></span>
시맨틱 태그
</h3>
<p class="text-sm text-gray-700 mb-3">
시맨틱(Semantic) 태그는 "의미가 있는" 태그다. <code>&lt;div&gt;</code> 쓰면 검색엔진이나 스크린리더가 내용을 이해하기 어렵다.
시맨틱 태그를 사용하면 "여기가 메뉴 영역이고, 여기가 본문이고, 여기가 푸터"라고 알려줄 있다.
</p>
<div class="code-block mb-4"><span class="code-comment">&lt;!-- 시맨틱 태그로 구성한 페이지 --&gt;</span>
<span class="code-tag">&lt;header&gt;</span> 로고, 네비게이션 (건물 입구) <span class="code-tag">&lt;/header&gt;</span>
<span class="code-tag">&lt;nav&gt;</span> 메뉴 목록 (안내 표지판) <span class="code-tag">&lt;/nav&gt;</span>
<span class="code-tag">&lt;main&gt;</span> 핵심 콘텐츠 (본관) <span class="code-tag">&lt;/main&gt;</span>
<span class="code-tag">&lt;section&gt;</span> 주제별 구역 ( ) <span class="code-tag">&lt;/section&gt;</span>
<span class="code-tag">&lt;article&gt;</span> 독립 콘텐츠 (개별 사무실) <span class="code-tag">&lt;/article&gt;</span>
<span class="code-tag">&lt;footer&gt;</span> 하단 정보 (건물 로비 안내판) <span class="code-tag">&lt;/footer&gt;</span></div>
<div class="bg-gray-50 rounded-lg p-4 border text-xs text-gray-700">
<p class="font-semibold text-gray-800 mb-2">DOM 트리 구조 (문서 객체 모델)</p>
<pre class="text-xs leading-relaxed text-gray-600">
document
└── html
├── head
└── title
└── body
├── header
└── nav
├── main
├── section
└── section
└── footer</pre>
<p class="mt-2 text-gray-500">
브라우저는 HTML을 읽어 위와 같은 트리(나무) 구조로 변환한다. 이를 <strong>DOM(Document Object Model)</strong>이라 한다.
</p>
</div>
</div>
</div>
</section>
{{-- ============================================================ --}}
{{-- 3. CSS 웹의 --}}
{{-- ============================================================ --}}
<section id="css" class="scroll-mt-20">
<div class="bg-white rounded-xl shadow-sm border border-gray-100 p-6">
<h2 class="text-xl font-bold text-gray-800 mb-6 flex items-center gap-3">
<span class="w-8 h-8 bg-purple-500 text-white rounded-lg flex items-center justify-center text-sm font-bold">3</span>
CSS 웹의
</h2>
<!-- 3-1. 선택자와 박스모델 -->
<div id="css-selector" class="scroll-mt-20 mb-8">
<h3 class="text-lg font-semibold text-gray-800 mb-3 flex items-center gap-2">
<span class="w-2 h-2 bg-purple-400 rounded-full"></span>
선택자와 박스모델
</h3>
<div class="bg-amber-50 rounded-lg p-4 border border-amber-100 mb-4">
<p class="font-semibold text-amber-800 mb-2">비유: 인테리어 디자인</p>
<p class="text-xs text-amber-900 leading-relaxed">
CSS는 <strong>인테리어</strong> 같다. HTML이 방의 위치를 정했다면, CSS는 벽지 , 가구 크기, 조명 밝기를 결정한다.
"거실 벽은 흰색, 소파는 가운데 배치" 같은 지시서가 CSS인 셈이다.
</p>
</div>
<p class="text-sm text-gray-700 mb-3">
CSS(Cascading Style Sheets) HTML 요소의 외양을 꾸미는 스타일 언어다.
<strong>선택자</strong> "어떤 요소를" 지정하고, <strong>속성</strong>으로 "어떻게" 꾸밀지 정한다.
</p>
<div class="code-block mb-4"><span class="code-comment">/* CSS 선택자 기초 */</span>
<span class="code-tag">p</span> { <span class="code-attr">color</span>: <span class="code-string">blue</span>; } <span class="code-comment">/* 태그 선택자 모든 &lt;p&gt; */</span>
<span class="code-tag">.warning</span> { <span class="code-attr">color</span>: <span class="code-string">red</span>; } <span class="code-comment">/* 클래스 선택자 class="warning" */</span>
<span class="code-tag">#header</span> { <span class="code-attr">color</span>: <span class="code-string">green</span>; } <span class="code-comment">/* ID 선택자 — id="header" */</span></div>
<p class="text-sm text-gray-700 mb-3">
<strong>박스모델</strong>: 모든 HTML 요소는 상자(box) 취급된다. 상자 안쪽부터 바깥쪽 순서로 구성된다.
</p>
<div class="bg-gray-50 rounded-lg p-4 border text-xs text-gray-700 mb-4">
<pre class="text-center leading-loose text-gray-600">
┌──────────────── margin (바깥 여백) ────────────────┐
┌──────────── border (테두리) ──────────────┐
┌──────── padding (안쪽 여백) ────────┐
content (내용물)
└─────────────────────────────────────┘
└───────────────────────────────────────────┘
└────────────────────────────────────────────────────┘</pre>
</div>
</div>
<!-- 3-2. Flexbox와 Grid -->
<div id="css-layout" class="scroll-mt-20 mb-4">
<h3 class="text-lg font-semibold text-gray-800 mb-3 flex items-center gap-2">
<span class="w-2 h-2 bg-purple-400 rounded-full"></span>
Flexbox와 Grid
</h3>
<p class="text-sm text-gray-700 mb-3">
현대 CSS 레이아웃의 기둥이다. 요소를 가로/세로로 배치하는 강력한 도구다.
</p>
<div class="grid grid-cols-1 md:grid-cols-2 gap-4 mb-4">
<div class="bg-blue-50 rounded-lg p-4 border border-blue-200">
<p class="font-bold text-blue-800 mb-2 text-sm">Flexbox (1차원 배치)</p>
<p class="text-xs text-blue-700 mb-2"> (가로 또는 세로) 요소를 나란히 배치할 사용한다.</p>
<div class="code-block text-xs"><span class="code-attr">display</span>: <span class="code-string">flex</span>;
<span class="code-attr">justify-content</span>: <span class="code-string">space-between</span>;
<span class="code-attr">align-items</span>: <span class="code-string">center</span>;</div>
</div>
<div class="bg-green-50 rounded-lg p-4 border border-green-200">
<p class="font-bold text-green-800 mb-2 text-sm">Grid (2차원 배치)</p>
<p class="text-xs text-green-700 mb-2">행과 열을 동시에 제어하는 바둑판식 레이아웃에 사용한다.</p>
<div class="code-block text-xs"><span class="code-attr">display</span>: <span class="code-string">grid</span>;
<span class="code-attr">grid-template-columns</span>: <span class="code-string">1fr 1fr 1fr</span>;
<span class="code-attr">gap</span>: <span class="code-string">1rem</span>;</div>
</div>
</div>
<div class="bg-purple-50 rounded-lg p-4 border border-purple-100">
<p class="text-xs text-purple-800 leading-relaxed">
<strong>SAM에서는 Tailwind CSS를 사용한다.</strong>
Tailwind는 CSS를 파일에 따로 작성하지 않고, HTML 클래스명으로 직접 스타일을 적용하는 방식이다.
: <code class="bg-purple-100 px-1 rounded">class="flex items-center gap-2 bg-white rounded-lg p-4"</code>
</p>
</div>
</div>
</div>
</section>
{{-- ============================================================ --}}
{{-- 4. JavaScript 웹의 두뇌 --}}
{{-- ============================================================ --}}
<section id="javascript" class="scroll-mt-20">
<div class="bg-white rounded-xl shadow-sm border border-gray-100 p-6">
<h2 class="text-xl font-bold text-gray-800 mb-6 flex items-center gap-3">
<span class="w-8 h-8 bg-purple-500 text-white rounded-lg flex items-center justify-center text-sm font-bold">4</span>
JavaScript 웹의 두뇌
</h2>
<!-- 4-1. 변수와 함수 -->
<div id="js-basics" class="scroll-mt-20 mb-8">
<h3 class="text-lg font-semibold text-gray-800 mb-3 flex items-center gap-2">
<span class="w-2 h-2 bg-purple-400 rounded-full"></span>
변수와 함수
</h3>
<div class="bg-amber-50 rounded-lg p-4 border border-amber-100 mb-4">
<p class="font-semibold text-amber-800 mb-2">비유: 전기 배선</p>
<p class="text-xs text-amber-900 leading-relaxed">
JavaScript는 <strong>전기 배선</strong> 같다. HTML이 방을 만들고 CSS가 꾸몄다면,
JavaScript는 스위치를 누르면 조명이 켜지고, 리모컨을 누르면 TV가 켜지는 <strong>동작</strong> 담당한다.
</p>
</div>
<div class="code-block mb-4"><span class="code-comment">// 변수 값을 담는 상자</span>
<span class="code-keyword">let</span> <span class="code-func">userName</span> = <span class="code-string">'홍길동'</span>; <span class="code-comment">// 변경 가능</span>
<span class="code-keyword">const</span> <span class="code-func">MAX_COUNT</span> = <span class="code-number">100</span>; <span class="code-comment">// 변경 불가 (상수)</span>
<span class="code-comment">// 함수 재사용 가능한 명령 묶음</span>
<span class="code-keyword">function</span> <span class="code-func">greet</span>(name) {
<span class="code-keyword">return</span> <span class="code-string">'안녕하세요, '</span> + name + <span class="code-string">'님!'</span>;
}
<span class="code-func">greet</span>(<span class="code-string">'김사원'</span>); <span class="code-comment">// "안녕하세요, 김사원님!"</span></div>
<div class="grid grid-cols-1 md:grid-cols-2 gap-3 text-xs mb-4">
<div class="bg-gray-50 rounded-lg p-3 border">
<p class="font-bold text-gray-800 mb-1">이벤트 처리</p>
<p class="text-gray-600">클릭, 입력, 스크롤 사용자 행동을 감지하여 반응한다.</p>
</div>
<div class="bg-gray-50 rounded-lg p-3 border">
<p class="font-bold text-gray-800 mb-1">JSON (데이터 형식)</p>
<p class="text-gray-600">서버와 데이터를 주고받을 사용하는 텍스트 형식이다.</p>
</div>
</div>
</div>
<!-- 4-2. DOM 조작 -->
<div id="js-dom" class="scroll-mt-20 mb-4">
<h3 class="text-lg font-semibold text-gray-800 mb-3 flex items-center gap-2">
<span class="w-2 h-2 bg-purple-400 rounded-full"></span>
DOM 조작과 비동기 통신
</h3>
<p class="text-sm text-gray-700 mb-3">
JavaScript는 DOM(문서 객체) 조작하여 화면을 동적으로 변경할 있다.
또한 <code>fetch()</code> 사용하면 페이지 새로고침 없이 서버 데이터를 가져올 있다.
</p>
<div class="code-block mb-4"><span class="code-comment">// 버튼 클릭 API 호출 화면 업데이트 예시</span>
<span class="code-keyword">const</span> <span class="code-func">btn</span> = document.<span class="code-func">querySelector</span>(<span class="code-string">'#load-btn'</span>);
<span class="code-keyword">const</span> <span class="code-func">result</span> = document.<span class="code-func">querySelector</span>(<span class="code-string">'#result'</span>);
btn.<span class="code-func">addEventListener</span>(<span class="code-string">'click'</span>, <span class="code-keyword">async</span> () => {
<span class="code-keyword">const</span> <span class="code-func">response</span> = <span class="code-keyword">await</span> <span class="code-func">fetch</span>(<span class="code-string">'/api/orders'</span>);
<span class="code-keyword">const</span> <span class="code-func">data</span> = <span class="code-keyword">await</span> response.<span class="code-func">json</span>();
result.<span class="code-func">textContent</span> = <span class="code-string">`주문 </span>${data.length}<span class="code-string">건 로드 완료`</span>;
});</div>
<div class="bg-purple-50 rounded-lg p-4 border border-purple-100">
<p class="text-xs text-purple-800 leading-relaxed">
<strong>비동기 통신이란?</strong> 서버에 데이터를 요청하면서도 화면이 멈추지 않는 방식이다.
마치 식당에서 주문을 넣고 기다리는 동안 물을 마시거나 대화를 있는 것과 같다.
<code>fetch()</code>, <code>async/await</code>, <code>Promise</code> 역할을 한다.
</p>
</div>
</div>
</div>
</section>
{{-- ============================================================ --}}
{{-- 5. 프레임워크와 라이브러리 --}}
{{-- ============================================================ --}}
<section id="frameworks" class="scroll-mt-20">
<div class="bg-white rounded-xl shadow-sm border border-gray-100 p-6">
<h2 class="text-xl font-bold text-gray-800 mb-6 flex items-center gap-3">
<span class="w-8 h-8 bg-purple-500 text-white rounded-lg flex items-center justify-center text-sm font-bold">5</span>
프레임워크와 라이브러리
</h2>
<!-- 5-1. 프레임워크 비교 -->
<div id="fw-compare" class="scroll-mt-20 mb-8">
<h3 class="text-lg font-semibold text-gray-800 mb-3 flex items-center gap-2">
<span class="w-2 h-2 bg-purple-400 rounded-full"></span>
프레임워크 vs 라이브러리
</h3>
<div class="bg-amber-50 rounded-lg p-4 border border-amber-100 mb-4">
<p class="font-semibold text-amber-800 mb-2">비유: 반조립 가구 vs 공구 세트</p>
<p class="text-xs text-amber-900 leading-relaxed">
<strong>프레임워크</strong> 이케아의 반조립 가구 설계도와 부품이 정해져 있어서 순서대로 조립하면 완성된다.
<strong>라이브러리</strong> 공구 세트 필요할 원하는 도구만 꺼내 쓴다. 설계는 내가 한다.
</p>
</div>
<div class="grid grid-cols-1 md:grid-cols-3 gap-3 text-xs mb-4">
<div class="bg-blue-50 rounded-lg p-4 border border-blue-200">
<div class="flex items-center gap-2 mb-2">
<span class="w-6 h-6 bg-blue-500 text-white rounded flex items-center justify-center text-xs font-bold">R</span>
<span class="font-bold text-blue-800">React</span>
</div>
<p class="text-blue-700 mb-2">Meta(Facebook) 개발</p>
<ul class="text-blue-600 space-y-1">
<li> 컴포넌트 기반 설계</li>
<li> 가상 DOM으로 빠른 렌더링</li>
<li> 생태계가 가장 </li>
</ul>
</div>
<div class="bg-emerald-50 rounded-lg p-4 border border-emerald-200">
<div class="flex items-center gap-2 mb-2">
<span class="w-6 h-6 bg-emerald-500 text-white rounded flex items-center justify-center text-xs font-bold">V</span>
<span class="font-bold text-emerald-800">Vue</span>
</div>
<p class="text-emerald-700 mb-2">Evan You 개발</p>
<ul class="text-emerald-600 space-y-1">
<li> 학습 곡선이 완만</li>
<li> 양방향 데이터 바인딩</li>
<li> 한국에서 인기</li>
</ul>
</div>
<div class="bg-red-50 rounded-lg p-4 border border-red-200">
<div class="flex items-center gap-2 mb-2">
<span class="w-6 h-6 bg-red-500 text-white rounded flex items-center justify-center text-xs font-bold">A</span>
<span class="font-bold text-red-800">Angular</span>
</div>
<p class="text-red-700 mb-2">Google 개발</p>
<ul class="text-red-600 space-y-1">
<li> (Full) 프레임워크</li>
<li> TypeScript 기본</li>
<li> 대규모 엔터프라이즈</li>
</ul>
</div>
</div>
<div class="overflow-x-auto mb-4">
<table class="w-full text-sm border-collapse">
<thead>
<tr class="border-b-2 border-gray-200 bg-gray-50">
<th class="text-left py-2 px-3 font-medium text-gray-600">기술</th>
<th class="text-left py-2 px-3 font-medium text-gray-600">유형</th>
<th class="text-left py-2 px-3 font-medium text-gray-600">특징</th>
</tr>
</thead>
<tbody class="text-xs text-gray-700">
<tr class="border-b border-gray-100">
<td class="py-2 px-3 font-medium">Next.js</td>
<td class="py-2 px-3">React 기반 프레임워크</td>
<td class="py-2 px-3">서버사이드 렌더링(SSR), 파일 기반 라우팅</td>
</tr>
<tr class="border-b border-gray-100">
<td class="py-2 px-3 font-medium">HTMX</td>
<td class="py-2 px-3">경량 라이브러리</td>
<td class="py-2 px-3">HTML 속성만으로 AJAX 요청 처리</td>
</tr>
<tr>
<td class="py-2 px-3 font-medium">jQuery</td>
<td class="py-2 px-3">라이브러리 (레거시)</td>
<td class="py-2 px-3">DOM 조작 간소화, 2006 등장 시대를 풍미</td>
</tr>
</tbody>
</table>
</div>
</div>
<!-- 5-2. SAM의 선택 -->
<div id="fw-sam" class="scroll-mt-20 mb-4">
<h3 class="text-lg font-semibold text-gray-800 mb-3 flex items-center gap-2">
<span class="w-2 h-2 bg-purple-400 rounded-full"></span>
SAM의 프론트엔드 구조
</h3>
<div class="bg-purple-50 rounded-lg p-5 border border-purple-100">
<p class="text-sm text-purple-900 leading-relaxed mb-3">
<strong>SAM은 이중 프론트엔드 구조</strong> 사용한다.
</p>
<div class="grid grid-cols-1 md:grid-cols-2 gap-3 text-xs">
<div class="bg-white rounded-lg p-3 border">
<p class="font-bold text-purple-800 mb-1">MNG (관리자 )</p>
<p class="text-purple-700">Laravel Blade + HTMX + Tailwind CSS</p>
<p class="text-gray-500 mt-1">서버에서 HTML을 생성하여 전달</p>
</div>
<div class="bg-white rounded-lg p-3 border">
<p class="font-bold text-purple-800 mb-1">React (모바일/대시보드)</p>
<p class="text-purple-700">Next.js + React 18</p>
<p class="text-gray-500 mt-1">브라우저에서 JavaScript로 화면 구성</p>
</div>
</div>
</div>
</div>
</div>
</section>
{{-- ============================================================ --}}
{{-- 6. 반응형 디자인 --}}
{{-- ============================================================ --}}
<section id="responsive" class="scroll-mt-20">
<div class="bg-white rounded-xl shadow-sm border border-gray-100 p-6">
<h2 class="text-xl font-bold text-gray-800 mb-6 flex items-center gap-3">
<span class="w-8 h-8 bg-purple-500 text-white rounded-lg flex items-center justify-center text-sm font-bold">6</span>
반응형 디자인
</h2>
<div id="rwd-breakpoint" class="scroll-mt-20 mb-4">
<h3 class="text-lg font-semibold text-gray-800 mb-3 flex items-center gap-2">
<span class="w-2 h-2 bg-purple-400 rounded-full"></span>
브레이크포인트와 모바일 퍼스트
</h3>
<div class="bg-amber-50 rounded-lg p-4 border border-amber-100 mb-4">
<p class="font-semibold text-amber-800 mb-2">비유: 물은 그릇 모양에 따라 변한다</p>
<p class="text-xs text-amber-900 leading-relaxed">
반응형 디자인은 <strong></strong> 같다. 컵에 담으면 모양, 접시에 부으면 접시 모양이 된다.
화면 크기(모바일, 태블릿, 데스크톱) 따라 레이아웃이 자동으로 바뀌는 것이 반응형이다.
</p>
</div>
<p class="text-sm text-gray-700 mb-3">
<strong>브레이크포인트(Breakpoint)</strong> 레이아웃이 전환되는 화면 너비 기준점이다.
</p>
<div class="overflow-x-auto mb-4">
<table class="w-full text-sm border-collapse">
<thead>
<tr class="border-b-2 border-gray-200 bg-gray-50">
<th class="text-left py-2 px-3 font-medium text-gray-600">기기</th>
<th class="text-left py-2 px-3 font-medium text-gray-600">너비</th>
<th class="text-left py-2 px-3 font-medium text-gray-600">Tailwind 접두사</th>
<th class="text-left py-2 px-3 font-medium text-gray-600">예시</th>
</tr>
</thead>
<tbody class="text-xs text-gray-700">
<tr class="border-b border-gray-100">
<td class="py-2 px-3">모바일</td>
<td class="py-2 px-3">~639px</td>
<td class="py-2 px-3 font-mono">(기본)</td>
<td class="py-2 px-3">스마트폰</td>
</tr>
<tr class="border-b border-gray-100">
<td class="py-2 px-3">태블릿</td>
<td class="py-2 px-3">640px~</td>
<td class="py-2 px-3 font-mono">sm:</td>
<td class="py-2 px-3">아이패드</td>
</tr>
<tr class="border-b border-gray-100">
<td class="py-2 px-3">중간</td>
<td class="py-2 px-3">768px~</td>
<td class="py-2 px-3 font-mono">md:</td>
<td class="py-2 px-3">태블릿 가로</td>
</tr>
<tr class="border-b border-gray-100">
<td class="py-2 px-3">데스크톱</td>
<td class="py-2 px-3">1024px~</td>
<td class="py-2 px-3 font-mono">lg:</td>
<td class="py-2 px-3">노트북</td>
</tr>
<tr>
<td class="py-2 px-3">대형</td>
<td class="py-2 px-3">1280px~</td>
<td class="py-2 px-3 font-mono">xl:</td>
<td class="py-2 px-3">대형 모니터</td>
</tr>
</tbody>
</table>
</div>
<div class="code-block mb-4"><span class="code-comment">/* 모바일 퍼스트 작은 화면부터 설계 */</span>
<span class="code-tag">.card</span> {
<span class="code-attr">width</span>: <span class="code-string">100%</span>; <span class="code-comment">/* 모바일: 전체 너비 */</span>
}
<span class="code-keyword">@media</span> (<span class="code-attr">min-width</span>: <span class="code-number">768</span>px) {
<span class="code-tag">.card</span> { <span class="code-attr">width</span>: <span class="code-string">50%</span>; } <span class="code-comment">/* 태블릿: 2 */</span>
}
<span class="code-keyword">@media</span> (<span class="code-attr">min-width</span>: <span class="code-number">1024</span>px) {
<span class="code-tag">.card</span> { <span class="code-attr">width</span>: <span class="code-string">33.3%</span>; } <span class="code-comment">/* 데스크톱: 3 */</span>
}</div>
<div class="bg-gray-50 rounded-lg p-4 border text-xs text-gray-700 mb-4">
<p class="font-semibold text-gray-800 mb-2">디자인 흐름 (모바일 퍼스트)</p>
<div class="flex items-center gap-2 flex-wrap">
<span class="bg-purple-500 text-white rounded-full px-3 py-1 text-xs font-bold">1</span>
<span>모바일 레이아웃</span>
<span class="text-purple-400"></span>
<span class="bg-purple-500 text-white rounded-full px-3 py-1 text-xs font-bold">2</span>
<span>태블릿 확장</span>
<span class="text-purple-400"></span>
<span class="bg-purple-500 text-white rounded-full px-3 py-1 text-xs font-bold">3</span>
<span>데스크톱 완성</span>
</div>
</div>
<div class="bg-purple-50 rounded-lg p-4 border border-purple-100">
<p class="text-xs text-purple-800 leading-relaxed">
<strong>viewport 메타 태그:</strong>
<code class="bg-purple-100 px-1 rounded">&lt;meta name="viewport" content="width=device-width, initial-scale=1"&gt;</code>
줄이 없으면 모바일에서 데스크톱 크기로 축소되어 보인다. 모든 반응형 페이지의 필수 태그다.
</p>
</div>
</div>
</div>
</section>
{{-- ============================================================ --}}
{{-- 7. 브라우저 동작 원리 --}}
{{-- ============================================================ --}}
<section id="browser" class="scroll-mt-20">
<div class="bg-white rounded-xl shadow-sm border border-gray-100 p-6">
<h2 class="text-xl font-bold text-gray-800 mb-6 flex items-center gap-3">
<span class="w-8 h-8 bg-purple-500 text-white rounded-lg flex items-center justify-center text-sm font-bold">7</span>
브라우저 동작 원리
</h2>
<div id="browser-render" class="scroll-mt-20 mb-4">
<h3 class="text-lg font-semibold text-gray-800 mb-3 flex items-center gap-2">
<span class="w-2 h-2 bg-purple-400 rounded-full"></span>
렌더링 파이프라인
</h3>
<div class="bg-amber-50 rounded-lg p-4 border border-amber-100 mb-4">
<p class="font-semibold text-amber-800 mb-2">비유: 통역사</p>
<p class="text-xs text-amber-900 leading-relaxed">
브라우저는 <strong>통역사</strong> 같다. HTML/CSS/JavaScript라는 "외국어" 읽고, 우리가 있는 화면으로 번역해준다.
번역 과정을 <strong>렌더링(Rendering)</strong>이라 한다.
</p>
</div>
<div class="bg-gray-50 rounded-lg p-4 border text-xs text-gray-700 mb-4">
<p class="font-semibold text-gray-800 mb-3">렌더링 과정 (6단계)</p>
<div class="space-y-2">
<div class="flex items-center gap-3">
<span class="w-7 h-7 bg-purple-500 text-white rounded-full flex items-center justify-center text-xs font-bold shrink-0">1</span>
<div><strong>HTML 파싱</strong> HTML 코드를 읽어 DOM 트리를 생성한다</div>
</div>
<div class="flex items-center gap-3">
<span class="w-7 h-7 bg-purple-500 text-white rounded-full flex items-center justify-center text-xs font-bold shrink-0">2</span>
<div><strong>CSS 파싱</strong> CSS를 읽어 CSSOM(스타일 트리) 생성한다</div>
</div>
<div class="flex items-center gap-3">
<span class="w-7 h-7 bg-purple-500 text-white rounded-full flex items-center justify-center text-xs font-bold shrink-0">3</span>
<div><strong>렌더 트리</strong> DOM + CSSOM을 합쳐 실제 화면에 표시할 요소를 결정한다</div>
</div>
<div class="flex items-center gap-3">
<span class="w-7 h-7 bg-purple-500 text-white rounded-full flex items-center justify-center text-xs font-bold shrink-0">4</span>
<div><strong>레이아웃</strong> 요소의 정확한 위치와 크기를 계산한다</div>
</div>
<div class="flex items-center gap-3">
<span class="w-7 h-7 bg-purple-500 text-white rounded-full flex items-center justify-center text-xs font-bold shrink-0">5</span>
<div><strong>페인트</strong> 계산된 결과를 실제 픽셀로 그린다</div>
</div>
<div class="flex items-center gap-3">
<span class="w-7 h-7 bg-purple-500 text-white rounded-full flex items-center justify-center text-xs font-bold shrink-0">6</span>
<div><strong>합성</strong> 여러 레이어를 합쳐 최종 화면을 완성한다</div>
</div>
</div>
</div>
<div class="grid grid-cols-1 md:grid-cols-2 gap-3 text-xs mb-4">
<div class="bg-gray-50 rounded-lg p-4 border">
<p class="font-bold text-gray-800 mb-2">개발자 도구 (F12)</p>
<p class="text-gray-600 mb-2">브라우저에서 F12 키를 누르면 개발자 도구가 열린다.</p>
<ul class="text-gray-600 space-y-1">
<li><strong>Elements</strong> HTML 구조 확인/수정</li>
<li><strong>Console</strong> JavaScript 실행/오류 확인</li>
<li><strong>Network</strong> API 요청/응답 확인</li>
<li><strong>Performance</strong> 성능 분석</li>
</ul>
</div>
<div class="bg-gray-50 rounded-lg p-4 border">
<p class="font-bold text-gray-800 mb-2">주요 브라우저</p>
<ul class="text-gray-600 space-y-1">
<li><strong>Chrome</strong> 점유율 1, V8 엔진</li>
<li><strong>Safari</strong> Apple 기기 기본 브라우저</li>
<li><strong>Firefox</strong> Mozilla 재단, 개인정보 보호</li>
<li><strong>Edge</strong> Microsoft, Chromium 기반</li>
</ul>
</div>
</div>
<details class="bg-gray-50 rounded-lg border">
<summary class="p-4 cursor-pointer text-sm font-semibold text-gray-700">
CORS 에러가 발생하는 이유
</summary>
<div class="px-4 pb-4 text-xs text-gray-600 leading-relaxed">
<p class="mb-2">
<strong>CORS(Cross-Origin Resource Sharing)</strong> 브라우저의 보안 정책이다.
A 도메인의 웹페이지에서 B 도메인의 API를 호출하면, 브라우저가 "이거 허가받은 요청이야?" 하고 확인한다.
</p>
<p class="mb-2">
서버가 응답 헤더에 <code>Access-Control-Allow-Origin</code> 포함하지 않으면 브라우저가 요청을 차단한다.
이때 콘솔에 빨간 CORS 에러가 표시된다.
</p>
<p>
<strong>해결법:</strong> 서버(백엔드) 쪽에서 CORS 헤더를 설정해야 한다. 프론트엔드만으로는 해결할 없다.
</p>
</div>
</details>
</div>
</div>
</section>
{{-- ============================================================ --}}
{{-- 8. API 연동 --}}
{{-- ============================================================ --}}
<section id="api-integration" class="scroll-mt-20">
<div class="bg-white rounded-xl shadow-sm border border-gray-100 p-6">
<h2 class="text-xl font-bold text-gray-800 mb-6 flex items-center gap-3">
<span class="w-8 h-8 bg-purple-500 text-white rounded-lg flex items-center justify-center text-sm font-bold">8</span>
API 연동
</h2>
<div id="api-http" class="scroll-mt-20 mb-4">
<h3 class="text-lg font-semibold text-gray-800 mb-3 flex items-center gap-2">
<span class="w-2 h-2 bg-purple-400 rounded-full"></span>
REST API와 HTTP 메서드
</h3>
<div class="bg-amber-50 rounded-lg p-4 border border-amber-100 mb-4">
<p class="font-semibold text-amber-800 mb-2">비유: 식당의 주문서</p>
<p class="text-xs text-amber-900 leading-relaxed">
API는 <strong>주문서</strong> 같다. 프론트엔드() 백엔드(주방) "이 데이터를 주세요"라고 정해진 양식으로 요청하는 것이다.
주문서에는 "무엇을(URL) 어떻게(메서드) 해달라" 적는다.
</p>
</div>
<div class="overflow-x-auto mb-4">
<table class="w-full text-sm border-collapse">
<thead>
<tr class="border-b-2 border-gray-200 bg-gray-50">
<th class="text-left py-2 px-3 font-medium text-gray-600">HTTP 메서드</th>
<th class="text-left py-2 px-3 font-medium text-gray-600">비유</th>
<th class="text-left py-2 px-3 font-medium text-gray-600">용도</th>
<th class="text-left py-2 px-3 font-medium text-gray-600">예시</th>
</tr>
</thead>
<tbody class="text-xs text-gray-700">
<tr class="border-b border-gray-100">
<td class="py-2 px-3 font-mono font-bold text-blue-600">GET</td>
<td class="py-2 px-3">메뉴판 보기</td>
<td class="py-2 px-3">데이터 조회</td>
<td class="py-2 px-3 font-mono">GET /api/orders</td>
</tr>
<tr class="border-b border-gray-100">
<td class="py-2 px-3 font-mono font-bold text-green-600">POST</td>
<td class="py-2 px-3"> 주문하기</td>
<td class="py-2 px-3">데이터 생성</td>
<td class="py-2 px-3 font-mono">POST /api/orders</td>
</tr>
<tr class="border-b border-gray-100">
<td class="py-2 px-3 font-mono font-bold text-orange-600">PUT</td>
<td class="py-2 px-3">주문 변경</td>
<td class="py-2 px-3">데이터 수정</td>
<td class="py-2 px-3 font-mono">PUT /api/orders/1</td>
</tr>
<tr>
<td class="py-2 px-3 font-mono font-bold text-red-600">DELETE</td>
<td class="py-2 px-3">주문 취소</td>
<td class="py-2 px-3">데이터 삭제</td>
<td class="py-2 px-3 font-mono">DELETE /api/orders/1</td>
</tr>
</tbody>
</table>
</div>
<div class="grid grid-cols-1 md:grid-cols-2 gap-3 text-xs mb-4">
<div>
<p class="font-bold text-gray-800 mb-2">JSON 데이터 형식</p>
<div class="code-block">{
<span class="code-attr">"id"</span>: <span class="code-number">1</span>,
<span class="code-attr">"customer"</span>: <span class="code-string">"홍길동"</span>,
<span class="code-attr">"amount"</span>: <span class="code-number">150000</span>,
<span class="code-attr">"status"</span>: <span class="code-string">"진행중"</span>
}</div>
</div>
<div>
<p class="font-bold text-gray-800 mb-2">fetch() API 호출</p>
<div class="code-block"><span class="code-keyword">const</span> res = <span class="code-keyword">await</span> <span class="code-func">fetch</span>(
<span class="code-string">'/api/orders'</span>,
{
<span class="code-attr">method</span>: <span class="code-string">'POST'</span>,
<span class="code-attr">headers</span>: { <span class="code-string">'Content-Type'</span>: <span class="code-string">'application/json'</span> },
<span class="code-attr">body</span>: <span class="code-func">JSON.stringify</span>({ <span class="code-attr">customer</span>: <span class="code-string">'홍길동'</span> })
}
);</div>
</div>
</div>
<div class="overflow-x-auto mb-4">
<table class="w-full text-sm border-collapse">
<thead>
<tr class="border-b-2 border-gray-200 bg-gray-50">
<th class="text-left py-2 px-3 font-medium text-gray-600">상태 코드</th>
<th class="text-left py-2 px-3 font-medium text-gray-600">의미</th>
<th class="text-left py-2 px-3 font-medium text-gray-600">비유</th>
</tr>
</thead>
<tbody class="text-xs text-gray-700">
<tr class="border-b border-gray-100">
<td class="py-2 px-3 font-mono font-bold text-green-600">200</td>
<td class="py-2 px-3">성공</td>
<td class="py-2 px-3">주문한 음식이 나왔다</td>
</tr>
<tr class="border-b border-gray-100">
<td class="py-2 px-3 font-mono font-bold text-orange-600">400</td>
<td class="py-2 px-3">잘못된 요청</td>
<td class="py-2 px-3">주문서를 잘못 작성했다</td>
</tr>
<tr class="border-b border-gray-100">
<td class="py-2 px-3 font-mono font-bold text-orange-600">401</td>
<td class="py-2 px-3">인증 실패</td>
<td class="py-2 px-3">회원증 없이 회원 전용 식당에 왔다</td>
</tr>
<tr class="border-b border-gray-100">
<td class="py-2 px-3 font-mono font-bold text-orange-600">404</td>
<td class="py-2 px-3">찾을 없음</td>
<td class="py-2 px-3">해당 메뉴가 없다</td>
</tr>
<tr>
<td class="py-2 px-3 font-mono font-bold text-red-600">500</td>
<td class="py-2 px-3">서버 오류</td>
<td class="py-2 px-3">주방에서 화재가 났다</td>
</tr>
</tbody>
</table>
</div>
<div class="bg-purple-50 rounded-lg p-4 border border-purple-100">
<p class="text-xs text-purple-800 leading-relaxed">
<strong>SAM의 API 통신:</strong>
SAM React 앱은 <code>api.sam-erp.com</code> API 서버와 통신한다. MNG에서는 HTMX가 서버에 요청을 보내고 HTML 조각을 받아 화면을 업데이트한다.
</p>
</div>
</div>
</div>
</section>
{{-- ============================================================ --}}
{{-- 9. 개발 도구와 워크플로우 --}}
{{-- ============================================================ --}}
<section id="tooling" class="scroll-mt-20">
<div class="bg-white rounded-xl shadow-sm border border-gray-100 p-6">
<h2 class="text-xl font-bold text-gray-800 mb-6 flex items-center gap-3">
<span class="w-8 h-8 bg-purple-500 text-white rounded-lg flex items-center justify-center text-sm font-bold">9</span>
개발 도구와 워크플로우
</h2>
<div id="tool-workflow" class="scroll-mt-20 mb-4">
<h3 class="text-lg font-semibold text-gray-800 mb-3 flex items-center gap-2">
<span class="w-2 h-2 bg-purple-400 rounded-full"></span>
핵심 도구와 개발 흐름
</h3>
<div class="grid grid-cols-1 md:grid-cols-2 gap-3 text-xs mb-4">
<div class="bg-blue-50 rounded-lg p-4 border border-blue-200">
<p class="font-bold text-blue-800 mb-2">VS Code</p>
<p class="text-blue-700">가장 널리 쓰이는 코드 에디터. 확장 프로그램으로 기능을 무한히 추가할 있다. 무료.</p>
</div>
<div class="bg-orange-50 rounded-lg p-4 border border-orange-200">
<p class="font-bold text-orange-800 mb-2">npm (Node Package Manager)</p>
<p class="text-orange-700">JavaScript 패키지(라이브러리) 설치·관리하는 도구. <code>npm install</code> 의존성을 설치한다.</p>
</div>
<div class="bg-gray-50 rounded-lg p-4 border">
<p class="font-bold text-gray-800 mb-2">Git</p>
<p class="text-gray-600">코드 버전 관리. 변경 이력 추적, 협업, 되돌리기가 가능하다. ( 서버지식 백과사전 참고)</p>
</div>
<div class="bg-purple-50 rounded-lg p-4 border border-purple-200">
<p class="font-bold text-purple-800 mb-2">린터 & 포매터</p>
<p class="text-purple-700">ESLint(코드 오류 검출), Prettier(코드 스타일 자동 정리). PHP에서는 Pint를 사용한다.</p>
</div>
</div>
<div class="grid grid-cols-1 md:grid-cols-2 gap-4 mb-4">
<div class="bg-emerald-50 rounded-lg p-4 border border-emerald-200">
<p class="font-bold text-emerald-800 mb-2 text-sm">Vite (현대적 번들러)</p>
<p class="text-xs text-emerald-700 mb-2">차세대 프론트엔드 빌드 도구. 빠른 개발 서버와 효율적인 번들링을 제공한다.</p>
<ul class="text-xs text-emerald-600 space-y-1">
<li> 즉시 시작되는 개발 서버</li>
<li> 변경 사항 즉시 반영 (HMR)</li>
<li> Rollup 기반 최적 빌드</li>
</ul>
</div>
<div class="bg-gray-50 rounded-lg p-4 border">
<p class="font-bold text-gray-800 mb-2 text-sm">Webpack (전통적 번들러)</p>
<p class="text-xs text-gray-600 mb-2">오랫동안 표준이었던 번들러. 복잡하지만 강력한 설정이 가능하다.</p>
<ul class="text-xs text-gray-500 space-y-1">
<li> 풍부한 플러그인 생태계</li>
<li> 세밀한 설정 가능</li>
<li> 대규모 프로젝트에 적합</li>
</ul>
</div>
</div>
<div class="bg-gray-50 rounded-lg p-4 border text-xs text-gray-700 mb-4">
<p class="font-semibold text-gray-800 mb-3">개발 워크플로우</p>
<div class="space-y-2">
<div class="flex items-center gap-3">
<span class="w-7 h-7 bg-purple-500 text-white rounded-full flex items-center justify-center text-xs font-bold shrink-0">1</span>
<div><strong>코드 작성</strong> VS Code에서 HTML/CSS/JS 작성</div>
</div>
<div class="flex items-center gap-3">
<span class="w-7 h-7 bg-purple-500 text-white rounded-full flex items-center justify-center text-xs font-bold shrink-0">2</span>
<div><strong>린트 검사</strong> ESLint/Prettier로 코드 품질 확인</div>
</div>
<div class="flex items-center gap-3">
<span class="w-7 h-7 bg-purple-500 text-white rounded-full flex items-center justify-center text-xs font-bold shrink-0">3</span>
<div><strong>로컬 테스트</strong> 브라우저에서 동작 확인 (개발 서버)</div>
</div>
<div class="flex items-center gap-3">
<span class="w-7 h-7 bg-purple-500 text-white rounded-full flex items-center justify-center text-xs font-bold shrink-0">4</span>
<div><strong>Git 커밋</strong> 변경사항 저장 (버전 관리)</div>
</div>
<div class="flex items-center gap-3">
<span class="w-7 h-7 bg-purple-500 text-white rounded-full flex items-center justify-center text-xs font-bold shrink-0">5</span>
<div><strong>빌드</strong> 프로덕션용 최적화 코드 생성</div>
</div>
<div class="flex items-center gap-3">
<span class="w-7 h-7 bg-purple-500 text-white rounded-full flex items-center justify-center text-xs font-bold shrink-0">6</span>
<div><strong>배포</strong> 서버에 적용하여 사용자에게 서비스</div>
</div>
</div>
</div>
</div>
</div>
</section>
{{-- ============================================================ --}}
{{-- 10. 성능 최적화 --}}
{{-- ============================================================ --}}
<section id="performance" class="scroll-mt-20">
<div class="bg-white rounded-xl shadow-sm border border-gray-100 p-6">
<h2 class="text-xl font-bold text-gray-800 mb-6 flex items-center gap-3">
<span class="w-8 h-8 bg-purple-500 text-white rounded-lg flex items-center justify-center text-sm font-bold">10</span>
성능 최적화
</h2>
<div id="perf-vitals" class="scroll-mt-20 mb-4">
<h3 class="text-lg font-semibold text-gray-800 mb-3 flex items-center gap-2">
<span class="w-2 h-2 bg-purple-400 rounded-full"></span>
Lighthouse와 Core Web Vitals
</h3>
<p class="text-sm text-gray-700 mb-3">
<strong>Lighthouse</strong> Google이 제공하는 성능 측정 도구다.
Chrome 개발자 도구(F12) Lighthouse 탭에서 실행할 있다.
</p>
<div class="grid grid-cols-2 md:grid-cols-4 gap-3 text-xs mb-4">
<div class="bg-green-50 rounded-lg p-3 border border-green-200 text-center">
<p class="font-bold text-green-800 mb-1">Performance</p>
<p class="text-green-600">로딩 속도</p>
</div>
<div class="bg-blue-50 rounded-lg p-3 border border-blue-200 text-center">
<p class="font-bold text-blue-800 mb-1">Accessibility</p>
<p class="text-blue-600">접근성</p>
</div>
<div class="bg-orange-50 rounded-lg p-3 border border-orange-200 text-center">
<p class="font-bold text-orange-800 mb-1">Best Practices</p>
<p class="text-orange-600">모범 사례</p>
</div>
<div class="bg-purple-50 rounded-lg p-3 border border-purple-200 text-center">
<p class="font-bold text-purple-800 mb-1">SEO</p>
<p class="text-purple-600">검색 최적화</p>
</div>
</div>
<div class="overflow-x-auto mb-4">
<table class="w-full text-sm border-collapse">
<thead>
<tr class="border-b-2 border-gray-200 bg-gray-50">
<th class="text-left py-2 px-3 font-medium text-gray-600">지표</th>
<th class="text-left py-2 px-3 font-medium text-gray-600">이름</th>
<th class="text-left py-2 px-3 font-medium text-gray-600">비유</th>
<th class="text-left py-2 px-3 font-medium text-gray-600">좋은 기준</th>
</tr>
</thead>
<tbody class="text-xs text-gray-700">
<tr class="border-b border-gray-100">
<td class="py-2 px-3 font-bold">LCP</td>
<td class="py-2 px-3">Largest Contentful Paint</td>
<td class="py-2 px-3"> 간판이 보이는 시간</td>
<td class="py-2 px-3">2.5 이내</td>
</tr>
<tr class="border-b border-gray-100">
<td class="py-2 px-3 font-bold">FID</td>
<td class="py-2 px-3">First Input Delay</td>
<td class="py-2 px-3">버튼 눌렀을 반응 시간</td>
<td class="py-2 px-3">100ms 이내</td>
</tr>
<tr>
<td class="py-2 px-3 font-bold">CLS</td>
<td class="py-2 px-3">Cumulative Layout Shift</td>
<td class="py-2 px-3">화면 레이아웃이 튀는 정도</td>
<td class="py-2 px-3">0.1 이내</td>
</tr>
</tbody>
</table>
</div>
<div class="grid grid-cols-1 md:grid-cols-2 gap-3 text-xs mb-4">
<div class="bg-green-50 rounded-lg p-4 border border-green-200">
<p class="font-bold text-green-800 mb-2">최적화 방법</p>
<ul class="text-green-700 space-y-1">
<li> <strong>이미지</strong>: WebP 포맷, 적절한 크기, lazy loading</li>
<li> <strong>코드 분할</strong>: 필요한 코드만 로드</li>
<li> <strong>캐싱</strong>: 브라우저 캐시, CDN 활용</li>
<li> <strong>압축</strong>: gzip/brotli로 전송 크기 축소</li>
</ul>
</div>
<div class="bg-red-50 rounded-lg p-4 border border-red-200">
<p class="font-bold text-red-800 mb-2">성능 저하 원인</p>
<ul class="text-red-700 space-y-1">
<li> 대용량 이미지 무압축 로드</li>
<li> 사용하지 않는 JavaScript 번들</li>
<li> 렌더링 차단 CSS/JS</li>
<li> 너무 많은 API 요청</li>
</ul>
</div>
</div>
<details class="bg-gray-50 rounded-lg border">
<summary class="p-4 cursor-pointer text-sm font-semibold text-gray-700">
Lighthouse로 SAM 성능 측정하는
</summary>
<div class="px-4 pb-4 text-xs text-gray-600 leading-relaxed space-y-2">
<p>1. Chrome에서 SAM 페이지를 연다</p>
<p>2. F12를 눌러 개발자 도구를 연다</p>
<p>3. 상단 탭에서 <strong>Lighthouse</strong> 클릭한다</p>
<p>4. "Analyze page load" 클릭한다</p>
<p>5. 30~1 결과가 표시된다</p>
<p class="mt-2 text-gray-500">
항목에서 100점에 가까울수록 좋다. 90 이상이면 녹색, 50~89점은 주황색, 49 이하는 빨간색이다.
</p>
</div>
</details>
<!-- 핵심 정리 -->
<div class="mt-6 bg-purple-50 rounded-lg p-5 border border-purple-100">
<h4 class="font-semibold text-purple-800 mb-2 text-sm">핵심 정리</h4>
<p class="text-xs text-purple-700 leading-relaxed">
프론트엔드는 <strong>"사용자가 보고 만지는 모든 것"</strong>이다.
HTML로 뼈대를 만들고, CSS로 꾸미고, JavaScript로 동작을 넣는다.
React, Vue 같은 프레임워크로 복잡한 화면을 효율적으로 관리하고,
반응형 디자인으로 모든 기기에서 보이게 만든다.
API를 통해 백엔드와 데이터를 주고받고, Lighthouse로 성능을 측정하여 최적화한다.
SAM은 MNG(Blade+HTMX) React(Next.js) 이중 프론트엔드 구조로, 모든 기술을 활용하고 있다.
</p>
</div>
</div>
</div>
</section>
</div>
</div>
</div>
<!-- hover 프리뷰 오버레이 -->
<div id="hover-preview">
<img id="hover-preview-img" src="" alt="">
<span class="hover-caption" id="hover-preview-caption"></span>
</div>
<!-- 클릭 라이트박스 -->
<div id="lightbox" onclick="closeLightbox()">
<button onclick="closeLightbox()" style="position:absolute; top:1rem; right:1rem; background:none; border:none; cursor:pointer; color:rgba(255,255,255,0.8); padding:0.5rem;">
<svg style="width:2rem; height:2rem;" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M6 18L18 6M6 6l12 12" /></svg>
</button>
<img id="lightbox-img" onclick="event.stopPropagation()">
</div>
<script>
(function() {
var preview = document.getElementById('hover-preview');
var previewImg = document.getElementById('hover-preview-img');
var previewCaption = document.getElementById('hover-preview-caption');
var hoverTimer = null;
var isPreviewActive = false;
var HOVER_DELAY = 350;
document.querySelectorAll('.academy-img-hover').forEach(function(img) {
img.addEventListener('mouseenter', function() {
var el = this;
hoverTimer = setTimeout(function() {
showPreview(el);
}, HOVER_DELAY);
});
img.addEventListener('mouseleave', function() {
clearTimeout(hoverTimer);
if (isPreviewActive) {
hidePreview();
}
});
});
function showPreview(el) {
previewImg.src = el.src;
previewImg.alt = el.alt || '';
var caption = el.alt || '';
var nextP = el.parentElement && el.parentElement.querySelector('p');
if (nextP) caption = nextP.textContent;
previewCaption.textContent = caption;
preview.classList.add('is-active');
isPreviewActive = true;
}
function hidePreview() {
preview.classList.remove('is-active');
isPreviewActive = false;
}
window.openLightbox = function(el) {
var lb = document.getElementById('lightbox');
var img = document.getElementById('lightbox-img');
img.src = el.src;
img.alt = el.alt;
lb.classList.add('is-open');
document.body.style.overflow = 'hidden';
hidePreview();
};
window.closeLightbox = function() {
var lb = document.getElementById('lightbox');
lb.classList.remove('is-open');
document.body.style.overflow = '';
};
document.addEventListener('keydown', function(e) {
if (e.key === 'Escape') {
if (isPreviewActive) hidePreview();
closeLightbox();
}
});
})();
</script>
@include('components.academy-glossary', ['domain' => 'frontend-dev'])
@endsection