drawn-notebook-ui은(는) 무엇을 하나요?
개요
Drawn Notebook은 컴포넌트 라이브러리가 아닙니다. 그것은 디자인 언어입니다—모든 픽셀, 모든 선 두께, 모든 간격 리듬, 모든 애니메이션 타이밍 곡선이 일관된 철학을 따릅니다. 그 지배 원칙은 인터페이스가 살아있는 노트북처럼 느껴져야 한다는 것입니다: 크림색 종이에 잉크로 그려지고, 독자가 스크롤을 내리면서 천천히 드러나는 구절들, 물리적 여행처럼 페이지를 가로지르는 내비게이션 실. 아무것도 시끄럽지 않습니다. 아무것도 그 자체로 장식적이지 않습니다. UI는 모든 시각적 요소를 의미에 고정시킵니다.
이 스킬은 정확하고 포괄적인 참조 자료입니다. 이 UI를 구현할 때는 각 섹션을 순서대로 따르십시오. 토큰 정의를 건너뛰지 마십시오—모든 간격, 색상, 모션 값은 하중을 지탱합니다. 다크 모드 섹션을 건너뛰지 마십시오—두 테마 모두 동등한 일급 시민이며 항상 동시에 올바르게 유지되어야 합니다.
섹션 1 — 디자인 철학
1.1 핵심 원칙
자체 목적을 위한 미니멀리즘이 아닌, 조용한 자신감. 디자인은 여백이 많지만, 남아 있는 모든 요소는 목적이 있습니다. 빈 공간은 게으름이 아닙니다—페이지가 숨 쉬는 것입니다. 사용자의 시선은 색상 채도나 장식적 화려함이 아니라 구성, 무게, 움직임에 의해 인도됩니다.
문자적인 스큐어모피즘 없는 손으로 그린 미학. UI는 그림 그리기의 장인 정신—얇은 선 두께, 세리프 편집체, 종이 질감, 라인 드로잉으로 렌더링된 SVG 일러스트레이션—을 참조하지만, 종이인 척 하지는 않습니다. 서투르게 모방하지 않으면서 아날로그 공예의 촉감을 존중하는 디지털 표면입니다.
모든 섹션은 챕터입니다. 페이지는 연속 스크롤이며, 각 섹션은 노트북에서 새 페이지를 여는 것처럼 느껴집니다. 섹션 배경은 따뜻한 중성색 사이에서 미묘하게 변합니다. 연속적인 황금색 실(여정 라인 SVG)이 시각적으로 함께 꿰매줍니다.
모션은 내레이션이지, 오락이 아닙니다. 애니메이션은 손이 글자를 쓰는 방식처럼 콘텐츠를 드러냅니다—아래에서 위로 나타나고, 부드럽게 페이드 인되며, SVG 경로를 따라 그려집니다. 지속 시간은 현대적 기준으로 느립니다(리빌에 1.2초–2초). 이것은 의도적입니다. 속도는 소음을 의미합니다. 느림은 장인 정신을 의미합니다.
AI 슬롭 패턴을 피하십시오. 다음 패턴은 명시적으로 금지됩니다: 보라색에서 분홍색 그라데이션 히어로 배경, 동일한 높이와 동일한 모서리 반경의 카드 그리드, 네온으로 빛나는 호버 상태, 대부분의 요소에서 14px를 초과하는 큰 모서리 반올림, 퍼센트 숫자가 포함된 색상 코딩된 스킬 바, 글머리 기호와 굵은 날짜가 있는 타임라인, 장식으로서의 이모지 사용.
섹션 2 — 디자인 토큰
2.1 색상 팔레트 — 라이트 모드 (데이라이트 노트북)
라이트 모드의 모든 색상은 종이, 크림, 자연 잉크에서 파생된 따뜻한 중성색입니다. 단일 악센트 계열이 있습니다: 골드/테라코타—음소거된 호박색에서 따뜻한 벽돌색까지의 범위입니다.
/* 라이트 모드 (:root에 적용) */
--cream: #F7F5F0; /* 페이지 배경 — 기본 표면 */
--sage: #EEF3ED; /* 소개 섹션 배경 — 가장 밝은 회녹색 */
--parchment: #F1ECE3; /* 경력 + 이력서 섹션 배경 */
--warm-white: #FAF8F5; /* 스킬 섹션 배경 — 가장 밝은 표면 */
--linen: #F3EFE8; /* 프로젝트 섹션 배경 */
--sage-tint: #EFF3EE; /* 학습 섹션 배경 */
--charcoal: #1A1A1A; /* 기본 텍스트, SVG 선, 테두리 */
--soft-black: #2C2C2C; /* 보조 텍스트, 강한 레이블 */
--warm-grey: #8A8580; /* 음소거된 레이블, 타임스탬프, 캡션 */
--light-grey: #C5BFB8; /* 스크롤 프롬프트, 장식적 구분선 */
--terracotta: #B87A5A; /* 호버 상태, 글머리 기호, 활성 웨이포인트 */
--indigo: #6B6EA0; /* 예약됨 — 기본 패턴에 사용되지 않음 */
--gold: #C4956A; /* 기본 악센트 — 여정 라인, 스킬 아이콘, 칩 */
--gold-dim: rgba(196, 149, 106, 0.3); /* 그림자, 테두리용 소프트 골드 */
--blush: #F0EBE5; /* 칩/배지 배경 (호버 시) */
--sage-dark: #8B9E8B; /* 섹션 테두리 구분선 색조 */
2.2 색상 팔레트 — 다크 모드 (나이트 노트북)
다크 모드는 단순한 반전이 아닙니다. 배경은 따뜻한 크림색에서 깊고 따뜻한 검정색으로 이동합니다—거의 잉크에 얼룩진 듯한 품질입니다. 악센트 색상은 어두운 표면에서 가독성을 유지하기 위해 약간 밝아집니다.
/* 다크 모드 (:root[data-theme="dark"]에 적용) */
--cream: #141210; /* 페이지 배경 — 깊고 따뜻한 검정 */
--sage: #171816; /* 소개 섹션 배경 */
--parchment: #1A1815; /* 경력 + 이력서 배경 */
--warm-white: #1E1B18; /* 스킬 섹션 배경 */
--linen: #181614; /* 프로젝트 섹션 배경 */
--sage-tint: #161815; /* 학습 섹션 배경 */
--charcoal: #EDE8E1; /* 기본 텍스트 — 따뜻한 오프 화이트 */
--soft-black: #D8D2C8; /* 보조 텍스트 */
--warm-grey: #9E978F; /* 음소거된 레이블 */
--light-grey: #38342E; /* 장식적 구분선 */
--terracotta: #D98A62; /* 호버 악센트 — 라이트 모드보다 약간 더 밝음 */
--indigo: #8C8FB8;
--gold: #D4A373; /* 기본 악센트 — 라이트 모드보다 약간 더 따뜻함 */
--gold-dim: rgba(212, 163, 115, 0.3);
--blush: #241E1A;
--sage-dark: #9EAF9E;
/* 표면 토큰 */
--card-glass: rgba(30, 27, 24, 0.72);
--card-glass-hover: rgba(42, 38, 34, 0.95);
--card-item-bg: rgba(24, 21, 19, 0.78);
--card-item-hover: rgba(38, 34, 30, 0.96);
--card-border: rgba(212, 163, 115, 0.22);
--card-border-hover: rgba(212, 163, 115, 0.48);
--card-shadow: 0 4px 16px rgba(0, 0, 0, 0.25);
--card-shadow-hover: 0 6px 20px rgba(0, 0, 0, 0.45);
--card-inset: inset 0 1px 0 rgba(255, 255, 255, 0.05);
--card-inset-hover: inset 0 1px 0 rgba(255, 255, 255, 0.08);
--badge-bg: rgba(24, 21, 19, 0.88);
--grain-opacity: 0.022; /* 다크에서 흐릿함을 피하기 위해 더 낮춤 */
2.3 색상 팔레트 — 라이트 모드 표면 토큰
/* 라이트 모드 표면 토큰 */
--card-glass: rgba(255, 255, 255, 0.65);
--card-glass-hover: #ffffff;
--card-item-bg: rgba(247, 245, 240, 0.8);
--card-item-hover: rgba(255, 255, 255, 0.98);
--card-border: rgba(196, 149, 106, 0.22);
--card-border-hover: rgba(196, 149, 106, 0.45);
--card-shadow: 0 4px 16px rgba(26, 26, 26, 0.04);
--card-shadow-hover: 0 6px 20px rgba(196, 149, 106, 0.12);
--card-inset: inset 0 1px 0 rgba(255, 255, 255, 0.9);
--card-inset-hover: inset 0 1px 0 rgba(255, 255, 255, 0.95);
--badge-bg: rgba(247, 245, 240, 0.82);
--grain-opacity: 0.035;
2.4 테마 전환 — 플래시 없는 구현
테마 감지는 페이지가 렌더링되기 전에 <head>에서 동기적으로 실행되어야 잘못된 테마의 플래시(FOUT)를 방지할 수 있습니다. 이것은 중요한 구현 요구 사항입니다:
<head>
<!-- 스타일시트 링크 전에 <head>의 첫 번째 스크립트여야 함 -->
<script>
(function () {
try {
var stored = localStorage.getItem('color-scheme');
var prefersDark = window.matchMedia &&
window.matchMedia('(prefers-color-scheme: dark)').matches;
var theme = (stored === 'dark' || (!stored && prefersDark)) ? 'dark' : 'light';
document.documentElement.setAttribute('data-theme', theme);
var meta = document.querySelector('meta[name="color-scheme"]');
if (meta && (stored === 'dark' || stored === 'light')) meta.content = stored;
var themeColor = document.querySelector('meta[name="theme-color"]');
if (themeColor) themeColor.content = theme === 'dark' ? '#141210' : '#F8F4F0';
} catch (e) {}
})();
</script>
</head>
Flutter/Dart에서는 기본값으로 ThemeMode.system을 사용하고, SharedPreferences를 통해 지속적인 재정의를 적용합니다. 키는 color-scheme이고, 값은 'dark' 또는 'light'입니다.
2.5 타이포그래피 토큰
--font-serif: 'Cormorant Garamond', 'Georgia', serif;
--font-sans: 'Inter', 'Helvetica Neue', sans-serif;
Cormorant Garamond는 이 디자인의 편집적 목소리에 있어 타협할 수 없는 요소입니다. 가중치 300, 400, 500, 600으로 로드되며, 300과 400에는 이탤릭 변형이 포함됩니다. 모든 제목, 섹션 제목, 히어로 이름, 칩, 레일 레이블, 웨이포인트 메시지 및 "손으로 쓴" 느낌이 필요한 모든 곳에 사용됩니다. 가중치 600 이상에서는 절대 사용해서는 안 됩니다—이것은 굵은 서체가 아닙니다.
Inter는 기능적 동반자입니다. 캡션, 스킬 태그, 타임스탬프, 대문자 키커, 밀집된 정보 컨텍스트의 본문 텍스트에 사용됩니다. 가중치 300, 400, 500만 로드합니다.
/* Google Fonts 가져오기 */
@import url('https://fonts.googleapis.com/css2?family=Cormorant+Garamond:ital,wght@0,300;0,400;0,500;0,600;1,300;1,400&family=Inter:wght@300;400;500&display=swap');
2.6 간격 토큰
모든 간격은 clamp()를 사용하여 유동적입니다. 섹션 패딩이나 콘텐츠 너비 제약 조건에 하드 픽셀 값을 사용하지 마십시오.
--section-pad: clamp(80px, 12vh, 160px); /* 주요 섹션의 수직 패딩 */
--content-max: 800px; /* 좁은 산문 열 */
--content-wide: 1100px; /* 그리드용 넓은 레이아웃 */
--side-pad: clamp(24px, 5vw, 80px); /* 수평 페이지 여백 */
2.7 애니메이션 토큰
--ease-out: cubic-bezier(0.25, 0.46, 0.45, 0.94); /* 일반 이즈 아웃 */
--ease-smooth: cubic-bezier(0.4, 0, 0.2, 1); /* Material과 유사한 부드러움 */
--duration-slow: 1.2s; /* 리빌 애니메이션 */
--duration-med: 0.8s; /* 중간 전환 */
--duration-fast: 0.4s; /* 빠른 마이크로 상호작용 */
섹션 3 — 글로벌 기반
3.1 CSS 리셋 및 베이스
*, *::before, *::after {
box-sizing: border-box;
margin: 0;
padding: 0;
}
html {
font-size: 16px;
scroll-behavior: smooth;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
}
body {
background-color: var(--cream);
color: var(--charcoal);
font-family: var(--font-sans);
font-weight: 300;
line-height: 1.7;
overflow-x: hidden;
position: relative;
}
3.2 텍스트 선택
선택 강조 표시는 부드러운 골드 워시입니다—공격적이지 않으면서 악센트 팔레트를 반영합니다:
::selection {
background: rgba(196, 149, 106, 0.2);
color: var(--charcoal);
}
::-moz-selection {
background: rgba(196, 149, 106, 0.2);
color: var(--charcoal);
}
3.3 SVG 선 적응
모든 인라인 SVG는 라이트 모드 팔레트의 하드코딩된 16진수 선(#1A1A1A, #2C2C2C)을 사용합니다. SVG 마크업을 건드리지 않고 다크 모드에 적응하려면 CSS 속성 선택기 재정의를 사용하십시오:
svg [stroke="#1A1A1A"], svg [stroke="#1a1a1a"] { stroke: var(--charcoal); }
svg [fill="#1A1A1A"], svg [fill="#1a1a1a"] { fill: var(--charcoal); }
svg [stroke="#2C2C2C"], svg [stroke="#2c2c2c"] { stroke: var(--soft-black); }
svg [fill="#2C2C2C"], svg [fill="#2c2c2c"] { fill: var(--soft-black); }
svg text[fill="#1A1A1A"] { fill: var(--charcoal); }
svg text[fill="#8A8580"] { fill: var(--warm-grey); }
SVG의 골드 악센트(#C4956A)는 의도적으로 재정의되지 않습니다. 골드 악센트는 두 테마에서 고정 참조 색상입니다. 다크 모드에서 토큰 --gold는 #D4A373으로 밝아지지만, SVG 인라인 골드는 어두운 배경에 대한 대비가 여전히 허용 가능하므로 다시 매핑할 필요가 없습니다.
3.4 부드러운 테마 전환
테마 간에 변경되는 모든 표면에 조정된 전환을 적용합니다. 이것은 급격한 색상 점프를 방지합니다:
body, section,
.about, .experience, .resume-section, .skills, .projects, .learning, .closing,
.exp-card, .exp-item, .skill-cell, .compact-card, .compact-card__icon,
.about__point, .about__visual-card, .about__chip, .closing__link,
.journey-waypoint__message, .rail-node__label, .resume-modal__panel,
.resume-modal__header {
transition:
background-color 0.35s var(--ease-out),
color 0.35s var(--ease-out),
border-color 0.35s var(--ease-out);
}
/* 항상 사용자 모션 선호도 존중 */
@media (prefers-reduced-motion: reduce) {
*, *::before, *::after { transition: none !important; }
}
섹션 4 — 종이 질감 오버레이
미묘한 종이 질감 텍스처가 전체 뷰포트 고정 오버레이로 적용됩니다. z-index: 9999에 위치합니다—모든 것 위에—하지만 pointer-events: none 덕분에 상호작용을 절대 가로채지 않습니다.
.grain-overlay {
position: fixed;
inset: 0;
pointer-events: none;
z-index: 9999;
opacity: var(--grain-opacity, 0.035);
background-image: url("data:image/svg+xml,%3Csvg viewBox='0 0 256 256' xmlns='http://www.w3.org/2000/svg'%3E%3Cfilter id='noise'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.85' numOctaves='4' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23noise)'/%3E%3C/svg%3E");
background-repeat: repeat;
background-size: 200px 200px;
transform: translateZ(0);
will-change: transform;
transition: opacity 0.35s var(--ease-out);
}
/* 다크 모드에서는 스크린 블렌드가 질감을 더 자연스럽게 드러냄 */
:root[data-theme="dark"] .grain-overlay {
mix-blend-mode: screen;
}
Flutter에서: 위젯 트리 최상단에 shader 기반 노이즈 패턴을 가진 CustomPaint 위젯을 사용하여 이를 재현하거나, 약 3% 불투명도의 PNG 자산으로 질감을 구워서 다크 모드에서 BlendMode.screen과 함께 사용하십시오.
섹션 5 — 테마 토글 (천체 스위처)
테마 토글은 오른쪽 상단 모서리에 고정된 작은 알약 버튼입니다.
...