Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -33,4 +33,4 @@ jobs:
run: pnpm tsc --noEmit

- name: Run tests
run: pnpm test:run
run: pnpm test
91 changes: 91 additions & 0 deletions .kiro/steering/project-structure.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
# 프로젝트 구조 및 개발 가이드라인

## 프로젝트 개요

Next.js 15 기반의 정적 블로그 애플리케이션으로, MDX를 사용한 콘텐츠 관리와 도메인 주도 설계를 따릅니다.

## 기술 스택

- **프레임워크**: Next.js 15 (App Router)
- **콘텐츠**: MDX with rehype-pretty-code
- **스타일링**: Tailwind CSS + shadcn/ui
- **언어**: TypeScript
- **코드 품질**: Biome (formatting/linting)
- **테스팅**: Vitest
- **패키지 매니저**: pnpm

## 디렉토리 구조

```
src/
├── app/ # Next.js App Router 루트
│ ├── _components/ # 전역 컴포넌트
│ ├── _fonts/ # 폰트 설정
│ ├── _lib/ # 유틸리티 함수
│ ├── posts/[slug]/ # 동적 포스트 페이지
│ ├── about/ # About 페이지
│ ├── layout.tsx # 루트 레이아웃
│ └── globals.css # 전역 스타일
├── entities/ # 도메인 엔티티
│ ├── posts/ # 포스트 도메인 로직
│ └── tags/ # 태그 도메인 로직
└── contents/ # MDX 블로그 포스트
```

## 네이밍 컨벤션

- **라우트가 아닌 폴더**: 언더스코어 접두사 사용 (`_components`, `_hooks`)
- **컴포넌트 스코프**:
- 전역: `src/app/_components/`
- 페이지별: `src/app/[route]/_components/`
- **파일명**: kebab-case 또는 PascalCase (컴포넌트)

## 도메인 아키텍처

### 엔티티 구조
- `src/entities/posts/`: 포스트 관련 비즈니스 로직
- `index.ts`: 공개 API
- `types.ts`: 타입 정의
- `logic.ts`: 비즈니스 로직
- `*.test.ts`: 테스트 파일

### 데이터 흐름
1. MDX 파일 (`src/contents/`) → gray-matter 파싱
2. 엔티티 레이어에서 비즈니스 로직 처리
3. App Router 페이지에서 렌더링

## 스타일링 가이드라인

### Tailwind CSS
- **컬러 팔레트**: `stone` 계열 사용 (`text-stone-900`, `border-stone-200`)
- **반응형**: 모바일 퍼스트 접근
- **다크모드**: CSS 변수 기반 테마 지원

### shadcn/ui 컴포넌트
- **설치**: `npx shadcn@latest add <component>`
- **위치**: `src/app/_components/ui/`
- **스타일**: "new-york" 스타일, stone 베이스 컬러
- **아이콘**: Lucide React 사용

## 콘텐츠 관리

### 콘텐츠 위치
`src/contents/*.mdx`

### MDX 구조
```yaml
---
title: '포스트 제목'
slug: 'post-slug'
date: 2025-01-01
tags: ['tag1', 'tag2']
---

# 포스트 내용
```

## 배포 설정

- **basePath**: `/blog` (GitHub Pages 등을 위한 설정)
- **출력**: 정적 파일 (`out/` 디렉토리)
- **환경**: Node.js 환경에서 빌드, 정적 호스팅 가능
170 changes: 170 additions & 0 deletions .kiro/steering/task-execution-process.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,170 @@
# 작업 실행 프로세스

## 작업 진행 원칙

- 작업의 단위를 가능하면 작게 설정
- 지시가 모호하다고 느껴지면 질문 후 진행

## 구현 원칙

### 점진적 개발
- 한 번에 하나의 태스크만 집중하여 구현
- 태스크 완료 후 사용자 검토 대기, 자동으로 다음 태스크 진행하지 않음
- 각 단계에서 이전 단계의 결과물을 기반으로 구축

### 코드 품질
- TypeScript 엄격 모드 준수, any 타입 사용 금지
- 컴포넌트는 단일 책임 원칙 적용
- Props 인터페이스 명시적 정의
- 적절한 기본값 설정

