Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
54 commits
Select commit Hold shift + click to select a range
109be71
docs: 코딩 스타일 가이드 추가
kimzeze Nov 17, 2025
3d9c450
docs: 커밋 컨벤션 가이드 추가
kimzeze Nov 17, 2025
10efeba
docs: 개인 회고 작성 가이드 추가
kimzeze Nov 17, 2025
7188e0c
chore: 개인 회고 시스템 설정
kimzeze Nov 17, 2025
2c39856
docs: 기본 및 심화 과제 요구사항 추가
kimzeze Nov 17, 2025
2bd00b1
docs: 단계별 실행 체크리스트 추가
kimzeze Nov 17, 2025
d309e31
feat(utils): isEmptyValue 구현
kimzeze Nov 17, 2025
c3138ce
feat(utils): shallowEquals, deepEquals구현
kimzeze Nov 17, 2025
753da00
docs: 체크리스트 업데이트
kimzeze Nov 17, 2025
0abae92
feat(utils): createElement, createTextElement, normalizeNode 구현
kimzeze Nov 17, 2025
a7810ae
docs: 단계별 체크리스트 업데이트 - deepEquals 및 createElement 구현 완료 체크 추가
kimzeze Nov 18, 2025
1ebcd43
feat(context): 전역 컨텍스트 구현
kimzeze Nov 18, 2025
aae015c
feat(core): 루트 setup 구현
kimzeze Nov 18, 2025
236e462
feat(dom): setDomProps 구현
kimzeze Nov 18, 2025
ddc59d5
feat(dom): updateDomProps, getDomNodes, getFirstDom 구현
kimzeze Nov 18, 2025
c7f7f22
fix(react): render 메서드에 null 타입 추가
kimzeze Nov 18, 2025
7079237
docs: 단계별 체크리스트 업데이트
kimzeze Nov 18, 2025
7dc57d2
feat(dom): insertInstance, removeInstance 구현
kimzeze Nov 19, 2025
e827bbb
feat(utils): enqueue, withEnqueue 구현
kimzeze Nov 19, 2025
01aab4f
fix(types): EffectsContext queue 타입 수정
kimzeze Nov 19, 2025
9e7d3a4
feat(hooks): cleanupUnusedHooks 구현
kimzeze Nov 19, 2025
29c1a14
feat(core): render, flushEffects, enqueueRender 구현
kimzeze Nov 19, 2025
141add6
feat(reconciler): mount 함수 구현
kimzeze Nov 19, 2025
fafe8ba
feat(reconciler): update, unmount, mountComponent, updateComponent 구현
kimzeze Nov 20, 2025
306cf3c
docs: 체크리스트 업데이트 - Phase 3, 4 일부 완료 체크
kimzeze Nov 20, 2025
e207aa7
fix(core): createElement와 setup 버그 수정
kimzeze Nov 20, 2025
357d790
feat(hooks): useState와 useEffect 구현
kimzeze Nov 20, 2025
380cf7a
refactor(hooks): HookTypes 사용하여 타입 명시
kimzeze Nov 20, 2025
3ca3795
fix(core): container 변경 시 초기화 버그 수정
kimzeze Nov 20, 2025
29995cd
fix(core): setup rootNode null 검증 추가
kimzeze Nov 20, 2025
a53a731
fix(core): useEffect를 비동기로 실행하도록 수정
kimzeze Nov 20, 2025
564ede4
fix(dom): boolean 속성 처리 개선
kimzeze Nov 20, 2025
da73748
fix(reconciler): unmount 시 cleanup 실행 추가
kimzeze Nov 20, 2025
0386ccd
feat(reconciler): key 기반 reconciliation 및 타입 기반 매칭 구현
kimzeze Nov 20, 2025
ad29f24
feat(reconciler): key 기반 reconciliation 및 path collision 버그 수정
kimzeze Nov 21, 2025
cc40bb8
feat(hooks): useRef 구현
kimzeze Nov 21, 2025
1413be5
feat(hooks): useMemo 구현
kimzeze Nov 21, 2025
1e9dddf
feat(hooks): useCallback 구현
kimzeze Nov 21, 2025
f5d4a32
feat(hooks): useDeepMemo 구현
kimzeze Nov 21, 2025
2462c69
feat(hooks): useAutoCallback 구현
kimzeze Nov 21, 2025
e98475e
feat(hocs): memo HOC 구현
kimzeze Nov 21, 2025
d1327c2
fix(hocs): memo HOC를 클로저 기반으로 수정
kimzeze Nov 21, 2025
818d525
fix(react): jsx-runtime export 추가
kimzeze Nov 21, 2025
241a9c4
fix(app): 카테고리 로딩 상태 표시 개선
kimzeze Nov 21, 2025
4385e82
fix(app): 카테고리 초기 상태를 null로 변경
kimzeze Nov 21, 2025
3c3eda6
fix(app): MSW API 지연 시간을 1초로 증가
kimzeze Nov 21, 2025
77ce636
refactor(react): simplify jsx-runtime exports
kimzeze Nov 21, 2025
c53c806
fix(hooks): useRef의 useState import 경로 수정
kimzeze Nov 21, 2025
26f0e5e
fix(hooks): useMemo를 useState 기반으로 변경
kimzeze Nov 21, 2025
bcc6be9
fix(hooks): useMemo를 다시 useRef 기반으로 변경
kimzeze Nov 21, 2025
7efc23a
fix(react): resolve useState hook initialization and import issues
kimzeze Nov 21, 2025
e4530c4
fix(reconciler): 컴포넌트 자식에 고유한 path 생성
kimzeze Nov 21, 2025
31b0cf2
chore: GitHub Pages 배포 workflow 추가
kimzeze Nov 21, 2025
4b874ab
chore: trigger CI rerun
kimzeze Nov 21, 2025
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
54 changes: 54 additions & 0 deletions .github/workflows/deploy.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
name: Deploy to GitHub Pages

