@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-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);
    }

    .help-balloon-trigger {
        display: inline-flex;
        align-items: center;
        justify-content: center;
        width: 18px;
        height: 18px;
        border-radius: 50%;
        background: #fff7ed;
        color: #c2410c;
        font-size: 11px;
        font-weight: 700;
        cursor: pointer;
        border: 1.5px solid #fdba74;
        vertical-align: middle;
        margin-left: 4px;
        transition: all 0.15s ease;
        position: relative;
        user-select: none;
    }
    .help-balloon-trigger:hover {
        background: #c2410c;
        color: white;
        border-color: #9a3412;
    }
    .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;
        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, #431407 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: #fb923c;">
                    <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: #fdba74;">백엔드 개발</span>
                </div>
                <h1 class="text-3xl font-bold mb-2" style="color: #ffffff;">백엔드 개발</h1>
                <p class="text-sm" style="color: #cbd5e1;">서버, 데이터베이스, API부터 배포까지 — 비개발자도 이해하는 백엔드 가이드</p>
            </div>
            <div class="shrink-0" style="width: 240px; padding: 1.5rem;">
                <div class="overflow-hidden rounded-xl">
                    <img src="{{ asset('images/academy/backend-dev/1.svg') }}" alt="3계층 아키텍처"
                         class="w-full rounded-xl cursor-pointer academy-img-hover"
                         onclick="openLightbox(this)">
                </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-orange-50 border border-orange-200 rounded-xl p-5">
                    <h2 class="font-semibold text-orange-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-backend" class="block text-orange-700 hover:text-orange-900 py-1 font-medium">1. 백엔드란?</a>
                        <a href="#frontend-vs-backend" class="block text-orange-600 hover:text-orange-800 py-0.5 pl-3">프론트 vs 백엔드</a>
                        <a href="#backend-roles" class="block text-orange-600 hover:text-orange-800 py-0.5 pl-3">백엔드의 역할</a>

                        <a href="#server-client" class="block text-orange-700 hover:text-orange-900 py-1 font-medium mt-2">2. 서버와 클라이언트</a>
                        <a href="#http-cycle" class="block text-orange-600 hover:text-orange-800 py-0.5 pl-3">HTTP 요청/응답</a>
                        <a href="#url-structure" class="block text-orange-600 hover:text-orange-800 py-0.5 pl-3">URL 구조</a>

                        <a href="#database" class="block text-orange-700 hover:text-orange-900 py-1 font-medium mt-2">3. 데이터베이스</a>
                        <a href="#rdb-nosql" class="block text-orange-600 hover:text-orange-800 py-0.5 pl-3">RDB vs NoSQL</a>
                        <a href="#sql-crud" class="block text-orange-600 hover:text-orange-800 py-0.5 pl-3">SQL CRUD</a>

                        <a href="#laravel" class="block text-orange-700 hover:text-orange-900 py-1 font-medium mt-2">4. Laravel</a>
                        <a href="#mvc-pattern" class="block text-orange-600 hover:text-orange-800 py-0.5 pl-3">MVC 패턴</a>
                        <a href="#eloquent-orm" class="block text-orange-600 hover:text-orange-800 py-0.5 pl-3">Eloquent ORM</a>

                        <a href="#api-design" class="block text-orange-700 hover:text-orange-900 py-1 font-medium mt-2">5. API 설계</a>
                        <a href="#rest-principles" class="block text-orange-600 hover:text-orange-800 py-0.5 pl-3">REST 원칙</a>
                        <a href="#api-auth" class="block text-orange-600 hover:text-orange-800 py-0.5 pl-3">API 인증</a>

                        <a href="#auth-security" class="block text-orange-700 hover:text-orange-900 py-1 font-medium mt-2">6. 인증과 보안</a>
                        <a href="#session-vs-token" class="block text-orange-600 hover:text-orange-800 py-0.5 pl-3">세션 vs 토큰</a>
                        <a href="#security-threats" class="block text-orange-600 hover:text-orange-800 py-0.5 pl-3">보안 위협</a>

                        <a href="#business-logic" class="block text-orange-700 hover:text-orange-900 py-1 font-medium mt-2">7. 비즈니스 로직</a>
                        <a href="#service-layer" class="block text-orange-600 hover:text-orange-800 py-0.5 pl-3">서비스 레이어</a>
                        <a href="#transaction" class="block text-orange-600 hover:text-orange-800 py-0.5 pl-3">트랜잭션</a>

                        <a href="#queue-async" class="block text-orange-700 hover:text-orange-900 py-1 font-medium mt-2">8. 큐와 비동기</a>
                        <a href="#sync-vs-async" class="block text-orange-600 hover:text-orange-800 py-0.5 pl-3">동기 vs 비동기</a>
                        <a href="#queue-worker" class="block text-orange-600 hover:text-orange-800 py-0.5 pl-3">큐/워커</a>

                        <a href="#caching-performance" class="block text-orange-700 hover:text-orange-900 py-1 font-medium mt-2">9. 캐싱과 성능</a>
                        <a href="#cache-basics" class="block text-orange-600 hover:text-orange-800 py-0.5 pl-3">캐시 원리</a>
                        <a href="#n-plus-one" class="block text-orange-600 hover:text-orange-800 py-0.5 pl-3">N+1 문제</a>

                        <a href="#deployment" class="block text-orange-700 hover:text-orange-900 py-1 font-medium mt-2">10. 배포와 운영</a>
                        <a href="#environments" class="block text-orange-600 hover:text-orange-800 py-0.5 pl-3">환경 분리</a>
                        <a href="#deploy-monitor" class="block text-orange-600 hover:text-orange-800 py-0.5 pl-3">Docker 배포</a>
                    </div>
                </div>
            </div>
        </nav>

        <!-- 우측 콘텐츠 -->
        <div class="flex-1 min-w-0 space-y-10">

            <!-- 모바일 목차 -->
            <div class="lg:hidden bg-orange-50 border border-orange-200 rounded-xl p-4 mb-6">
                <details>
                    <summary class="font-semibold text-orange-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-backend" class="block text-orange-700 hover:text-orange-900 py-1">1. 백엔드란?</a>
                        <a href="#server-client" class="block text-orange-700 hover:text-orange-900 py-1">2. 서버와 클라이언트</a>
                        <a href="#database" class="block text-orange-700 hover:text-orange-900 py-1">3. 데이터베이스 기초</a>
                        <a href="#laravel" class="block text-orange-700 hover:text-orange-900 py-1">4. Laravel 프레임워크</a>
                        <a href="#api-design" class="block text-orange-700 hover:text-orange-900 py-1">5. API 설계</a>
                        <a href="#auth-security" class="block text-orange-700 hover:text-orange-900 py-1">6. 인증과 보안</a>
                        <a href="#business-logic" class="block text-orange-700 hover:text-orange-900 py-1">7. 비즈니스 로직</a>
                        <a href="#queue-async" class="block text-orange-700 hover:text-orange-900 py-1">8. 큐와 비동기 처리</a>
                        <a href="#caching-performance" class="block text-orange-700 hover:text-orange-900 py-1">9. 캐싱과 성능 최적화</a>
                        <a href="#deployment" class="block text-orange-700 hover:text-orange-900 py-1">10. 배포와 운영</a>
                    </nav>
                </details>
            </div>

            {{-- ============================================================ --}}
            {{-- 1. 백엔드란? --}}
            {{-- ============================================================ --}}
            <section id="what-is-backend" 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-orange-500 text-white rounded-lg flex items-center justify-center text-sm font-bold">1</span>
                        백엔드란?
                    </h2>

                    <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-orange-400 rounded-full"></span>
                            프론트엔드 vs 백엔드
                            <span class="help-balloon-trigger" onclick="toggleBalloon(this)">?<span class="help-balloon">3계층(3-Tier) 아키텍처란 프레젠테이션(화면), 애플리케이션(로직), 데이터(DB)를 분리하는 설계 방식이다. 각 계층은 독립적으로 수정·확장할 수 있다.</span></span>
                        </h3>
                        <div class="bg-orange-50 rounded-lg p-5 border border-orange-100 mb-4">
                            <p class="text-sm text-orange-900 leading-relaxed">
                                <strong>백엔드(Back-end)</strong>란 사용자 눈에 보이지 않는 서버 측 영역이다.
                                데이터를 저장하고, 비즈니스 규칙을 처리하고, 보안을 관리하고, API를 통해 프론트엔드에 데이터를 전달하는 역할을 한다.
                            </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>이다. 고객은 완성된 제품(화면)만 보지만,
                                그 뒤에서는 원자재(데이터) 입고, 가공(비즈니스 로직), 품질검사(유효성 검증), 출하(API 응답)가 이루어진다.
                                프론트엔드가 매장(쇼룸)이라면, 백엔드는 그 뒤의 공장 전체다.
                            </p>
                        </div>
                        <div class="grid grid-cols-1 md:grid-cols-2 gap-3 text-xs">
                            <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="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-orange-800 mb-1">프론트엔드 (매장)</p>
                                <p class="text-orange-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, Laravel, MySQL<br>데이터 저장, 인증, API</p>
                            </div>
                        </div>
                    </div>

                    <div id="backend-roles" 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-orange-400 rounded-full"></span>
                            백엔드의 4가지 역할
                        </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-1">1. 데이터 저장/관리</p>
                                <p class="text-blue-700">주문, 고객, 제품 정보를 데이터베이스에 저장하고 필요할 때 꺼내온다.</p>
                            </div>
                            <div class="bg-green-50 rounded-lg p-4 border border-green-200">
                                <p class="font-bold text-green-800 mb-1">2. 비즈니스 로직 처리</p>
                                <p class="text-green-700">견적 계산, 재고 차감, 할인 적용 등 업무 규칙을 코드로 구현한다.</p>
                            </div>
                            <div class="bg-purple-50 rounded-lg p-4 border border-purple-200">
                                <p class="font-bold text-purple-800 mb-1">3. 보안/인증</p>
                                <p class="text-purple-700">로그인, 권한 확인, 비밀번호 암호화 등 보안을 책임진다.</p>
                            </div>
                            <div class="bg-orange-50 rounded-lg p-4 border border-orange-200">
                                <p class="font-bold text-orange-800 mb-1">4. API 제공</p>
                                <p class="text-orange-700">프론트엔드(앱, 웹)에 데이터를 전달하는 창구를 만들어 제공한다.</p>
                            </div>
                        </div>
                        <div class="bg-orange-50 rounded-lg p-4 border border-orange-100 mb-4">
                            <p class="text-xs text-orange-800 leading-relaxed">
                                <strong>SAM 시스템의 백엔드:</strong>
                                SAM은 API 서버(Laravel)가 백엔드를 담당한다. MNG(관리자 웹)와 React 앱이 API를 통해 데이터를 받고,
                                MySQL 데이터베이스에 주문·견적·재고 등 모든 데이터가 저장된다.
                            </p>
                        </div>
                        <div class="mb-5 bg-gray-50 rounded-xl p-4 border flex justify-center academy-img-wrap">
                            <img src="{{ asset('images/academy/backend-dev/1.svg') }}" alt="3계층 아키텍처 다이어그램"
                                 class="rounded-lg cursor-pointer academy-img-hover"
                                 style="max-height: 320px; width: auto;"
                                 onclick="openLightbox(this)">
                        </div>
                        <p class="text-xs text-gray-400 mb-4 text-center">3계층 아키텍처 — 브라우저, API 서버, 데이터베이스</p>
                    </div>
                </div>
            </section>

            {{-- ============================================================ --}}
            {{-- 2. 서버와 클라이언트 --}}
            {{-- ============================================================ --}}
            <section id="server-client" 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-orange-500 text-white rounded-lg flex items-center justify-center text-sm font-bold">2</span>
                        서버와 클라이언트
                    </h2>

                    <div id="http-cycle" 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-orange-400 rounded-full"></span>
                            HTTP 요청과 응답
                            <span class="help-balloon-trigger" onclick="toggleBalloon(this)">?<span class="help-balloon">HTTP는 HyperText Transfer Protocol. 웹에서 데이터를 주고받는 약속(규약)이다. 브라우저가 서버에 "이것 주세요"라고 요청하면, 서버가 "여기 있습니다"라고 응답한다.</span></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>를 보낸다. 편지 봉투에는 받는 주소(URL), 요청 종류(GET/POST), 내용이 들어 있다.
                                서버는 편지를 읽고 처리한 뒤, <strong>답장(응답)</strong>을 보낸다. 답장에는 상태 코드(200 성공, 404 없음)와 데이터가 들어 있다.
                            </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>
                                    </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">GET</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-blue-600">POST</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">PUT</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">DELETE</td>
                                        <td class="py-2 px-3">데이터 삭제</td>
                                        <td class="py-2 px-3">주문 취소</td>
                                    </tr>
                                </tbody>
                            </table>
                        </div>
                    </div>

                    <div id="url-structure" 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-orange-400 rounded-full"></span>
                            URL 구조와 HTTPS
                        </h3>
                        <div class="code-block mb-4"><span class="code-comment">// URL 구조 분해</span>
