사내 문서관리 시스템 (DocuFlow) 서버 운영 및 유지보수 매뉴얼
사내 리눅스 서버(Ubuntu) 환경에서 구동 중인 견적요청서, 발주서 작성기 및 구매 영수증·거래명세서 자동인식(OCR) 전산 관리 시스템의 구조, 신규 구축, 일상 운영 명령어, 백업 및 장애 대응 요령을 기술합니다.
시스템 개요 및 운영 아키텍처
DocuFlow (견적/발주서 작성 + 구매 영수증·거래명세서 OCR 관리)
http://fileserver.countec-pnf.com:8080/ (영수증: /receipts)
Ubuntu Server / /var/www/docuflow/
PM2 (docuflow) / 우분투 로컬 JSON DB (server_db.json) / Tesseract OCR (kor+eng)
주식회사 피앤에프소프트젤
585-87-01568 (대표자: 이종호)
[사내 사용자 브라우저 (PC / 모바일)]
│
▼ (HTTP 포트 8080)
[Node.js Express 백엔드 (server.js)] ◄───► [프론트엔드 단일 웹 앱 (public/index.html & receipts.html)]
│
├── 하이웍스 SSO 토큰 검증 및 로그인 리다이렉트 (/auth/hiworks/sso)
├── 견적/발주서 REST API (/api/documents, /api/partners, /api/senders, /api/guests)
├── Tesseract OCR 한국어 이미지 판독 파이프라인 (/api/ocr)
├── 영수증·거래명세서 전산 원장 API (/api/receipts)
├── Paperless-ngx 문서 연동 (영수증 등록 시 자동 업로드, 다운로드 우선 제공, 삭제 동기화)
└── 엑셀 대량 벌크 등록 엔드포인트 (/api/partners/bulk, /api/senders/bulk)
▼
[사내서버 로컬 영구 스토리지]
├─ 메타데이터 DB: /var/www/docuflow/server_db.json
├─ 스캔 PDF 물리 저장소: /var/www/docuflow/storage/receipts/
└─ Paperless 문서 저장소: ~/paperless-office/ (동일 서버 Docker, 내부 포트 8000 · 외부 미개방)
신규 서버 설치 및 환경 구성 (Server Provisioning)
새로운 우분투 서버나 초기화된 리눅스 환경에서 DocuFlow 시스템 및 OCR 엔진을 밑바닥부터 배포할 때 사용하는 표준 셋업 절차입니다.
1 시스템 패키지 갱신 및 Node.js 20 LTS 설치
# 1. 패키지 저장소 최신화
sudo apt update && sudo apt upgrade -y
# 2. Node.js 20.x LTS 저장소 등록 및 설치
curl -fsSL https://deb.nodesource.com/setup_20.x | sudo -E bash -
sudo apt install -y nodejs build-essential
# 3. 설치 확인 (v20.x 확인)
node -v && npm -v
# 4. 무중단 프로세스 관리자 PM2 전역 설치
sudo npm install -g pm2
2 서비스 디렉터리 생성 및 일반 계정 소유권 부여
# 전용 폴더 및 정적 파일 폴더 생성
sudo mkdir -p /var/www/docuflow/public
# 현재 로그인 계정($USER)에 소유권 부여 (sudo 없이 관리 가능)
sudo chown -R $USER:$USER /var/www/docuflow
cd /var/www/docuflow
3 Node.js 핵심 의존성 및 Tesseract 한국어 OCR 엔진 설치
# 1. Node.js 핵심 모듈 설치
cd /var/www/docuflow
npm init -y
npm install express axios cookie-parser
# 2. [필수] 복합기 스캔 이미지 OCR 판독용 Tesseract 및 한국어 언어팩 설치
sudo apt update && sudo apt install -y tesseract-ocr tesseract-ocr-kor
# 3. OCR 지원 언어 확인 (kor, eng 표시 확인)
tesseract --list-langs
# 4. 영수증 PDF 파일 물리 보관소 생성
mkdir -p /var/www/docuflow/storage/receipts
4 방화벽 8080 개방 및 PM2 부팅 자동 등록
# 1. 8080 TCP 포트 방화벽 허용
sudo ufw allow 8080/tcp
sudo ufw reload
# 2. PM2로 서버 가동 및 부팅 등록
cd /var/www/docuflow
pm2 start server.js --name "docuflow"
pm2 save
pm2 startup
파일 및 디렉터리 구성
| 절대 경로 | 파일명 | 역할 및 설명 |
|---|---|---|
| /var/www/docuflow/ | server.js | Express 백엔드 서버. REST API, 하이웍스 SSO 인증, DB 입출력 및 Tesseract OCR 판독 전담 |
| /var/www/docuflow/ | server_db.json | 견적/발주서, 거래처, 담당자, 사원 프로필 및 영수증 메타데이터 영구 보관 DB (핵심 백업 대상) |
| /var/www/docuflow/storage/receipts/ | 업로드된 스캔 영수증 원본 PDF 물리 파일 보관소 (백업 대상) | |
| /var/www/docuflow/ | package.json | Node.js 프로젝트 의존성 라이브러리 명세 |
| /var/www/docuflow/public/ | index.html | 견적요청서 및 발주서 작성 단일 웹 애플리케이션 |
| /var/www/docuflow/public/ | receipts.html | 거래명세서 및 영수증 전산 관리 전용 웹 애플리케이션 (접속: /receipts) |
| /var/www/docuflow/public/ | manual.html | 시스템 종합 운영 및 유지보수 웹 매뉴얼 페이지 |
| /var/www/docuflow/public/ | receipts_manual.html | 영수증 및 거래명세서 관리 전용 현장 실무 상세 매뉴얼 (접속: /receipts_manual.html) |
| /var/www/docuflow/storage/ | stamp.png | 회사 직인 이미지. 공개 폴더에서 분리되어 인증된 세션으로만 제공됨 (2026-10-23 보안 적용) |
| /home/freebabo28/ | .docuflow_session_secret / .docuflow_paperless_token | 세션 서명 비밀키 / Paperless API 토큰 (권한 600, 값 외부 공유 금지) |
| /home/freebabo28/paperless-office/ | docker-compose.yml 등 | Paperless-ngx v3.3.4 문서관리 (webserver·PostgreSQL·Redis). 영수증 문서 보관·OCR·검색 담당, 내부 포트 8000 |
핵심 반영 사항 및 문제 해결 이력
자사 상호명을 구버전 표기(`피앤에프소프트젤`)에서 `주식회사 피앤에프소프트젤`로 전면 통일하고, 브라우저 캐시나 DB에 남아있던 예전 상호명 데이터를 자동으로 새 상호명으로 치환하는 마이그레이션 로직 탑재.
2026-10-23 통합 보안 적용: 하이웍스가 넘긴 토큰을 서버가 공식 조회 API(link-api.hiworks.com)로 직접 검증하는 방식으로 교체(토큰 없거나 검증 실패 시 세션 미발급). 로그인 세션은 HMAC 서명 쿠키(httpOnly)로 발급되며, 모든 /api/*는 로그인 없이는 401로 차단됩니다. 회사 직인 이미지도 인증된 세션에만 제공되고, 보안 헤더(nosniff 등)와 DB 일일 자동 백업(03:30)이 함께 적용되었습니다.
수신(공급업체) 테이블의 불필요한 직위/부서 행을 제거하고 `담당자(직위 포함)`로 통합. 맨 아래에 `비고` 행을 추가하여 좌우 높이를 7행으로 완벽 일치시키고 거래처 DB와 실시간 동기화.
삭제 버튼 클릭 시 즉시 지워지던 위험을 방지하기 위해 2차 확인 모달(`z-[60]`) 추가 및 브라우저 캐시 누락에 대비한 **자가 치유(Self-Healing) 동적 모달 주입 로직** 내장.
상세 모델명이나 긴 스펙 입력 시 텍스트가 잘려 보이던 현상을 해결하기 위해 단일행 `input`을 자동 확장형 `textarea`로 교체하였습니다. 내용 길이에 맞춰 칸 높이가 실시간으로 늘어나며, 출력/PDF 저장 시(`@media print`)에도 내용이 잘리지 않고 온전히 출력되도록 스타일을 최적화했습니다.
품목 테이블 본문 행의 불필요한 '세액' 열을 제거하여 품목명/규격 공간을 넓게 확보하였습니다. 상단 `[부가세(10%) 계산]` 토글 기능은 온전히 유지되며, 하단 집계 영역(공급가액 소계 / 부가가치세 10% / 총 합계 금액)에서 일괄 계산·표시되도록 공문서 표준 서식으로 정돈되었습니다.
종이 거래명세서와 카드 영수증의 분실 방지 및 단가 이력 조회를 위해 독립된 영수증 전산 관리 시스템이 구축되었습니다.
복합기 스캔본 업로드 시 1차 SHA-256 해시 중복 차단 ➔ 2차 사내 서버 Tesseract OCR 한국어 분석 ➔ 3차 원본 대조 검수 모달을 거쳐 {YYMMDD}_{업체명}.pdf로 자동 리네이밍되어 사내 서버에 영구 보관됩니다.
원장 테이블은 1개 영수증의 다중 품목을 각각 1줄씩 행 분리(Row Splitting)하여 수량·단가·금액을 명확히 대조하며, 엑셀 일괄 다운로드 및 한글 파일명 원본 다운로드를 완벽 지원합니다.
(상세 사용법은 영수증 전용 운영 매뉴얼 참조)
하이웍스 계정이 없는 외주 인력·임시 사용자를 위한 게스트 로그인 기능입니다. 웹에서의 자가 회원가입은 차단된 상태이며, 계정 발급·수정은 로그인한 사용자가 상단 [게스트 관리] 버튼 → 게스트 계정 통합 관리 모달에서 직접 수행합니다. 게스트는 로그인하면 직원과 동일하게 전 기능을 사용할 수 있고(권한 구분 없음), 세션 유지 시간만 12시간으로 짧습니다.
- 신규 등록: [신규 등록] → 아이디·비밀번호·표시 이름·직위·부서·연락처·이메일 입력 후 [서버에 저장]
- 수정: 목록에서 계정 선택 후 정보 수정. 비밀번호 칸을 비워 두면 기존 비밀번호가 유지됩니다.
- 삭제: [삭제] 버튼 → 확인 후 즉시 삭제되며 해당 계정으로 로그인할 수 없게 됩니다.
- 보관 방식: 비밀번호는 평문이 아닌 scrypt 해시로
server_db.json의guests배열에 저장됩니다. DB 파일을 직접 편집해 평문 비밀번호를 넣는 구 방식은 동작하지 않으니 반드시 관리 화면을 이용하십시오. - 표시 수정 (2026-10-24): 게스트 로그인 직후 직인·거래처 리스트·담당자 프로필이 표시되지 않던 문제를 수정했습니다 (로그인 성공 시 데이터·직인을 다시 불러옴).
좌측: DocuFlow 로고 → 로그인 정보 배지 → 새 문서·문서 보관함·견적요청서·발주서(PO)·서버에 저장 / 우측: 영수증 관리·거래처 관리·담당자 관리·게스트 관리·운영 매뉴얼·예시·출력 순으로 재배치하고, 모든 버튼 높이를 30px로 통일했습니다. 기존 로그아웃 버튼은 제거되어, 계정 전환은 세션 만료(게스트 12시간·직원 365일) 또는 브라우저 쿠키 삭제 시 가능합니다.
동일 서버에 Paperless-ngx를 구축해 영수증을 이중 보관합니다. 신규 등록 시 자동 업로드되어 거래처·날짜·합계와 함께 분류되고 자체 OCR(한+영)로 전문 검색이 가능하며, 다운로드는 Paperless를 우선 제공하고 삭제도 양쪽 동기화됩니다. 기존 영수증 397건도 전량 이전 완료했습니다. (작동 방식 상세는 영수증 매뉴얼 §8 참조)
일상 서버 운영 및 관리 명령어
모든 유지보수 작업은 우분투 터미널(SSH)에서 수행합니다.
# 프로세스 상태 확인 (online 확인)
pm2 status
# 최근 30줄 실시간 로그 및 에러 패킷 모니터링
pm2 logs docuflow --lines 30
# 누적 로그 비우기
pm2 flush
# 서비스 재시작
pm2 restart docuflow
# Node.js 구문 문법 오류 사전 검사 (오류 없을 시 아무 출력 없음)
node -c /var/www/docuflow/server.js
데이터 백업 및 복구 상세 가이드
DocuFlow는 메타데이터 DB(server_db.json)와 업로드된 스캔 영수증 PDF 저장소(/storage/receipts/)의 2원 체계로 안전하게 보관됩니다.
/var/www/docuflow/server_db.json
/var/www/docuflow/storage/receipts/
문서 보관함, 거래처 50여 곳, 담당자 프로필, 그리고 업로드된 영수증 스캔 원본 PDF가 저장되는 핵심 자산입니다.
/var/backup/docuflow/
웹 서비스 폴더와 물리적으로 분리된 백업 전용 폴더에 보관하여 실수로 인한 덮어쓰기나 삭제를 원천 방지합니다.
수동 즉시 + 자정 Cron + 오프사이트
점검 전 즉시 스냅샷, 자정 자동 백업(30일 보관), 주간 단위 사내 관리자 PC 다운로드 3중 보호를 권장합니다.
server_db.json을 ~/docuflow-backups/daily/server_db-YYYYMMDD.json으로 복사하고 14일 지난 파일은 자동 삭제합니다. 아래의 수동·오프사이트 백업 절차와 병행됩니다.
1 작업 전 즉시 수동 백업 (Manual Snapshot) 코드 수정 및 서버 점검 직전 필수 수행
서버 코드를 수정하거나 대량의 거래처 엑셀 파일을 일괄 업로드하기 전, 현재 시점의 타임스탬프(초 단위)를 붙여 DB와 영수증 파일을 즉시 백업합니다.
# 1. 백업 폴더가 없는 경우 최초 1회 생성
sudo mkdir -p /var/backup/docuflow
sudo chown -R $USER:$USER /var/backup/docuflow
# 2. 메타데이터 DB 즉시 스냅샷 복사
cp /var/www/docuflow/server_db.json /var/backup/docuflow/server_db_manual_$(date +%Y%m%d_%H%M%S).json
# 3. 영수증 원본 PDF 저장소 동기화 백업
rsync -av /var/www/docuflow/storage/receipts/ /var/backup/docuflow/receipts_backup/
# 4. 백업 파일 생성 및 정상 여부 확인
ls -lh /var/backup/docuflow/
2 매일 자정 자동 스냅샷 및 30일 경과 백업 자동 정리 (Crontab) 자동 무인 운영
우분투 스케줄러(Cron)를 이용해 매일 자정(00:00)에 그날의 DB를 스냅샷으로 저장하고 영수증 PDF를 백업하며, **30일이 지난 오래된 백업본은 자동으로 영구 삭제**합니다.
# 1. 현재 계정의 크론탭 편집기 열기
crontab -e
# 2. 크론탭 파일의 맨 아래 줄에 다음 내용 추가 및 저장:
# [1] 매일 자정(00:00) DB 스냅샷 생성 & 영수증 PDF 증분 백업
0 0 * * * cp /var/www/docuflow/server_db.json /var/backup/docuflow/server_db_$(date +\%Y\%m\%d).json 2>/dev/null && rsync -a /var/www/docuflow/storage/receipts/ /var/backup/docuflow/receipts_archive/
# [2] 매일 새벽 1시(01:00) 30일 지난 DB 백업 자동 제거
0 1 * * * find /var/backup/docuflow/ -name "server_db_*.json" -mtime +30 -delete
# 3. 등록된 크론 작업 확인
crontab -l
3 장애/실수 발생 시 특정 시점 데이터 복구 (Disaster Recovery)
긴급 복구실수로 거래처를 일괄 삭제했거나, 잘못된 문서 덮어쓰기 등으로 데이터가 손상된 경우 과거 백업본으로 안전하게 롤백(Rollback)하는 표준 4단계 절차입니다.
# [STEP 1] DB 쓰기 충돌 방지를 위해 PM2 서비스 잠시 중지
pm2 stop docuflow
# [STEP 2] 만약을 위해 현재 상태의 손상된 DB도 격리 백업
cd /var/www/docuflow
mv server_db.json server_db_broken_$(date +%Y%m%d_%H%M%S).json
# [STEP 3] 정상 작동하던 시점(예: 20260913 백업본)을 원본 파일명으로 복사
cp /var/backup/docuflow/server_db_20260913.json /var/www/docuflow/server_db.json
# [STEP 4] JSON 유효성(문법) 검사 후 서비스 재시작
node -e "JSON.parse(require('fs').readFileSync('server_db.json'))" && echo "DB 문법 정상"
pm2 restart docuflow
# [STEP 5] 브라우저(F5)에서 문서 보관함 및 거래처 목록 정상 복원 확인
4 원격 PC로 DB 파일 다운로드 보관 (Off-site 2차 백업) 서버 하드디스크 고장 대비
서버 물리 디스크 고장이나 화재·정전 등 하드웨어 전손에 대비해, 관리자 개인 PC(Windows/Mac)로 DB 파일을 주 1회 안전하게 다운로드받아 보관하는 방법입니다.
# 관리자 Windows PC의 명령 프롬프트(CMD) 또는 PowerShell에서 실행 (SSH 포트 기본 22)
scp freebabo28@fileserver.countec-pnf.com:/var/www/docuflow/server_db.json C:\Users\사용자명\Desktop\docuflow_db_backup.json
# 또는 사내 내부 IP로 직접 다운로드 시:
scp freebabo28@192.168.0.xxx:/var/www/docuflow/server_db.json C:\Users\사용자명\Desktop\docuflow_db_backup.json
서버 재부팅 및 장애 발생 시 조치 요령 (FAQ)
Q1. 서버 전원이 꺼졌다 켜진 뒤 웹페이지에 접속되지 않을 때
원인: 우분투 서버 재부팅 시 PM2 데몬의 자동 실행 등록이 누락되었을 수 있습니다.
cd /var/www/docuflow
pm2 start server.js --name "docuflow"
pm2 startup
pm2 save
Q2. 8080 포트가 충돌하거나 바인딩 에러(EADDRINUSE)가 발생할 때
조치: 포트를 점유하고 있는 이전 고스트 프로세스를 강제 종료하고 재시작합니다.
sudo fuser -k 8080/tcp
pm2 restart docuflow
Q3. 코드를 수정했는데 브라우저에 예전 화면이 계속 뜰 때
브라우저가 이전 정적 캐시를 보관하고 있는 경우입니다. 브라우저에서 Ctrl + Shift + R 또는 Ctrl + F5를 눌러 캐시를 비우고 강력 새로고침을 수행하세요.