청구한 돈이 실제로 들어왔는지, 세금까지 맞춰서 추적하는 1인 사업자용 미수금 관리 서비스.
npm starthttp://127.0.0.1:5050 — 데이터는 ~/.netto/netto.db 하나에 들어갑니다.
유지보수하지 않습니다. 실행에는 문제가 없고, 로컬에서 쓰기에는 그대로 동작합니다.
이 저장소는 "아이디어부터 최종 테스트까지 에이전트가 질문 없이 혼자 만든다" 는 실험의 결과물입니다. 2026-08-23 하루 만에 기획·설계·구현·테스트까지 끝냈고, 테스트 232건이 통과합니다. 이후 워크스페이스의 기준 스택이 Next.js + Cloudflare Workers + D1 로 바뀌면서 이 구조(의존성 0개 · 로컬 SQLite · 자체 비밀번호 인증)는 더 이상 이어지지 않습니다.
| 라이트 | 다크 |
|---|---|
![]() |
![]() |
한국에서 프리랜서·1인 사업자가 돈을 받는 과정에는 다른 나라 도구가 모르는 함정이 있습니다.
청구액 ≠ 입금액
- 사업소득(3.3% 원천징수) 거래처는 100만원을 청구하면 966,700원을 보냅니다.
- 부가세 과세사업자는 100만원짜리 일에 110만원을 청구하고, 그중 10만원은 내 돈이 아닙니다.
- 같은 사람이 두 유형의 거래처를 동시에 갖습니다.
그래서 통장에 찍힌 숫자만으로는 이 건이 다 들어온 건지, 일부만 들어온 건지, 아직인지 알 수 없습니다. 매번 계산기를 두드려야 하고, 그러다 보면 못 받고 있다는 사실을 늦게 압니다. 미수금은 오래될수록 회수율이 떨어집니다.
세금을 아는 대사. 세금 유형을 고르면 실입금 예정액이 즉시 계산됩니다. 통장에 967,000원이 찍히면 그 건은 완납입니다.
용역대금 1,000,000원
원천징수 -33,000원 (소득세 30,000 + 지방소득세 3,000)
─────────────────────────
실입금 예정 967,000원
소액부징수(소득세 1,000원 미만)와 기타소득 과세최저한(기타소득금액 5만원 이하)까지 계산합니다. 10원 미만 절사도 국세 실무 그대로입니다. 이 계산은 서버와 브라우저가 같은 파일을 씁니다 — 편집기에서 보이는 숫자와 저장되는 숫자가 갈라질 수 없습니다.
연체를 먼저 보여주는 화면. 홈 최상단은 총매출이 아니라 아직 안 들어온 돈입니다. 연체가 맨 위에, 오래된 순으로 옵니다.
넥스트미디어 2,335,000원 24일 연체
넥스트미디어 1,353,800원 D-25
한빛교육원 1,094,400원 D-27
정기 청구서는 초안까지만 만듭니다. 매달 같은 금액을 청구하는 계약을 걸어두면 발행일마다 초안이 자동으로 생깁니다. 자동으로 발행하지는 않습니다 — 청구서는 대외 문서라 확인 없이 나가면 사고가 됩니다. 31일 계약은 짧은 달에 말일로 접혔다가 다음 달에 다시 31일로 돌아옵니다.
신고 기간에 그대로 쓰는 집계. 부가세 과세기간(1기·2기)과 귀속연도 기준으로 과세표준·매출세액·원천징수 합계를 뽑습니다. 재분류가 없습니다.
| Free | Pro | Business | |
|---|---|---|---|
| 0원 | 월 9,900원 / 연 99,000원 | 월 24,900원 / 연 249,000원 | |
| 거래처 | 3곳 | 무제한 | 무제한 |
| 월 청구서 발행 | 5건 | 무제한 | 무제한 |
| 정기 청구서 · 세금 리포트 · CSV · 브랜딩 | — | ✓ | ✓ |
| 사업장 | 1곳 | 1곳 | 무제한 |
한도에 걸려도 만든 데이터는 그대로 조회·수정·입금 기록·인쇄·백업이 됩니다. 추가만 막힙니다. 전체 데이터 백업은 무료 플랜에서도 언제나 가능합니다.
Toss Payments를 씁니다. 자동 갱신(빌링키)과 이번 기간만 결제(결제창) 두 경로가 있습니다. 서버가 승인을 검증하고, 금액은 서버가 계산하며, 중복 결제·실패·취소·환불·웹훅까지 처리합니다.
NETTO_PAYMENTS=sandbox # 기본값 — 인프로세스 시뮬레이터, 네트워크 나가지 않음
NETTO_PAYMENTS=live # 실제 Toss API. 키 3개가 없으면 기동하지 않습니다
NETTO_PAYMENTS=off # 결제 UI를 숨김sandbox에서는 화면 상단에 "테스트 결제 모드" 배지가 상시 표시됩니다. 승인 검증·멱등·상태 전이·환불·웹훅 코드는 두 모드가 완전히 같습니다 — 전송만 갈립니다.
의존성 0개, 빌드 없음. Node 22.5+의 node:sqlite와 브라우저 네이티브 ES Modules만 씁니다.
bin/netto.js CLI
src/domain/ 순수 계산 (세금 · 금액 · 날짜 · 청구서 · 요금제)
src/data/ SQLite · 마이그레이션 · 저장소 · 백업
src/payments/ Toss 계약 · live 클라이언트 · sandbox 시뮬레이터
src/services/ 유스케이스 (청구 · 입금 · 정기 · 리포트 · 구독 · 결제)
src/http/ 라우터 · 미들웨어 · 응답
public/js/shared/ ★ 서버와 브라우저가 함께 쓰는 세금·금액 계산
public/ 화면 (빌드 없는 ES Modules · innerHTML 0건)
docs/ 아이디어부터 최종 테스트까지의 기록
디자인은 *DESIGN*/design-md/krds(대한민국 정부 디자인 시스템)를 단일 기준으로 삼았습니다.
명암비는 토큰을 파싱해 라이트·다크 전 조합을 계산으로 검증합니다.
-p, --port <번호> 기본 5050
--host <주소> 기본 127.0.0.1
--data-dir <경로> 기본 ~/.netto
--log-level <레벨> debug | info | warn | error | silent
환경변수는 NETTO_ 접두사를 씁니다 (NETTO_PORT, NETTO_DATA_DIR, NETTO_PAYMENTS …).
npm test # 232건 / 약 1.1초세금 검산 8건, 결제 멱등성, 환불 5분기, 웹훅 3중 검증, 무료 한도, 디자인 시스템 준수 13종, 명암비 34쌍 × 3테마, 프런트 정적 검사 13종, 문구 일관성 7종, 6개월 전체 여정.
은행 계좌 연동 인증·보안·비용 대비 가치가 낮습니다. 하루 몇 건은 수동 입력이 30초입니다
이메일 발송 외부 의존. 전달은 인쇄 / PDF로 충분합니다
세금계산서 국세청 전송 공인인증·홈택스 연동. 1인 제품 범위 밖입니다
멤버 초대 · 권한 관리 1인 제품입니다
다중 통화 원천징수·부가세는 원화 기준으로만 성립합니다
이 저장소는 실제 Toss Payments 가맹점 계약으로 실결제를 처리한 적이 없습니다. sandbox 드라이버는 Toss가 문서화한 REST 계약을 구현한 것이지 Toss 자체가 아닙니다. live 전환 시 최초 1회는 Toss 테스트 키로 실제 연동 검증이 필요합니다.
MIT

