diff --git a/resources/views/academy/frontend-dev.blade.php b/resources/views/academy/frontend-dev.blade.php index fd3de1d1..4a1078a1 100644 --- a/resources/views/academy/frontend-dev.blade.php +++ b/resources/views/academy/frontend-dev.blade.php @@ -84,6 +84,82 @@ box-shadow: 0 25px 50px rgba(0, 0, 0, 0.5); } + /* 도움말 풍선 */ + .help-balloon-trigger { + display: inline-flex; + align-items: center; + justify-content: center; + width: 18px; + height: 18px; + border-radius: 50%; + background: #ede9fe; + color: #7c3aed; + font-size: 11px; + font-weight: 700; + cursor: pointer; + border: 1.5px solid #c4b5fd; + vertical-align: middle; + margin-left: 4px; + transition: all 0.15s ease; + position: relative; + user-select: none; + } + .help-balloon-trigger:hover { + background: #7c3aed; + color: white; + border-color: #6d28d9; + } + .help-balloon { + display: none; + position: absolute; + bottom: calc(100% + 10px); + left: 50%; + transform: translateX(-50%) scale(0.95); + background: #1e293b; + color: #f1f5f9; + font-size: 12px; + font-weight: 400; + line-height: 1.6; + padding: 10px 14px; + border-radius: 10px; + max-width: 300px; + min-width: 200px; + width: max-content; + white-space: normal; + word-break: keep-all; + box-shadow: 0 8px 24px rgba(0, 0, 0, 0.25); + z-index: 40; + opacity: 0; + transition: opacity 0.15s ease, transform 0.15s ease; + pointer-events: none; + } + .help-balloon::after { + content: ''; + position: absolute; + top: 100%; + left: 50%; + transform: translateX(-50%); + border: 7px solid transparent; + border-top-color: #1e293b; + } + .help-balloon-trigger.is-active .help-balloon { + display: block; + opacity: 1; + transform: translateX(-50%) scale(1); + pointer-events: auto; + } + /* 풍선이 왼쪽으로 넘치지 않도록 */ + .help-balloon-trigger.is-active .help-balloon.balloon-right { + left: auto; + right: -10px; + transform: scale(1); + } + .help-balloon-trigger.is-active .help-balloon.balloon-right::after { + left: auto; + right: 14px; + transform: none; + } + /* 코드 블록 스타일 */ .code-block { background: #1e1e2e; @@ -122,19 +198,10 @@

HTML, CSS, JavaScript부터 프레임워크, 성능 최적화까지 — 비개발자도 이해하는 프론트엔드 가이드

-
- - - - - - - - - - - </> - +
+ 코드 에디터와 브라우저 프리뷰
@@ -229,6 +296,7 @@

프론트엔드 vs 백엔드 + ?프론트엔드는 사용자의 브라우저에서 실행되는 코드(HTML, CSS, JS)이고, 백엔드는 서버에서 실행되는 코드(PHP, Python 등)다. 둘은 API를 통해 데이터를 주고받는다.

@@ -294,13 +362,20 @@

전기 배선
스위치를 누르면 조명이 켜진다

-
+

SAM 시스템의 프론트엔드: SAM도 프론트엔드와 백엔드로 분리되어 있다. MNG(관리자 웹)는 Blade + HTMX로, React 앱은 Next.js로 화면을 구성하고, API 서버(Laravel)가 데이터를 처리한다.

+
+ 프론트엔드 vs 백엔드 비교 다이어그램 +
+

프론트엔드와 백엔드 — 식당의 홀과 주방

@@ -413,6 +488,7 @@

시맨틱 태그 + ?시맨틱(Semantic)은 "의미를 가진"이라는 뜻이다. <div> 대신 <header>, <nav>, <main> 등을 사용하면 검색엔진과 스크린리더가 페이지 구조를 이해할 수 있다.

시맨틱(Semantic) 태그는 "의미가 있는" 태그다. <div>만 쓰면 검색엔진이나 스크린리더가 내용을 이해하기 어렵다. @@ -443,6 +519,13 @@ 브라우저는 HTML을 읽어 위와 같은 트리(나무) 구조로 변환한다. 이를 DOM(Document Object Model)이라 한다.

+
+ HTML DOM 트리 구조 다이어그램 +
+

DOM 트리 — HTML 문서의 구조

@@ -462,6 +545,7 @@

선택자와 박스모델 + ?선택자(Selector)는 "어떤 HTML 요소에 스타일을 적용할지" 지정하는 규칙이다. 박스모델은 모든 요소가 content → padding → border → margin 4겹 상자로 구성된다는 개념이다.

비유: 인테리어 디자인

@@ -495,11 +579,20 @@
+
+ CSS 박스모델 다이어그램 +
+

CSS 박스모델 — margin, border, padding, content

+

Flexbox와 Grid + ?Flexbox는 한 방향(가로 또는 세로)으로 요소를 나열할 때 사용하고, Grid는 가로+세로 2차원으로 배치할 때 사용한다. SAM에서는 Tailwind CSS의 flex/grid 클래스를 활용한다.

현대 CSS 레이아웃의 두 기둥이다. 요소를 가로/세로로 배치하는 강력한 도구다. @@ -581,6 +674,7 @@

DOM 조작과 비동기 통신 + ?DOM 조작은 JavaScript로 화면의 내용을 동적으로 변경하는 것이다. 비동기 통신(fetch)은 페이지 새로고침 없이 서버에서 데이터를 가져오는 기술이다.

JavaScript는 DOM(문서 객체)을 조작하여 화면을 동적으로 변경할 수 있다. @@ -602,6 +696,15 @@ fetch(), async/await, Promise가 이 역할을 한다.

+ + +
+ JavaScript 이벤트 흐름과 DOM 조작 +
+

JavaScript 이벤트 처리와 DOM 조작 흐름

@@ -621,6 +724,7 @@

프레임워크 vs 라이브러리 + ?프레임워크는 전체 구조를 제공하고 개발자가 그 안에서 코드를 작성한다. 라이브러리는 필요한 기능만 골라 쓸 수 있는 도구 모음이다.

비유: 반조립 가구 vs 공구 세트

@@ -720,6 +824,15 @@
+ + +
+ 프레임워크 비교: React, Vue, Angular +
+

React / Vue / Angular 비교와 SAM 아키텍처

@@ -738,6 +851,7 @@

브레이크포인트와 모바일 퍼스트 + ?브레이크포인트는 화면 너비에 따라 레이아웃이 바뀌는 기준점이다. 모바일 퍼스트는 작은 화면부터 디자인한 후 큰 화면으로 확장하는 접근법이다.

비유: 물은 그릇 모양에 따라 변한다

@@ -823,6 +937,15 @@ — 이 한 줄이 없으면 모바일에서 데스크톱 크기로 축소되어 보인다. 모든 반응형 페이지의 필수 태그다.

+ + +
+ 반응형 디자인: 모바일, 태블릿, 데스크톱 +
+

모바일 / 태블릿 / 데스크톱 반응형 레이아웃

@@ -841,6 +964,7 @@

렌더링 파이프라인 + ?렌더링 파이프라인은 브라우저가 HTML/CSS/JS 코드를 화면의 픽셀로 변환하는 일련의 처리 과정이다.

비유: 통역사

@@ -917,6 +1041,15 @@

+ + +
+ 브라우저 렌더링 파이프라인 +
+

HTML 코드가 화면의 픽셀로 변환되는 6단계 과정

@@ -935,6 +1068,7 @@

REST API와 HTTP 메서드 + ?REST API는 URL과 HTTP 메서드(GET/POST/PUT/DELETE)를 조합하여 서버 자원을 조작하는 규약이다. 웹에서 가장 널리 쓰이는 API 설계 방식이다.

비유: 식당의 주문서

@@ -1047,6 +1181,15 @@ SAM React 앱은 api.sam-erp.com의 API 서버와 통신한다. MNG에서는 HTMX가 서버에 요청을 보내고 HTML 조각을 받아 화면을 업데이트한다.

+ + +
+ API 요청과 응답 흐름 +
+

프론트엔드와 백엔드 간 API 요청/응답 흐름

@@ -1065,6 +1208,7 @@

핵심 도구와 개발 흐름 + ?프론트엔드 개발에는 코드 에디터(VS Code), 패키지 관리자(npm), 버전 관리(Git), 번들러(Vite) 등 여러 도구를 조합하여 사용한다.

@@ -1133,6 +1277,15 @@
+ + +
+ 개발 워크플로우 +
+

코드 작성부터 배포까지 — 개발 워크플로우

@@ -1151,6 +1304,7 @@

Lighthouse와 Core Web Vitals + ?Lighthouse는 Google이 제공하는 웹 성능 측정 도구이다. Core Web Vitals는 LCP(로딩 속도), FID(반응 속도), CLS(레이아웃 안정성) 3가지 핵심 지표이다.

Lighthouse는 Google이 제공하는 웹 성능 측정 도구다. @@ -1339,6 +1493,28 @@ function hidePreview() { closeLightbox(); } }); + + // 도움말 풍선 토글 + window.toggleBalloon = function(el) { + var wasActive = el.classList.contains('is-active'); + // 모든 열린 풍선 닫기 + document.querySelectorAll('.help-balloon-trigger.is-active').forEach(function(t) { + t.classList.remove('is-active'); + }); + // 클릭한 풍선만 토글 + if (!wasActive) { + el.classList.add('is-active'); + } + }; + + // 풍선 외부 클릭 시 닫기 + document.addEventListener('click', function(e) { + if (!e.target.closest('.help-balloon-trigger')) { + document.querySelectorAll('.help-balloon-trigger.is-active').forEach(function(t) { + t.classList.remove('is-active'); + }); + } + }); })();