尚未检测到更新。GitHub 发布版本后会显示在这里。
个人 GitHub 账号下公开仓库的所有者可以登录并验证所有权,自行管理介绍,无需管理员批准。
登录并生成验证文件,在 30 分钟内将其提交到此仓库的默认分支。其他分支或分叉仓库中的文件无效。然后在下方检查文件,即可无需管理员批准直接管理项目。请保留文件以维持管理权限。
如需登录,将前往登录页面。登录后请回到此处,再次点击所选的验证按钮。
在项目文件夹中运行 /nomorevibe verify,即可验证所有权并自行管理介绍。
一分钟完成验证正在加载完整 README。 以下为已保存的摘录。
나 혼자 쓰는 복식부기 가계부. 왼쪽(차변)·오른쪽(대변)을 한 줄로 입력하면 잔액·자산현황·손익이 자동으로 도출되는 복식부기 방식을 직접 구현합니다. • Next.js 16 (App Router) + TypeScript • Drizzle ORM + libSQL (로컬은 SQLite 파일, 배포는 Turso) • Tailwind CSS • Auth.js v5 (Google / Naver) • Vitest (단위 테스트) + Playwright (E2E) • 자체 경량 i18n (한국어 / English) • PWA (홈화면에 추가하면 주소창 없이 실행) 기본적으로 로컬 SQLite 파일(./moneybook.db)을 사용합니다. TURSO_DATABASE_URL/TURSO_AUTH_TOKEN을 설정하면 원격 Turso DB로 전환됩니다. 배포는 docs/DEPLOYMENT.md를 따라가면 됩니다 (Turso + Vercel + Google OAuth). 설정 화면에서 네 종류를 내보내고 가져올 수 있습니다. 이 넷이면 가계부 전체가 복원됩니다.查看完整 README ↗
나 혼자 쓰는 복식부기 가계부. 왼쪽(차변)·오른쪽(대변)을 한 줄로 입력하면 잔액·자산현황·손익이 자동으로 도출되는 복식부기 방식을 직접 구현합니다.
npm install
cp .env.example .env.local # 필요한 값 채우기 (로컬은 대부분 비워둬도 됨)
npm run dev
기본적으로 로컬 SQLite 파일(./moneybook.db)을 사용합니다. TURSO_DATABASE_URL/TURSO_AUTH_TOKEN을 설정하면 원격 Turso DB로 전환됩니다.
배포는 docs/DEPLOYMENT.md를 따라가면 됩니다 (Turso + Vercel + Google OAuth).
| 명령 | 설명 |
|---|---|
npm run dev | 개발 서버 |
npm run build | 프로덕션 빌드 |
npm run lint | ESLint |
npm run typecheck | TypeScript 타입 검사 |
npm run test | Vitest 단위 테스트 |
npm run e2e | Playwright E2E (개발 서버 자동 기동) |
npm run format | Prettier 포맷 적용 |
npm run db:generate | 스키마 변경으로 마이그레이션 생성 |
npm run db:migrate | 마이그레이션 적용 |
npm run db:studio | Drizzle Studio |
npm run db:schema | docs/schema.sql 재생성 |
npm run db:schema:check | docs/schema.sql이 마이그레이션과 맞는지 확인 (CI) |
app/ 라우트, 페이지, 서버 액션, 레이아웃
db/ Drizzle 스키마 + DB 클라이언트
lib/ 도메인 로직 (잔액 엔진, 통화, 날짜/타임존 유틸 등)
i18n/ 번역 사전(ko/en), 로케일 쿠키, 언어 전환
drizzle/ 생성된 마이그레이션 파일
e2e/ Playwright E2E 테스트 (데스크탑 + 모바일 뷰포트)
demo/ 나레이션 붙은 워크스루 녹화 (npm run e2e 와는 별개)
docs/ 배포 런북 + schema.sql (스키마 붙여넣기용) · reset.sql (전체 삭제)
설정 화면에서 네 종류를 내보내고 가져올 수 있습니다. 이 넷이면 가계부 전체가 복원됩니다.
| CSV | 내용 |
|---|---|
| 계정과목 | 분류, 이름, 통화, 사용 기간(activeFrom/activeTo), 메모, 상위 그룹 |
| 거래 | 분개선 한 줄 = CSV 한 행, transactionKey로 거래 단위 그룹핑 (줄 메모 포함) |
| 예산 | 계정 이름 · 연월 · 금액 |
| 환율 | 날짜 · 통화쌍 · 환율 · 출처 (수동 보정값은 API로 복원할 수 없으므로 포함) |
가져오기는 미리보기 → 확정 2단계입니다. 미리보기에서 신규/기존/오류 건수와 오류 사유를 보여주고, 확정할 때만 씁니다. 거래는 커밋 전에 assertBalanced를 통과해야 하며, 균형이 맞지 않는 거래는 그 거래만 건너뛰고 나머지는 정상 반영됩니다. 첫 줄은 반드시 헤더여야 하고, 열 이름이 다르면 파일 전체를 거부합니다.
용량: 업로드 한도는 32MB(next.config.ts의 serverActions.bodySizeLimit)로, 10~15년치 일일 가계부를 한 파일로 복원하기에 충분합니다. 내보내기는 스트리밍이라 크기 제한이 없습니다.
단, Vercel에 배포한 경우 요청 본문 4.5MB 제한이 별도로 걸립니다. 이건 플랫폼 인프라 한도라 앱 설정으로 못 올립니다(문서). 대략 3만 건이 넘는 거래를 복원하려면 파일을 나눠서 가져오거나, Node 서버로 자체 호스팅하면 32MB 한도가 그대로 적용됩니다.
다섯 번째 가져오기 폼은 이 앱 형식이 아니라 한 행에 거래 하나가 통째로 담긴 CSV를
그대로 읽습니다 (날짜,아이템,금액,기간내합계,왼쪽,,오른쪽,,메모). 한 행이 곧 한
거래라 좌·우가 이미 한 줄에 다 있고, 여기서는 그게 분개선 두 줄이 됩니다.
side에
담고 음수 금액을 금지하므로, 부호를 좌우로 접는 것이 같은 분개를 표현하는 유일한
방법입니다.기간내합계는 버립니다 — 내보낸 기간에서만 맞는 러닝 합계이고, 잔액은 언제나
분개선에서 다시 계산합니다.순자산은 자본으로 들어가되, 거래 구분은 normal 그대로입니다. 순자산은
분류지 거래 구분이 아니라서, 기초로 찍어버리면 진짜 자본 거래를 잘못 이름
붙이게 됩니다.기간을 book 시작일까지 늘려서 내보내세요. 이런 내보내기는 흔히 최근 몇 년 구간이 기본이고, 그 앞의 잔액은 파일 어디에도 없습니다. 구간만 가져오면 그 구간의 증감은 정확하지만 출발점이 0이 됩니다.
transaction_lines)의 합이 항상 같아야 합니다. 이 불변식은 lib/ledger.ts의 assertBalanced가 모든 저장 경로에서 강제합니다.transaction_lines에서 나온 사실입니다. 계정의 사용 기간(active_from/active_to, lib/accounts.ts)은 카탈로그만 거릅니다 — 입력 폼의 계정 선택, 예산 행, 계정과목 목록. 잔액은 수준(level)이라 올해 거래가 없던 예금도 잔액을 그대로 들고 있고, 사용 기간으로 그걸 가리면 합계에서 실제 돈이 빠집니다. 자산현황에서 계정이 접히는 조건이 잔액 0 **그리고** 종료됨인 이유가 이것입니다: 기여도가 정확히 0인 행만 사라지므로 어떤 합계도 움직일 수 없고, 종료된 계정에 거래가 들어오면 행이 다시 나타납니다.app/entry-actions.ts), CSV 가져오기는 어느 것도 막지 않습니다 — 백업에는 이미 해지한 계정의 과거가 들어 있고, 여기서 막으면 내보낸 파일을 되돌릴 수 없게 됩니다.환율 반영 동작으로만 손익에 반영됩니다.환율 반영 버튼으로 평가차액을 거래로 계상해야 합니다. 환율을 못 가져온 통화는 해당 계정에 환율 없음으로만 표시되고, 장부가 합계와 나머지 화면은 영향을 받지 않습니다.