<span class="code-string">https</span>://<span class="code-func">api.sam-erp.com</span>/<span class="code-keyword">api/v1</span>/<span class="code-attr">orders</span>/<span class="code-number">123</span>?<span class="code-tag">status=active</span>

<span class="code-comment">// https   → 프로토콜 (암호화 통신)</span>
<span class="code-comment">// api.sam-erp.com → 도메인 (서버 주소)</span>
<span class="code-comment">// /api/v1 → API 접두사 + 버전</span>
<span class="code-comment">// /orders → 자원 (Resource)</span>
<span class="code-comment">// /123    → 특정 자원의 ID</span>
<span class="code-comment">// ?status=active → 쿼리 파라미터 (필터)</span></div>
                        <div class="bg-orange-50 rounded-lg p-4 border border-orange-100 mb-4">
                            <p class="text-xs text-orange-800 leading-relaxed">
                                <strong>SAM의 API 통신:</strong>
                                SAM은 HTTPS로 암호화된 통신을 사용한다. API 서버 주소는 별도 도메인으로 운영되며,
                                MNG와 React 앱이 REST API를 통해 데이터를 주고받는다.
                            </p>
                        </div>
                        <div class="mb-5 bg-gray-50 rounded-xl p-4 border flex justify-center academy-img-wrap">
                            <img src="{{ asset('images/academy/backend-dev/2.svg') }}" alt="요청-응답 사이클"
                                 class="rounded-lg cursor-pointer academy-img-hover"
                                 style="max-height: 320px; width: auto;"
                                 onclick="openLightbox(this)">
                        </div>
                        <p class="text-xs text-gray-400 mb-4 text-center">요청-응답 사이클 — 클라이언트와 서버의 대화</p>
                    </div>
                </div>
            </section>

            {{-- ============================================================ --}}
            {{-- 3. 데이터베이스 기초 --}}
            {{-- ============================================================ --}}
            <section id="database" 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-orange-500 text-white rounded-lg flex items-center justify-center text-sm font-bold">3</span>
                        데이터베이스 기초
                    </h2>

                    <div id="rdb-nosql" 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-orange-400 rounded-full"></span>
                            RDB vs NoSQL
                            <span class="help-balloon-trigger" onclick="toggleBalloon(this)">?<span class="help-balloon">RDB(관계형 데이터베이스)는 엑셀처럼 행과 열로 데이터를 저장한다. NoSQL은 JSON 문서, 키-값 쌍 등 유연한 형태로 저장한다. SAM은 MySQL(RDB)을 사용한다.</span></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>
                        <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">RDB (관계형)</p>
                                <ul class="text-blue-700 space-y-1">
                                    <li>• 행과 열로 구성된 테이블</li>
                                    <li>• SQL 언어로 데이터 조작</li>
                                    <li>• 테이블 간 관계(FK) 설정</li>
                                    <li>• 예: MySQL, PostgreSQL</li>
                                </ul>
                            </div>
                            <div class="bg-gray-50 rounded-lg p-4 border">
                                <p class="font-bold text-gray-800 mb-2">NoSQL (비관계형)</p>
                                <ul class="text-gray-600 space-y-1">
                                    <li>• JSON 형태로 유연하게 저장</li>
                                    <li>• 대량 데이터에 강함</li>
                                    <li>• 스키마 없이 자유로운 구조</li>
                                    <li>• 예: MongoDB, Redis</li>
                                </ul>
                            </div>
                        </div>
                        <p class="text-sm text-gray-700 mb-3">
                            데이터베이스의 핵심 개념 세 가지: <strong>PK(Primary Key)</strong>는 각 행을 고유하게 식별하는 번호(사원번호),
                            <strong>FK(Foreign Key)</strong>는 다른 테이블을 참조하는 연결고리(부서코드),
                            <strong>인덱스</strong>는 빠른 검색을 위한 색인이다.
                        </p>
                    </div>

                    <div id="sql-crud" 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-orange-400 rounded-full"></span>
                            SQL CRUD와 인덱스
                            <span class="help-balloon-trigger" onclick="toggleBalloon(this)">?<span class="help-balloon">인덱스는 특정 컬럼의 값과 위치를 미리 정리해둔 목록이다. 책 뒷면의 색인처럼, 전체를 훑지 않고 원하는 데이터를 빠르게 찾을 수 있다.</span></span>
                        </h3>
                        <div class="code-block mb-4"><span class="code-comment">-- CREATE: 데이터 생성</span>
