기여하기
Elftia에 기여하고자 하는 관심에 감사드립니다. 이 문서는 개발에 참여하는 전체 워크플로를 설명합니다.
개발 환경 설정
자세한 단계는 로컬 개발 가이드를 참조하세요. 빠른 요약:
{/* Prerequisites */}
{/* Node.js v24 (see .nvmrc) + native build tools */}
git clone <repo-url> elftia
cd elftia
npm install
cp .env.example .env
npm run dev
브랜치 전략
| 브랜치 | 목적 | 보호 규칙 |
|---|---|---|
main | 안정적인 릴리스, 항상 배포 가능 상태 | PR + 리뷰 필요 |
dev/* | 기능 개발 브랜치 | - |
fix/* | 버그 수정 브랜치 | - |
브랜치 이름 규칙
{/* New feature */}
git checkout -b dev/feature-name
{/* Bug fix */}
git checkout -b fix/bug-description
{/* Examples */}
git checkout -b dev/notes-feature
git checkout -b fix/chat-scroll-issue
코드 표준
전체 사양은 코드 표준을 참조하세요. 주요 사항:
ESLint
- error 수준 규칙은 커밋을 차단합니다 (import 순서,
no-var,eqeqeq,prefer-const, Hook 규칙) - warn 수준 규칙은 커밋을 허용하지만 수정을 권장합니다
- Husky는 커밋 전에
eslint --fix를 자동으로 실행합니다
파일 크기
| 파일 유형 | 권장 한도 | 하드 한도 |
|---|---|---|
| React 컴포넌트 | 400줄 | 800줄 |
| 커스텀 Hook | 300줄 | 600줄 |
| 유틸리티 함수 | 150줄 | 300줄 |
| 타입 정의 | 100줄 | 200줄 |
| 서비스 | 300줄 | 600줄 |
네이밍
- 컴포넌트: PascalCase (
UserMessage.tsx) - Hook: usePascalCase (
useChatActions.ts) - 디렉터리: kebab-case (
chat-messages/) - 시맨틱 토큰 사용 (하드코딩된 색상 금지)
커밋 컨벤션
Conventional Commits 형식을 사용하세요:
<type>: <description>
[optional body]
[optional footer]
타입 참조
| 타입 | 설명 | 예시 |
|---|---|---|
feat | 새 기능 | feat: add notes export feature |
fix | 버그 수정 | fix: resolve chat scroll position reset |
refactor | 리팩터링 | refactor: split ChatInterface into smaller components |
docs | 문서 | docs: update IPC channels reference |
style | 코드 포맷팅 (로직 변경 없음) | style: fix import ordering |
test | 테스트 | test: add unit tests for useFavorites |
chore | 빌드/툴링 변경 | chore: update Vite to v7.1 |
예시
git commit -m "feat: add favorites feature with session-scoped bookmarks
- Add FavoritesService with SQLite persistence
- Add FavoritesRouter with Zod validation
- Add useFavorites hook and FavoritesList component
- Add i18n support for en/zh/ja"
Pull Request 요구사항
핵심 원칙
- PR 하나에 하나의 작업 — 기능 개발과 버그 수정을 혼합하지 마세요
- 테스트 — 새 기능에는 테스트를 포함하세요
- 문서 — 필요한 경우 문서를 업데이트하세요
- CI 통과 — 모든 검사가 통과되어야 합니다
PR 제목
Conventional Commits 형식으로 변경 사항을 간결하게 설명하세요:
feat: add favorites feature
fix: resolve chat message duplication
refactor: extract message rendering into separate components
PR 설명 템플릿
## Changes
- Brief description of change 1
- Brief description of change 2
## How to Test
- [ ] Manual test step 1
- [ ] Manual test step 2
- [ ] Unit tests pass
## Screenshots (if UI changes)
새 기능 개발 체크리스트
전체 엔드투엔드 흐름은 기능 추가하기를 참조하세요.
백엔드
| 단계 | 파일 위치 | 설명 |
|---|---|---|
| 1. 공유 타입 | packages/desktop/app/shared/contracts/ | 프론트엔드와 백엔드 간에 공유되는 타입 정의 |
| 2. 서비스 | packages/desktop/app/main/services/ | 비즈니스 로직 캡슐화 |
| 3. 라우터 | packages/desktop/app/main/services/routers/ | IPC 라우팅 + Zod 유효성 검사 |
| 4. 등록 | routers/index.ts → registerAllRouters() | 인스턴스 생성 및 등록 |
| 5. Preload | packages/desktop/app/preload/index.ts | 프론트엔드에 노출 |
프론트엔드
| 단계 | 파일 위치 | 설명 |
|---|---|---|
| 1. Hook | packages/renderer/src/features/<feature>/hooks/ (크로스 기능 Hook은 shared/hooks/에 위치) | 데이터 페칭 및 상태 관리 |
| 2. 컴포넌트 | packages/renderer/src/features/<feature>/components/ (공유 UI는 components/ui/에 위치) | UI 렌더링 |
| 3. 라우트 | app/lazy/ (pages.tsx 등) + app/App.tsx | 새 페이지는 지연 로드 등록 필요 (레거시 import 경로 from '../lazy'는 lazy/index.ts 배럴을 통해 여전히 호환) |
| 4. i18n | packages/renderer/src/locales/{en,zh,ja}/ | 3개 언어 번역 |
문서
| 조건 | 업데이트 필요 대상 |
|---|---|
| 새 모듈 추가 | .claude/skills/architecture-index/SKILL.md |
| 사용자 가시 기능 | docs/elfi-kb/ 지식 베이스 |
| 새 라우트 추가 | docs/elfi-kb/INDEX.md 매핑 테이블 |
코드 리뷰 중점 사항
프론트엔드/백엔드 분리
- 프론트엔드는 사용자 입력과 구성 파라미터만 전달하는가?
- 백엔드가 모든 외부 호출을 처리하는가?
- 반환된 데이터가 최종 형태인가?
- IPC를 통해 base64 같은 대용량 데이터를 전송하는 것을 피하고 있는가?
보안
- Router 파라미터가 Zod로 유효성 검사되고 있는가?
- API 키가 메인 프로세스에서만 사용되는가?
- XSS 위험 가능성이 있는가?
파일 크기
- 새 파일이 권장 한도 내에 있는가?
- 수정된 파일이 경고 임계값을 초과하는가?
- 분리가 필요한가?
에러 처리
- 네트워크 요청에 try-catch가 있는가?
- 에러 메시지가 사용자 친화적인가?
- 적절한 로딩 상태와 빈 상태가 있는가?
문서
- 아키텍처 인덱스가 업데이트되었는가?
- 지식 베이스가 업데이트되었는가?
- 3개 i18n 언어가 동기화되어 있는가?
버그 리포트
리포트 템플릿
## Environment
- OS: Windows 11 / macOS 15 / Ubuntu 24
- Elftia version: v0.5.0
- Node.js version: v24.x
## Steps to Reproduce
1. Open the settings page
2. Switch to the "Appearance" tab
3. Click on wallpaper settings
4. After selecting an image...
## Expected Behavior
The wallpaper should display normally.
## Actual Behavior
The wallpaper does not display; console error: TypeError: Cannot read property 'path' of undefined
## Additional Information
- Diagnostic data export (Settings → Advanced → Export Diagnostic Data)
- Screenshots or screen recordings
- Console error logs
진단 데이터 내보내기
문제 해결을 돕기 위해 앱 내에서 진단 데이터를 내보낼 수 있습니다:
Settings → Advanced → Diagnostic Tools → Export Diagnostic Data
또는 DevTools 콘솔을 통해:
const data = await window.api.diagnostics.bundle({ includeLogs: true });
문의
- 프로젝트 이슈 — 기능 요청 및 버그 리포트
- Pull Request — 코드 기여
- Discussions — 기술 토론 및 질문