cda9cd65435f43784435736c48f3ab99382ec944
퍼스트가든용 기상청 API를 활용해 공지사항 자동 등록 시스템
기상정보에 따른 이벤트 진행에 대한 정확한 기준 부여를 위해 기상청 API를 사용하여, 영업시간 내 강수정보를 파악하고 자동으로 공지를 올리기 위한 프로젝트.
📁 폴더 구조
project-root/
├── logs/ # 크론 실행 로그 저장 경로
│ └── cron.log # Crontab 실행 로그
│
├── data/ # SQLite DB, 캡처 이미지 저장 경로 (공용 볼륨)
│ ├── weather.sqlite # 날씨 DB (precipitation, summary 테이블)
│ └── weather_capture_YYYYMMDD.png # 일자별 날씨 캡처 이미지
│
├── app/ # gnu-autouploader + API 서버 (통합)
│ ├── gnu_autoupload.py # 메인 실행 스크립트 (Selenium → FTP → DB)
│ ├── weather_capture.py # Selenium 기반 날씨 이미지 캡처 + 강우량 추출
│ ├── weather.py # 기상청 API 데이터 처리 및 sqlite 저장
│ ├── send_message.py # Mattermost 알림 발송
│ ├── selenium_manager.py # Selenium 브라우저 관리
│ ├── api_server.py # Flask 기반 카카오 챗봇 웹훅 서버 ⭐
│ ├── config.py # 설정값 로드 (DB, FTP, API KEY 등)
│ ├── requirements.txt # Python 의존성
│ └── run.sh # 수동 실행용 셸 스크립트 (개발 시 사용)
│
├── webhook/ # (더 이상 사용 안 함 - app/api_server.py로 통합)
│ └── webhook.py # (참고용 아카이브)
│
├── build/
│ ├── app/
│ │ ├── Dockerfile # gnu-autouploader + Flask 통합 이미지
│ │ ├── entrypoint.sh # Flask + Cron 동시 실행 스크립트 ⭐
│ │ └── run.sh # (위의 app/run.sh와 동일)
│ └── webhook/
│ └── Dockerfile # (더 이상 사용 안 함)
│
├── .env.example # 환경 변수 템플릿 (.env로 복사하여 수정)
├── docker-compose.yml # Docker Compose 서비스 정의 (gnu-autouploader만)
└── README.md # 프로젝트 문서
📋 주요 스크립트 설명
app/gnu_autoupload.py (메인)
- 역할: 날씨 캡처 → FTP 업로드 → 그누보드 DB에 게시글 등록
- 실행 방식:
- 매일 09:00 Crontab 자동 실행
docker exec또는run.sh로 수동 실행 가능
- 오류 발생 시: Mattermost으로 알림 발송
app/weather_capture.py ⭐ (개선)
- 이전: Selenium으로 웹페이지 캡처만 수행
- 현재:
- Selenium으로 기상청 웹페이지 접근
- 페이지에서 강우량 데이터 자동 추출 (10시~21시)
- '-'는 0mm, '~1'은 0.5mm로 자동 계산
- 추출된 강우량을 SQLite에 저장 (
rainfall_capture,rainfall_summary테이블) - 웹페이지 이미지 캡처 저장
app/weather.py
- 기상청 API에서 시간별 강수량 데이터 수집
- 10:00 ~ 22:00 영업시간 강수 데이터 HTML 테이블 생성
- SQLite DB에 저장
webhook/webhook.py ⭐ (개선)
- Flask 기반 카카오 챇봇 응답 서버
- 주요 기능:
- 당일 조회: 09:00 캡처된 실제 강우량 데이터 응답
- 미래 날짜 조회: 기상청 API 기반 예보 강우량 응답
- 예보 시 "변동될 수 있음" 경고 문구 표시
- 10mm 초과 시 이벤트 적용 안내
- 날씨 캡처 이미지 함께 전송
- 통합: 현재
app/api_server.py로 통합되어 동일 컨테이너에서 실행
app/config.py
- 환경 변수 로드 (
.env또는 컨테이너 환경 변수) - 필수 변수 부재 시 즉시 오류 출력 후 종료
🚀 설치 & 실행
1. 환경 설정
# .env 파일 생성
cp .env.example .env
# 필수 정보 입력
vim .env
필수 환경 변수
# 게시판 정보
BOARD_ID=news
BOARD_CA_NAME=카테고리명
BOARD_CONTENT=글 내용
BOARD_MB_ID=user_id
BOARD_NICKNAME=닉네임
# MySQL 연결 (로컬: localhost, Docker: db 서비스명, Synology: 실제 호스트 IP/도메인)
DB_HOST=localhost
DB_USER=db_user
DB_PASSWORD=db_password
DB_NAME=database_name
# FTP 업로드
FTP_HOST=ftp.example.com
FTP_USER=ftp_user
FTP_PASSWORD=ftp_password
FTP_UPLOAD_DIR=/data/file/news/
# 기상청 API
SERVICE_KEY=your_api_key_here
# Mattermost 알림 (선택사항)
MATTERMOST_URL=https://mattermost.example.com
MATTERMOST_TOKEN=token
MATTERMOST_CHANNEL_ID=channel_id
2. Docker Compose 실행
# 빌드 및 실행
docker-compose up -d
# 로그 확인
docker-compose logs -f gnu-autouploader
# 크론 실행 로그 확인
docker exec gnu-autouploader tail -f /logs/cron.log
3. 수동 실행
# 컨테이너에서 직접 실행
docker exec -it gnu-autouploader /usr/bin/python /app/gnu_autoupload.py
# 또는 run.sh 사용
docker exec -it gnu-autouploader /app/run.sh
🎯 시스템 동작 플로우
아키텍처 (통합 구조)
[gnu-autouploader 컨테이너] (포트 5151:5000 노출)
├─ Crontab 데몬 (포그라운드)
│ └─ 매일 09:00 크론 작업 실행
│
└─ Flask 웹서버 (백그라운드)
└─ 포트 5000에서 지속 실행
일일 작업 플로우
매일 09:00
↓
[Crontab 작업 시작]
├─ 1. weather_capture.py 실행
│ ├─ Selenium으로 기상청 웹페이지 접근
│ ├─ 강우량 데이터 추출 (10시~21시) ⭐
│ ├─ SQLite 저장
│ └─ 웹페이지 이미지 캡처 저장
├─ 2. weather.py 실행 (선택적)
│ └─ API 기반 시간별 강수 데이터 저장
└─ 3. gnu_autoupload.py 실행
├─ 캡처된 이미지 FTP 업로드
└─ 그누보드 게시글 자동 등록
동시에 실행 중: Flask 웹서버
↓ (사용자 요청 시)
[Flask 웹훅 엔드포인트]
├─ "오늘의 강우량은?" → SQLite에서 실제 데이터 응답 ✓
├─ "내일 강우량은?" → API 예보 데이터 + 경고 문구 응답 ⚠️
└─ "강우량 10mm 초과?" → 이벤트 적용 여부 자동 판단
🗄️ SQLite 데이터베이스 스키마
rainfall_capture (웹페이지 캡처 데이터)
CREATE TABLE rainfall_capture (
id INTEGER PRIMARY KEY,
date TEXT, -- 'YYYYMMDD'
hour INTEGER, -- 10~21 (10시~21시)
rainfall REAL -- mm 단위
);
rainfall_summary (일일 합계)
CREATE TABLE rainfall_summary (
id INTEGER PRIMARY KEY,
date TEXT UNIQUE, -- 'YYYYMMDD'
total_rainfall REAL, -- mm 단위
capture_time TEXT -- '2025-12-19 09:00:00'
);
💬 카카오 챗봇 응답 예시
당일 조회 (실제 데이터)
📅 12월 19일(금)
📊 실제 강수량 (09:00 캡처 기준)
10:00 → ☀️ 강수 없음
11:00 → ☀️ 강수 없음
12:00 → 0.5mm
...
21:00 → 2.3mm
💧 총 강수량: 5.2mm
❌ 이벤트 기준(10mm 초과)을 충족하지 않음
[날씨 캡처 이미지]
미래 날짜 조회 (API 예보)
📅 12월 20일(토)
📊 예보 강수량 (08:00 발표 기준)
10:00 → 1.2mm
11:00 → 2.1mm
...
21:00 → 0.8mm
💧 총 강수량: 12.5mm
✅ 식음료 2만원 이상 결제 시 무료입장권 제공
⚠️ 이는 기상청 08:00 발표 예보입니다. 실제 이벤트 적용 기준은 당일 09:00 캡처 데이터입니다.
⚙️ 크론탭 설정
Docker 컨테이너 내부에서 매일 09:00에 자동 실행됩니다.
0 9 * * * /usr/bin/python /app/gnu_autoupload.py >> /logs/cron.log 2>&1
로그 확인:
docker exec gnu-autouploader tail -f /logs/cron.log
🔍 문제 해결
MySQL 연결 오류
- 오류:
Can't connect to MySQL server on 'localhost' - 원인: Docker 컨테이너에서 localhost는 컨테이너 자신을 가리킴
- 해결:
- Docker 환경:
DB_HOST=db(docker-compose 서비스명) - Synology:
DB_HOST=192.168.x.x(호스트 IP)
- Docker 환경:
Mattermost 알림 실패
- 오류:
Invalid URL '/api/v4/posts': No scheme supplied - 원인: URL에
http://또는https://가 없음 - 해결:
MATTERMOST_URL=https://mattermost.example.com명시
크론탭에서 환경 변수 미로드
- 원인: 기존 버전에서 crontab이
.env파일 접근 불가 - 해결: 현재는
docker-compose.yml에서.env를 volume mount + env_file로 처리
📝 설정 변경 후 재배포
# 컨테이너 재시작
docker-compose restart gnu-autouploader
# 또는 재빌드
docker-compose up -d --build
🛠️ 개발 & 디버깅
로컬 테스트 (가상환경)
# 가상환경 생성
python -m venv .venv
source .venv/bin/activate # Windows: .venv\Scripts\activate
# 의존성 설치
pip install -r app/requirements.txt
# .env 파일 생성 후 직접 실행
python app/gnu_autoupload.py
Docker 내 수동 실행
# 날씨 캡처 + 강우량 추출
docker exec gnu-autouploader /usr/bin/python /app/weather_capture.py
# 메인 작업 (게시글 등록)
docker exec gnu-autouploader /usr/bin/python /app/gnu_autoupload.py
# 기상청 API 데이터 (선택사항)
docker exec gnu-autouploader /usr/bin/python /app/weather.py
로그 확인
# Crontab + Flask 통합 로그
docker-compose logs -f gnu-autouploader
# Crontab 실행 로그만
docker exec gnu-autouploader tail -f /logs/cron.log
# Flask 웹서버 로그
docker exec gnu-autouploader tail -f /logs/flask.log
Description
Languages
Python
95.9%
Dockerfile
2.6%
Shell
1.5%