<span class="code-keyword">INSERT INTO</span> <span class="code-func">orders</span> (customer_name, total) <span class="code-keyword">VALUES</span> (<span class="code-string">'주일산업'</span>, <span class="code-number">1500000</span>);

<span class="code-comment">-- READ: 데이터 조회</span>
<span class="code-keyword">SELECT</span> * <span class="code-keyword">FROM</span> <span class="code-func">orders</span> <span class="code-keyword">WHERE</span> status = <span class="code-string">'active'</span>;

<span class="code-comment">-- UPDATE: 데이터 수정</span>
<span class="code-keyword">UPDATE</span> <span class="code-func">orders</span> <span class="code-keyword">SET</span> status = <span class="code-string">'shipped'</span> <span class="code-keyword">WHERE</span> id = <span class="code-number">123</span>;

<span class="code-comment">-- DELETE: 데이터 삭제</span>
<span class="code-keyword">DELETE FROM</span> <span class="code-func">orders</span> <span class="code-keyword">WHERE</span> id = <span class="code-number">123</span>;</div>
                        <div class="bg-orange-50 rounded-lg p-4 border border-orange-100 mb-4">
                            <p class="text-xs text-orange-800 leading-relaxed">
                                <strong>SAM의 데이터베이스:</strong>
                                SAM은 MySQL 8.0을 사용하며, <code>tenant_id</code> 컬럼으로 회사(테넌트)별 데이터를 격리한다.
                                주문, 견적, 품목, 사용자 등 모든 데이터가 관계형 테이블에 저장된다.
                            </p>
                        </div>
                        <div class="mb-5 bg-gray-50 rounded-xl p-4 border flex justify-center academy-img-wrap">
                            <img src="{{ asset('images/academy/backend-dev/3.svg') }}" alt="ERD 테이블 관계도"
                                 class="rounded-lg cursor-pointer academy-img-hover"
                                 style="max-height: 320px; width: auto;"
                                 onclick="openLightbox(this)">
                        </div>
                        <p class="text-xs text-gray-400 mb-4 text-center">ERD 테이블 관계 — 주문, 주문항목, 품목</p>
                    </div>
                </div>
            </section>

            {{-- ============================================================ --}}
            {{-- 4. Laravel 프레임워크 --}}
            {{-- ============================================================ --}}
            <section id="laravel" 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-orange-500 text-white rounded-lg flex items-center justify-center text-sm font-bold">4</span>
                        Laravel 프레임워크
                    </h2>

                    <div id="mvc-pattern" 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-orange-400 rounded-full"></span>
                            MVC 패턴
                            <span class="help-balloon-trigger" onclick="toggleBalloon(this)">?<span class="help-balloon">미들웨어는 요청이 컨트롤러에 도달하기 전에 거치는 관문이다. 로그인 확인, 권한 검사, 요청 로깅 등을 처리한다. 공장의 보안 검색대와 같다.</span></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>Model(모델)</strong>은 자재 창고 — 데이터를 보관하고 꺼내준다.
                                <strong>View(뷰)</strong>는 쇼룸 — 완성품을 예쁘게 진열한다.
                                <strong>Controller(컨트롤러)</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 text-center">
                                <p class="font-bold text-blue-800 mb-1">Model (모델)</p>
                                <p class="text-blue-700">데이터 = DB 테이블<br>데이터 조회·저장·수정</p>
                            </div>
                            <div class="bg-green-50 rounded-lg p-4 border border-green-200 text-center">
                                <p class="font-bold text-green-800 mb-1">View (뷰)</p>
                                <p class="text-green-700">화면 = HTML 템플릿<br>데이터를 사용자에게 표시</p>
                            </div>
                            <div class="bg-orange-50 rounded-lg p-4 border border-orange-200 text-center">
                                <p class="font-bold text-orange-800 mb-1">Controller (컨트롤러)</p>
                                <p class="text-orange-700">중재자 = 비즈니스 로직<br>요청 처리, 모델·뷰 연결</p>
                            </div>
                        </div>
                        <div class="code-block mb-4"><span class="code-comment">// routes/web.php — URL과 컨트롤러 연결</span>
