feat(expense): 개인경비 모듈 + ERP 좌측메뉴 셸 + expense_db 연결
- ERP 셸: 좌측 사이드바 + 상단 헤더 + 콘텐츠 영역(erp_base.html)
- 분기: 슈퍼관리자 → 업무모듈 카드, 일반사용자 → ERP 메인(erp_home.html)
- 신규 라우트: /modules (슈퍼관리자 모듈 카드 재진입)
- 개인경비 모듈: app/modules/expense/ (라우터/저장소/템플릿)
- JSON 저장소(ExpenseStore) + PostgreSQL 저장소(ExpenseDBStore)
- 팩토리: EXPENSE_DB_URL 있으면 DB, 없으면 JSON 폴백
- DB: scripts/sql/expense_db_init.sql (멱등 DDL, postgres-db 컨테이너)
- expense_db, 역할 expense_app, 테이블 expense_items, 인덱스/트리거
- 마이그레이션: scripts/migrate_expense_json_to_db.py (멱등, --dry-run)
- 의존성: psycopg[binary,pool]>=3.2
- 환경변수: EXPENSE_DB_URL 추가
- 문서: CLAUDE.md 작업 기준 + docs/{PROJECT_OVERVIEW,SERVER_ARCHITECTURE,DATABASES,DEPLOYMENT}.md
- main-app 배포 경로 /opt/www/main 고정 명시
- 위험 명령(DROP/TRUNCATE/rm -rf/volume 삭제) 사용자 승인 정책
This commit is contained in:
@@ -0,0 +1,174 @@
|
||||
# Databases
|
||||
|
||||
## PostgreSQL DB 목록
|
||||
|
||||
| DB명 | 용도 |
|
||||
| --- | --- |
|
||||
| `itemcode_db` | 상품코드, 단품/세트 구성, 채널 ↔ 사내 코드 매칭 |
|
||||
| `orderlist_db` | 주문 수집·분석·관리 (구 `orderlist_app`) |
|
||||
| `return_db` | 반품·교환·CS 데이터 |
|
||||
| `expense_db` | 개인경비 / 법인카드 사용내역 / 정산 |
|
||||
|
||||
---
|
||||
|
||||
## 명명 규칙
|
||||
|
||||
- 모든 DB 이름은 **소문자 + 언더스코어**, **`_db`로 끝낸다**.
|
||||
- ✅ `inventory_db`, `cs_db`
|
||||
- ❌ `inventoryApp`, `cs-database`
|
||||
- 신규 DB가 필요하면 **사용자 승인 후** 생성한다.
|
||||
- 신규 DB 생성 시 함께 정리할 항목:
|
||||
- 용도와 책임 모듈
|
||||
- 소유자(OWNER) 계정
|
||||
- 백업 주기와 위치
|
||||
- `.env`의 연결 정보 변수명
|
||||
|
||||
---
|
||||
|
||||
## 레거시 이름 매핑
|
||||
|
||||
| 예전 이름 | 현재 기준 |
|
||||
| --- | --- |
|
||||
| `orderlist_app` | `orderlist_db` |
|
||||
|
||||
코드/문서/설정에서 `orderlist_app`을 발견하면 `orderlist_db`로 수정한다 (수정 전 영향 범위 확인).
|
||||
|
||||
---
|
||||
|
||||
## DB 작업 원칙
|
||||
|
||||
1. **작업 전 백업 우선**. 백업 없는 변경은 진행하지 않는다.
|
||||
2. 테이블 owner, 권한, sequence 권한을 확인한다.
|
||||
3. 운영 DB의 `DROP`, `TRUNCATE`, 조건 없는 대량 `DELETE/UPDATE`는 **사용자 확인 없이 실행 금지**.
|
||||
4. 스키마 변경은 마이그레이션 스크립트(`scripts/` 또는 alembic 등)로 관리한다.
|
||||
5. 운영 DB와 개발 DB의 접속 정보를 혼동하지 않는다 (`.env`로 분리).
|
||||
|
||||
---
|
||||
|
||||
## 위험 명령 (사용자 승인 필수)
|
||||
|
||||
| 명령 | 비고 |
|
||||
| --- | --- |
|
||||
| `DROP DATABASE` | 복구 불가. 백업 없으면 절대 실행 금지 |
|
||||
| `DROP TABLE` / `DROP SCHEMA` | 의존 객체 확인 필수 |
|
||||
| `TRUNCATE` | FK CASCADE 시 광범위 삭제 위험 |
|
||||
| 조건 없는 `DELETE` / `UPDATE` | `WHERE` 없는 문 차단 |
|
||||
| `docker volume rm <postgres_volume>` | 운영 데이터 영구 손실 |
|
||||
| `docker compose down -v` | 볼륨까지 제거. 운영에서 금지 |
|
||||
|
||||
실행 전 반드시:
|
||||
|
||||
1. 백업 확인 (`pg_dump`, 컨테이너 외부 마운트)
|
||||
2. 영향 범위 설명
|
||||
3. 사용자 명시 승인
|
||||
|
||||
---
|
||||
|
||||
## 자주 쓰는 점검 명령
|
||||
|
||||
```bash
|
||||
# 컨테이너/네트워크
|
||||
docker ps
|
||||
docker network ls
|
||||
docker inspect <postgres_container_name>
|
||||
|
||||
# DB 목록 / 접속
|
||||
sudo -u postgres psql -l
|
||||
docker exec -it <postgres_container_name> psql -U postgres -l
|
||||
|
||||
# 특정 DB 접속
|
||||
docker exec -it <postgres_container_name> psql -U <user> -d itemcode_db
|
||||
|
||||
# 테이블/권한 확인
|
||||
\dt
|
||||
\dn+
|
||||
\du
|
||||
\z <table_name>
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## expense_db 스키마 / 초기화
|
||||
|
||||
DDL: `scripts/sql/expense_db_init.sql` (멱등). DB·역할·테이블·인덱스·트리거를 한 번에 생성.
|
||||
|
||||
### 테이블 `expense_items`
|
||||
|
||||
| 컬럼 | 타입 | 비고 |
|
||||
| --- | --- | --- |
|
||||
| `id` | TEXT PK | 12자 hex (uuid4 앞 12자) |
|
||||
| `owner` | TEXT | 소유자 email (소문자) |
|
||||
| `spent_at` | DATE | 사용일 |
|
||||
| `category` | TEXT | 식대/교통/숙박/비품/접대/통신/기타 |
|
||||
| `method` | TEXT | 법인카드/개인지출/현금 |
|
||||
| `merchant` | TEXT | 가맹점 |
|
||||
| `amount` | BIGINT | 원 단위, ≥ 0 |
|
||||
| `memo` | TEXT | 비고 |
|
||||
| `status` | TEXT | 작성중/제출/승인/반려/정산완료 |
|
||||
| `created_at` / `updated_at` | TIMESTAMPTZ | 트리거로 자동 갱신 |
|
||||
|
||||
인덱스: `(owner, spent_at DESC)`, `(status)`, `(created_at DESC)`.
|
||||
|
||||
### 운영 서버 초기화 (1회)
|
||||
|
||||
```bash
|
||||
# 1) 비밀번호 변수 준비 (셸 히스토리에 남지 않게 환경변수 사용)
|
||||
read -s -p "expense_app password: " APP_PWD; echo
|
||||
|
||||
# 2) PostgreSQL 컨테이너에 DDL 적용
|
||||
docker exec -i postgres-db psql -U postgres \
|
||||
-v app_password="$APP_PWD" \
|
||||
< scripts/sql/expense_db_init.sql
|
||||
|
||||
# 3) main-app .env 에 EXPENSE_DB_URL 추가
|
||||
# EXPENSE_DB_URL=postgresql://expense_app:<APP_PWD>@postgres-db:5432/expense_db
|
||||
|
||||
# 4) main-app 재기동
|
||||
docker compose up -d --build
|
||||
```
|
||||
|
||||
### JSON → DB 마이그레이션
|
||||
|
||||
```bash
|
||||
docker exec -e EXPENSE_DB_URL="$EXPENSE_DB_URL" -it dbx-main \
|
||||
python scripts/migrate_expense_json_to_db.py \
|
||||
--json /data/expense.json --dry-run
|
||||
# 결과 확인 후
|
||||
docker exec -e EXPENSE_DB_URL="$EXPENSE_DB_URL" -it dbx-main \
|
||||
python scripts/migrate_expense_json_to_db.py --json /data/expense.json
|
||||
```
|
||||
|
||||
> 멱등 INSERT(`ON CONFLICT DO NOTHING`). 원본 JSON 은 건드리지 않는다.
|
||||
|
||||
---
|
||||
|
||||
## 백업 / 복구 (안전 절차)
|
||||
|
||||
### 백업
|
||||
|
||||
```bash
|
||||
# 단일 DB 덤프 (운영 권장)
|
||||
docker exec -t <postgres_container_name> \
|
||||
pg_dump -U <user> -F c -d orderlist_db \
|
||||
> /var/backups/postgres/orderlist_db_$(date +%F).dump
|
||||
```
|
||||
|
||||
### 복구 (덮어쓰기 위험 → 사용자 승인 필수)
|
||||
|
||||
```bash
|
||||
# 1) 신규 DB로 먼저 복구해 검증
|
||||
docker exec -i <postgres_container_name> \
|
||||
pg_restore -U <user> -d <new_db_name> < backup.dump
|
||||
|
||||
# 2) 검증 완료 후 운영 DB 교체 (필요 시)
|
||||
```
|
||||
|
||||
> `pg_restore --clean`은 기존 객체를 삭제한다. **운영 대상 DB에서 절대 무단 실행 금지**.
|
||||
|
||||
---
|
||||
|
||||
## .env 관련
|
||||
|
||||
- DB 접속 정보(`*_HOST`, `*_PORT`, `*_USER`, `*_PASSWORD`, `*_NAME`)는 모두 `.env`로 관리한다.
|
||||
- `.env`는 **Git에 올리지 않는다**. `.env.example`만 커밋한다.
|
||||
- 비밀값 유출이 의심되면 즉시 회전(비밀번호/키 변경)을 진행한다.
|
||||
@@ -0,0 +1,189 @@
|
||||
# Deployment
|
||||
|
||||
## 기본 배포 흐름
|
||||
|
||||
```text
|
||||
[Windows 개발 PC]
|
||||
│ git push (Gitea)
|
||||
▼
|
||||
[Gitea Repository]
|
||||
│ git pull (서버에서)
|
||||
▼
|
||||
[Ubuntu Server]
|
||||
│ .env 확인 → docker compose up --build -d
|
||||
▼
|
||||
[Docker]
|
||||
│ main-app, postgres 컨테이너 실행
|
||||
▼
|
||||
[NPM (Nginx Proxy Manager)]
|
||||
│ 외부 HTTPS 종단 → 내부 :80
|
||||
▼
|
||||
[서비스 정상 동작]
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 운영 서버 배포 경로
|
||||
|
||||
운영 서버는 Ubuntu Server. 동일 호스트에 여러 서비스가 있으므로 경로를 분리한다.
|
||||
|
||||
| 경로 | 용도 |
|
||||
| --- | --- |
|
||||
| **`/opt/www/main`** | **main-app (본 프로젝트) 배포 경로 — 기본** |
|
||||
| `/opt/dbx-corm` | CORM (CS/발주/반품/코드관리) 서비스 경로 |
|
||||
| `/opt/dbx-orderlist` | 주문관리/orderlist 서비스 경로 |
|
||||
|
||||
> main-app 관련 모든 명령/문서 작성 시 `/opt/www/main` 사용.
|
||||
> 새로운 경로가 필요하면 **사용자 지시**를 받은 뒤 결정한다.
|
||||
|
||||
---
|
||||
|
||||
## 사전 준비
|
||||
|
||||
- 서버에 Docker, Docker Compose 설치 완료
|
||||
- Gitea 접근 권한 있는 SSH/HTTPS 인증 설정 완료
|
||||
- NPM에 호스트 매핑 등록: `dbx.no1king.freeddns.org → http://192.168.0.194:80`
|
||||
- `.env` 값 확보 (Google OAuth, 세션 키, DB 비밀번호 등)
|
||||
|
||||
---
|
||||
|
||||
## 최초 배포
|
||||
|
||||
```bash
|
||||
# 1) main-app 배포 경로
|
||||
sudo mkdir -p /opt/www/main
|
||||
sudo chown $USER:$USER /opt/www/main
|
||||
cd /opt/www/main
|
||||
|
||||
# 2) 저장소 클론
|
||||
git clone https://gitea.no1king.freeddns.org/king/dbx-main.git .
|
||||
|
||||
# 3) 환경 변수 파일 준비
|
||||
cp .env.example .env
|
||||
nano .env # 실제 값으로 수정 (절대 Git에 커밋 금지)
|
||||
|
||||
# 4) 빌드 및 백그라운드 실행
|
||||
docker compose up --build -d
|
||||
|
||||
# 5) 로그 확인
|
||||
docker compose logs -f
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 업데이트 배포
|
||||
|
||||
```bash
|
||||
cd /opt/www/main
|
||||
git pull
|
||||
docker compose up --build -d
|
||||
docker compose logs -f --tail=200
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 컨테이너 관리
|
||||
|
||||
```bash
|
||||
docker compose ps # 상태 확인
|
||||
docker compose restart web # 단일 서비스 재시작
|
||||
docker compose stop # 중지 (볼륨 유지)
|
||||
docker compose down # 컨테이너 제거 (볼륨 유지)
|
||||
# docker compose down -v # ⚠ 볼륨까지 삭제. 운영에서 금지
|
||||
```
|
||||
|
||||
> `docker compose down -v`, `docker volume rm`, `docker system prune -a --volumes` 는 **사용자 승인 없이 실행 금지**.
|
||||
|
||||
---
|
||||
|
||||
## .env / 비밀값 관리
|
||||
|
||||
- `.env`, `.env.local`, `.env.production` 은 **절대 Git에 올리지 않는다**.
|
||||
- 예시 파일(`.env.example`)만 커밋한다.
|
||||
- 신규 변수 추가 시 `.env.example`과 본 문서를 함께 갱신한다.
|
||||
- 비밀값 유출 의심 시 즉시 회전(rotate)한다 (특히 `GOOGLE_CLIENT_SECRET`, `SESSION_SECRET_KEY`, DB 비밀번호).
|
||||
|
||||
### 주요 환경 변수
|
||||
|
||||
| 변수 | 설명 |
|
||||
| --- | --- |
|
||||
| `GOOGLE_CLIENT_ID` | Google OAuth 클라이언트 ID |
|
||||
| `GOOGLE_CLIENT_SECRET` | Google OAuth 클라이언트 보안 비밀 |
|
||||
| `SESSION_SECRET_KEY` | 세션 쿠키 서명용 랜덤 문자열 |
|
||||
| `SESSION_COOKIE_SECURE` | HTTPS 환경 `true` / 로컬 HTTP `false` |
|
||||
| `PUBLIC_BASE_URL` | 외부 접속 주소 (예: `https://dbx.no1king.freeddns.org`) |
|
||||
| `CS_ORDER_URL` | CS 발주 업무 버튼 이동 주소 |
|
||||
| `CUSTOMER_ORDER_LIST_URL` | 고객 주문리스트 프로그램 버튼 이동 주소 |
|
||||
| `*_DB_HOST`, `*_DB_USER`, `*_DB_PASSWORD`, `*_DB_NAME` | 각 PostgreSQL DB 접속 정보 |
|
||||
| `EXPENSE_DB_URL` | 개인경비 DB DSN (예: `postgresql://expense_app:<pwd>@postgres-db:5432/expense_db`). 미설정 시 JSON 폴백 |
|
||||
|
||||
---
|
||||
|
||||
## 로컬 Docker 테스트
|
||||
|
||||
```powershell
|
||||
# 1) 로컬 env 파일 준비
|
||||
copy .env.local.example .env.local
|
||||
# .env.local 을 열어 실제 값으로 수정
|
||||
|
||||
# 2) 이미지 빌드 및 실행
|
||||
docker compose -f docker-compose.local.yml up --build
|
||||
|
||||
# 3) 브라우저 확인
|
||||
# http://localhost:8080
|
||||
```
|
||||
|
||||
> 로컬 OAuth: Google Cloud Console 리디렉션 URI에 `http://localhost:8080/auth/google` 추가 필요.
|
||||
|
||||
---
|
||||
|
||||
## 복구 절차
|
||||
|
||||
### 컨테이너만 깨진 경우
|
||||
|
||||
```bash
|
||||
docker compose up --build -d
|
||||
docker compose logs -f
|
||||
```
|
||||
|
||||
### DB 데이터가 깨진 경우 (사용자 승인 필수)
|
||||
|
||||
1. 즉시 트래픽 차단 (NPM 비활성화 또는 점검 페이지)
|
||||
2. 가장 최근 백업 확인
|
||||
3. **새 DB 이름으로 먼저 복구**해 검증
|
||||
4. 검증 완료 후 운영 DB 교체
|
||||
5. 복구 후 로그/주문 정합성 점검
|
||||
|
||||
> 운영 DB에 직접 `pg_restore --clean`을 실행하지 않는다. `DATABASES.md` 참고.
|
||||
|
||||
---
|
||||
|
||||
## 위험 명령 (사용자 승인 없이 실행 금지)
|
||||
|
||||
| 명령 | 위험 |
|
||||
| --- | --- |
|
||||
| `rm -rf` | 파일/디렉터리 영구 삭제 |
|
||||
| `docker compose down -v` | 볼륨 포함 삭제 → DB 손실 |
|
||||
| `docker volume rm`, `docker volume prune` | 볼륨 영구 삭제 |
|
||||
| `docker system prune -a --volumes` | 이미지·네트워크·볼륨 일괄 삭제 |
|
||||
| `DROP DATABASE`, `DROP TABLE`, `TRUNCATE` | DB 파괴 (`DATABASES.md` 참고) |
|
||||
| `git reset --hard`, `git push --force`, `git clean -fd` | 작업 내역 손실 |
|
||||
| 운영 `.env` 덮어쓰기 / 삭제 | 인증·세션 붕괴 |
|
||||
|
||||
원칙:
|
||||
|
||||
1. 실행 전 현재 상태 확인 명령을 먼저 보여준다.
|
||||
2. 백업 위치를 명시한다.
|
||||
3. 사용자 명시 승인 후에만 실행한다.
|
||||
|
||||
---
|
||||
|
||||
## 점검 체크리스트
|
||||
|
||||
- [ ] `docker compose ps` 모든 서비스 `running`
|
||||
- [ ] `docker compose logs --tail=200` 에러 없음
|
||||
- [ ] `https://dbx.no1king.freeddns.org` 200 응답
|
||||
- [ ] Google 로그인 정상 동작
|
||||
- [ ] PostgreSQL 컨테이너 볼륨 마운트 정상
|
||||
- [ ] 최근 DB 백업 존재 여부
|
||||
- [ ] `.env` 미커밋 상태 (`git status`로 확인)
|
||||
@@ -0,0 +1,117 @@
|
||||
# Project Overview
|
||||
|
||||
## 한 줄 정의
|
||||
|
||||
`main-app`은 DBX ERP 시스템의 **메인 프로젝트(허브)** 이다.
|
||||
주문 수집부터 상품코드 매칭, 재고, CS, 반품, 외부 쇼핑몰 API 연동까지 ERP 운영 전체를 담당한다.
|
||||
|
||||
---
|
||||
|
||||
## 기능 범위
|
||||
|
||||
| 모듈 | 설명 |
|
||||
| --- | --- |
|
||||
| 주문관리 | 다채널 주문 수집·통합, 상태 추적, 분석 |
|
||||
| 상품코드 매칭 | 채널별 상품코드 ↔ 사내 표준 상품코드 매핑, 단품/세트 구성 |
|
||||
| 재고관리 | 입고/출고/재고 조정, 채널별 재고 동기화 |
|
||||
| CS관리 | 문의/응대 이력, 발주 업무 트리거 |
|
||||
| 반품관리 | 반품/교환 접수, 처리, 환불 연계 |
|
||||
| 외부 연동 | 쇼핑몰·통합관리·택배사·문자 API 연동 |
|
||||
| 개인경비 | 법인카드/개인지출 등록·증빙·정산 신청 (`app/modules/expense/`) |
|
||||
| 휴가 (준비중) | 연차/반차/특별휴가 신청·잔여일수 관리 |
|
||||
|
||||
---
|
||||
|
||||
## 모듈 디렉토리 규약
|
||||
|
||||
신규 업무 모듈은 **별도 디렉토리 한 곳**에 라우터·저장소·템플릿을 모은다.
|
||||
|
||||
```
|
||||
app/modules/<name>/
|
||||
├─ __init__.py # router export
|
||||
├─ router.py # FastAPI APIRouter (prefix=/<name>)
|
||||
├─ store.py # 데이터 저장소 (JSON → 향후 <name>_db)
|
||||
└─ templates/<name>/ # Jinja 템플릿 (ChoiceLoader 로 검색)
|
||||
```
|
||||
|
||||
신규 모듈 등록 시 `app/main.py` 의:
|
||||
|
||||
1. `_MODULE_TEMPLATE_DIRS` 에 템플릿 경로 추가
|
||||
2. `app.include_router(<name>_router)` 추가
|
||||
3. `app.state.<name>_store = ...` 등 상태 등록
|
||||
4. `MODULE_KEYS` (`app/store.py`) 와 `_menu_items_for()` 메뉴 항목 동기화
|
||||
|
||||
---
|
||||
|
||||
## 외부 연동 대상
|
||||
|
||||
- **쇼핑몰**: 카페24, 네이버 스마트스토어
|
||||
- **통합 관리**: 사방넷
|
||||
- **물류**: CJ대한통운(CJ Logistics) 외 택배사 API
|
||||
- **알림**: 문자 발송 API
|
||||
- **인증**: Google OAuth (Google Workspace 계정 기반)
|
||||
|
||||
---
|
||||
|
||||
## 기술 스택
|
||||
|
||||
| 영역 | 사용 기술 |
|
||||
| --- | --- |
|
||||
| Backend | Python, FastAPI |
|
||||
| DB | PostgreSQL (Docker 컨테이너) |
|
||||
| 컨테이너 | Docker, Docker Compose |
|
||||
| Reverse Proxy | Nginx Proxy Manager (NPM) |
|
||||
| OS | Ubuntu Server (Proxmox VM) |
|
||||
| 인증 | Google OAuth + 화이트리스트 |
|
||||
| 저장소 | Gitea (self-hosted) |
|
||||
|
||||
---
|
||||
|
||||
## 관련 DB
|
||||
|
||||
| DB명 | 용도 |
|
||||
| --- | --- |
|
||||
| `itemcode_db` | 상품코드, 단품/세트 구성, 매칭 정보 |
|
||||
| `orderlist_db` | 주문 수집·분석·관리 (구 `orderlist_app`) |
|
||||
| `return_db` | 반품·교환·CS 데이터 |
|
||||
| `expense_db` | 개인경비 / 법인카드 / 정산 (`EXPENSE_DB_URL` 미설정 시 JSON 폴백) |
|
||||
|
||||
### DB 후보
|
||||
|
||||
| 모듈 | 현재 저장소 | 비고 |
|
||||
| --- | --- | --- |
|
||||
| 휴가 | (미개발) | `vacation_db` (승인 후 생성) |
|
||||
|
||||
> 신규 DB가 필요하면 **승인 요청 후** 생성하며, 이름은 `_db`로 끝낸다. 상세는 `DATABASES.md`.
|
||||
|
||||
---
|
||||
|
||||
## 접속/도메인
|
||||
|
||||
| 환경 | 주소 |
|
||||
| --- | --- |
|
||||
| 운영 | `https://dbx.no1king.freeddns.org` |
|
||||
| 로컬 | `http://localhost:8080` |
|
||||
| Git 저장소 | `https://gitea.no1king.freeddns.org/king/dbx-main.git` |
|
||||
|
||||
---
|
||||
|
||||
## 허용 사용자 (서버 측 화이트리스트)
|
||||
|
||||
`app/main.py`의 `ALLOWED_EMAILS`에서 검사한다.
|
||||
|
||||
- king@dbxcorp.co.kr
|
||||
- julie@dbxcorp.co.kr
|
||||
- ellen@dbxcorp.co.kr
|
||||
- bj@dbxcorp.co.kr
|
||||
|
||||
Google `hd=dbxcorp.co.kr` 힌트는 클라이언트 편의용이며, **실제 권한 검사는 항상 서버 측**에서 수행한다.
|
||||
|
||||
---
|
||||
|
||||
## 작업 우선순위 / 원칙
|
||||
|
||||
1. 운영 데이터 안전이 최우선. 위험 명령은 사용자 승인 후 실행.
|
||||
2. 신규 기능보다 기존 데이터 일관성 유지 우선.
|
||||
3. 외부 API 연동은 실패 재시도와 로깅을 기본으로 한다.
|
||||
4. 비밀값은 `.env`로만 관리하고 Git에 절대 올리지 않는다.
|
||||
@@ -0,0 +1,90 @@
|
||||
# Server Architecture
|
||||
|
||||
## 전체 구성도
|
||||
|
||||
```text
|
||||
[Windows 개발 PC]
|
||||
│ Git push / 파일 수정
|
||||
▼
|
||||
[Gitea Repository] (https://gitea.no1king.freeddns.org/king/dbx-main.git)
|
||||
│ git pull
|
||||
▼
|
||||
[Ubuntu Server / Proxmox VM]
|
||||
│
|
||||
├─ Nginx Proxy Manager (NPM)
|
||||
│ dbx.no1king.freeddns.org → http://192.168.0.194:80
|
||||
│
|
||||
├─ Docker
|
||||
│ ├─ main-app 컨테이너 (FastAPI / Uvicorn)
|
||||
│ ├─ PostgreSQL 컨테이너
|
||||
│ └─ 기타 부속 컨테이너
|
||||
│
|
||||
└─ PostgreSQL Databases
|
||||
├─ itemcode_db
|
||||
├─ orderlist_db
|
||||
└─ return_db
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 요청 흐름
|
||||
|
||||
1. 사용자 브라우저 → `https://dbx.no1king.freeddns.org`
|
||||
2. NPM(외부 HTTPS) → 내부 HTTP `192.168.0.194:80`
|
||||
3. 서버 내부 Nginx/Compose 포워딩 → `main-app` 컨테이너 (FastAPI)
|
||||
4. FastAPI → PostgreSQL 컨테이너(같은 Docker 네트워크) 또는 외부 쇼핑몰/택배 API
|
||||
|
||||
---
|
||||
|
||||
## 구성요소
|
||||
|
||||
| 구성요소 | 설명 |
|
||||
| --- | --- |
|
||||
| **Ubuntu Server** | 호스트 OS. 도커 호스트. systemd로 docker.service 관리 |
|
||||
| **Docker** | 모든 앱·DB는 컨테이너로 운영. Compose 파일 단위 배포 |
|
||||
| **PostgreSQL** | Docker 컨테이너에서 운영. 데이터는 named volume |
|
||||
| **Nginx Proxy Manager** | 외부 HTTPS 종단, 인증서 자동 갱신, 호스트명 라우팅 |
|
||||
| **FastAPI (main-app)** | 메인 ERP 백엔드. 인증·라우팅·외부 API 연동 |
|
||||
| **Gitea** | 소스 저장소(사내 호스팅) |
|
||||
|
||||
---
|
||||
|
||||
## 네트워크 / 포트
|
||||
|
||||
| 항목 | 값 |
|
||||
| --- | --- |
|
||||
| 외부 도메인 | `dbx.no1king.freeddns.org` (HTTPS, NPM 종단) |
|
||||
| 내부 호스트 | `192.168.0.194` |
|
||||
| 내부 노출 포트 | `80` (NPM → 컨테이너) |
|
||||
| 로컬 개발 포트 | `8080` |
|
||||
| PostgreSQL | Docker 내부 네트워크에서만 접근 (호스트 노출 금지 권장) |
|
||||
|
||||
---
|
||||
|
||||
## 배포 경로
|
||||
|
||||
운영 서버 기준, 아래 중 하나에 클론한다. 상세는 `DEPLOYMENT.md`.
|
||||
|
||||
- `/opt/dbx-corm`
|
||||
- `/opt/dbx-orderlist`
|
||||
- `/opt/www/main`
|
||||
|
||||
> 같은 호스트에 여러 서비스를 운영하므로, 경로는 서비스별로 분리한다.
|
||||
|
||||
---
|
||||
|
||||
## 인증 흐름
|
||||
|
||||
1. 사용자가 `/auth/google` 진입 → Google OAuth 동의 화면
|
||||
2. 콜백에서 `id_token` 검증 (`hd=dbxcorp.co.kr` 힌트는 참고용)
|
||||
3. 서버에서 이메일 도메인 + `ALLOWED_EMAILS` 화이트리스트 검사
|
||||
4. 통과 시 세션 쿠키 발급(`SESSION_SECRET_KEY` 서명)
|
||||
|
||||
---
|
||||
|
||||
## 운영 시 점검 포인트
|
||||
|
||||
- NPM 호스트 매핑이 살아있는가 (`dbx.no1king.freeddns.org → 192.168.0.194:80`)
|
||||
- `docker compose ps`로 `main-app`, `postgres` 컨테이너 상태
|
||||
- PostgreSQL volume 마운트 경로와 백업 위치
|
||||
- `.env` 값 유실 여부 (특히 `GOOGLE_CLIENT_*`, `SESSION_SECRET_KEY`)
|
||||
Reference in New Issue
Block a user