|
| 1 | +# 개발 가이드라인 |
| 2 | + |
| 3 | +이 블로그 프로젝트의 핵심 패턴과 구현 원칙을 정의합니다. |
| 4 | + |
| 5 | +## 아키텍처 패턴 |
| 6 | + |
| 7 | +### 도메인 중심 설계 |
| 8 | +- **도메인 로직**: `src/domain/blog/` 에 통합 |
| 9 | +- **UI 컴포넌트**: `src/app/` 하위에 구현 |
| 10 | +- **타입 정의**: `src/domain/blog/types.ts` 중앙 집중 |
| 11 | + |
| 12 | +```typescript |
| 13 | +// 도메인 API 사용 예시 |
| 14 | +import { getCategoryById, getPostsByCategory, getRelatedPostsByTags } from '@/domain/blog' |
| 15 | + |
| 16 | +const category = getCategoryById('dev') |
| 17 | +const posts = getPostsByCategory('dev') |
| 18 | +const related = getRelatedPostsByTags(currentSlug, 3) |
| 19 | +``` |
| 20 | + |
| 21 | +### 모듈 레벨 캐싱 |
| 22 | +빌드 타임에 모든 데이터를 사전 로드하여 SSG 최적화 |
| 23 | + |
| 24 | +```typescript |
| 25 | +// src/domain/blog/index.ts |
| 26 | +export const allPosts = await getAllPosts() |
| 27 | +export const allCategories = await getAllCategories() |
| 28 | +export const allTags = extractTagsFromPosts(allPosts) |
| 29 | +export const tagGraph = createTagGraph(allPosts, allTags) |
| 30 | +export const tagClusters = createTagClusters(tagGraph) |
| 31 | +``` |
| 32 | + |
| 33 | +### 태그 그래프 시스템 |
| 34 | +graphology 라이브러리로 태그 간 관계 분석 |
| 35 | + |
| 36 | +```typescript |
| 37 | +// 태그 관계 분석 |
| 38 | +const relationships = getTagRelationships() |
| 39 | +const clusters = getTagClusters() |
| 40 | +const relatedPosts = getRelatedPostsByTags(currentSlug, 3) |
| 41 | +``` |
| 42 | + |
| 43 | +## 콘텐츠 구조 |
| 44 | + |
| 45 | +### MDX 파일 구조 |
| 46 | +``` |
| 47 | +src/contents/ |
| 48 | +├── dev/ # 개발 카테고리 |
| 49 | +│ ├── category.json |
| 50 | +│ └── *.mdx |
| 51 | +└── life/ # 일상 카테고리 |
| 52 | + ├── category.json |
| 53 | + └── *.mdx |
| 54 | +``` |
| 55 | + |
| 56 | +### 포스트 frontmatter |
| 57 | +```yaml |
| 58 | +--- |
| 59 | +title: '포스트 제목' |
| 60 | +date: 2025-01-17 |
| 61 | +tags: ['tag1', 'tag2'] |
| 62 | +description: '포스트 설명' |
| 63 | +category: 'dev' # 또는 'life' |
| 64 | +--- |
| 65 | +``` |
| 66 | + |
| 67 | +### 카테고리 메타데이터 |
| 68 | +```json |
| 69 | +{ |
| 70 | + "name": "개발", |
| 71 | + "description": "개발 관련 포스트", |
| 72 | + "color": "blue", |
| 73 | + "icon": "💻" |
| 74 | +} |
| 75 | +``` |
| 76 | + |
| 77 | +## 컴포넌트 패턴 |
| 78 | + |
| 79 | +### 타입 정의 |
| 80 | +```typescript |
| 81 | +interface PostHeaderProps { |
| 82 | + title: string |
| 83 | + date: string |
| 84 | + tags: string[] |
| 85 | + category?: CategoryId |
| 86 | + readingTime?: number |
| 87 | + author?: string |
| 88 | + className?: string |
| 89 | +} |
| 90 | +``` |
| 91 | + |
| 92 | +### 컴포넌트 구현 |
| 93 | +```typescript |
| 94 | +// 서버 컴포넌트 기본, 상호작용 필요시만 클라이언트 |
| 95 | +export function PostHeader({ title, date, tags, category }: PostHeaderProps) { |
| 96 | + return ( |
| 97 | + <header className={cn('mb-8 pb-8', className)}> |
| 98 | + <div className="flex items-center gap-3 mb-4"> |
| 99 | + {category && <CategoryBadge categoryId={category} />} |
| 100 | + <h1 className="text-3xl font-bold">{title}</h1> |
| 101 | + </div> |
| 102 | + <TagList tags={tags} /> |
| 103 | + </header> |
| 104 | + ) |
| 105 | +} |
| 106 | +``` |
| 107 | + |
| 108 | +## 품질 기준 |
| 109 | + |
| 110 | +### TypeScript 엄격 모드 |
| 111 | +- `any` 타입 사용 금지 |
| 112 | +- 모든 Props 인터페이스 명시적 정의 |
| 113 | +- 도메인 타입 재사용 (`CategoryId`, `Post`, `Tag`) |
| 114 | + |
| 115 | +### 테스트 패턴 |
| 116 | +```typescript |
| 117 | +// 비즈니스 로직 테스트 |
| 118 | +describe('태그 그래프 시스템', () => { |
| 119 | + it('관련 포스트를 태그 유사도로 찾는다', () => { |
| 120 | + const related = getRelatedPostsByTags('test-slug', 3) |
| 121 | + expect(related).toHaveLength(3) |
| 122 | + }) |
| 123 | +}) |
| 124 | +``` |
| 125 | + |
| 126 | +### 성능 최적화 |
| 127 | +- 모든 데이터 빌드 타임 사전 계산 |
| 128 | +- `generateStaticParams()` 사용한 정적 경로 생성 |
| 129 | +- 컴포넌트 간 props 최소화 |
| 130 | + |
| 131 | +## 디렉토리 구조 |
| 132 | + |
| 133 | +``` |
| 134 | +src/ |
| 135 | +├── app/ # Next.js App Router |
| 136 | +│ ├── [category]/ # 카테고리 페이지 |
| 137 | +│ │ ├── [slug]/ # 포스트 상세 |
| 138 | +│ │ └── _components/ # 페이지별 컴포넌트 |
| 139 | +│ └── _components/ # 전역 컴포넌트 |
| 140 | +├── domain/blog/ # 도메인 로직 |
| 141 | +│ ├── index.ts # 공개 API + 캐싱 |
| 142 | +│ ├── types.ts # 타입 정의 |
| 143 | +│ └── logic/ # 비즈니스 로직 |
| 144 | +│ ├── posts.ts |
| 145 | +│ ├── categories.ts |
| 146 | +│ └── tags.ts |
| 147 | +└── contents/ # MDX 콘텐츠 |
| 148 | + ├── dev/ |
| 149 | + └── life/ |
| 150 | +``` |
| 151 | + |
| 152 | +## 구현 원칙 |
| 153 | + |
| 154 | +1. **도메인 API 사용**: 직접 파일 시스템 접근 금지 |
| 155 | +2. **타입 안전성**: 모든 데이터 흐름 타입 보장 |
| 156 | +3. **모듈 레벨 캐싱**: 빌드 타임 데이터 사전 로드 |
| 157 | +4. **컴포넌트 단순화**: 단일 책임 원칙 |
0 commit comments