<span class="code-keyword">Route</span>::<span class="code-func">get</span>(<span class="code-string">'/orders'</span>, [<span class="code-tag">OrderController</span>::class, <span class="code-string">'index'</span>]);

<span class="code-comment">// Controller — 요청을 처리하는 중재자</span>
<span class="code-keyword">class</span> <span class="code-tag">OrderController</span> {
    <span class="code-keyword">public function</span> <span class="code-func">index</span>() {
        $orders = <span class="code-tag">Order</span>::<span class="code-func">where</span>(<span class="code-string">'status'</span>, <span class="code-string">'active'</span>)-><span class="code-func">get</span>();
        <span class="code-keyword">return</span> <span class="code-func">view</span>(<span class="code-string">'orders.index'</span>, <span class="code-func">compact</span>(<span class="code-string">'orders'</span>));
    }
}</div>
                    </div>

                    <div id="eloquent-orm" 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-orange-400 rounded-full"></span>
                            Eloquent ORM과 Artisan
                            <span class="help-balloon-trigger" onclick="toggleBalloon(this)">?<span class="help-balloon">ORM(Object-Relational Mapping)은 SQL을 직접 쓰지 않고 PHP 코드로 데이터베이스를 다루는 기술이다. 통역사처럼 PHP 언어를 SQL로 자동 변환해준다.</span></span>
                        </h3>
                        <div class="code-block mb-4"><span class="code-comment">// SQL 직접 작성</span>
<span class="code-keyword">SELECT</span> * <span class="code-keyword">FROM</span> orders <span class="code-keyword">WHERE</span> status = <span class="code-string">'active'</span> <span class="code-keyword">ORDER BY</span> created_at <span class="code-keyword">DESC</span>;

<span class="code-comment">// Eloquent ORM — 같은 결과를 PHP로</span>
$orders = <span class="code-tag">Order</span>::<span class="code-func">where</span>(<span class="code-string">'status'</span>, <span class="code-string">'active'</span>)
              -><span class="code-func">orderBy</span>(<span class="code-string">'created_at'</span>, <span class="code-string">'desc'</span>)
              -><span class="code-func">get</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">Artisan 주요 명령어</p>
                            <div class="space-y-1 font-mono">
                                <p><span class="text-orange-600">php artisan migrate</span> — DB 테이블 생성/수정</p>
                                <p><span class="text-orange-600">php artisan make:controller</span> — 컨트롤러 생성</p>
                                <p><span class="text-orange-600">php artisan make:model</span> — 모델 생성</p>
                                <p><span class="text-orange-600">php artisan cache:clear</span> — 캐시 초기화</p>
                                <p><span class="text-orange-600">php artisan tinker</span> — 대화형 PHP 콘솔</p>
                            </div>
                        </div>
                        <div class="bg-orange-50 rounded-lg p-4 border border-orange-100 mb-4">
                            <p class="text-xs text-orange-800 leading-relaxed">
                                <strong>SAM의 Laravel:</strong>
                                SAM은 Laravel 11 + PHP 8.3을 사용한다. MNG와 API 모두 Laravel 프레임워크 기반이며,
                                Eloquent ORM으로 MySQL 데이터를 다루고, Artisan 명령어로 마이그레이션·캐시 관리를 한다.
                            </p>
                        </div>
                        <div class="mb-5 bg-gray-50 rounded-xl p-4 border flex justify-center academy-img-wrap">
                            <img src="{{ asset('images/academy/backend-dev/4.svg') }}" alt="MVC 흐름도"
                                 class="rounded-lg cursor-pointer academy-img-hover"
                                 style="max-height: 320px; width: auto;"
                                 onclick="openLightbox(this)">
                        </div>
                        <p class="text-xs text-gray-400 mb-4 text-center">MVC 흐름도 — Route → Controller → Model → View</p>
                    </div>
                </div>
            </section>

            {{-- ============================================================ --}}
            {{-- 5. API 설계 --}}
            {{-- ============================================================ --}}
            <section id="api-design" 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-orange-500 text-white rounded-lg flex items-center justify-center text-sm font-bold">5</span>
                        API 설계
                    </h2>

                    <div id="rest-principles" 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-orange-400 rounded-full"></span>
                            REST 원칙과 JSON
                            <span class="help-balloon-trigger" onclick="toggleBalloon(this)">?<span class="help-balloon">REST는 URL로 자원(Resource)을 표현하고 HTTP 메서드로 행위를 나타내는 설계 방식이다. /orders는 주문 자원, GET은 조회, POST는 생성 행위를 의미한다.</span></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">
                                API는 <strong>주문 창구</strong>다. 메뉴판(API 문서)을 보고 정해진 양식(JSON)으로 주문(요청)하면,
                                주방(서버)에서 요리(처리)해서 음식(데이터)을 내준다.
                                아무렇게나 주문하면 안 되고, 정해진 형식을 따라야 한다.
                            </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">메서드</th>
                                        <th class="text-left py-2 px-3 font-medium text-gray-600">URL</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">GET</td>
                                        <td class="py-2 px-3 font-mono">/api/v1/orders</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-green-600">GET</td>
                                        <td class="py-2 px-3 font-mono">/api/v1/orders/123</td>
                                        <td class="py-2 px-3">주문 #123 상세 조회</td>
                                    </tr>
                                    <tr class="border-b border-gray-100">
                                        <td class="py-2 px-3 font-mono font-bold text-blue-600">POST</td>
                                        <td class="py-2 px-3 font-mono">/api/v1/orders</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">PUT</td>
                                        <td class="py-2 px-3 font-mono">/api/v1/orders/123</td>
                                        <td class="py-2 px-3">주문 #123 수정</td>
                                    </tr>
                                    <tr>
                                        <td class="py-2 px-3 font-mono font-bold text-red-600">DELETE</td>
                                        <td class="py-2 px-3 font-mono">/api/v1/orders/123</td>
                                        <td class="py-2 px-3">주문 #123 삭제</td>
                                    </tr>
                                </tbody>
                            </table>
                        </div>
                        <div class="code-block mb-4"><span class="code-comment">// JSON 응답 예시</span>
{
  <span class="code-attr">"data"</span>: {
    <span class="code-attr">"id"</span>: <span class="code-number">123</span>,
    <span class="code-attr">"customer"</span>: <span class="code-string">"주일산업"</span>,
    <span class="code-attr">"total"</span>: <span class="code-number">1500000</span>,
    <span class="code-attr">"status"</span>: <span class="code-string">"active"</span>,
    <span class="code-attr">"items"</span>: [
      { <span class="code-attr">"name"</span>: <span class="code-string">"방화셔터 A형"</span>, <span class="code-attr">"qty"</span>: <span class="code-number">5</span> }
    ]
  }
}</div>
                    </div>

                    <div id="api-auth" 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-orange-400 rounded-full"></span>
                            API 인증과 버전 관리
                            <span class="help-balloon-trigger" onclick="toggleBalloon(this)">?<span class="help-balloon">Sanctum은 Laravel 공식 인증 패키지다. 모바일 앱과 SPA를 위한 토큰 발급, API 인증을 간단하게 구현한다. 회원증을 발급받아 매번 보여주는 것과 같다.</span></span>
                        </h3>
                        <div class="code-block mb-4"><span class="code-comment">// Bearer Token 인증 — 회원증 제시</span>