on:
push:
branches:
- main
- release-*

permissions:
contents: read
pages: write
id-token: write

concurrency:
group: "pages"
cancel-in-progress: true

jobs:
deploy:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4

- name: Install pnpm
uses: pnpm/action-setup@v4
with:
version: 10.22.0

- name: Setup Node
uses: actions/setup-node@v4
with:
node-version-file: ".nvmrc"
cache: "pnpm"

- name: Install dependencies
run: pnpm install --frozen-lockfile

- name: Build
run: pnpm run build

- name: Create SPA fallback
run: cp packages/app/dist/index.html packages/app/dist/404.html

- name: Setup Pages
uses: actions/configure-pages@v4

- name: Upload artifact
uses: actions/upload-pages-artifact@v3
with:
path: "packages/app/dist"

- name: Deploy to GitHub Pages
id: deployment
uses: actions/deploy-pages@v4
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -25,3 +25,6 @@ dist-ssr
/test-results/
/playwright-report/
/coverage/

# Review files (개인 회고, PR 작성용)
review/
173 changes: 173 additions & 0 deletions CODE_STYLE.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,173 @@
# Mini-React 코딩 스타일 가이드

> React의 핵심을 구현하며 배우는 깔끔한 TypeScript 코드

## 1. 네이밍 규칙

### 타입

- **PascalCase**: `VNode`, `Instance`, `Context`, `HookState`
- **Interface**: `ComponentType<P>`

### 변수

- **camelCase**: `currentPath`, `hookList`, `newInstance`
- **Boolean**: `is/has/should/can` 접두사
- `isComponent`, `hasChanged`, `shouldUpdate`, `canRender`

### 함수

- **camelCase + 동사**: `mount`, `unmount`, `reconcile`, `setDomProps`
- **Hook**: `use` 접두사 - `useState`, `useEffect`, `useMemo`
- **Private**: 언더스코어 접두사 - `_cleanup`, `_updateCursor`

### 상수

- **UPPER_SNAKE_CASE**: `MAX_DEPTH`, `DEFAULT_STATE`
- **Symbol**: camelCase - `Fragment`

## 2. 함수 작성

### 길이 제한

- **함수**: 30줄 이내
- **파일**: 200줄 이내
- 초과 시 분리 또는 주석으로 이유 명시

### Early Return 패턴

```typescript
function reconcile(container, newNode, oldInstance) {
if (newNode === null) return handleUnmount(oldInstance);
if (oldInstance === null) return handleMount(container, newNode);
if (isDifferentType(newNode, oldInstance)) return handleReplace(...);
return handleUpdate(...);
}
```

### JSDoc

```typescript
/**
* VNode를 실제 DOM으로 마운트합니다
*
* @param container - DOM을 추가할 부모 요소
* @param vnode - 마운트할 가상 DOM 노드
* @returns 생성된 Instance 객체
*/
```

## 3. 타입 안전성

### any 금지

- ❌ `any` 사용 금지
- ✅ `unknown` 사용 후 타입 가드

### 제네릭 활용

```typescript
function useState<T>(initialValue: T | (() => T)): [T, Dispatcher<T>];
function useMemo<T>(factory: () => T, deps: unknown[]): T;
```

### 타입 가드

```typescript
const isComponent = (type: VNode["type"]): type is Function => {
return typeof type === "function";
};
```

## 4. 재조정 패턴

### 4가지 케이스 명확히 구분

1. **Unmount**: `newNode === null`
2. **Mount**: `oldInstance === null`
3. **Replace**: `type` 또는 `key` 다름
4. **Update**: `type`과 `key` 동일

### 불변성 유지

- 항상 새 배열/객체 반환
- 원본 수정 금지

```typescript
// ✅ Good
const newInstances = oldInstances.map(update);
return [...newInstances, newInstance];

// ❌ Bad
oldInstances.push(newInstance);
return oldInstances;
```

## 5. Hook 구현

### Hook 규칙 강제

```typescript
get currentPath(): string {
if (this.componentStack.length === 0) {
throw new Error("Hook은 컴포넌트 내부에서만 호출 가능합니다");
}
return this.componentStack[this.componentStack.length - 1];
}
```

### 상태 캡슐화

- Context를 통한 간접 접근
- Private 상태, Public API

## 6. Import 순서

```typescript
// 1. 타입
import type { VNode, Instance } from "./types";

// 2. 내부 모듈 (알파벳 순)
import { context } from "./context";
import { reconcile } from "./reconciler";

// 3. DOM/Utils
import { setDomProps } from "./dom";
import { shallowEquals } from "../utils/equals";

// 4. 상수
import { Fragment } from "./constants";
```

## 7. 체크리스트

### 타입

- [ ] `any` 대신 `unknown` 사용
- [ ] 제네릭 활용
- [ ] 반환 타입 명시

### 함수

- [ ] 30줄 이내
- [ ] Early return 사용
- [ ] JSDoc 작성 (export 함수)
- [ ] 단일 책임

### 재조정

- [ ] 4가지 케이스 구분
- [ ] 불변성 유지
- [ ] 타입 안전

### Hook

- [ ] 규칙 강제
- [ ] 상태 캡슐화
- [ ] 커서 관리

### 파일

- [ ] 200줄 이내
- [ ] Import 순서
- [ ] 단일 책임
Loading