방문통계 수집 및 작성
  • Python 47.5%
  • JavaScript 28.9%
  • HTML 20.3%
  • CSS 2.8%
  • Dockerfile 0.5%
Find a file
Repository files (latest commit first)
Filename Latest commit message Latest commit date
KWON 22264b3206 style: 매장별 누락일 관리 헤더 매장명 좌측 정렬 보장
- 더보기/접기 버튼 전용 너비 스타일(80px, center)을 button.toggle-shop-detail로 한정
- 매장명 영역 클래스를 분리하여 text-start 및 text-align: left, justify-content: flex-start 강제 적용
2026-10-16 12:35:19 +09:00
app style: 매장별 누락일 관리 헤더 매장명 좌측 정렬 보장 2026-10-16 12:35:19 +09:00
build feat: 기상청 예보 발표 연동 방문객 예측 자동 구동 및 최근 실행일시 표시 2026-10-06 16:55:09 +09:00
conf perf: Proxmox LXC 4GB 환경 및 대량 데이터 조회를 위한 MariaDB 튜닝 설정 추가 2026-10-15 11:16:36 +09:00
lib feat: 매장별 누락일 관리(모니터링 토글/전체 제외/오름차순 정렬) 및 업로드 페이지 누락일 조회·스킵 기능 추가 2026-10-16 12:00:26 +09:00
scripts fix: UPS 마이그레이션 스크립트에 누락된 SQLAlchemy delete 임포트 추가 2026-10-13 14:47:49 +09:00
.dockerignore chore(auth): GA4 서비스 계정 인증 파일 경로를 .secret으로 변경 및 gitignore 적용 2026-09-29 13:31:42 +09:00
.env.example .env.example의 민감 데이터일 수 있는 부분 삭제 2026-10-15 10:34:16 +09:00
.gitignore chore: AGY 에이전트 커스터마이제이션 디렉토리(.agents/) gitignore 추가 2026-09-30 13:58:46 +09:00
CHANGELOG.md feat: POS 조회 기간 선택 확장(1년, 전년도) 및 그래프 연도별 집계 기능 추가 2026-10-12 11:49:56 +09:00
daily_run.py perf: 방문객 예측 데이터 1일 1회 DB 재사용(Cache-Aside) 및 daily_run 배치 연동 2026-10-02 15:37:17 +09:00
DEVELOPMENT.md chore(docker): switch MariaDB to official LTS and align project directory tree 2026-09-29 11:04:18 +09:00
docker-compose.yml 패키지 경로 업데이트 2026-10-13 15:56:46 +09:00
README.md feat(pos): 상세 데이터 목록에 결제시간(시:분) 컬럼 추가 및 영수증 원장 건별 출력 구현 2026-09-30 13:12:15 +09:00
README.md.old feat: Flask 애플리케이션 모듈화 및 웹 대시보드 구현 2025-12-26 17:31:37 +09:00
requirements.txt 설정: YAML 설정을 .env로 통합 2026-09-22 14:11:43 +09:00
static.code-workspace feat: Flask 애플리케이션 모듈화 및 웹 대시보드 구현 2025-12-26 17:31:37 +09:00

First Garden 방문통계 분석 서비스 (Static Analysis Service)

Python Version Docker License Status

퍼스트가든 방문객 데이터 자동 수집, 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 서비스 계정

  1. Google Cloud Console에서 서비스 계정 생성
  2. JSON 키 다운로드
  3. .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일