<span class="code-keyword">GET</span> /api/v1/orders
<span class="code-tag">Authorization</span>: <span class="code-string">Bearer eyJhbGciOiJIUzI1NiIs...</span>

<span class="code-comment">// 버전 관리 — API가 바뀌어도 기존 앱이 동작</span>
/api/<span class="code-func">v1</span>/orders  <span class="code-comment">← 현재 버전</span>
/api/<span class="code-func">v2</span>/orders  <span class="code-comment">← 새 버전 (구조 변경)</span></div>
                        <div class="bg-orange-50 rounded-lg p-4 border border-orange-100 mb-4">
                            <p class="text-xs text-orange-800 leading-relaxed">
                                <strong>SAM의 API 인증:</strong>
                                SAM API는 <code>/api/v1/</code> 접두사를 사용하고, Laravel Sanctum으로 토큰 인증을 처리한다.
                                React 앱에서 로그인하면 토큰을 발급받아 이후 모든 API 요청에 포함한다.
                            </p>
                        </div>
                        <div class="mb-5 bg-gray-50 rounded-xl p-4 border flex justify-center academy-img-wrap">
                            <img src="{{ asset('images/academy/backend-dev/5.svg') }}" alt="REST API 구조"
                                 class="rounded-lg cursor-pointer academy-img-hover"
                                 style="max-height: 320px; width: auto;"
                                 onclick="openLightbox(this)">
                        </div>
                        <p class="text-xs text-gray-400 mb-4 text-center">REST API 구조 — URL 분해와 JSON 응답</p>
                    </div>
                </div>
            </section>

            {{-- ============================================================ --}}
            {{-- 6. 인증과 보안 --}}
            {{-- ============================================================ --}}
            <section id="auth-security" 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-orange-500 text-white rounded-lg flex items-center justify-center text-sm font-bold">6</span>
                        인증과 보안
                    </h2>

                    <div id="session-vs-token" 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-orange-400 rounded-full"></span>
                            세션 vs 토큰
                            <span class="help-balloon-trigger" onclick="toggleBalloon(this)">?<span class="help-balloon">bcrypt는 비밀번호를 되돌릴 수 없는 형태로 변환(해싱)하는 알고리즘이다. 같은 비밀번호라도 매번 다른 해시값을 생성하여 보안성이 높다.</span></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">비유: 도장카드 vs 출입배지</p>
                            <p class="text-xs text-amber-900 leading-relaxed">
                                <strong>세션</strong>은 <strong>도장카드</strong>다. 가게(서버)에 내 도장카드를 보관해두고, 올 때마다 번호표(세션ID)만 보여준다. 가게가 기록을 관리한다.
                                <strong>토큰</strong>은 <strong>출입배지</strong>다. 내가 배지(JWT)를 가지고 다니며, 입장할 때마다 배지를 보여준다. 건물(서버)은 배지 진위만 확인한다.
                            </p>
                        </div>
                        <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">세션 (Session)</p>
                                <ul class="text-blue-700 space-y-1">
                                    <li>• 서버에 상태 저장 (Stateful)</li>
                                    <li>• 쿠키로 세션 ID 전달</li>
                                    <li>• 서버 메모리/DB 사용</li>
                                    <li>• SAM MNG에서 사용</li>
                                </ul>
                            </div>
                            <div class="bg-orange-50 rounded-lg p-4 border border-orange-200">
                                <p class="font-bold text-orange-800 mb-2">토큰 (Token)</p>
                                <ul class="text-orange-700 space-y-1">
                                    <li>• 서버에 상태 미저장 (Stateless)</li>
                                    <li>• Authorization 헤더로 전달</li>
                                    <li>• 확장성이 좋음 (서버 무상태)</li>
                                    <li>• SAM API에서 사용 (Sanctum)</li>
                                </ul>
                            </div>
                        </div>
                    </div>

                    <div id="security-threats" 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-orange-400 rounded-full"></span>
                            보안 위협과 방어
                        </h3>
                        <div class="grid grid-cols-1 md:grid-cols-2 gap-3 text-xs mb-4">
                            <div class="bg-red-50 rounded-lg p-4 border border-red-200">
                                <p class="font-bold text-red-800 mb-2">SQL Injection</p>
                                <p class="text-red-700 mb-2">사용자 입력에 악의적 SQL을 삽입하는 공격</p>
                                <p class="text-green-700">방어: 파라미터 바인딩 (Eloquent 자동 처리)</p>
                            </div>
                            <div class="bg-red-50 rounded-lg p-4 border border-red-200">
                                <p class="font-bold text-red-800 mb-2">CSRF</p>
                                <p class="text-red-700 mb-2">사용자 모르게 악의적 요청을 보내는 공격</p>
                                <p class="text-green-700">방어: CSRF 토큰 검증 (Laravel 자동 처리)</p>
                            </div>
                        </div>
                        <div class="bg-orange-50 rounded-lg p-4 border border-orange-100 mb-4">
                            <p class="text-xs text-orange-800 leading-relaxed">
                                <strong>SAM의 보안:</strong>
                                SAM MNG는 세션 기반 인증 + CSRF 토큰으로 보안을 처리하고,
                                API 서버는 Sanctum 토큰 인증을 사용한다. 비밀번호는 bcrypt로 해싱하여 저장한다.
                            </p>
                        </div>
                        <div class="mb-5 bg-gray-50 rounded-xl p-4 border flex justify-center academy-img-wrap">
                            <img src="{{ asset('images/academy/backend-dev/6.svg') }}" alt="세션 vs 토큰 비교"
                                 class="rounded-lg cursor-pointer academy-img-hover"
                                 style="max-height: 320px; width: auto;"
                                 onclick="openLightbox(this)">
                        </div>
                        <p class="text-xs text-gray-400 mb-4 text-center">인증 비교 — 세션 방식 vs 토큰 방식</p>
                    </div>
                </div>
            </section>

            {{-- ============================================================ --}}
            {{-- 7. 비즈니스 로직 --}}
            {{-- ============================================================ --}}
            <section id="business-logic" 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-orange-500 text-white rounded-lg flex items-center justify-center text-sm font-bold">7</span>
                        비즈니스 로직
                    </h2>

                    <div id="service-layer" 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-orange-400 rounded-full"></span>
                            서비스 레이어와 유효성 검증
                            <span class="help-balloon-trigger" onclick="toggleBalloon(this)">?<span class="help-balloon">서비스 레이어는 컨트롤러에서 비즈니스 로직을 분리한 클래스다. 컨트롤러가 "무엇을 할지" 결정하면, 서비스가 "어떻게 할지" 실행한다.</span></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>이다. "견적 금액이 100만원 이상이면 팀장 승인 필요",
                                "재고가 0이면 주문 불가" 같은 규칙을 코드로 구현한 것이다.
                                규정이 바뀌면 서비스 클래스만 수정하면 된다.
                            </p>
                        </div>
                        <div class="code-block mb-4"><span class="code-comment">// Validation — 입력값 검증</span>
