개발 가이드 프론트엔드 정적 에셋 관리
최종 수정:

정적 에셋 관리

CSS/JS/이미지 관리 규칙 및 디자인 토큰

정적 에셋 관리

디렉토리 구조

static/
├── css/
│   ├── tokens.css        # 디자인 토큰 (CSS 변수)
│   ├── reset.css         # CSS 리셋
│   ├── style.css         # 사이트 공통 스타일 (@import 조합)
│   ├── layout.css        # 레이아웃 (grid, flex)
│   ├── header.css        # 헤더 컴포넌트
│   ├── components.css    # 공통 컴포넌트 (버튼, 카드 등)
│   ├── admin.css         # 어드민 전용 스타일
│   ├── notes.css         # 노트 페이지 전용
│   ├── resume.css        # 이력서 페이지 전용
│   └── guide.css         # 개발 가이드 전용
└── js/
    ├── data.js           # 정적 데이터
    └── guide.js          # 개발 가이드 JS

디자인 토큰

/* tokens.css */
:root {
  --bg:             #F8F7F4;
  --white:          #FFFFFF;
  --text-primary:   #1A1917;
  --text-secondary: #6B6965;
  --text-muted:     #9B9894;
  --border:         #E4E2DD;
  --border-light:   #EEECEA;
  --accent:         oklch(0.52 0.14 258);
  --accent-bg:      oklch(0.95 0.04 258);
  --tag-bg:         #F0EFEB;
  --max-w:          1100px;
  --max-w-resume:   900px;
}

색상 사용 규칙

토큰사용 용도
--bg페이지 배경
--white카드, 모달 배경
--text-primary제목, 주요 텍스트
--text-secondary부제목, 보조 텍스트
--text-muted힌트, 비활성 텍스트
--border기본 경계선
--border-light연한 구분선
--accent링크, 버튼, 강조
--accent-bg강조 배경
--tag-bg태그 배경

하드코딩 금지

/* 잘못된 예 */
color: #1A1917;
background: oklch(0.52 0.14 258);

/* 올바른 예 */
color: var(--text-primary);
background: var(--accent);

CSS 작성 규칙

파일 구성

  • 파일당 하나의 컴포넌트/페이지 담당
  • style.css에서 @import로 조합
  • 전역 선택자(*, body) 수정 → reset.css에서만

선택자 규칙

/* BEM-like 네이밍 */
.news-card {}           /* 블록 */
.news-card-title {}     /* 요소 */
.news-card--featured {} /* 변형 */

/* 상태 클래스 */
.nav-link.active {}
.btn:disabled {}

반응형 브레이크포인트

/* 모바일 우선 */
.container { width: 100%; }

@media (min-width: 768px) {
    .container { max-width: var(--max-w); }
}

JavaScript 작성 규칙

기본 원칙

// eval() 절대 금지
// innerHTML 직접 할당 금지 → textContent 또는 DOM API 사용

// 잘못된 예
element.innerHTML = userInput;

// 올바른 예
element.textContent = userInput;
// 또는 안전한 DOM 조작
const span = document.createElement('span');
span.textContent = userInput;
element.appendChild(span);

이벤트 리스너

// 이벤트 위임 패턴 (성능 최적화)
document.querySelector('.list').addEventListener('click', (e) => {
    const btn = e.target.closest('.delete-btn');
    if (!btn) return;
    handleDelete(btn.dataset.id);
});

API 호출

async function fetchData(url, body) {
    const res = await fetch(url, {
        method: 'POST',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify(body)
    });
    if (!res.ok) throw new Error(`HTTP ${res.status}`);
    return res.json();
}

외부 CDN 보안

외부 CDN 사용 시 SRI(Subresource Integrity) 해시 필수:

<link rel="stylesheet"
      href="https://cdn.example.com/lib.css"
      integrity="sha384-..."
      crossorigin="anonymous">

<script src="https://cdn.example.com/lib.js"
        integrity="sha384-..."
        crossorigin="anonymous"></script>

SRI 해시 생성: srihash.org


이미지 최적화

<!-- WebP 우선, PNG 폴백 -->
<picture>
    <source srcset="/img/photo.webp" type="image/webp">
    <img src="/img/photo.png" alt="설명" loading="lazy" width="800" height="600">
</picture>

<!-- 중요한 이미지 (LCP) -->
<img src="/img/hero.png" alt="..." loading="eager" fetchpriority="high">
AI 문서 검색

현재 페이지 내용을 기반으로 질문하세요.