podo-ui 0.1.43 → 0.1.46
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/ARCHITECTURE.md +727 -0
- package/package.json +1 -1
- package/public/logo.svg +57 -0
- package/readme.md +13 -3
- package/scss/form/select.scss +3 -0
- package/scss/icon/font/icon.woff +0 -0
- package/scss/icon/icon-name.scss +1 -0
- package/src/app/components/button/page.module.scss +253 -0
- package/src/app/components/button/page.tsx +366 -0
- package/src/app/components/checkbox-radio/page.module.scss +95 -0
- package/src/app/components/checkbox-radio/page.tsx +265 -0
- package/src/app/components/input/page.module.scss +112 -0
- package/src/app/components/input/page.tsx +196 -0
- package/src/app/components/select/page.module.scss +90 -0
- package/src/app/components/select/page.tsx +225 -0
- package/src/app/components/textarea/page.module.scss +81 -0
- package/src/app/components/textarea/page.tsx +103 -0
- package/src/app/foundation/colors/page.module.scss +370 -0
- package/src/app/foundation/colors/page.tsx +200 -0
- package/src/app/foundation/icons/page.module.scss +229 -0
- package/src/app/foundation/icons/page.tsx +229 -0
- package/src/app/foundation/spacing/page.module.scss +258 -0
- package/src/app/foundation/spacing/page.tsx +289 -0
- package/src/app/foundation/typography/page.module.scss +148 -0
- package/src/app/foundation/typography/page.tsx +207 -0
- package/src/app/getting-started/installation/page.module.scss +157 -0
- package/src/app/getting-started/installation/page.tsx +154 -0
- package/src/app/getting-started/usage/page.module.scss +209 -0
- package/src/app/getting-started/usage/page.tsx +242 -0
- package/src/app/home.module.scss +541 -0
- package/src/app/layout/grid/page.module.scss +178 -0
- package/src/app/layout/grid/page.tsx +217 -0
- package/src/app/layout/responsive/page.module.scss +237 -0
- package/src/app/layout/responsive/page.tsx +279 -0
- package/src/app/layout.module.scss +14 -0
- package/src/app/layout.tsx +13 -1
- package/src/app/page.tsx +262 -2690
- package/src/components/CodeBlock.module.scss +29 -0
- package/src/components/CodeBlock.tsx +18 -0
- package/src/components/Navigation.module.scss +104 -0
- package/src/components/Navigation.tsx +96 -0
- package/src/components/PageHeader.module.scss +24 -0
- package/src/components/PageHeader.tsx +17 -0
- package/src/components/ThemeToggle.module.scss +34 -0
- package/src/components/ThemeToggle.tsx +47 -0
- package/src/styles/doc-common.scss +119 -0
- package/SECURITY.md +0 -21
package/ARCHITECTURE.md
ADDED
|
@@ -0,0 +1,727 @@
|
|
|
1
|
+
# Podo-UI Architecture
|
|
2
|
+
|
|
3
|
+
## 프로젝트 개요
|
|
4
|
+
|
|
5
|
+
**Podo-UI**는 SCSS 모듈 기반의 디자인 시스템이자 React용 UI 컴포넌트 라이브러리입니다. CSS 클래스를 주로 제공하면서, 복잡한 폼 인터랙션을 위한 일부 React 컴포넌트도 포함하는 하이브리드 라이브러리입니다.
|
|
6
|
+
|
|
7
|
+
- **버전:** 0.1.44
|
|
8
|
+
- **라이선스:** MIT
|
|
9
|
+
- **저장소:** https://github.com/hada0127/podo-ui
|
|
10
|
+
- **핵심 특징:** SCSS 우선, 라이트/다크 테마, 반응형 그리드, 아이콘 폰트 시스템
|
|
11
|
+
|
|
12
|
+
---
|
|
13
|
+
|
|
14
|
+
## 목차
|
|
15
|
+
|
|
16
|
+
1. [프로젝트 구조](#1-프로젝트-구조)
|
|
17
|
+
2. [SCSS 디자인 시스템](#2-scss-디자인-시스템)
|
|
18
|
+
3. [React 컴포넌트](#3-react-컴포넌트)
|
|
19
|
+
4. [CLI 도구](#4-cli-도구)
|
|
20
|
+
5. [스타일링 접근법](#5-스타일링-접근법)
|
|
21
|
+
6. [빌드 및 배포](#6-빌드-및-배포)
|
|
22
|
+
7. [개발 워크플로우](#7-개발-워크플로우)
|
|
23
|
+
8. [핵심 기술 스택](#8-핵심-기술-스택)
|
|
24
|
+
|
|
25
|
+
---
|
|
26
|
+
|
|
27
|
+
## 1. 프로젝트 구조
|
|
28
|
+
|
|
29
|
+
### 루트 디렉토리 구조
|
|
30
|
+
|
|
31
|
+
```
|
|
32
|
+
podo-ui/
|
|
33
|
+
├── cli/ # CLI 도구 (아이콘 생성)
|
|
34
|
+
├── react/ # React 컴포넌트 소스
|
|
35
|
+
│ ├── atom/ # 원자 단위 컴포넌트
|
|
36
|
+
│ └── molecule/ # 분자 단위 컴포넌트
|
|
37
|
+
├── scss/ # SCSS 디자인 시스템
|
|
38
|
+
│ ├── button/ # 버튼 스타일
|
|
39
|
+
│ ├── color/ # 컬러 시스템
|
|
40
|
+
│ ├── form/ # 폼 요소
|
|
41
|
+
│ ├── icon/ # 아이콘 시스템
|
|
42
|
+
│ ├── layout/ # 레이아웃 유틸리티
|
|
43
|
+
│ ├── molecule/ # 복합 컴포넌트
|
|
44
|
+
│ └── typo/ # 타이포그래피
|
|
45
|
+
├── src/ # Next.js 데모/문서 앱
|
|
46
|
+
│ └── app/ # 앱 라우트
|
|
47
|
+
├── global.scss # 글로벌 스타일 진입점
|
|
48
|
+
├── mixin.scss # SCSS 함수/믹스인
|
|
49
|
+
├── react.ts # React 컴포넌트 표준 내보내기
|
|
50
|
+
├── next.ts # Next.js용 컴포넌트 내보내기
|
|
51
|
+
└── package.json # 패키지 설정
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
### 주요 설정 파일
|
|
55
|
+
|
|
56
|
+
#### package.json
|
|
57
|
+
|
|
58
|
+
```json
|
|
59
|
+
{
|
|
60
|
+
"type": "module",
|
|
61
|
+
"scripts": {
|
|
62
|
+
"dev": "next dev",
|
|
63
|
+
"build": "next build",
|
|
64
|
+
"icon": "node cli/icon-scss.js",
|
|
65
|
+
"pages:build": "pnpm next-on-pages",
|
|
66
|
+
"deploy": "pnpm pages:build && wrangler pages deploy"
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
- **타입:** ESM 모듈
|
|
72
|
+
- **주요 의존성:** React 18, Next.js 14, Sass, Zod, SunEditor
|
|
73
|
+
- **빌드 타겟:** Next.js + Cloudflare Pages
|
|
74
|
+
|
|
75
|
+
#### tsconfig.json
|
|
76
|
+
|
|
77
|
+
- Strict 모드 활성화
|
|
78
|
+
- Next.js 플러그인 통합
|
|
79
|
+
- 경로 별칭: `@/*` → `./src/*`
|
|
80
|
+
- 모듈 해석: bundler
|
|
81
|
+
|
|
82
|
+
---
|
|
83
|
+
|
|
84
|
+
## 2. SCSS 디자인 시스템
|
|
85
|
+
|
|
86
|
+
### 디렉토리 구조
|
|
87
|
+
|
|
88
|
+
```
|
|
89
|
+
scss/
|
|
90
|
+
├── button/ # 버튼 스타일
|
|
91
|
+
│ ├── class.scss # 색상 변형 클래스
|
|
92
|
+
│ └── layout.scss # 기본 버튼 레이아웃
|
|
93
|
+
├── color/ # 컬러 시스템
|
|
94
|
+
│ ├── class.scss # 컬러 유틸리티 클래스
|
|
95
|
+
│ ├── function.scss # 컬러 SCSS 함수
|
|
96
|
+
│ └── theme.scss # 라이트/다크 테마 변수
|
|
97
|
+
├── form/ # 폼 요소
|
|
98
|
+
│ ├── checkbox-radio.scss
|
|
99
|
+
│ ├── file.scss
|
|
100
|
+
│ ├── input.scss
|
|
101
|
+
│ ├── label.scss
|
|
102
|
+
│ ├── select.scss
|
|
103
|
+
│ ├── textarea.scss
|
|
104
|
+
│ └── toggle.scss
|
|
105
|
+
├── icon/ # 아이콘 시스템
|
|
106
|
+
│ ├── font/icon.woff # 아이콘 폰트 파일
|
|
107
|
+
│ ├── function.scss # 아이콘 헬퍼 함수
|
|
108
|
+
│ ├── icon-name.scss # 자동 생성된 아이콘 맵
|
|
109
|
+
│ └── icon.scss # 아이콘 기본 스타일
|
|
110
|
+
├── layout/ # 레이아웃 유틸리티
|
|
111
|
+
│ ├── grid.scss # 그리드 시스템
|
|
112
|
+
│ ├── spacing.scss # 간격 시스템
|
|
113
|
+
│ ├── radius.scss # 테두리 반경
|
|
114
|
+
│ ├── border.scss # 테두리
|
|
115
|
+
│ └── device.scss # 반응형 브레이크포인트
|
|
116
|
+
├── molecule/ # 복합 컴포넌트
|
|
117
|
+
│ ├── pagination.scss
|
|
118
|
+
│ ├── tab.scss
|
|
119
|
+
│ └── table.scss
|
|
120
|
+
├── typo/ # 타이포그래피
|
|
121
|
+
│ ├── font/ # Pretendard 폰트 (9가지 굵기)
|
|
122
|
+
│ ├── font-family.scss
|
|
123
|
+
│ ├── font-size.scss
|
|
124
|
+
│ ├── mixin.scss # 타이포그래피 믹스인
|
|
125
|
+
│ └── typo.scss
|
|
126
|
+
└── reset.scss # CSS 리셋
|
|
127
|
+
```
|
|
128
|
+
|
|
129
|
+
### 핵심 디자인 토큰
|
|
130
|
+
|
|
131
|
+
#### 컬러 시스템
|
|
132
|
+
|
|
133
|
+
**테마 아키텍처** ([scss/color/theme.scss](scss/color/theme.scss)):
|
|
134
|
+
|
|
135
|
+
- CSS 변수 기반 테마
|
|
136
|
+
- `data-color-mode` 속성으로 라이트/다크 모드 전환
|
|
137
|
+
- `data-color-tone` 속성으로 웜 톤 지원
|
|
138
|
+
- 8가지 시맨틱 컬러: primary, default, default-deep, info, link, success, warning, danger
|
|
139
|
+
- 각 컬러는 7가지 변형: base, hover, pressed, focus, fill, reverse, outline
|
|
140
|
+
|
|
141
|
+
**사용법:**
|
|
142
|
+
|
|
143
|
+
```scss
|
|
144
|
+
@use 'podo-ui/mixin' as *;
|
|
145
|
+
|
|
146
|
+
.button {
|
|
147
|
+
background: color(primary-base);
|
|
148
|
+
|
|
149
|
+
&:hover {
|
|
150
|
+
background: color(primary-hover);
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
```
|
|
154
|
+
|
|
155
|
+
#### 간격 시스템
|
|
156
|
+
|
|
157
|
+
**간격 스케일** ([scss/layout/spacing.scss](scss/layout/spacing.scss)):
|
|
158
|
+
|
|
159
|
+
```
|
|
160
|
+
0: 0px 1: 2px 2: 4px 3: 8px 4: 12px
|
|
161
|
+
5: 16px 6: 24px 7: 32px 8: 40px 9: 48px
|
|
162
|
+
10: 64px 11: 80px 12: 96px 13: 160px
|
|
163
|
+
```
|
|
164
|
+
|
|
165
|
+
**SCSS 함수:**
|
|
166
|
+
|
|
167
|
+
```scss
|
|
168
|
+
@use 'podo-ui/mixin' as *;
|
|
169
|
+
|
|
170
|
+
.card {
|
|
171
|
+
padding: s(5); // 16px
|
|
172
|
+
margin-bottom: s(6); // 24px
|
|
173
|
+
}
|
|
174
|
+
```
|
|
175
|
+
|
|
176
|
+
**유틸리티 클래스:**
|
|
177
|
+
|
|
178
|
+
```html
|
|
179
|
+
<div class="p-5 m-b-6"> <!-- padding: 16px, margin-bottom: 24px -->
|
|
180
|
+
<div class="p-t-3 m-l-4"> <!-- padding-top: 8px, margin-left: 12px -->
|
|
181
|
+
```
|
|
182
|
+
|
|
183
|
+
#### 그리드 시스템
|
|
184
|
+
|
|
185
|
+
**반응형 그리드** ([scss/layout/grid.scss](scss/layout/grid.scss)):
|
|
186
|
+
|
|
187
|
+
- PC: 12컬럼, 태블릿: 6컬럼, 모바일: 4컬럼
|
|
188
|
+
- 자동 래핑 그리드: `.grid` 클래스
|
|
189
|
+
- 고정 컬럼 그리드: `.grid-fix-2` ~ `.grid-fix-6`
|
|
190
|
+
- 너비 유틸리티: `.w-1` ~ `.w-12`, `.w-1_4`, `.w-2_6` 등
|
|
191
|
+
- 픽셀 기반 너비: `.w-{n}px` (0-5000)
|
|
192
|
+
|
|
193
|
+
**사용 예:**
|
|
194
|
+
|
|
195
|
+
```html
|
|
196
|
+
<!-- 자동 래핑 그리드 -->
|
|
197
|
+
<div class="grid">
|
|
198
|
+
<div class="w-4">컬럼 1</div>
|
|
199
|
+
<div class="w-8">컬럼 2</div>
|
|
200
|
+
</div>
|
|
201
|
+
|
|
202
|
+
<!-- 고정 3컬럼 그리드 -->
|
|
203
|
+
<div class="grid-fix-3">
|
|
204
|
+
<div>항목 1</div>
|
|
205
|
+
<div>항목 2</div>
|
|
206
|
+
<div>항목 3</div>
|
|
207
|
+
</div>
|
|
208
|
+
```
|
|
209
|
+
|
|
210
|
+
#### 아이콘 시스템
|
|
211
|
+
|
|
212
|
+
**구조** ([scss/icon/](scss/icon/)):
|
|
213
|
+
|
|
214
|
+
- 커스텀 아이콘 폰트: `icon.woff`
|
|
215
|
+
- 100개 이상의 아이콘
|
|
216
|
+
- 자동 생성된 [icon-name.scss](scss/icon/icon-name.scss)
|
|
217
|
+
- SCSS 맵 구조: `$icon-name: (star: \e900, star-fill: \e901, ...)`
|
|
218
|
+
|
|
219
|
+
**사용법:**
|
|
220
|
+
|
|
221
|
+
```html
|
|
222
|
+
<i class="icon-star"></i>
|
|
223
|
+
<i class="icon-heart-fill"></i>
|
|
224
|
+
<i class="icon-check"></i>
|
|
225
|
+
```
|
|
226
|
+
|
|
227
|
+
#### 테두리 반경
|
|
228
|
+
|
|
229
|
+
**함수** ([scss/layout/radius.scss](scss/layout/radius.scss)):
|
|
230
|
+
|
|
231
|
+
```scss
|
|
232
|
+
@use 'podo-ui/mixin' as *;
|
|
233
|
+
|
|
234
|
+
.card {
|
|
235
|
+
border-radius: r(4); // 특정 반경 값
|
|
236
|
+
}
|
|
237
|
+
```
|
|
238
|
+
|
|
239
|
+
**유틸리티 클래스:**
|
|
240
|
+
|
|
241
|
+
```html
|
|
242
|
+
<div class="r-2"> <!-- 작은 반경 -->
|
|
243
|
+
<div class="r-4"> <!-- 중간 반경 -->
|
|
244
|
+
<div class="r-full"> <!-- 완전한 원형 -->
|
|
245
|
+
```
|
|
246
|
+
|
|
247
|
+
#### 타이포그래피
|
|
248
|
+
|
|
249
|
+
**폰트 패밀리:** Pretendard (9가지 굵기: 100-900)
|
|
250
|
+
|
|
251
|
+
**타이포그래피 믹스인:**
|
|
252
|
+
|
|
253
|
+
```scss
|
|
254
|
+
@use 'podo-ui/mixin' as *;
|
|
255
|
+
|
|
256
|
+
.title {
|
|
257
|
+
@include display1; // 큰 제목
|
|
258
|
+
}
|
|
259
|
+
|
|
260
|
+
.body {
|
|
261
|
+
@include p1; // 본문 텍스트
|
|
262
|
+
}
|
|
263
|
+
|
|
264
|
+
.caption {
|
|
265
|
+
@include p5; // 캡션 텍스트
|
|
266
|
+
}
|
|
267
|
+
```
|
|
268
|
+
|
|
269
|
+
**스타일:**
|
|
270
|
+
- Display: `display1` ~ `display7`
|
|
271
|
+
- Paragraph: `p1` ~ `p5` (semibold 변형 포함)
|
|
272
|
+
|
|
273
|
+
---
|
|
274
|
+
|
|
275
|
+
## 3. React 컴포넌트
|
|
276
|
+
|
|
277
|
+
### 아토믹 디자인 구조
|
|
278
|
+
|
|
279
|
+
```
|
|
280
|
+
react/
|
|
281
|
+
├── atom/ # 원자 단위 컴포넌트
|
|
282
|
+
│ ├── input.tsx # 검증 기능 입력
|
|
283
|
+
│ ├── input.module.scss
|
|
284
|
+
│ ├── textarea.tsx # 텍스트영역
|
|
285
|
+
│ ├── textarea.module.scss
|
|
286
|
+
│ ├── editor.tsx # WYSIWYG 에디터
|
|
287
|
+
│ ├── editor.module.scss
|
|
288
|
+
│ └── editor-view.tsx # 읽기 전용 에디터
|
|
289
|
+
└── molecule/ # 분자 단위 컴포넌트
|
|
290
|
+
├── field.tsx # 폼 필드 래퍼
|
|
291
|
+
└── field.module.scss
|
|
292
|
+
```
|
|
293
|
+
|
|
294
|
+
### 주요 컴포넌트
|
|
295
|
+
|
|
296
|
+
#### Input 컴포넌트
|
|
297
|
+
|
|
298
|
+
**파일:** [react/atom/input.tsx](react/atom/input.tsx)
|
|
299
|
+
|
|
300
|
+
**특징:**
|
|
301
|
+
- TypeScript 완전 지원
|
|
302
|
+
- Zod 검증 통합
|
|
303
|
+
- 아이콘 지원 (좌/우)
|
|
304
|
+
- 단위 표시 (예: "원")
|
|
305
|
+
- 자동 검증 상태 (success/danger)
|
|
306
|
+
|
|
307
|
+
**사용 예:**
|
|
308
|
+
|
|
309
|
+
```tsx
|
|
310
|
+
import { Input } from 'podo-ui/react'
|
|
311
|
+
import { z } from 'zod'
|
|
312
|
+
|
|
313
|
+
const emailValidator = z.string().email()
|
|
314
|
+
|
|
315
|
+
function MyForm() {
|
|
316
|
+
return (
|
|
317
|
+
<Input
|
|
318
|
+
value={email}
|
|
319
|
+
validator={emailValidator}
|
|
320
|
+
placeholder="이메일을 입력하세요"
|
|
321
|
+
withIcon="mail"
|
|
322
|
+
/>
|
|
323
|
+
)
|
|
324
|
+
}
|
|
325
|
+
```
|
|
326
|
+
|
|
327
|
+
#### Textarea 컴포넌트
|
|
328
|
+
|
|
329
|
+
**파일:** [react/atom/textarea.tsx](react/atom/textarea.tsx)
|
|
330
|
+
|
|
331
|
+
**특징:**
|
|
332
|
+
- Input과 유사한 검증 패턴
|
|
333
|
+
- 표준 textarea 래퍼
|
|
334
|
+
|
|
335
|
+
#### Editor 컴포넌트
|
|
336
|
+
|
|
337
|
+
**파일:** [react/atom/editor.tsx](react/atom/editor.tsx)
|
|
338
|
+
|
|
339
|
+
**특징:**
|
|
340
|
+
- SunEditor 기반 WYSIWYG 에디터
|
|
341
|
+
- 이미지 업로드 (커스텀 헤더 지원)
|
|
342
|
+
- Zod 검증
|
|
343
|
+
- 한국어 지원
|
|
344
|
+
- 풍부한 플러그인 (테이블, 비디오, 링크 등)
|
|
345
|
+
- UUID 기반 고유 ID (다중 인스턴스 지원)
|
|
346
|
+
|
|
347
|
+
**사용 예:**
|
|
348
|
+
|
|
349
|
+
```tsx
|
|
350
|
+
import { Editor } from 'podo-ui/next' // Next.js용
|
|
351
|
+
|
|
352
|
+
function MyEditor() {
|
|
353
|
+
return (
|
|
354
|
+
<Editor
|
|
355
|
+
value={content}
|
|
356
|
+
onChange={setContent}
|
|
357
|
+
imageUploadUrl="/api/upload"
|
|
358
|
+
/>
|
|
359
|
+
)
|
|
360
|
+
}
|
|
361
|
+
```
|
|
362
|
+
|
|
363
|
+
#### Field 컴포넌트
|
|
364
|
+
|
|
365
|
+
**파일:** [react/molecule/field.tsx](react/molecule/field.tsx)
|
|
366
|
+
|
|
367
|
+
**특징:**
|
|
368
|
+
- 레이블, 도움말, 검증이 있는 폼 필드 래퍼
|
|
369
|
+
- 필수 필드 표시
|
|
370
|
+
- Validator 통합
|
|
371
|
+
|
|
372
|
+
**사용 예:**
|
|
373
|
+
|
|
374
|
+
```tsx
|
|
375
|
+
import { Field, Input } from 'podo-ui/react'
|
|
376
|
+
|
|
377
|
+
function MyForm() {
|
|
378
|
+
return (
|
|
379
|
+
<Field
|
|
380
|
+
label="이메일"
|
|
381
|
+
required
|
|
382
|
+
helper="유효한 이메일을 입력하세요"
|
|
383
|
+
validator={emailValidator}
|
|
384
|
+
value={email}
|
|
385
|
+
>
|
|
386
|
+
<Input value={email} onChange={handleChange} />
|
|
387
|
+
</Field>
|
|
388
|
+
)
|
|
389
|
+
}
|
|
390
|
+
```
|
|
391
|
+
|
|
392
|
+
### 내보내기 전략
|
|
393
|
+
|
|
394
|
+
#### 표준 내보내기 ([react.ts](react.ts))
|
|
395
|
+
|
|
396
|
+
```typescript
|
|
397
|
+
export { Input, Textarea, Editor, EditorView, Field }
|
|
398
|
+
```
|
|
399
|
+
|
|
400
|
+
#### Next.js 내보내기 ([next.ts](next.ts))
|
|
401
|
+
|
|
402
|
+
```typescript
|
|
403
|
+
'use client' // 클라이언트 컴포넌트
|
|
404
|
+
|
|
405
|
+
// Editor는 동적 임포트 (SSR 비활성화)
|
|
406
|
+
const Editor = dynamic(() => import('./react/atom/editor'), { ssr: false })
|
|
407
|
+
```
|
|
408
|
+
|
|
409
|
+
---
|
|
410
|
+
|
|
411
|
+
## 4. CLI 도구
|
|
412
|
+
|
|
413
|
+
### 아이콘 SCSS 생성기
|
|
414
|
+
|
|
415
|
+
**파일:** [cli/icon-scss.js](cli/icon-scss.js)
|
|
416
|
+
|
|
417
|
+
**목적:** 아이콘 폰트에서 SCSS 아이콘 이름 매핑 자동 생성
|
|
418
|
+
|
|
419
|
+
**기술:** Node.js + opentype.js
|
|
420
|
+
|
|
421
|
+
**프로세스:**
|
|
422
|
+
1. `/scss/icon/font/icon.woff` 읽기
|
|
423
|
+
2. 글리프 이름과 유니코드 값 추출
|
|
424
|
+
3. SCSS 맵 생성
|
|
425
|
+
4. 글리프 이름의 언더스코어를 하이픈으로 변환
|
|
426
|
+
|
|
427
|
+
**입력:**
|
|
428
|
+
```
|
|
429
|
+
/scss/icon/font/icon.woff
|
|
430
|
+
```
|
|
431
|
+
|
|
432
|
+
**출력:**
|
|
433
|
+
```scss
|
|
434
|
+
// /scss/icon/icon-name.scss
|
|
435
|
+
$icon-name: (
|
|
436
|
+
star: \e900,
|
|
437
|
+
star-fill: \e901,
|
|
438
|
+
exchange-horizontally: \e902,
|
|
439
|
+
// ... 100개 이상의 아이콘
|
|
440
|
+
);
|
|
441
|
+
```
|
|
442
|
+
|
|
443
|
+
**사용법:**
|
|
444
|
+
|
|
445
|
+
```bash
|
|
446
|
+
npm run icon
|
|
447
|
+
```
|
|
448
|
+
|
|
449
|
+
---
|
|
450
|
+
|
|
451
|
+
## 5. 스타일링 접근법
|
|
452
|
+
|
|
453
|
+
### SCSS 모듈 아키텍처
|
|
454
|
+
|
|
455
|
+
#### 글로벌 스타일 ([global.scss](global.scss))
|
|
456
|
+
|
|
457
|
+
- 글로벌 스타일 진입점
|
|
458
|
+
- `@forward`로 모든 SCSS 컴포넌트 임포트
|
|
459
|
+
- 순서: 리셋 → 컬러 → 레이아웃 → 타이포그래피 → 아이콘 → 버튼 → 폼 → Molecule
|
|
460
|
+
|
|
461
|
+
#### 믹스인 파일 ([mixin.scss](mixin.scss))
|
|
462
|
+
|
|
463
|
+
- SCSS 모듈에서 사용
|
|
464
|
+
- 글로벌 스타일 없이 함수와 믹스인 제공
|
|
465
|
+
- 포함: 컬러 함수, 간격, 반경, 테두리, 타이포그래피 믹스인, 아이콘 유틸리티
|
|
466
|
+
|
|
467
|
+
#### Vite 전용 폰트 ([vite-fonts.scss](vite-fonts.scss))
|
|
468
|
+
|
|
469
|
+
- Vite 번들러의 폰트 경로 문제 해결
|
|
470
|
+
- 아이콘과 Pretendard 폰트 경로 재정의
|
|
471
|
+
- Vite 프로젝트에만 필요 (Next.js나 CRA 제외)
|
|
472
|
+
|
|
473
|
+
### 하이브리드 CSS + React 접근법
|
|
474
|
+
|
|
475
|
+
**철학:**
|
|
476
|
+
- 대부분의 UI는 순수 CSS 클래스 (버튼, 폼, 테이블 등)
|
|
477
|
+
- React 컴포넌트는 상태 보존/복잡한 요소에만 사용 (입력 검증, WYSIWYG 에디터)
|
|
478
|
+
- 모든 프레임워크나 바닐라 JS에서 사용 가능
|
|
479
|
+
|
|
480
|
+
**장점:**
|
|
481
|
+
- 프레임워크 독립적
|
|
482
|
+
- 빠른 성능 (JS 번들 최소화)
|
|
483
|
+
- 점진적 채택 가능
|
|
484
|
+
- CSS 우선, 필요시 React
|
|
485
|
+
|
|
486
|
+
---
|
|
487
|
+
|
|
488
|
+
## 6. 빌드 및 배포
|
|
489
|
+
|
|
490
|
+
### 빌드 설정
|
|
491
|
+
|
|
492
|
+
#### Next.js 구성
|
|
493
|
+
|
|
494
|
+
- Next.js 14.1.0 + Edge 런타임
|
|
495
|
+
- Cloudflare Pages 어댑터 (`@cloudflare/next-on-pages`)
|
|
496
|
+
- Cloudflare 호환성을 위한 `setupDevPlatform`
|
|
497
|
+
|
|
498
|
+
#### NPM 무시
|
|
499
|
+
|
|
500
|
+
**배포 제외:**
|
|
501
|
+
- node_modules, .git, tests, .env, .vscode, .vercel, .wrangler, .next
|
|
502
|
+
|
|
503
|
+
**배포 포함:**
|
|
504
|
+
- scss/, react/, 루트 SCSS 파일, TypeScript 파일
|
|
505
|
+
|
|
506
|
+
### 배포 전략
|
|
507
|
+
|
|
508
|
+
**진입점:**
|
|
509
|
+
1. `podo-ui/global.scss` - 글로벌 스타일
|
|
510
|
+
2. `podo-ui/mixin` - 모듈용 SCSS 함수/믹스인
|
|
511
|
+
3. `podo-ui/react` - React 컴포넌트 (표준)
|
|
512
|
+
4. `podo-ui/next` - React 컴포넌트 (Next.js)
|
|
513
|
+
5. `podo-ui/vite-fonts.scss` - Vite 폰트 경로 수정
|
|
514
|
+
|
|
515
|
+
**Cloudflare Pages 배포:**
|
|
516
|
+
|
|
517
|
+
```bash
|
|
518
|
+
npm run pages:build # Cloudflare Pages용 빌드
|
|
519
|
+
npm run deploy # Cloudflare에 배포
|
|
520
|
+
```
|
|
521
|
+
|
|
522
|
+
---
|
|
523
|
+
|
|
524
|
+
## 7. 개발 워크플로우
|
|
525
|
+
|
|
526
|
+
### 표준 워크플로우
|
|
527
|
+
|
|
528
|
+
**1. 설치:**
|
|
529
|
+
|
|
530
|
+
```bash
|
|
531
|
+
npm install podo-ui
|
|
532
|
+
```
|
|
533
|
+
|
|
534
|
+
**2. 글로벌 스타일 임포트:**
|
|
535
|
+
|
|
536
|
+
```typescript
|
|
537
|
+
// app.tsx or main.tsx
|
|
538
|
+
import 'podo-ui/global.scss'
|
|
539
|
+
```
|
|
540
|
+
|
|
541
|
+
**3. CSS 클래스 사용:**
|
|
542
|
+
|
|
543
|
+
```tsx
|
|
544
|
+
function Button() {
|
|
545
|
+
return <button className="primary">클릭</button>
|
|
546
|
+
}
|
|
547
|
+
```
|
|
548
|
+
|
|
549
|
+
**4. React 컴포넌트 사용:**
|
|
550
|
+
|
|
551
|
+
```tsx
|
|
552
|
+
import { Input, Field } from 'podo-ui/react'
|
|
553
|
+
|
|
554
|
+
function Form() {
|
|
555
|
+
return (
|
|
556
|
+
<Field label="이름">
|
|
557
|
+
<Input value={name} onChange={setName} />
|
|
558
|
+
</Field>
|
|
559
|
+
)
|
|
560
|
+
}
|
|
561
|
+
```
|
|
562
|
+
|
|
563
|
+
**5. SCSS 함수 사용:**
|
|
564
|
+
|
|
565
|
+
```scss
|
|
566
|
+
@use 'podo-ui/mixin' as *;
|
|
567
|
+
|
|
568
|
+
.custom-card {
|
|
569
|
+
padding: s(5);
|
|
570
|
+
background: color(primary);
|
|
571
|
+
border-radius: r(4);
|
|
572
|
+
}
|
|
573
|
+
```
|
|
574
|
+
|
|
575
|
+
### 아이콘 개발 워크플로우
|
|
576
|
+
|
|
577
|
+
**1. 아이콘 폰트 업데이트:**
|
|
578
|
+
|
|
579
|
+
```bash
|
|
580
|
+
# /scss/icon/font/icon.woff 파일 교체
|
|
581
|
+
```
|
|
582
|
+
|
|
583
|
+
**2. 아이콘 맵 재생성:**
|
|
584
|
+
|
|
585
|
+
```bash
|
|
586
|
+
npm run icon
|
|
587
|
+
```
|
|
588
|
+
|
|
589
|
+
**3. 사용:**
|
|
590
|
+
|
|
591
|
+
```html
|
|
592
|
+
<i class="icon-new-icon-name"></i>
|
|
593
|
+
```
|
|
594
|
+
|
|
595
|
+
### 데모 개발
|
|
596
|
+
|
|
597
|
+
**1. 개발 서버 시작:**
|
|
598
|
+
|
|
599
|
+
```bash
|
|
600
|
+
npm run dev
|
|
601
|
+
```
|
|
602
|
+
|
|
603
|
+
**2. 컴포넌트 테스트:**
|
|
604
|
+
|
|
605
|
+
[src/app/page.tsx](src/app/page.tsx) 편집
|
|
606
|
+
|
|
607
|
+
**3. 확인:**
|
|
608
|
+
|
|
609
|
+
http://localhost:3000
|
|
610
|
+
|
|
611
|
+
---
|
|
612
|
+
|
|
613
|
+
## 8. 핵심 기술 스택
|
|
614
|
+
|
|
615
|
+
### 코어 스택
|
|
616
|
+
|
|
617
|
+
- **React 18** - 컴포넌트 라이브러리
|
|
618
|
+
- **Next.js 14** - 문서/데모 앱 프레임워크
|
|
619
|
+
- **Sass** - 스타일링 시스템
|
|
620
|
+
- **TypeScript** - 타입 안정성
|
|
621
|
+
- **Zod** - 스키마 검증
|
|
622
|
+
|
|
623
|
+
### 전문 라이브러리
|
|
624
|
+
|
|
625
|
+
- **SunEditor** - WYSIWYG 에디터
|
|
626
|
+
- **opentype.js** - 아이콘 생성용 폰트 파싱
|
|
627
|
+
- **UUID** - 고유 ID 생성
|
|
628
|
+
|
|
629
|
+
### 빌드 도구
|
|
630
|
+
|
|
631
|
+
- **Next.js** - 주 번들러
|
|
632
|
+
- **Cloudflare Pages** - 배포 플랫폼
|
|
633
|
+
- **ESLint** - 코드 린팅
|
|
634
|
+
- **Prettier** - 코드 포매팅
|
|
635
|
+
|
|
636
|
+
---
|
|
637
|
+
|
|
638
|
+
## 특별한 기능 및 패턴
|
|
639
|
+
|
|
640
|
+
### 1. 하이브리드 CSS + React 접근법
|
|
641
|
+
|
|
642
|
+
**비율:**
|
|
643
|
+
- 97% CSS 기반 컴포넌트 (최대 유연성)
|
|
644
|
+
- 3% React 컴포넌트 (복잡한 상태 인터랙션)
|
|
645
|
+
|
|
646
|
+
**장점:**
|
|
647
|
+
- 모든 프레임워크에서 사용 가능
|
|
648
|
+
- 최소한의 JavaScript 번들 크기
|
|
649
|
+
- 점진적 채택 가능
|
|
650
|
+
|
|
651
|
+
### 2. 런타임 테마 시스템
|
|
652
|
+
|
|
653
|
+
**전환 방법:**
|
|
654
|
+
|
|
655
|
+
```html
|
|
656
|
+
<!-- 라이트/다크 모드 -->
|
|
657
|
+
<html data-color-mode="light">
|
|
658
|
+
<html data-color-mode="dark">
|
|
659
|
+
<html data-color-mode=""> <!-- 자동 (시스템 설정) -->
|
|
660
|
+
|
|
661
|
+
<!-- 컬러 톤 -->
|
|
662
|
+
<html data-color-tone=""> <!-- 기본 -->
|
|
663
|
+
<html data-color-tone="warm"> <!-- 웜 톤 -->
|
|
664
|
+
```
|
|
665
|
+
|
|
666
|
+
**특징:**
|
|
667
|
+
- CSS 변수 기반 (리빌드 불필요)
|
|
668
|
+
- 즉각적인 전환
|
|
669
|
+
- JavaScript로 동적 제어 가능
|
|
670
|
+
|
|
671
|
+
### 3. 반응형 그리드
|
|
672
|
+
|
|
673
|
+
**자동 브레이크포인트 적응:**
|
|
674
|
+
|
|
675
|
+
```scss
|
|
676
|
+
// PC: 12컬럼
|
|
677
|
+
// 태블릿: 6컬럼
|
|
678
|
+
// 모바일: 4컬럼
|
|
679
|
+
// Gap과 padding이 브레이크포인트마다 조정
|
|
680
|
+
```
|
|
681
|
+
|
|
682
|
+
### 4. 아이콘 폰트 자동화
|
|
683
|
+
|
|
684
|
+
**장점:**
|
|
685
|
+
- CLI 도구가 수동 아이콘 매핑 제거
|
|
686
|
+
- 단일 소스 (WOFF 파일)
|
|
687
|
+
- SCSS 맵을 통한 타입 안전 아이콘 이름
|
|
688
|
+
|
|
689
|
+
**워크플로우:**
|
|
690
|
+
|
|
691
|
+
```
|
|
692
|
+
icon.woff → npm run icon → icon-name.scss → CSS 클래스
|
|
693
|
+
```
|
|
694
|
+
|
|
695
|
+
### 5. 검증 통합
|
|
696
|
+
|
|
697
|
+
**Zod 스키마 검증:**
|
|
698
|
+
- 모든 입력 컴포넌트에 통합
|
|
699
|
+
- 시각적 피드백 (success/danger 상태)
|
|
700
|
+
- 커스터마이징 가능한 오류 메시지
|
|
701
|
+
|
|
702
|
+
**예:**
|
|
703
|
+
|
|
704
|
+
```tsx
|
|
705
|
+
import { z } from 'zod'
|
|
706
|
+
|
|
707
|
+
const schema = z.string().min(2, '2자 이상 입력하세요')
|
|
708
|
+
|
|
709
|
+
<Input validator={schema} value={value} />
|
|
710
|
+
```
|
|
711
|
+
|
|
712
|
+
---
|
|
713
|
+
|
|
714
|
+
## 요약
|
|
715
|
+
|
|
716
|
+
**Podo-UI**는 다음을 제공하는 잘 설계된 SCSS 우선 디자인 시스템입니다:
|
|
717
|
+
|
|
718
|
+
- **97% CSS 기반 컴포넌트** - 최대 유연성
|
|
719
|
+
- **3% React 컴포넌트** - 복잡한 상태 인터랙션용
|
|
720
|
+
- **포괄적인 디자인 토큰** - 간격, 컬러, 타이포그래피, 반경
|
|
721
|
+
- **내장 테마** - 라이트/다크 모드
|
|
722
|
+
- **반응형 그리드 시스템** - 모바일 우선 접근
|
|
723
|
+
- **아이콘 시스템** - 폰트로부터 자동 생성
|
|
724
|
+
- **타입 안전 검증** - Zod 통합
|
|
725
|
+
- **프로덕션 준비** - Cloudflare Pages 배포
|
|
726
|
+
|
|
727
|
+
이 아키텍처는 명확한 관심사 분리, 아토믹 디자인 원칙, 그리고 SCSS 함수, TypeScript 지원, 포괄적인 문서를 통한 우수한 개발자 경험과 함께 현대적인 모범 사례를 따릅니다.
|