$request-><span class="code-func">validate</span>([
    <span class="code-string">'customer_name'</span> => <span class="code-string">'required|max:100'</span>,
    <span class="code-string">'email'</span>         => <span class="code-string">'required|email'</span>,
    <span class="code-string">'total'</span>         => <span class="code-string">'required|numeric|min:0'</span>,
]);

<span class="code-comment">// Event/Listener — 이벤트 기반 처리</span>
<span class="code-comment">// 주문 생성 → 이벤트 발생 → 리스너가 알림 발송</span>
<span class="code-keyword">event</span>(<span class="code-keyword">new</span> <span class="code-tag">OrderCreated</span>($order));
<span class="code-comment">// → SendOrderNotification 리스너가 자동 실행</span></div>
                    </div>

                    <div id="transaction" 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-orange-400 rounded-full"></span>
                            트랜잭션
                            <span class="help-balloon-trigger" onclick="toggleBalloon(this)">?<span class="help-balloon">트랜잭션은 여러 DB 작업을 하나의 단위로 묶는 것이다. 모두 성공하면 확정(commit), 하나라도 실패하면 전부 취소(rollback)한다.</span></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">
                                A 계좌에서 10만원을 빼고 B 계좌에 10만원을 넣는 이체를 생각해보자.
                                A에서 빼기는 성공했는데 B에 넣기가 실패하면? 돈이 사라진다!
                                <strong>트랜잭션</strong>은 두 작업을 하나로 묶어 "둘 다 성공하거나, 둘 다 취소"하도록 보장한다.
                            </p>
                        </div>
                        <div class="code-block mb-4"><span class="code-comment">// Laravel 트랜잭션 예시</span>
<span class="code-tag">DB</span>::<span class="code-func">transaction</span>(<span class="code-keyword">function</span> () {
    <span class="code-comment">// 1. A 계좌에서 출금</span>
    $accountA-><span class="code-func">decrement</span>(<span class="code-string">'balance'</span>, <span class="code-number">100000</span>);

    <span class="code-comment">// 2. B 계좌에 입금</span>
    $accountB-><span class="code-func">increment</span>(<span class="code-string">'balance'</span>, <span class="code-number">100000</span>);

    <span class="code-comment">// 둘 다 성공 → 자동 commit</span>
    <span class="code-comment">// 하나라도 실패 → 자동 rollback</span>
});</div>
                        <div class="bg-orange-50 rounded-lg p-4 border border-orange-100 mb-4">
                            <p class="text-xs text-orange-800 leading-relaxed">
                                <strong>SAM의 비즈니스 로직:</strong>
                                SAM은 견적 계산, 주문 처리, 재고 관리 등의 비즈니스 로직을 서비스 클래스에서 처리한다.
                                주문 생성 시 재고 차감, 이력 기록 등을 트랜잭션으로 묶어 데이터 무결성을 보장한다.
                            </p>
                        </div>
                        <div class="mb-5 bg-gray-50 rounded-xl p-4 border flex justify-center academy-img-wrap">
                            <img src="{{ asset('images/academy/backend-dev/7.svg') }}" alt="트랜잭션 다이어그램"
                                 class="rounded-lg cursor-pointer academy-img-hover"
                                 style="max-height: 320px; width: auto;"
                                 onclick="openLightbox(this)">
                        </div>
                        <p class="text-xs text-gray-400 mb-4 text-center">트랜잭션 — 성공(commit)과 실패(rollback)</p>
                    </div>
                </div>
            </section>

            {{-- ============================================================ --}}
            {{-- 8. 큐와 비동기 처리 --}}
            {{-- ============================================================ --}}
            <section id="queue-async" 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-orange-500 text-white rounded-lg flex items-center justify-center text-sm font-bold">8</span>
                        큐와 비동기 처리
                    </h2>

                    <div id="sync-vs-async" 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-orange-400 rounded-full"></span>
                            동기 vs 비동기
                            <span class="help-balloon-trigger" onclick="toggleBalloon(this)">?<span class="help-balloon">큐는 선입선출(FIFO) 방식의 작업 대기열이다. 은행 대기표처럼 먼저 들어온 작업부터 순서대로 처리한다.</span></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>는 은행 창구에서 줄 서는 것 — 앞 사람이 끝날 때까지 기다려야 한다.
                                <strong>비동기 처리</strong>는 대기표를 받는 것 — 번호표를 받고 자기 볼일을 보다가, 호출되면 처리한다.
                                이메일 100통을 보낼 때, 동기면 30초 기다려야 하지만 비동기(큐)면 즉시 "발송 예약됨"이 표시된다.
                            </p>
                        </div>
                        <div class="grid grid-cols-1 md:grid-cols-2 gap-3 text-xs mb-4">
                            <div class="bg-red-50 rounded-lg p-4 border border-red-200">
                                <p class="font-bold text-red-800 mb-2">동기 처리 (Synchronous)</p>
                                <p class="text-red-700">순서대로 하나씩 처리<br>앞 작업 끝나야 다음 시작<br>사용자가 기다려야 함</p>
                            </div>
                            <div class="bg-green-50 rounded-lg p-4 border border-green-200">
                                <p class="font-bold text-green-800 mb-2">비동기 처리 (Asynchronous)</p>
                                <p class="text-green-700">큐에 넣고 즉시 응답<br>워커가 백그라운드에서 처리<br>사용자는 기다리지 않음</p>
                            </div>
                        </div>
                    </div>

                    <div id="queue-worker" 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-orange-400 rounded-full"></span>
                            큐/워커와 스케줄러
                        </h3>
                        <div class="code-block mb-4"><span class="code-comment">// Job 클래스 — 큐에 넣을 작업 단위</span>
