셀프 호스팅 인보이스 소프트웨어 5종 비교 분석
Invoice Ninja, InvoiceShelf, InvoicePlane, Kimai, ERPNext의 기능을 비교합니다. 정기 결제, 세금 설정, 결제 게이트웨이 연동 및 라이선스 정책을 분석하여 VPS 환경에 가장 적합한 소프트웨어를 선택하는 기준을 제시합니다.
어떤 셀프 호스팅 인보이스 소프트웨어를 선택해야 할까요?
셀프 호스팅 인보이스 소프트웨어는 하나의 VPS에서 운영할 수 있는 5가지 현실적인 선택지로 압축되며, 이들은 서로 완벽하게 대체 가능한 관계가 아닙니다. Invoice Ninja는 가장 완성도가 높은 제품으로, 정기 인보이스 발행, 고객 포털, 결제 게이트웨이, 전자 인보이스 형식 등 모든 기능이 설치 첫날부터 정상 작동합니다. InvoiceShelf는 더 가볍고 완전한 오픈 소스 옵션입니다. InvoicePlane은 별도의 오케스트레이션이 필요 없는 단순한 PHP 애플리케이션입니다. Kimai는 항목별 청구가 아닌 추적된 시간 단위로 비용을 청구합니다. ERPNext는 인보이스 발행 기능을 포함한 완전한 회계 시스템입니다.
셀프 호스팅 인보이스 환경을 구축할 때 기능 부족보다 훨씬 더 자주 발생하는 문제는 두 가지입니다. 첫 번째는 이메일입니다. 스팸 메일함에 들어간 인보이스는 미납 인보이스와 다름없으며, 이 사실을 알려주는 시스템도 없습니다. 두 번째는 백업입니다. 이는 데이터가 손실될 경우 단순한 불편함을 넘어 세무 문제로 직결되는 유일한 셀프 호스팅 데이터베이스입니다.
기능 목록을 읽기 전에 라이선스를 먼저 확인하십시오. 이 5가지 소프트웨어 중 3개는 카피레프트(copyleft) 라이선스이며, 1개는 허용적(permissive) 라이선스, 나머지 1개는 사용 범위에 실질적인 제한이 있는 소스 가용(source-available) 라이선스를 따릅니다.
다섯 가지 선택지와 각 대상
Invoice Ninja
Laravel 애플리케이션이며 현재 v5 버전을 사용합니다. 자체 호스팅은 무료이며 반복 청구서, 견적서, 프로젝트, 시간 추적, 비용 관리, 고객 포털, Stripe 및 PayPal을 포함한 결제 게이트웨이 등 모든 기능을 제한 없이 제공합니다. 이 프로젝트는 스스로를 "Laravel로 구축된 소스 공개형 청구서, 견적서, 프로젝트 및 시간 추적 앱"이라고 정의합니다. 자체 호스팅 사용자가 비용을 지불해야 하는 경우는 두 가지입니다. 첫 번째는 브랜딩 제거입니다. 프로젝트 측 설명에 따르면 "고객 대면 화면에서 Invoice Ninja 브랜딩을 제거하기 위해 연간 40달러의 화이트 라벨 라이선스를 제공합니다." 이 가격은 2026년 10월 기준입니다. 두 번째는 Peppol 네트워크를 통한 전자 청구서 송수신이며, 이를 위해서는 화이트 라벨 라이선스와 선불 e-크레딧이 필요합니다. 이는 아래 회계사가 요구할 사항 항목에서 다룹니다.
가장 완벽한 기능을 원하고 규모가 큰 스택을 운영할 의향이 있다면 이 제품을 선택하십시오.
InvoiceShelf
Crater의 포크 버전으로 GNU Affero General Public License version 3 (AGPL-3.0)를 따릅니다. 청구서, 견적서, 반복 청구, 비용, 세금, 다중 통화, 고객 포털 및 다중 회사 기능을 지원합니다. 결제 및 화이트 라벨링은 별도의 공식 모듈 저장소에서 제공되며, 둘 다 AGPL-3.0 라이선스이며 무료입니다. 카드 결제는 Stripe checkout을 통해 처리됩니다.
소규모의 완전한 오픈 소스 애플리케이션을 원하고 수십 개의 게이트웨이가 필요하지 않다면 이 제품을 선택하십시오.
InvoicePlane
CodeIgniter 기반의 PHP 애플리케이션으로 MIT 라이선스로 배포됩니다. 이 목록에서 유일하게 웹 루트에 파일 압축을 푸는 방식으로 설치하는 옵션입니다. Docker나 Node 빌드 과정이 필요 없습니다. PDF는 mPDF를 통해 생성되므로 템플릿은 HTML과 CSS로 작성합니다. 고객은 게스트 링크를 통해 청구서를 확인하고 결제할 수 있습니다.
결제 기능이 과거에는 문제였습니다. InvoicePlane 1.6은 기본적으로 Stripe만 지원하고 다른 제공업체는 제거했습니다. 2026년 8월 28일에 릴리스된 1.7.2 버전에서는 Stripe와 PayPal이 다시 도입되었으며, PayPal Advanced Credit Cards와 Venmo가 추가되었습니다. 1.7.2와 함께 제공된 설치 가이드는 PHP 8.2 이상(8.3 및 8.4 지원)과 MariaDB를 요구하지만, 프로젝트 위키의 요구 사항 페이지에는 여전히 PHP 8.0에서 8.1 범위가 표시되어 있습니다. 다운로드하는 릴리스의 노트를 반드시 확인하십시오.
공유 호스팅이나 512 MB VPS 환경이라면 이 제품을 선택하십시오.
Kimai
타임시트에서 청구서를 생성하는 AGPL-3.0 기반 시간 추적기입니다. 시간을 기준으로 비용을 청구하는 모든 사용자에게 적합한 솔루션입니다. 청구서 템플릿은 DOCX, ODS 또는 XLSX 파일로 업로드해야 하며(문서에 따르면 이 형식들만 허용됨), 이를 PDF나 HTML로 렌더링합니다. CSS를 작성하는 대신 워드 프로세서에서 청구서 레이아웃을 구성할 수 있어 대부분의 사용자에게 더 편리합니다.
Kimai는 결제 게이트웨이가 없으며 스토어에도 결제 플러그인이 등록되어 있지 않으므로 PDF를 이메일로 전송해야 합니다. Customer Portal이라는 무료 벤더 플러그인을 사용하면 비밀 URL(선택적으로 비밀번호 보호 가능)을 통해 고객 및 프로젝트 통계와 타임시트를 공유할 수 있지만, 이는 청구서가 아닌 타임시트를 보여줍니다. 구조화된 전자 청구서 기능은 E-Invoice Plus라는 유료 스토어 플러그인으로 제공되며, 2026년 10월 기준 부가세 제외 연간 99 EUR입니다. 이 플러그인은 CII 또는 UBL 형식의 EN16931, Extended 및 XRechnung 3.0 프로필, 베타 버전의 Peppol UBL, 그리고 ZUGFeRD 및 Factur-X 하이브리드 PDF를 지원합니다.
청구서가 추적된 시간의 결과물이라면 이 제품을 선택하십시오.
ERPNext
GPL-3.0 라이선스를 따르며, 앞선 소프트웨어들과는 범주가 다릅니다. 판매 청구서는 계정과목표, 분개장, 재고 및 급여 관리를 포함한 전체 회계 시스템 내의 문서 유형 중 하나일 뿐입니다. 청구서 발행이 업무의 전부가 아닌 경우에 적합한 솔루션입니다. 8명의 고객을 둔 프리랜서 한 명에게는 지나치게 방대한 소프트웨어입니다. 시스템 구축 자체가 하나의 프로젝트이며, 자세한 내용은 running ERPNext on a VPS에서 다룹니다.
반복 청구서는 보이지 않는 스케줄러에 의존합니다
Invoice Ninja, InvoiceShelf, InvoicePlane 및 ERPNext는 모두 반복 청구서를 생성합니다. Kimai는 핵심 기능에 반복 청구서 기능이 없는데, 이는 Kimai의 청구서가 특정 기간의 타임시트 항목을 기반으로 작성되기 때문입니다.
Laravel 기반 애플리케이션에서 발생하는 실패 유형은 모두 동일하며, 조용하게 발생합니다. 반복 청구서는 Laravel의 스케줄러에 의해 생성되는데, 이 스케줄러는 php artisan schedule:run을 호출하는 cron이나 장시간 실행되는 php artisan schedule:work 프로세스에 의해 매분 트리거되어야 합니다. 이를 트리거하는 요소가 없으면 반복 청구서 목록에는 다음 발송 예정일이 표시되지만, 해당 날짜가 지나도 청구서는 생성되지 않습니다. 코드가 실행되지 않으므로 오류 로그도 남지 않습니다.
따라서 첫 번째 반복 청구서를 생성한 후, 다음 발송 예정일을 몇 분 뒤로 설정하고 기다려 보십시오. 아무런 반응이 없다면 스케줄러가 실행되지 않는 것입니다. Docker 설치 환경에서 이는 일반적으로 스케줄러 서비스나 프로세스가 시작되지 않았거나 종료되었음을 의미합니다. 현재 Invoice Ninja 및 InvoiceShelf 이미지에서는 스케줄러가 별도의 서비스가 아닌 애플리케이션 컨테이너 내부에서 실행되므로, 해당 컨테이너의 로그를 확인해야 합니다.
docker compose ps
docker compose logs --tail 50파일 내의 모든 서비스는 running 상태를 보고해야 합니다. exited 상태에 머물러 있는 서비스가 있다면 해당 서비스의 로그를 읽어야 합니다.
다중 통화 및 세금: 커밋 전 확인 사항
기능 목록에 기재된 "다중 통화"는 제품마다 의미하는 바가 크게 다릅니다. 데모 인스턴스에서 귀사의 실제 수치를 사용하여 다음 네 가지 항목을 확인하십시오. 이 부분에서 발생하는 실수는 본인이 아닌 회계사가 발견하게 되기 때문입니다.
- 송장에 발행일 기준 환율이 저장됩니까? 반드시 저장되어야 합니다. 애플리케이션이 실시간 환율로 합계를 재계산하면 지난 분기 보고서가 열 때마다 변경되며, 장부가 이미 신고한 내용과 일치하지 않게 됩니다.
- 세금이 품목별로 적용됩니까, 송장 전체에 적용됩니까, 아니면 둘 다 가능합니까? 송장 단위의 단일 세율은 한 품목이라도 면세 대상이 되는 순간 문제가 발생합니다.
- 가격을 세금 포함 및 세금 별도 방식으로 모두 입력할 수 있습니까? 사후에 변환하면 품목당 1센트 단위의 반올림 오차가 발생하며, 이러한 오차는 1년 동안 누적됩니다.
- 부가가치세(VAT) 납부 의무가 없는 타국 고객에게 발행하는 문서에는 무엇이 표시됩니까? 세금 열에 단순히 0을 표시하는 것이 아니라, 송장에 면세 사유 문구가 인쇄되어야 합니다.
Invoice Ninja와 ERPNext는 위 네 가지 사항을 모두 처리합니다. InvoiceShelf는 기능 목록에 세금 및 다중 통화를 포함하고 있습니다. InvoicePlane과 Kimai는 상대적으로 단순하므로, 가장 쉬운 송장이 아닌 가장 까다로운 송장을 기준으로 테스트하십시오.
클라이언트 포털 및 결제 게이트웨이
클라이언트 포털은 고객이 자신의 청구서를 확인하고, PDF를 다운로드하며, 결제를 진행할 수 있는 페이지입니다. 이 기능은 생각보다 중요합니다. 이메일로 결제를 독촉하는 것이 청구서를 작성하는 것보다 더 많은 시간을 소모하기 때문입니다.
Invoice Ninja는 이 분야에서 가장 강력한 기능을 제공합니다. 완전한 포털, 다양한 게이트웨이, 결제 수단 저장, 정기 청구서 자동 결제 기능을 갖추고 있습니다. InvoiceShelf는 고객 포털을 제공하며 결제 모듈을 통해 Stripe checkout을 추가할 수 있습니다. InvoicePlane은 각 청구서에 게스트 링크를 제공하며 Stripe를 지원하고, 1.7.2 버전부터는 PayPal도 다시 지원합니다. Kimai는 결제 게이트웨이가 없으며, 무료 Customer Portal 플러그인은 청구서 대신 타임시트와 통계를 공유하므로 PDF는 첨부 파일로 발송해야 합니다.
한 가지 자주 혼동되는 점이 있습니다. 인보이스 애플리케이션을 직접 호스팅한다고 해서 카드 번호를 직접 보관하는 것은 아닙니다. Stripe checkout을 사용하면 클라이언트는 Stripe 페이지로 리다이렉트되어 그곳에 카드 정보를 입력하게 되며, 사용자의 VPS는 카드 번호를 전혀 볼 수 없습니다. 결제 폼을 직접 구축하지 않기 때문에 PCI(결제 카드 산업) 준수 범위가 작게 유지되는 것입니다. 나중에 하나 이상의 결제 처리기가 필요하거나 국가별로 결제를 라우팅해야 한다면, 이는 Hyperswitch를 이용한 자체 호스팅 결제 오케스트레이션과 같은 별도의 계층에서 처리해야 합니다.
PDF 품질 및 편집하게 될 템플릿
템플릿을 직접 편집해야 합니다. 기본 설정은 사용자의 국가와 맞지 않는 위치에 주소를 표시합니다.
Invoice Ninja는 이미지에 포함된 헤드리스 Chrome(arm64 환경에서는 Chromium)을 사용하여 HTML 및 CSS 템플릿을 PDF로 렌더링하며, 이 때문에 컨테이너 용량이 큽니다. 메모리 할당 시 주의하십시오. 헤드리스 브라우저는 스택에서 가장 무거운 프로세스이므로 1 GB VPS 환경은 빠듯할 수 있습니다. InvoicePlane은 mPDF를 사용하는데, 이는 순수 PHP 기반으로 가볍지만 최신 CSS 일부를 지원하지 않는다는 단점이 있습니다. Kimai는 이와 반대로 DOCX 또는 ODS 파일을 업로드하는 방식을 취하므로, 스타일시트를 작성해 본 적 없는 사용자도 LibreOffice나 Word를 통해 레이아웃을 구성할 수 있습니다.
디자인된 청구서가 중요하고 CSS는 중요하지 않다면 Kimai의 방식이 유리합니다. 템플릿을 버전 관리 시스템에 포함하고 차이점을 비교해야 한다면 HTML 방식이 더 적합합니다.
상업적 용도로 사용할 수 있는 라이선스인가요?
다섯 가지 소프트웨어 모두 고객에게 청구서를 발행하는 용도로 사용할 수 있습니다. 그 이상의 작업을 수행할 때 차이점이 발생합니다.
Invoice Ninja는 Elastic License 2.0을 따릅니다. 다음 두 조항이 중요합니다.
귀하는 소프트웨어의 상당한 기능이나 기능을 사용자에게 제공하는 호스팅 또는 관리형 서비스로서 제3자에게 소프트웨어를 제공할 수 없습니다.
귀하는 소프트웨어의 라이선스 키 기능을 이동, 변경, 비활성화하거나 우회할 수 없습니다.
따라서 자신의 사업을 위해 운영하는 것은 괜찮지만, 고객을 위한 제품으로 인스턴스를 운영하는 것은 허용되지 않습니다. 두 번째 조항 때문에 브랜딩을 제거하려면 소스 코드를 수정하는 대신 40달러의 라이선스를 구매해야 합니다.
InvoiceShelf, Kimai, Crater는 AGPL-3.0을 따릅니다. 상업적 이용은 무료이며 상위 등급은 존재하지 않습니다. 13조에 따른 의무가 있는데, 코드를 수정하고 수정된 버전을 네트워크를 통해 다른 사람들이 사용하게 할 경우 해당 변경 사항의 소스 코드를 제공해야 합니다. 수정하지 않은 인스턴스는 이미 업스트림의 공개 소스에 포함되므로, 대부분의 자가 호스팅 사용자는 이 조항에 해당하지 않습니다.
InvoicePlane은 MIT 라이선스를 따르며, 이 그룹에서 의무 사항이 가장 적습니다. 다만 README에 명시된 대로 이름과 로고는 프로젝트의 소유로 남습니다.
ERPNext는 GPL-3.0을 따릅니다. 배포하는 수정 사항은 공유해야 하지만, 비공개로 운영하는 경우에는 아무런 의무가 없습니다.
위 내용은 라이선스 텍스트에 대한 설명일 뿐 법률적 조언이 아닙니다.
프로젝트가 여전히 유지보수되고 있습니까? 커밋 로그를 확인하십시오
Crater는 수년간 널리 사용된 오픈 소스 인보이스 애플리케이션이었으며, 여전히 많은 가이드에서 이를 추천하고 있습니다. 기본 브랜치는 2023년 2월 19일 이후로 1329일 동안 커밋이 발생하지 않았습니다.
이 차트의 데이터
[
{
"label": "ERPNext",
"commit_gap": 0
},
{
"label": "InvoicePlane",
"commit_gap": 0
},
{
"label": "Kimai",
"commit_gap": 4
},
{
"label": "InvoiceShelf",
"commit_gap": 11
},
{
"label": "Invoice Ninja",
"commit_gap": 22
},
{
"label": "Crater",
"commit_gap": 1329
}
]해당 블록에 있는 6개의 프로젝트 중 5개는 최근 4주 이내에, 3개는 최근 1주 이내에 커밋이 있었습니다. InvoiceShelf는 Crater의 작업을 이어받은 포크 프로젝트로, 동일한 AGPL-3.0 라이선스와 데이터 모델을 사용합니다. 따라서 전환 시 재작성이 아닌 데이터 마이그레이션만 수행하면 됩니다. Crater가 아닌 InvoiceShelf를 설치하십시오.
VPS에 각각 설치하기
InvoicePlane을 제외한 모든 서비스는 Docker Compose를 사용하는 것이 가장 간편합니다. Docker Compose가 생소하다면 VPS에서 첫 Docker Compose 스택 구성하기를 먼저 읽고 돌아오십시오.
Invoice Ninja는 자체 compose 저장소를 제공합니다. 현재 지침은 debian 브랜치를 사용하며, compose 파일은 같은 이름의 하위 디렉터리에 있습니다.
git clone https://github.com/invoiceninja/dockerfiles.git -b debian
cd dockerfiles/debian
docker run --rm -it invoiceninja/invoiceninja-debian php artisan key:generate --show전체 출력 내용을 해당 디렉터리의 .env 파일 내 APP_KEY에 복사하고, 실제 APP_URL도 함께 입력하십시오. 첫 번째 계정을 위한 IN_USER_EMAIL과 IN_PASSWORD도 설정해야 합니다. 비워두면 기본 로그인 정보는 admin@example.com이며 비밀번호는 changeme!로 설정됩니다. 그 후 서비스를 시작하십시오.
docker compose up -d번들로 포함된 nginx 서비스는 호스트의 80번 포트를 사용하므로, 앞에 TLS 프록시를 두거나 매핑을 변경하십시오. 설정 마법사에서 데이터베이스 호스트로 mysql를 입력하십시오. 이는 compose 네트워크상의 서비스 이름입니다. localhost은 애플리케이션 컨테이너 자체를 가리킵니다.
InvoiceShelf는 데이터베이스 엔진별로 준비된 compose 파일을 제공합니다.
curl -fLO https://raw.githubusercontent.com/InvoiceShelf/docker/master/docker-compose.mysql.yml
mv docker-compose.mysql.yml docker-compose.yml시작하기 전에 파일을 여십시오. 파일 내 모든 비밀번호는 임시 값이며 주석으로도 명시되어 있습니다. APP_URL, SESSION_DOMAIN, SANCTUM_STATEFUL_DOMAINS은 모두 localhost로 기본 설정되어 있으므로, 첫 로그인 전에 세 항목 모두 실제 호스트 이름으로 변경해야 합니다. 그 후 서비스를 실행하십시오.
docker compose up -d이 서비스는 호스트의 8090번 포트를 사용하며 컨테이너 내부에서는 8080번 포트로 서비스합니다. 클라이언트가 접속하기 전에 반드시 TLS(전송 계층 보안)가 적용된 리버스 프록시를 앞에 두십시오.
프로젝트 문서에서 가져온 Kimai 운영용 compose 파일
services:
sqldb:
image: mysql:8.3
volumes:
- mysql:/var/lib/mysql
environment:
- MYSQL_DATABASE=kimai
- MYSQL_USER=kimaiuser
- MYSQL_PASSWORD=kimaipassword
- MYSQL_ROOT_PASSWORD=changemeplease
command: --default-storage-engine innodb
restart: unless-stopped
healthcheck:
test: mysqladmin -uroot -p$$MYSQL_ROOT_PASSWORD ping -h 127.0.0.1 --silent
interval: 10s
timeout: 5s
retries: 12
start_period: 30s
kimai:
image: kimai/kimai2:stable
depends_on:
sqldb:
condition: service_healthy
restart: true
volumes:
- data:/opt/kimai/var/data
- plugins:/opt/kimai/var/plugins
ports:
- 8001:8001
environment:
- APP_SECRET=your-fantastic-long-random-and-ultra-secure-secret
- TRUSTED_HOSTS=kimai.example.com
- ADMINMAIL=admin@example.com
- ADMINPASS=changemeplease
- DATABASE_URL=mysql://kimaiuser:kimaipassword@sqldb/kimai?charset=utf8mb4&serverVersion=8.3.0
restart: unless-stopped
volumes:
data:
mysql:
plugins:APP_SECRET을 길고 무작위인 문자열로 설정하고, TRUSTED_HOSTS를 실제 사용할 도메인으로 설정하십시오. ADMINMAIL과 ADMINPASS은 첫 부팅 시 첫 번째 관리자 계정을 생성하므로, 이후 인터페이스에서 비밀번호를 변경하고 파일에서 해당 항목을 제거하십시오.
InvoicePlane은 컨테이너를 지원하지 않습니다. 먼저 빈 데이터베이스를 생성하십시오.
sudo mysql -e "CREATE DATABASE invoiceplane CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;"프로젝트 릴리스 페이지에서 아카이브를 다운로드하여 웹 루트에 압축을 해제하고, ipconfig.php.example를 ipconfig.php으로 복사한 뒤 파일 내 주석에 따라 URL을 설정하십시오. 그 후 https://your-domain.example/index.php/setup를 열어 설치 과정을 진행하십시오.
청구서가 스팸 메일함으로 분류되는 이유
이 문제는 금전적 손실을 야기하지만, 애플리케이션은 청구서가 정상적으로 발송되었다고 보고합니다.
VPS의 자체 IP 주소로 청구서 메일을 발송하지 마십시오. 새로운 VPS IP는 발송 이력이 없으며, 대형 메일 서비스 제공업체는 호스팅 대역의 알 수 없는 주소에서 온 첫 메시지를 기본적으로 의심스러운 것으로 간주합니다. 인증된 도메인의 SMTP(simple mail transfer protocol) 릴레이를 통해 발송하십시오. 이 과정을 처음부터 끝까지 수행하는 방법은 별도의 가이드가 필요하며, 자체 호스팅 애플리케이션에서 안정적으로 메일 발송하기 문서에서 릴레이 설정, DNS 레코드, 테스트 방법을 다룹니다.
대부분의 청구 시스템에서 가장 흔히 발생하는 실수는 From 주소 설정입니다. From 주소는 반드시 본인이 제어하는 도메인이어야 하며, 릴레이 서버가 DKIM(domainkeys identified mail)으로 서명하는 도메인이어야 합니다. 고객의 주소를 From에 넣는 것은 예의 바르게 보일 수 있으나 메일 전달을 방해합니다. 수신 서버는 From 도메인과 메시지를 인증한 도메인이 일치하는지 확인하기 때문입니다. 고객의 도메인이 p=reject의 DMARC 정책을 게시한 경우, Gmail은 해당 메시지를 즉시 거부합니다.
550 5.7.26 Unauthenticated email from example.com is not accepted due to domain's DMARC policy본인의 주소를 From에 유지하고 고객의 주소는 Reply-To에 넣으십시오. 실제 메일을 발송하기 전에 게시된 레코드를 확인하십시오.
dig +short TXT example.com
dig +short TXT _dmarc.example.com
dig +short TXT selector1._domainkey.example.com첫 번째 명령은 릴레이 서버를 지정하는 SPF(sender policy framework) 레코드를 반환해야 합니다. 두 번째 명령은 DMARC(domain-based message authentication, reporting and conformance) 정책을 반환해야 합니다. 세 번째 명령은 릴레이 서버가 제공한 셀렉터에 따라 달라지며, 결과가 비어 있다면 DKIM 레코드가 누락되었거나 잘못된 이름으로 게시된 것입니다. 이 경우 발송하는 모든 메시지의 서명 검사가 실패합니다.
그 후 대형 메일 서비스 제공업체에 소유한 계정으로 실제 청구서를 발송하고 원본 헤더를 확인하십시오. Authentication-Results 헤더의 dkim=pass 및 spf=pass만이 유효한 증거입니다. 애플리케이션 자체의 "sent" 플래그는 메시지가 릴레이 서버로 전달되었다는 사실만을 의미할 뿐입니다.
백업: 절대 잃어버려서는 안 될 데이터베이스
미디어 서버의 데이터를 잃어버리면 파일을 다시 다운로드하면 그만입니다. PhotoPrism이나 Immich와 같은 셀프 호스팅 사진 서버조차도 보통은 사진을 촬영한 휴대폰에 원본이 남아 있는 경우가 많습니다. 하지만 청구서 데이터베이스를 잃어버리면 무엇을 청구했고, 무엇을 입금받았으며, 무엇이 미납 상태인지 증명할 수 없게 됩니다. 따라서 데이터베이스는 그에 걸맞은 수준으로 관리해야 합니다.
다음 네 가지를 반드시 백업하십시오. 데이터베이스, 로고와 생성된 PDF 및 비용 영수증이 저장된 스토리지 볼륨, 애플리케이션의 환경 파일, 그리고 일반 파일로 보관된 렌더링 완료된 PDF입니다. PDF는 이를 생성한 애플리케이션이 없어도 10년 뒤에 열어볼 수 있기 때문입니다.
환경 파일은 생각보다 훨씬 중요합니다. Laravel은 해당 파일에 포함된 APP_KEY를 사용하여 결제 게이트웨이 자격 증명을 포함한 민감한 저장 값을 암호화합니다. 새로 생성된 키와 함께 데이터베이스를 복원하면 기존 값들을 복호화할 수 없습니다. 청구서 데이터는 모두 남아 있더라도 게이트웨이 설정은 읽을 수 없는 상태가 됩니다.
InvoiceShelf 스택의 덤프는 다음과 같은 형태입니다. 데이터베이스 서비스는 mariadb:10를 실행하므로, 컨테이너 내부의 도구는 mariadb-dump입니다.
docker compose exec -T database mariadb-dump \
--user=root --password=YOUR_ROOT_PASSWORD \
--single-transaction --databases invoiceshelf > invoiceshelf.sql--single-transaction는 InnoDB 테이블을 잠그지 않고 일관된 스냅샷을 생성하므로, 덤프가 실행되는 동안에도 애플리케이션은 정상적으로 서비스를 제공합니다. -T은 Docker가 터미널을 할당하지 않도록 하여, 리다이렉트된 출력값이 손상되어 가져오기(import)가 불가능한 덤프 파일이 생성되는 것을 방지합니다.
암호화된 restic 백업을 외부 저장소로 전송하는 작업을 스케줄에 따라 서버 밖으로 수행하고, 회계사가 요구하는 기간을 충족할 수 있도록 보관 주기를 충분히 길게 설정하십시오.
그런 다음 복원을 테스트하십시오. 일회용 컨테이너에 덤프를 올리고, 로그인한 뒤 지난달 청구서를 열어보십시오. 이 과정을 한 번이라도 수행해 보기 전까지는 백업이 제대로 작동하는지 알 수 없습니다.
회계사가 요청할 사항
이 튜토리얼을 세무 조언으로 받아들이지 마십시오. 아래 내용은 본 소프트웨어가 생성할 수 있는 데이터이며, 이를 바탕으로 귀하의 자문가와 상의하시기 바랍니다.
내보내기 가능한 데이터. 데이터베이스 클라이언트를 사용하거나 지원 티켓을 열지 않고도 인터페이스에서 청구서와 결제 내역을 CSV로 내보낼 수 있어야 합니다. SQL 덤프는 백업일 뿐 내보내기가 아니며, 회계사가 이를 직접 열어볼 수 없기 때문입니다.
변경 불가능한 번호 체계. 청구서 번호는 순차적으로 부여되어야 하며, 누락 없이 재사용되지 않아야 합니다. 청구서를 삭제하면 번호에 공백이 생기며, 이에 대한 소명이 필요합니다. 대신 취소(Cancel)나 대변(Credit) 처리를 하십시오. 본 문서에서 다루는 모든 애플리케이션은 이 기능을 지원합니다. 번호의 연속성이 법적으로 요구되는지 여부는 귀하가 등록된 지역에 따라 다르므로 미리 확인하는 것이 좋습니다.
보관. 데이터베이스 덤프와 생성된 PDF는 귀하의 규정에서 요구하는 기간만큼 보관하십시오. PDF는 실제로 발송된 문서이며, 청구서 분쟁 발생 시 가장 중요한 증빙 자료가 됩니다.
변경 이력. 누가 언제 청구서를 수정했는지 확인할 수 있는 기능은 유용하며, 애플리케이션마다 지원 범위가 다릅니다. Invoice Ninja는 레코드별 활동 로그를 유지합니다.
구조화된 전자 청구서(e-invoicing)는 EU 일부 지역에서 선택 사항이 아닌 필수 요구 사항이 되었습니다. Invoice Ninja는 ZUGFeRD, XRechnung, Facturae, FatturaPA 및 일반적인 EN16931을 포함한 공통 형식을 생성합니다. 자체 호스팅 인스턴스에서 Peppol 네트워크를 통한 전송은 Invoice Ninja의 자체 액세스 포인트를 거칩니다. 이를 위해서는 신원 확인 절차를 겸하는 검증된 화이트 라벨 라이선스 보유자여야 하며, e-크레딧을 구매해야 합니다. 12개월 이내에 발송 또는 수신하는 문서 500건당 50달러, 1,000건당 100달러입니다. 공급업체의 표현을 빌리자면 "네트워크를 통한 송수신은 안타깝게도 무료가 아니므로" 2026년 10월 기준 유료 서비스입니다. Kimai의 유료 E-Invoice Plus 플러그인은 EN16931, XRechnung, ZUGFeRD, Factur-X 및 베타 버전의 Peppol을 지원하지만, Facturae나 FatturaPA는 지원하지 않습니다. InvoicePlane은 전자 청구서 훅(hook)을 가지고 있으나 핵심 기능에 포함된 형식은 없습니다. 프로젝트의 InvoicePlane-e-invoices 저장소에서 템플릿을 추가해야 하며, 여기에는 ZUGFeRD, Factur-X 및 UBL 예제가 포함되어 있습니다. ERPNext는 ALYF에서 제공하는 무료 GPL-3.0 eu_einvoice 앱을 통해 XRechnung, ZUGFeRD, Factur-X를 지원하지만, UBL이나 Peppol 없이 CII 형식만 지원합니다. InvoiceShelf는 기능 목록에 전자 청구서 형식을 명시하고 있지 않습니다. Invoice Ninja는 이 모든 기능을 내장한 유일한 솔루션이며, EU 내에서 청구서를 발행해야 한다면 이를 선택해야 하는 가장 강력한 이유입니다.
FAQ
Crater와 InvoiceShelf 중 무엇을 설치해야 합니까?
InvoiceShelf를 선택하십시오. 2026년 10월 10일 기준으로 Crater의 기본 브랜치에는 1329일 동안 커밋이 없었으며, InvoiceShelf의 마이그레이션 가이드에서도 Crater를 "이제는 버려진 프로젝트"라고 명시하고 있습니다. InvoiceShelf는 동일한 AGPL-3.0 라이선스와 데이터 모델을 사용하므로, 두 프로젝트 간의 전환은 재작성이 아닌 데이터베이스 마이그레이션 수준에서 가능합니다. 여전히 Crater를 추천하는 가이드는 해당 프로젝트가 중단되기 전에 작성된 것입니다.
Invoice Ninja를 비용 지불 없이 제 사업에 사용할 수 있습니까?
네, 가능합니다. 자가 호스팅하는 Invoice Ninja는 Elastic License 2.0에 따라 반복 청구서, 고객 포털, 결제 게이트웨이 등 모든 기능을 무료로 사용할 수 있습니다. 비용이 발생하는 경우는 두 가지입니다. 고객에게 노출되는 페이지에서 Invoice Ninja 브랜딩을 제거하려면 화이트 라벨 라이선스가 필요하며, 2026년 10월 기준 프로젝트 공식 안내에 따르면 "연간 $40"입니다. Peppol 네트워크를 통해 전자 청구서를 송수신하려면 동일한 라이선스와 함께 선불 전자 크레딧이 필요하며, 12개월간 500개 문서를 처리하는 데 $50부터 시작합니다. 라이선스에서 금지하는 것은 이 소프트웨어를 타인을 위한 호스팅 서비스로 운영하는 행위입니다.
청구서 이메일이 왜 스팸 메일함으로 들어갑니까?
거의 대부분 From 주소의 도메인에 대해 메시지 인증이 이루어지지 않았기 때문입니다. VPS에서 직접 발송하지 말고 SMTP 릴레이를 통해 발송하십시오. 그 후 해당 도메인에 대해 SPF 및 DMARC 레코드를 게시하고, 릴레이 업체가 제공하는 셀렉터에 맞춰 DKIM 레코드를 추가하십시오. From 주소에는 본인의 주소를 유지하고, Reply-To에 고객 주소를 넣으십시오. 고객의 주소를 발신자로 설정하면, 고객 도메인에 DMARC reject 정책이 게시되어 있을 경우 Gmail이 550 5.7.26 Unauthenticated email from example.com is not accepted due to domain's DMARC policy 오류와 함께 메시지를 거부합니다. 테스트 메시지의 Authentication-Results 헤더에서 dkim=pass 및 spf=pass 항목을 확인하여 수정 사항을 검증하십시오.
시간 단위로 청구할 경우 무엇을 선택해야 합니까?
Kimai를 선택하십시오. Kimai는 시간 추적 도구로 시작했기 때문에, 승인된 타임시트 항목을 기반으로 청구서가 생성되며 작업 내용이 항목별로 기록됩니다. 템플릿은 워드 프로세서에서 직접 디자인할 수 있는 DOCX, ODS 또는 XLSX 파일이므로 CSS를 수정하는 것보다 훨씬 간편합니다. 단, Kimai는 온라인 결제를 지원하지 않습니다. 무료 Customer Portal 플러그인을 사용하면 비밀 링크를 통해 타임시트와 프로젝트 통계를 공유할 수 있지만 청구서 공유는 불가능하므로, PDF를 이메일로 보내고 계좌 이체로 대금을 받아야 합니다. Invoice Ninja 역시 시간 추적 기능을 제공하며 카드 결제가 가능한 전체 청구서 포털을 갖추고 있으므로, 타임시트의 상세함보다 온라인 카드 결제가 더 중요하다면 Invoice Ninja를 선택하십시오.
정확히 무엇을 백업해야 합니까?
데이터베이스, 로고와 생성된 PDF가 저장된 스토리지 볼륨, 환경 파일, 그리고 일반 파일로 보관된 렌더링된 PDF입니다. 환경 파일은 사람들이 가장 자주 놓치는 부분입니다. Invoice Ninja나 InvoiceShelf와 같은 Laravel 애플리케이션은 저장된 자격 증명을 APP_KEY로 암호화하므로, 새로 생성된 키와 함께 데이터베이스를 복원하면 기존 결제 게이트웨이 설정을 읽을 수 없게 됩니다. 백업이 제대로 작동하는지 확인하는 유일한 방법은 임시 인스턴스에 전체를 복원한 뒤 이전 청구서를 열어보는 것뿐입니다.