### 테스트 우선
- 비즈니스 로직 구현 시 단위 테스트 함께 작성
- AAA 패턴 (Arrange, Act, Assert) 준수
- 의미있는 테스트명 사용

## 구현 패턴

### 컴포넌트 설계
- **단일 책임 원칙**: 하나의 컴포넌트는 하나의 역할만
- **Props 인터페이스**: 모든 props에 대한 명시적 타입 정의
- **기본값 설정**: 선택적 props에 대한 적절한 기본값
- **커스텀훅**: 로직은 커스텀훅으로 분리함
- **컴포넌트 분리**: 50줄 이상의 컴포넌트는 분리 고려

### 컴포넌트 구현
```typescript
// 1. 인터페이스 정의
interface ComponentProps {
required: string
optional?: boolean
children?: React.ReactNode
}

// 2. 컴포넌트 구현
export function Component({
required,
optional = false,
children
}: ComponentProps) {
// 구현
}
```

### 비즈니스 로직 구현
```typescript
// 1. 타입 정의
export type DataType = {
id: string
value: string
}

// 2. 로직 함수 구현
export function processData(data: DataType[]): DataType[] {
// 구현
}

// 3. 테스트 작성
describe('processData', () => {
it('should process data correctly', () => {
// 테스트 구현
})
})
```

### 기능 구조 우선
- 스타일링보다 기능적 구조와 로직에 집중
- 컴포넌트의 역할과 책임을 명확히 정의
- 데이터 흐름과 상태 관리 구조 우선 설계
- UI는 기본적인 레이아웃만 구현하고 세부 스타일링은 후순위

### 아키텍처 중심 접근
- 도메인 로직과 UI 로직의 명확한 분리
- 컴포넌트 간의 의존성과 데이터 전달 구조 설계
- 재사용 가능한 로직의 추상화
- 확장 가능한 구조로 설계

### 최소 스타일링
- 구조화에 필요한 최소한의 스타일링 가능
- 필요시 shadcn/ui의 컴포넌트를 이용

```typescript
// 구조에 집중한 컴포넌트 예시
<div className="container"> {/* 기본 레이아웃만 */}
<header className="fixed inset-x-0 top-0 h-14">
{/* 기능적 구조 우선 */}
</header>
<main>
<div className="flex items-center gap-x-2">
{/* ... */}
</div>
</main>
</div>
```

### UI 구현
- **플레이스홀더 사용**: 실제 콘텐츠 대신 `[Page Title]`, `[Description]` 등 사용
- **사용자 승인**: UI 구조 구현 전 명시적 요구사항 확인
- **점진적 구현**: 한 번에 모든 기능 구현하지 않기

## 에러 처리

### 클라이언트 사이드
- 사용자 친화적 에러 메시지
- 적절한 폴백 UI 제공
- 개발 환경에서 상세 로깅

### 서버 사이드
- notFound() 함수 활용
- 적절한 에러 바운더리 설정
- Graceful degradation 적용

## 접근성 고려사항

### 필수 요소
- 시맨틱 HTML 태그 사용
- 적절한 ARIA 레이블
- 키보드 네비게이션 지원
- 충분한 색상 대비

### 구현 예시
```typescript
<button
aria-label="설명적인 레이블"
aria-expanded={isExpanded}
className="focus:outline-none focus:ring-2 focus:ring-stone-500"
>
```

## 문서화

### 코드 주석
- 복잡한 로직에 대한 설명 주석
- JSDoc 형태의 함수 문서화
- 타입 정의에 대한 설명

## 형상관리

### 브랜치 전략
- `main`: 프로덕션 준비 코드
- `feat/`: 새 기능 (`feat/search-functionality`)
- `fix/`: 버그 수정 (`fix/mobile-nav-issue`)
- `docs/`: 문서 업데이트

### 커밋 컨벤션
```
<type>: <description>

[optional body]
```

**타입:**
- `feat:` - 새 기능
- `fix:` - 버그 수정
- `docs:` - 문서 업데이트
- `config:` - 설정 변경
- `refactor:` - 리팩토링
- `chore:` - 유지보수

#### 커밋 전략
논리적 단위로 나누어서 커밋
Loading