- Python 47.5%
- JavaScript 28.9%
- HTML 20.3%
- CSS 2.8%
- Dockerfile 0.5%
| Filename | Latest commit message | Latest commit date |
|---|---|---|
- 더보기/접기 버튼 전용 너비 스타일(80px, center)을 button.toggle-shop-detail로 한정 - 매장명 영역 클래스를 분리하여 text-start 및 text-align: left, justify-content: flex-start 강제 적용 |
||
| app | ||
| build | ||
| conf | ||
| lib | ||
| scripts | ||
| .dockerignore | ||
| .env.example | ||
| .gitignore | ||
| CHANGELOG.md | ||
| daily_run.py | ||
| DEVELOPMENT.md | ||
| docker-compose.yml | ||
| README.md | ||
| README.md.old | ||
| requirements.txt | ||
| static.code-workspace | ||
First Garden 방문통계 분석 서비스 (Static Analysis Service)
퍼스트가든 방문객 데이터 자동 수집, DB 저장, 시계열 예측 분석 서비스
🚀 주요 기능
1. 자동 데이터 수집
- 기상청 ASOS 데이터: 일별 기온, 강수량, 습도 등 수집
- Google Analytics 4: 웹 방문자 데이터 수집 및 분석
- 대기환경 정보: 미세먼지(PM2.5) 등 대기질 데이터 수집
2. 웹 기반 파일 업로드 (포트 8889)
- 드래그 앤 드롭 파일 업로드: 직관적인 파일 선택 및 업로드
- 다중 파일 지원: 여러 POS 데이터 파일 일괄 처리
- 파일 형식 지원:
- OKPOS: 일자별 상품별, 영수증별매출상세현황 파일
- UPSOLUTION: POS 데이터 파일
- 실시간 상태 모니터링: 업로드, 검증, DB 저장 진행 상황 확인
- 데이터베이스 백업/복구: 웹 인터페이스의 별도 DB 백업 및 복구 영역에서 관리
3. 데이터베이스 관리
- MariaDB/MySQL 기반 데이터 적재
- 자동 중복 제거 및 데이터 검증
- 스케줄 기반 자동 업데이트 (매일 오전 10:31 KST)
- 웹 인터페이스를 통한 백업 및 복구
4. 방문객 예측 분석
- Prophet 시계열 모델: 장기 추세 및 계절성 반영
- 다중 외부 변수: 기상, 대기질, 휴일 정보 포함
- 신뢰도 구간: 상한/하한 예측값 제공
5. 컨테이너화 지원
- Docker & Docker Compose 완전 지원
- 모든 플랫폼(Linux, macOS, Windows)에서 실행 가능
- 헬스체크 및 자동 재시작 기능
- 실제 볼륨 마운트 (바인드 마운트) 지원
📋 사전 요구사항
로컬 실행
- Python 3.11 이상
- MariaDB 10.4 이상 또는 MySQL 5.7 이상
- pip (Python 패키지 관리자)
Docker 실행
- Docker 20.10 이상
- Docker Compose 1.29 이상
⚙️ 설치 및 설정
1. 저장소 클론
git clone https://git.siane.kr/firstgarden/static.git
cd static
2. 환경 변수 설정
# .env 파일 생성 (템플릿 복사)
cp .env.example .env
# .env 파일 편집
nano .env
.env 주요 변수:
# Database Configuration
DB_HOST=localhost
DB_PORT=3306
DB_NAME=firstgarden
DB_USER=firstgarden
DB_PASSWORD=your_secure_password
# API Keys (필수)
# service-account-credentials.json 경로는 .secret/ 디렉토리에 저장
# Timezone
TZ=Asia/Seoul
.env 값의 공백 뒤 #부터는 인라인 주석으로 처리됩니다. 값 자체에 #을
포함하려면 공백 없이 작성합니다.
DB_PORT=3306 # 실제 값은 3306
DB_PASSWORD=secret#fragment # 실제 값은 secret#fragment
호스트에서 Python 스크립트를 직접 실행할 때는 DB_HOST=localhost를 사용하고,
Docker Compose의 app 컨테이너에서는 Compose 설정이 DB_HOST=db를 주입합니다.
3. 설정 파일 준비
모든 애플리케이션 설정은 .env에서 관리합니다. .env.sample을 복사한 뒤
실제 DB 비밀번호와 API 키를 입력하세요.
cp .env.sample .env
POS 업로드 DB 처리 배치 크기는 다음처럼 설정합니다.
POS_BATCH_SIZE=1000
파일 감시자는 업로드된 파일을 대기열에 넣고 한 번에 하나씩 순차 처리합니다.
파일 업로드 처리의 병렬 실행 옵션은 제공하지 않습니다. MAX_WORKERS 설정은
GA4 API 조회에만 사용됩니다. 파일은 data/에서 직접 읽어 DB 처리를 마친 뒤
data/finish/로 이동하며, 영수증 상세 파일은
영수증별매출상세현황-{매장명}-{조회일자 yymmdd}.xls 형식으로 보관됩니다.
같은 이름의 파일이 있으면 전체 파일 내용을 비교합니다. 내용이 같으면 중복
파일을 건너뛰고, 다르면 기존 파일을 보존한 채 -1, -2 등의 번호를 붙입니다.
업로드 묶음의 모든 파일 처리가 끝나면 파일·데이터별 신규, 변경, 건너뛰기, 실패 건수가 한 번 출력됩니다. 매장별 누락 날짜는 파일 감시자를 직접 실행한 경우에만 시작 시 콘솔에 출력됩니다.
GA4 서비스 계정
- Google Cloud Console에서 서비스 계정 생성
- JSON 키 다운로드
.secret/service-account-credentials.json에 저장
🚀 실행 방법
방법 1: Docker Compose (권장)
# 이미지 빌드 및 서비스 시작
docker compose up -d --build
# 로그 확인
docker compose logs -f app
# 서비스 상태 확인
docker-compose ps
# 서비스 중지
docker compose down
운영용 이미지는 애플리케이션 소스(app, conf, lib, daily_run.py)를
이미지에 포함합니다. .env, 서비스 계정 키, 업로드 파일, 로그, DB 백업은
이미지에 넣지 않고 환경변수와 볼륨으로 관리합니다. 소스 변경 후에는 다음처럼
이미지를 다시 빌드해야 컨테이너에 반영됩니다.
docker compose build --no-cache app
docker compose up -d app
컨테이너 시작 시 cron, 파일 감시 서비스, Flask 웹서버가 실행되며 웹서버는
8889 포트에서 대시보드와 업로드·백업·조회 기능을 제공합니다. 사설 Git
저장소를 컨테이너 시작 시 git clone하는 방식은 인증정보와 네트워크에
실행이 의존하고 버전이 고정되지 않으므로 운영 방식으로 사용하지 않습니다.
웹 기반 파일 업로드 서버 접근
# 웹 브라우저에서 접근
http://localhost:8889
# 또는 Docker 컨테이너 내부에서
# http://fg-static-app:8889
웹 인터페이스 기능:
- 📁 드래그 앤 드롭 파일 업로드
- 📊 실시간 업로드 진행 상황 모니터링
- 📈 파일 처리 로그 대신 업로드 진행률과 완료 상태를 화면에 직접 표시
- ✅ 진행률과 중복되는 업로드 완료 메시지 박스는 표시하지 않음
- ⏱️ 10초 이상 처리가 진행 중인 파일명과 경과 시간을 진행률에 표시
- 📋 업로드 파일을
data/에서 직접 처리하고, 완료 파일은data/finish/에서 확인 - 📅 파일 처리 후 데이터 시작일과 최신일 등 매장별 데이터 범위 확인
- 🛠️ 관리 메뉴의 누락일 관리에서 날짜별·매장별 점검 제외 설정
- 📝 파일 처리 로그에는 업로드·진행률·완료 등 상태 메시지만 표시
- 💾 데이터베이스 백업 생성
- 🔄 백업 파일로부터 데이터베이스 복구
- ✅ 파일 검증 및 자동 처리
API 엔드포인트:
POST /api/upload- 파일 업로드 처리GET /api/status- 시스템 상태 조회POST /api/db-backup- 데이터베이스 백업 생성POST /api/db-restore- 데이터베이스 복구GET /api/db-backups- DB 백업 목록 조회- 기존
/api/backup,/api/restore,/api/backups경로도 호환됩니다.
대시보드 API:
GET /api/dashboard/okpos-product- OKPOS 상품별 통계GET /api/dashboard/okpos-receipt- OKPOS 영수증 통계GET /api/dashboard/upsolution- UPSOLUTION 통계GET /api/dashboard/weather- 날씨 데이터 통계GET /api/dashboard/weekly-forecast- 주간 예보 및 방문객 예상GET /api/dashboard/visitor-trend- 방문객 추이 (날짜 범위 조절 가능)
방법 2: 로컬 Python 실행
# 의존성 설치
pip install -r requirements.txt
# 데이터 수집 스크립트 실행
python daily_run.py
# 방문객 예측 실행
python -m lib.weekly_visitor_forecast_prophet
# 파일 감시자를 직접 실행하면 시작 시 매장별 누락 날짜를 콘솔에 출력
python -m lib.file_watch
매장별 누락 날짜 출력은 lib.file_watch를 직접 실행했을 때만 수행됩니다.
다른 모듈에서 파일 감시자를 가져오는 경우에는 누락 날짜를 출력하지 않습니다.
DB 연결 자체 테스트
conf/db.py를 직접 실행하면 설정 로드, SQLAlchemy 엔진 생성, SELECT 1
연결을 순서대로 검사하고 결과를 콘솔에 출력합니다.
python conf/db.py
방법 3: 크론 작업으로 자동 실행
# crontab 편집
crontab -e
# 매일 10:31에 실행하도록 추가
31 10 * * * cd /path/to/static && python daily_run.py >> logs/daily_run.log 2>&1
📊 데이터 흐름
┌─────────────────────────────────────────────────────────┐
│ 외부 API 데이터 수집 │
├──────────────────────────────────────────────────────────┤
│ • 기상청 ASOS (weather_asos.py) │
│ • 에어코리아 (air_quality.py) │
│ • Google Analytics 4 (ga4.py) │
│ • POS 시스템 (pos_update_*.py) │
└─────────────────┬──────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────┐
│ 데이터 저장 (MariaDB) │
├──────────────────────────────────────────────────────────┤
│ • fg_manager_static_weather (날씨 데이터) │
│ • fg_manager_static_air (대기질 데이터) │
│ • fg_manager_static_ga4_by_date (방문자 데이터) │
│ • fg_manager_static_pos (POS 데이터) │
└─────────────────┬──────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────┐
│ 시계열 분석 및 예측 │
├──────────────────────────────────────────────────────────┤
│ • 특성 공학 (lag features, moving averages) │
│ • Prophet 모델 훈련 │
│ • 미래 7일 방문객 예측 │
│ • 예측 결과 CSV 저장 (data/prophet_result.csv) │
└─────────────────────────────────────────────────────────┘
📁 프로젝트 구조
static/
├── app/ # Flask 웹 애플리케이션 및 REST API
│ ├── app.py # Flask 진입점 (대시보드, 업로드, 백업)
│ ├── file_processor.py # 파일 업로드/처리 및 DB 백업/복구 로직
│ ├── blueprints/ # API 및 페이지 라우트 (admin, backup, dashboard, upload 등)
│ ├── static/ # 정적 리소스 (CSS, JS)
│ └── templates/ # HTML 템플릿 (Bootstrap UI)
│
├── .secret/ # 보안 인증 파일 (git 제외)
│ └── service-account-credentials.json
├── conf/ # 설정 및 DB 정의
│ ├── mysql/ # MariaDB 공식 이미지 커스텀 설정 (conf.d)
│ │ └── custom.cnf # UTF-8mb4 및 타임존 설정
│ ├── migrations/ # DB 스키마 마이그레이션 SQL
│ ├── .env.sample # 환경변수 설정 샘플
│ ├── db.py # SQLAlchemy 연결 설정
│ ├── db_schema.py # DB 테이블 정의
│ ├── env.py # 환경변수 인라인 주석 처리
│ ├── install.sql # 초기 DB 스키마
│
├── lib/ # 데이터 처리 및 분석 모듈
│ ├── common.py # 공통 함수 (로깅, 설정 로드)
│ ├── weather_asos.py # 기상청 데이터 수집
│ ├── weather_forecast.py # 날씨 예보 조회
│ ├── air_quality.py # 대기환경 데이터 수집
│ ├── ga4.py # Google Analytics 수집
│ ├── holiday.py # 한국 휴일 관리
│ ├── weekly_visitor_forecast_prophet.py # 방문객 예측 (Prophet)
│ ├── weekly_visitor_forecast.py # 방문객 분석
│ ├── pos_update_*.py # POS 데이터 처리
│ ├── file_watch.py # 파일 변경 감시
│ └── requests_utils.py # HTTP 요청 유틸
│
├── data/ # 데이터 저장소
│ ├── finish/ # 처리 완료된 파일 보관
│ ├── cache/ # API 캐시
│ ├── prophet_result.csv # 예측 결과
│ └── sample.csv # 샘플 데이터
│
├── backups/ # 백업 저장소
│ └── database/ # MariaDB mysqldump 백업 파일 (.sql)
│
├── db_data/ # MariaDB 데이터 영속성 볼륨 (바인드 마운트)
├── logs/ # 애플리케이션 및 데몬 로그
├── output/ # 분석 결과 출력 파일
├── tmp/ # 파일 처리 임시 디렉토리
├── uploads/ # 웹 업로드 임시 수신 디렉토리
│
├── build/ # Docker 빌드
│ └── Dockerfile # Docker 이미지 정의
│
├── daily_run.py # 일일 작업 실행 스크립트
├── docker-compose.yml # Docker Compose 설정 (MariaDB LTS, App, PMA)
├── requirements.txt # Python 의존성
├── .env.example # 환경 변수 템플릿
├── .dockerignore # Docker 빌드 제외 설정
├── .gitignore # Git 무시 파일
└── README.md # 본 문서
🔧 주요 모듈 설명
daily_run.py
매일 정기적으로 실행되는 메인 스크립트
# 실행 명령
python daily_run.py
# 실행 순서
1. weather_asos.py - 기상 데이터 수집
2. ga4.py - Google Analytics 수집
3. air_quality.py - 대기질 데이터 수집
lib/weekly_visitor_forecast_prophet.py
Prophet을 이용한 고급 시계열 예측
특징:
- 1년 이상의 과거 데이터 학습
- Lag features & Moving averages 포함
- 기상, 대기질, 휴일 변수 통합
- 신뢰도 구간(95%) 제공
실행:
python -m lib.weekly_visitor_forecast_prophet
출력:
data/prophet_result.csv- 7일 예측 결과- 예측값, 하한, 상한 포함
lib/common.py
공통 유틸리티 함수
from lib.common import setup_logging, load_config, retry_on_exception
# 로거 설정
logger = setup_logging('my_module', 'INFO')
# 설정 로드
config = load_config()
# 재시도 데코레이터
@retry_on_exception(max_retries=3, delay=1.0, backoff=2.0)
def api_call():
...
📊 데이터베이스 스키마
초기 스키마는 conf/install.sql에 있습니다. 날씨 데이터는
여러 관측소의 같은 날짜 데이터를 저장할 수 있도록 (date, stnId) 복합
기본 키를 사용하며, avgPs 컬럼도 포함합니다. 기존 DB를 업그레이드할 때는
다음 마이그레이션을 적용합니다.
ALTER TABLE fg_manager_static_weather
ADD COLUMN avgPs FLOAT AFTER minPsHrmt;
ALTER TABLE fg_manager_static_weather
DROP PRIMARY KEY,
ADD PRIMARY KEY (date, stnId);
POS 영수증 상세 데이터는 fg_manager_static_pos_billdata에 저장됩니다.
복합 기본 키는 날짜·매장·포스·영수증번호·최초주문·결제시각·상품코드·
상품명·수량·총매출액·실매출액으로 구성합니다. 상품코드가 같아도 나머지
키 값이 다르면 별도 행으로 저장되며, 키 필드가 비어 있는 행은 저장 전에
오류로 거부합니다. 상품코드와 상품명은 대소문자를 구분하도록 저장합니다.
배치 저장 후 복합 기본 키를 다시 조회해 저장 여부를 검증합니다. 매장 코드
관리용 fg_manager_static_pos_shop_name 테이블도 초기 스키마에 포함됩니다.
매장별 누락일 관리는 fg_manager_static_pos_missing_date_skip에 날짜별 제외를,
fg_manager_static_pos_missing_date_shop_setting에 매장 전체 점검 제외 여부를
저장합니다. 기존 DB에는 다음 마이그레이션을 한 번 적용하세요.
mariadb -u firstgarden -p firstgarden < conf/migrations/20260928_pos_missing_date_skip.sql
firstgarden은 예시이며 .env의 DB_USER와 DB_NAME 값으로 바꿉니다.
웹 메뉴 가장 오른쪽의 관리 → 누락일 관리에서 누락일을 체크하면 해당 날짜는 이후 누락 목록과 파일 감시자의 누락 출력에서 제외됩니다. 체크된 날짜는 관리 화면의 스킵 목록에서 체크를 해제해 다시 점검할 수 있습니다. 매장 전체 제외를 선택하면 해당 매장의 누락 날짜 점검을 중단하며, 체크 해제 시 다시 점검합니다.
기존 DB에는 다음 마이그레이션을 적용합니다. 기존 키 필드에 NULL이 있으면
마이그레이션 전에 업무 데이터에 맞게 값을 보정해야 합니다.
SELECT COUNT(*) AS incomplete_rows
FROM fg_manager_static_pos_billdata
WHERE order_time IS NULL
OR pay_time IS NULL
OR product_name IS NULL
OR qty IS NULL
OR tot_sale_amt IS NULL
OR dcm_sale_amt IS NULL;
ALTER TABLE fg_manager_static_pos_billdata
MODIFY COLUMN order_time TIME NOT NULL,
MODIFY COLUMN pay_time TIME NOT NULL,
MODIFY COLUMN product_cd VARCHAR(20)
CHARACTER SET utf8mb4 COLLATE utf8mb4_bin NOT NULL,
MODIFY COLUMN product_name VARCHAR(100)
CHARACTER SET utf8mb4 COLLATE utf8mb4_bin NOT NULL,
MODIFY COLUMN qty INT NOT NULL,
MODIFY COLUMN tot_sale_amt INT NOT NULL,
MODIFY COLUMN dcm_sale_amt INT NOT NULL,
DROP PRIMARY KEY,
ADD PRIMARY KEY (
sale_date, shop_cd, pos_no, bill_no, order_time, pay_time,
product_cd, product_name, qty, tot_sale_amt, dcm_sale_amt
);
POS 업로드 배치 크기는 POS_BATCH_SIZE 환경변수로 설정합니다.
POS_BATCH_SIZE=1000
업로드 파일은 저장 전에 DB의 동일 복합 키 행과 모든 비키 컬럼을 비교합니다.
비교 결과는 동일, 변경, 신규 건수로 출력되며, 동일한 행은 DB 처리를
건너뜁니다. 변경·신규 행만 upsert하고, 업로드 파일 내부의 복합 키 중복이나
복합 키 필드 누락은 저장 전에 오류로 중단합니다.
두 POS 적재 모듈은 동일한 배치 설정을 사용합니다.
lib/pos_update_bill.py: OKPOS 영수증 상세 파일의 사전 비교, 변경·신규 upsert, 배치 저장 후 키 검증lib/pos_update_upsolution.py: UPSOLUTION 파일의 배치 upsert
POS 데이터 상세 조건 조회 (웹)
웹 대시보드의 'POS 상세 조건 조회'(/api/pos-query/view) 화면을 통해 다음과 같은 고급 분석 기능을 제공합니다:
- 다차원 필터링: 매장별, 품목 분류(ca01-ca05)별 (분류 계층 간 AND, 계층 내 OR 고정 결합, 분류 1 '입장권' 기본 선택 지원), 개별 품목별 조건 검색
- 기간 구분 필터:
전체: 선택 기간 전체 일자주말: 토요일, 일요일 및 법정 공휴일평일: 주말 및 공휴일을 제외한 평일주말-1일: 주말 하루 전(금요일 등) 평일 데이터와 주말/공휴일 데이터를 모두 포함하여 주말 연계 분석 지원
- 시간별 및 품목별 통계 차트: 09:00 - 22:00 시간대별 판매수량/매출액 집계, 마우스 휠 줌/팬 인터랙션, 상세 품목별 수량 차트(핵심 5개 품목 기본 활성화 및 범례 토글) 지원
- 상세 데이터 및 엑셀 다운로드: 영수증 원장 건별 판매일자 및 결제시간(시:분, HH:MM) 상세 내역 조회, 실시간 키워드 검색, 서식 적용 Excel 파일 내보내기
POS 조회 GUI
lib/pos_view_gui.py는 비어 있는 일반 POS 테이블이 아니라 실제 영수증 상세
테이블 fg_manager_static_pos_billdata를 조회합니다. 상품명, 수량, 매출액,
할인액, 실매출액 및 날짜별 요약을 표시하며, 기본 조회 기간은 DB에 저장된
최신 날짜 기준 최근 7일입니다. 상품 분류 컬럼이 영수증 상세 테이블에 없으므로
대분류·소분류 필터는 전체만 제공합니다.
날짜는 YYYY/MM/DD 형식으로 표시하고, 설치된 한글 폰트를 자동 선택합니다.
Docker 이미지에는 python3-tk와 fonts-noto-cjk가 포함되어 있습니다.
로컬 Ubuntu/Debian 환경에서는 다음 패키지가 필요합니다.
sudo apt-get install python3-tk fonts-noto-cjk
주요 테이블
fg_manager_static_ga4_by_date
| 컬럼명 | 타입 | 설명 |
|---|---|---|
| date | DATE | 기준 날짜 (PK) |
| activeUsers | INT | 활성 사용자 수 |
| screenPageViews | INT | 페이지뷰 |
| sessions | INT | 세션 수 |
fg_manager_static_weather
| 컬럼명 | 타입 | 설명 |
|---|---|---|
| date | DATE | 기준 날짜 (PK) |
| stnId | INT | 관측소 ID (PK) |
| minTa | FLOAT | 최저 기온 (℃) |
| maxTa | FLOAT | 최고 기온 (℃) |
| sumRn | FLOAT | 강수량 (mm) |
| avgRhm | FLOAT | 평균 습도 (%) |
fg_manager_static_air
| 컬럼명 | 타입 | 설명 |
|---|---|---|
| date | DATE | 기준 날짜 (PK) |
| station | VARCHAR | 측정소 이름 (PK) |
| pm25 | FLOAT | PM2.5 농도 (㎍/㎥) |
| pm10 | FLOAT | PM10 농도 (㎍/㎥) |
🐛 문제 해결
POS 배치 저장 검증 오류
저장 후 [ERROR] 배치 처리 실패가 출력되면 해당 배치의 기본 키가 실제
DB에 존재하는지 검증하는 단계에서 실패한 것입니다. 원인과 누락 키를 함께
출력하므로 DB 연결 상태와 대상 테이블 스키마를 확인합니다.
POS 매장 테이블 누락
fg_manager_static_pos_shop_name doesn't exist가 발생하면 conf/install.sql
의 매장 테이블 생성문을 적용하거나 다음 쿼리를 실행합니다.
CREATE TABLE IF NOT EXISTS fg_manager_static_pos_shop_name (
shop_cd VARCHAR(20) NOT NULL,
shop_name VARCHAR(100) NOT NULL,
used INT NOT NULL DEFAULT 1,
created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
updated_at DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
PRIMARY KEY (shop_cd)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
POS 조회 GUI 실행
lib/pos_view_gui.py는 Tk 기반 GUI입니다. Ubuntu/Debian에서는 시스템
패키지와 Python 의존성을 함께 설치합니다.
sudo apt-get install python3-tk
pip install -r requirements.txt
Docker 이미지에서 GUI 모듈을 import해야 하는 경우 build/Dockerfile의
python3-tk 설치가 포함된 이미지를 다시 빌드합니다.
POS 파일 감시
lib/file_watch.py는 data/ 폴더의 다음 파일을 감시하고 파일별로 처리합니다.
영수증별매출상세현황*.xls[x]일자별 (상품별)*.xls[x]
웹 업로드는 data/ 폴더 안의 비감시 임시 파일에 저장한 뒤 완성된 파일만
원자적으로 공개합니다. 감시자는 data/의 원본을 직접 읽고, DB 비교와
등록이 완료되면 data/finish/로 이동합니다. 영수증 상세 파일은
영수증별매출상세현황-{매장명}-{yymmdd}.xls[x] 형식으로 보관합니다.
같은 이름의 파일이 이미 있으면 전체 바이트 내용을 비교합니다. 완전히 같으면
중복 파일은 보관하지 않고, 내용이 다르면 -1, -2 등의 번호를 붙여 보존합니다.
Docker Compose에서는 data/ 마운트 안에 함께 보관됩니다.
파일 크기가 안정될 때까지 기다린 후 처리를 시작하며, 감시 시작 전에 이미 존재하는 파일과
파일시스템 이벤트가 누락되는 환경(WSL, Docker bind mount, 네트워크 드라이브)
도 주기적으로 검색합니다.
업로드 진행 상태는 data/와 분리된 프로젝트 루트 tmp/에 저장됩니다.
이벤트와 주기 검색에서 같은 파일이 반복 발견되어도 대기열에는 한 번만
등록하고, 단일 worker가 순서대로 처리합니다.
python -m lib.file_watch
감시 프로세스 시작 시 pos와 pos_billdata의 데이터 시작일, 최신일,
중간 누락일을 테이블별 블록으로 출력합니다. 누락된 날짜가 연속되면 범위로
묶어 표시합니다.
POS 피벗 조회
웹 대시보드의 POS 피벗 메뉴에서 fg_manager_static_pos_billdata를
피벗 테이블처럼 조회할 수 있습니다. 사용자가 다음 조건을 직접 변경할 수
있습니다.
- 행 기준: 판매일, 매장코드, 포스번호, 상품명, 상품코드, 구분
- 열 기준: 매장코드, 상품명, 구분, 포스번호 또는 없음
- 값: 수량, 총매출액, 할인액, 실매출액, 공급가액, 부가세
- 집계: 합계, 건수, 평균, 최소, 최대
- 필터: 시작일, 종료일, 매장코드, 상품명 포함
- 결제시각: 10:00~22:00 범위에서 1시간 단위 선택
- 제외 필터: 매장코드와 상품명 키워드를 여러 개 입력해 제외
피벗 API는 허용된 컬럼만 사용해 SQL을 구성하며, 조회 결과는 최대
10,000개 그룹까지 반환합니다. 화면 주소는 /api/dashboard/pos-pivot이고,
데이터 API는 /api/dashboard/pos-pivot/data입니다.
화면의 행·열·값·집계 조건은 엑셀 피벗 테이블처럼 변경할 수 있으며, 결과는 실제 업무 조회에 맞춘 일반 표 형태로 표시됩니다. 시간 범위는 선택한 시작·종료 시각을 모두 포함하고, 상품명 제외값은 쉼표 또는 줄바꿈으로 구분한 부분 일치 키워드입니다.
대시보드에는 매장코드 V83721의 품명별 시간대 결제량 그래프도 표시됩니다.
기본으로 DB 최신 판매일 기준 최근 1주일의 10:00~22:00 결제 수량을
보여주며, 더 보기 (누적 데이터)를 누르면 해당 매장의 전체 누적 기간으로
전환됩니다. 그래프의 각 선은 품명이고, 가로축은 1시간 단위 결제시각입니다.
Docker 실행 시 DB 연결 오류
# DB 컨테이너가 준비될 때까지 대기
docker-compose ps # 모든 서비스 상태 확인
# 로그 확인
docker-compose logs mariadb
API 요청 실패
- API Key 및 권한 확인
- 네트워크 연결 상태 확인
- API 할당량 확인
데이터 동기화 오류
# 강제 재동기화
python daily_run.py
# 특정 데이터만 재수집
python -c "from lib.weather_asos import main; main()"
🚀 성능 최적화
데이터베이스
- 연결 풀링 활성화 (pool_size=10, max_overflow=20)
- 1시간마다 자동 재연결
- 인덱스 기반 쿼리 최적화
API 요청
- GA4 데이터 조회 병렬 처리 (ThreadPoolExecutor)
- 재시도 메커니즘 (exponential backoff)
- 캐싱 (로컬 JSON 캐시)
모델 학습
- 충분한 메모리 할당 권장 (최소 2GB)
- GPU 미지원 (CPU 기반)
📈 향후 개선 계획
- 다중 예측 모델 앙상블 (Prophet + ARIMA + RandomForest)
- 설명 가능한 AI (SHAP)
- 이상 탐지 (Anomaly Detection)
- AutoML 파이프라인
- 모바일 앱 연동
🔐 보안
민감한 정보
.env파일은 절대 커밋하지 않기- API 키는 환경 변수로 관리
service-account-credentials.json보호- 프로덕션 환경에서 강한 DB 비밀번호 사용
권장 사항
- HTTPS 통신 사용
- 네트워크 방화벽 설정
- 정기적인 백업
- 로그 모니터링
📝 라이선스
MIT License - LICENSE 파일 참조
👥 기여자
개발: First Garden Team
📞 지원 및 문의
저장소: https://git.siane.kr/firstgarden/static
문제 보고: Gitea Issues 탭에서 등록
요청사항: Discussions 탭에서 논의
📚 참고 자료
마지막 업데이트: 2026년 9월 22일