d8a80f6272
이름만 다른(표기 변형) [[위키링크]]를 대상 문서의 canonical 제목으로 치환해 끊겼던 1,200개 링크를 연결. 제목/파일명 정규화 일치만 적용하고 별칭 매칭은 과병합 위험으로 제외(애매성 가드). 원본은 _link_reconcile_backup/ 에 백업. 도구: Datacollect/scripts/link_reconcile_apply.mjs Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
5.6 KiB
5.6 KiB
id, title, category, status, canonical_id, aliases, duplicate_of, source_trust_level, confidence_score, verification_status, tags, raw_sources, last_reinforced, github_commit, tech_stack
| id | title | category | status | canonical_id | aliases | duplicate_of | source_trust_level | confidence_score | verification_status | tags | raw_sources | last_reinforced | github_commit | tech_stack | ||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| wiki-2026-0508-렌더링-블로킹-방지를-위한-css-분할-및-로딩-최적화 | 렌더링 블로킹 방지를 위한 CSS 분할 및 로딩 최적화 | 10_Wiki/Topics | verified | self |
|
none | A | 0.95 | applied |
|
2026-05-10 | pending |
|
렌더링 블로킹 방지를 위한 CSS 분할 및 로딩 최적화
매 한 줄
"매 CSS는 default 로 render-blocking".
<link rel="stylesheet">가 도착할 때까지 브라우저는 paint 안 함. Critical CSS inline + non-critical async load + route-based split → LCP 50%+ 개선. 2026 표준은 Vite/Rollup chunk +media="print"trick.
매 핵심
매 왜 CSS 가 blocking 인가
- HTML parser 가
<link rel="stylesheet">만나면 CSSOM 만들 때까지 paint X. - CSSOM 없이는 element 의 final style 알 수 없음 → FOUC 방지 위해 block.
- 1 round-trip (HTTP) + parse + match = 100-500ms LCP cost.
매 분할 전략
- Critical CSS: above-the-fold 의 minimal CSS —
<style>으로 inline. - Async load: 나머지 CSS 는 non-blocking —
media="print"swap trick /rel="preload". - Route-based split: 각 route 마다 별도 CSS chunk — 안 쓰는 CSS 안 download.
- Component-scoped: CSS-in-JS / CSS Modules → 자동 split.
매 응용
- Marketing landing (LCP 핵심).
- SSR app (FOUC 방지 critical inline).
- SPA (route chunk).
💻 패턴
Critical CSS inline (manual)
<head>
<style>
/* 매 above-the-fold only — header, hero, font-face */
body { font-family: system-ui; margin: 0; }
.hero { height: 80vh; background: #111; color: #fff; }
</style>
<link
rel="preload"
href="/css/main.css"
as="style"
onload="this.onload=null;this.rel='stylesheet'"
/>
<noscript><link rel="stylesheet" href="/css/main.css" /></noscript>
</head>
Critical CSS extraction (Vite plugin)
// vite.config.ts
import { defineConfig } from 'vite';
import critical from 'rollup-plugin-critical';
export default defineConfig({
plugins: [
critical({
criticalUrl: 'https://example.com/',
criticalBase: './dist/',
criticalPages: [{ uri: '', template: 'index' }],
criticalConfig: { inline: true, dimensions: [{ width: 375, height: 812 }, { width: 1920, height: 1080 }] },
}),
],
});
print media swap trick (no JS)
<link rel="stylesheet" href="/css/main.css" media="print" onload="this.media='all'" />
브라우저가 media="print" 를 non-blocking 으로 download → onload 시 all 로 swap.
Route-based split (Next.js)
// app/products/page.tsx — 매 자동으로 별도 CSS chunk.
import './products.css'; // 매 only loaded on /products.
CSS Modules (component-scoped)
import styles from './Button.module.css';
<button className={styles.primary}>Click</button>;
// 매 build 시 hash → only used styles bundled.
Tailwind v4 (oxide engine, 2026)
/* main.css */
@import "tailwindcss";
@theme {
--color-brand: oklch(0.7 0.2 250);
}
PurgeCSS 자동 — 매 unused class 제거. 최종 bundle 5-10KB.
Preload key fonts + CSS together
<link rel="preload" href="/fonts/inter-var.woff2" as="font" type="font/woff2" crossorigin />
<link rel="preload" href="/css/main.css" as="style" />
CSS containment for paint isolation
.card {
contain: content; /* 매 layout + paint + style 격리 */
content-visibility: auto;
contain-intrinsic-size: 0 200px;
}
HTTP/2 push 대체 — 103 Early Hints
HTTP/1.1 103 Early Hints
Link: </css/main.css>; rel=preload; as=style
Link: </js/app.js>; rel=preload; as=script
Cloudflare/Vercel 자동 지원 — TTFB 안 기다리고 preload 시작.
Detect unused CSS (Chrome DevTools)
# 매 Coverage tab → Record → reload → unused % 확인.
# 매 80%+ unused = split 필요.
매 결정 기준
| 상황 | Approach |
|---|---|
| Marketing landing | Critical inline + async rest. |
| SPA | Route-based split + CSS Modules. |
| SSR (Next/Remix) | 매 자동 split — Tailwind v4 면 충분. |
| Component lib | CSS-in-JS 또는 CSS Modules — tree-shake. |
| Legacy multi-page | print media trick + critical extraction. |
기본값: Tailwind v4 + Vite/Next 자동 chunk + <link rel="preload"> for above-fold.
🔗 Graph
- 부모: Web Performance · Core Web Vitals Optimization (INP, LCP, CLS)
- 변형: Critical CSS · CSS_Architecture_and_Styling · CSS Modules
- 응용: Tailwind v4 · Vite · Next.js
🤖 LLM 활용
언제: LCP > 2.5s, CSS bundle > 100KB, FOUC 발생. 언제 X: 매 internal tool (LCP 무관), 매 tiny site (single CSS file 충분).
❌ 안티패턴
- Single mega CSS: 매 1MB CSS load — purge + split.
@importchain: serial load — bundle 로 합치거나<link>직접.- Inline ALL CSS: HTML 비대 → critical only.
- No font-display: FOIT (invisible text) →
font-display: swap. - CSS in
<body>: legacy hack 매 —<head>에서 preload. - Unused frameworks: Bootstrap full 250KB 인데 button 만 사용.
🧪 검증 / 중복
- Verified (web.dev/extract-critical-css, MDN preload, Vite docs, Tailwind v4 docs).
- 신뢰도 A.
🕓 Changelog
| 날짜 | 변경 |
|---|---|
| 2026-05-08 | Phase 1 |
| 2026-05-10 | Manual cleanup — critical CSS + Tailwind v4 + Early Hints |