<span class="code-keyword">class</span> <span class="code-tag">SendAlimtalk</span> <span class="code-keyword">implements</span> <span class="code-func">ShouldQueue</span> {
    <span class="code-keyword">public function</span> <span class="code-func">handle</span>() {
        <span class="code-comment">// 알림톡 발송 로직</span>
        <span class="code-tag">AlimtalkService</span>::<span class="code-func">send</span>($this->phone, $this->message);
    }
}

<span class="code-comment">// 큐에 작업 넣기</span>
<span class="code-tag">SendAlimtalk</span>::<span class="code-func">dispatch</span>($phone, $message);
<span class="code-comment">// → 즉시 응답, 워커가 나중에 처리</span>

<span class="code-comment">// 스케줄러 — 매일 새벽 2시에 백업</span>
$schedule-><span class="code-func">command</span>(<span class="code-string">'backup:run'</span>)-><span class="code-func">dailyAt</span>(<span class="code-string">'02:00'</span>);</div>
                        <div class="bg-orange-50 rounded-lg p-4 border border-orange-100 mb-4">
                            <p class="text-xs text-orange-800 leading-relaxed">
                                <strong>SAM의 큐 활용:</strong>
                                SAM은 알림톡 발송, PDF 생성, 이메일 발송 등을 큐로 비동기 처리한다.
                                Docker 컨테이너 안에서 Queue Worker가 상시 실행되며, Scheduler로 정기 작업을 자동 실행한다.
                            </p>
                        </div>
                        <div class="mb-5 bg-gray-50 rounded-xl p-4 border flex justify-center academy-img-wrap">
                            <img src="{{ asset('images/academy/backend-dev/8.svg') }}" alt="큐 처리 흐름"
                                 class="rounded-lg cursor-pointer academy-img-hover"
                                 style="max-height: 320px; width: auto;"
                                 onclick="openLightbox(this)">
                        </div>
                        <p class="text-xs text-gray-400 mb-4 text-center">큐 처리 — 요청 → 큐 → 워커 → 완료</p>
                    </div>
                </div>
            </section>

            {{-- ============================================================ --}}
            {{-- 9. 캐싱과 성능 최적화 --}}
            {{-- ============================================================ --}}
            <section id="caching-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-orange-500 text-white rounded-lg flex items-center justify-center text-sm font-bold">9</span>
                        캐싱과 성능 최적화
                    </h2>

                    <div id="cache-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-orange-400 rounded-full"></span>
                            캐시의 원리
                            <span class="help-balloon-trigger" onclick="toggleBalloon(this)">?<span class="help-balloon">캐시는 자주 사용하는 데이터를 빠른 저장소에 임시 보관하는 기법이다. DB에서 매번 조회하는 대신 캐시에서 바로 꺼내면 응답 속도가 수십 배 빨라진다.</span></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>에 놓아둔다. 필요할 때 바로 꺼내 쓸 수 있다.
                                가끔 쓰는 도구는 <strong>서랍(데이터베이스)</strong>에 보관한다. 서랍을 열고 찾는 데 시간이 더 걸린다.
                                캐시는 이처럼 자주 쓰는 데이터를 가까이 두어 빠르게 접근하는 기법이다.
                            </p>
                        </div>
                        <div class="code-block mb-4"><span class="code-comment">// Laravel 캐시 사용</span>
<span class="code-comment">// 캐시에 있으면 바로 반환, 없으면 DB에서 조회 후 캐시에 저장</span>
$orders = <span class="code-tag">Cache</span>::<span class="code-func">remember</span>(<span class="code-string">'active_orders'</span>, <span class="code-number">3600</span>, <span class="code-keyword">function</span> () {
    <span class="code-keyword">return</span> <span class="code-tag">Order</span>::<span class="code-func">where</span>(<span class="code-string">'status'</span>, <span class="code-string">'active'</span>)-><span class="code-func">get</span>();
});
<span class="code-comment">// 3600 = 1시간(초) 동안 캐시 유지</span></div>
                    </div>

                    <div id="n-plus-one" 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-orange-400 rounded-full"></span>
                            N+1 문제와 Eager Loading
                            <span class="help-balloon-trigger" onclick="toggleBalloon(this)">?<span class="help-balloon">N+1 문제는 1번의 쿼리로 목록을 가져온 뒤, 각 항목마다 추가 쿼리를 실행하는 것이다. 100개 주문을 조회하면 101번의 쿼리가 발생한다.</span></span>
                        </h3>
                        <div class="grid grid-cols-1 md:grid-cols-2 gap-3 text-xs mb-4">
                            <div class="bg-red-50 rounded-lg p-4 border border-red-200">
                                <p class="font-bold text-red-800 mb-2">N+1 문제 (느림)</p>
                                <div class="font-mono text-red-700 space-y-0.5">
                                    <p>1. SELECT * FROM orders</p>
                                    <p>2. SELECT * FROM items WHERE order_id=1</p>
                                    <p>3. SELECT * FROM items WHERE order_id=2</p>
                                    <p>... (N번 반복)</p>
                                    <p class="mt-1 font-sans font-bold">총 101번 쿼리!</p>
                                </div>
                            </div>
                            <div class="bg-green-50 rounded-lg p-4 border border-green-200">
                                <p class="font-bold text-green-800 mb-2">Eager Loading (빠름)</p>
                                <div class="font-mono text-green-700 space-y-0.5">
                                    <p>1. SELECT * FROM orders</p>
                                    <p>2. SELECT * FROM items WHERE order_id IN (1,2,...)</p>
                                    <p class="mt-1 font-sans font-bold">총 2번 쿼리!</p>
                                </div>
                            </div>
                        </div>
                        <div class="code-block mb-4"><span class="code-comment">// N+1 문제 발생</span>
$orders = <span class="code-tag">Order</span>::<span class="code-func">all</span>();       <span class="code-comment">// 1번 쿼리</span>
<span class="code-keyword">foreach</span> ($orders <span class="code-keyword">as</span> $order) {
    $order->items;             <span class="code-comment">// N번 추가 쿼리!</span>
}

<span class="code-comment">// Eager Loading으로 해결</span>
$orders = <span class="code-tag">Order</span>::<span class="code-func">with</span>(<span class="code-string">'items'</span>)-><span class="code-func">get</span>();  <span class="code-comment">// 2번 쿼리로 끝!</span></div>
                        <div class="bg-orange-50 rounded-lg p-4 border border-orange-100 mb-4">
                            <p class="text-xs text-orange-800 leading-relaxed">
                                <strong>SAM의 성능 최적화:</strong>
                                SAM은 config, route 캐싱으로 응답 속도를 최적화하고,
                                Eager Loading으로 N+1 문제를 방지한다. DB 인덱스를 적절히 설정하여 대량 데이터 조회 성능을 확보한다.
                            </p>
                        </div>
                        <div class="mb-5 bg-gray-50 rounded-xl p-4 border flex justify-center academy-img-wrap">
                            <img src="{{ asset('images/academy/backend-dev/9.svg') }}" alt="캐시 계층 다이어그램"
                                 class="rounded-lg cursor-pointer academy-img-hover"
                                 style="max-height: 320px; width: auto;"
                                 onclick="openLightbox(this)">
                        </div>
                        <p class="text-xs text-gray-400 mb-4 text-center">캐시 계층 — 캐시 히트와 캐시 미스</p>
                    </div>
                </div>
            </section>

            {{-- ============================================================ --}}
            {{-- 10. 배포와 운영 --}}
            {{-- ============================================================ --}}
            <section id="deployment" 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-orange-500 text-white rounded-lg flex items-center justify-center text-sm font-bold">10</span>
                        배포와 운영
                    </h2>

                    <div id="environments" 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-orange-400 rounded-full"></span>
                            환경 분리
                            <span class="help-balloon-trigger" onclick="toggleBalloon(this)">?<span class="help-balloon">.env 파일은 DB 접속 정보, API 키 등 환경마다 달라지는 설정을 모아둔 파일이다. 절대 Git에 커밋하면 안 된다.</span></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>시험생산(Local)</strong>에서 만들어보고, <strong>품질검사(Staging)</strong>를 통과하면,
                                비로소 <strong>출하(Production)</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 text-center">
                                <p class="font-bold text-blue-800 mb-1">Local (개발)</p>
                                <p class="text-blue-700">개발자 PC<br>자유롭게 실험<br>Docker 컨테이너</p>
                            </div>
                            <div class="bg-yellow-50 rounded-lg p-4 border border-yellow-200 text-center">
                                <p class="font-bold text-yellow-800 mb-1">Staging (테스트)</p>
                                <p class="text-yellow-700">운영과 동일한 환경<br>최종 검증<br>실 데이터 없음</p>
                            </div>
                            <div class="bg-green-50 rounded-lg p-4 border border-green-200 text-center">
                                <p class="font-bold text-green-800 mb-1">Production (운영)</p>
                                <p class="text-green-700">실제 서비스<br>실 사용자 접속<br>장애 시 즉시 대응</p>
                            </div>
                        </div>
                    </div>

                    <div id="deploy-monitor" 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-orange-400 rounded-full"></span>
                            Docker 배포와 모니터링
                        </h3>
                        <div class="code-block mb-4"><span class="code-comment"># SAM 배포 절차 (간략)</span>
<span class="code-comment"># 1. 코드 작성 & 커밋</span>
<span class="code-func">git add</span> . && <span class="code-func">git commit</span> -m <span class="code-string">"feat: 새 기능 추가"</span>

<span class="code-comment"># 2. 코드 푸시</span>
<span class="code-func">git push</span> origin develop

<span class="code-comment"># 3. 서버에서 코드 받기</span>
<span class="code-func">git pull</span> origin develop

<span class="code-comment"># 4. 의존성 설치 & 마이그레이션</span>
<span class="code-func">composer install</span>
<span class="code-func">php artisan migrate</span>
<span class="code-func">php artisan config:clear</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-4 border">
                                <p class="font-bold text-gray-800 mb-2">Git 브랜치 전략</p>
                                <ul class="text-gray-600 space-y-1">
                                    <li>• <code>develop</code> — 개발 진행 브랜치</li>
                                    <li>• <code>main</code> — 운영 배포 브랜치</li>
                                    <li>• <code>feature/*</code> — 기능 개발 브랜치</li>
                                    <li>• <code>hotfix/*</code> — 긴급 수정 브랜치</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>• <code>storage/logs/laravel.log</code> — 앱 로그</li>
                                    <li>• <code>nginx error.log</code> — 웹서버 로그</li>
                                    <li>• <code>php artisan queue:work</code> — 큐 상태</li>
                                    <li>• <code>docker ps</code> — 컨테이너 상태</li>
                                </ul>
                            </div>
                        </div>
                        <div class="bg-orange-50 rounded-lg p-4 border border-orange-100 mb-4">
                            <p class="text-xs text-orange-800 leading-relaxed">
                                <strong>SAM의 배포:</strong>
                                SAM은 Docker Compose로 로컬 개발 환경(MNG, API, MySQL, Nginx)을 구성하고,
                                운영 서버에는 직접 배포한다. develop 브랜치에서 개발을 진행하며,
                                코드 포맷팅(Pint), 캐시 클리어, 마이그레이션을 거쳐 배포한다.
                            </p>
                        </div>
                        <div class="mb-5 bg-gray-50 rounded-xl p-4 border flex justify-center academy-img-wrap">
                            <img src="{{ asset('images/academy/backend-dev/10.svg') }}" alt="배포 파이프라인"
                                 class="rounded-lg cursor-pointer academy-img-hover"
                                 style="max-height: 320px; width: auto;"
                                 onclick="openLightbox(this)">
                        </div>
                        <p class="text-xs text-gray-400 mb-4 text-center">배포 파이프라인 — 코드 → Git → 빌드 → 서버</p>

                        <!-- 핵심 정리 -->
                        <div class="mt-6 bg-orange-50 rounded-lg p-5 border border-orange-100">
                            <h4 class="font-semibold text-orange-800 mb-2 text-sm">핵심 정리</h4>
                            <p class="text-xs text-orange-700 leading-relaxed">
                                백엔드는 <strong>"사용자 눈에 보이지 않는 서버의 세계"</strong>다.
                                HTTP로 요청을 받아, 데이터베이스에서 데이터를 꺼내고, 비즈니스 로직을 처리하여 API로 응답한다.
                                Laravel 프레임워크가 MVC 패턴, ORM, 미들웨어, 큐, 캐시 등 핵심 기능을 제공하고,
                                세션·토큰으로 인증, 트랜잭션으로 데이터 무결성, Eager Loading으로 성능을 보장한다.
                                Docker로 개발 환경을 통일하고, Git으로 버전을 관리하여 안전하게 배포한다.
                                SAM은 이 모든 백엔드 기술을 활용하여 ERP/MES 통합 시스템을 운영하고 있다.
                            </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();
        }
    });

    // 도움말 풍선 토글
    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');
            });
        }
    });
})();
</script>

@include('components.academy-glossary', ['domain' => 'backend-dev'])
@endsection
