chore: 현재 작업 중간 커밋

This commit is contained in:
chungyeong
2026-03-05 11:00:45 +09:00
parent 02970df6af
commit be88b4fcec
43 changed files with 6837 additions and 466 deletions

View File

@@ -166,7 +166,7 @@ npm run parse -- "11월 말부터 12월 초까지 출발하는 일정 여행 기
LLM 기반 파라미터 가공 + 주기적 가격 추적 실행:
```bash
npm run watch -- "11월 말부터 12월 초까지 출발, 인천->마드리드, 20시간 이하, 비즈니스 2명" --interval-sec 60 --target-price 1300000 --alert-on both
npm run watch -- "11월 말부터 12월 초까지 출발, 인천->마드리드, 20시간 이하, 비즈니스 2명" --interval-sec 3600 --target-price 1300000 --alert-on both
```
한 번만 조회(테스트용):
@@ -191,7 +191,7 @@ npm run watch -- "11월 말부터 12월 초까지 출발, 인천->마드리드,
```
옵션:
- `--interval-sec`: 폴링 주기(초)
- `--interval-sec`: 폴링 주기(초, 기본 `3600`, `3600` 미만 입력 시 즉시 에러)
- `--target-price`: 목표 가격 이하 도달 시 알림 기준
- `--alert-on both|change|threshold`: 알림 조건 (가격 변동/임계값)
- `--rule-only`: LLM 호출 없이 규칙 파서만 사용
@@ -199,6 +199,7 @@ npm run watch -- "11월 말부터 12월 초까지 출발, 인천->마드리드,
환경 변수:
- `OPENAI_API_KEY`: 설정 시 자연어 입력 파라미터를 LLM으로 보정한다.
- `OPENAI_MODEL` (선택): 기본값 `gpt-4.1-mini`
- `LLM_REQUEST_TIMEOUT_MS` (선택): LLM HTTP 타임아웃(ms), 기본값 `20000`
- `CRAWLER_ENDPOINT` (선택): 설정 시 해당 엔드포인트로 POST 하여 실크롤러 결과를 받는다. 미설정 시 mock 크롤러 사용.
- `CRAWLER_PROVIDERS` (선택): `skyscanner,naver,google` 형태 우선순위 목록. 미설정 시 단일 `CRAWLER_ENDPOINT` 또는 mock 사용.
- `CRAWLER_ENDPOINT_SKYSCANNER` (선택): Skyscanner 전용 엔드포인트
@@ -224,6 +225,7 @@ npm run watch -- "11월 말부터 12월 초까지 출발, 인천->마드리드,
```bash
OPENAI_API_KEY=
OPENAI_MODEL=gpt-4.1-mini
LLM_REQUEST_TIMEOUT_MS=20000
CRAWLER_ENDPOINT=
CRAWLER_PROVIDERS=skyscanner,naver,google
@@ -293,12 +295,12 @@ npm run dashboard:fastify
대시보드에서 가능한 작업:
- 자연어 입력을 LLM/규칙 파서로 파싱해 검색 조건 JSON 확인
- 파싱된 조건으로 watch 생성 및 즉시 조회
- 파싱된 조건으로 watch 생성
- watch별 `크롤링 ON/OFF`, `알림 ON/OFF` 토글
- 전역 `전체 크롤링 ON/OFF`, `전체 알림 ON/OFF` 토글
- 최근 가격 이벤트(목표가 도달/가격 변동) 확인
### 7.1 MySQL 연동 (개인 DB 사용)
### 7.1 MySQL 연동 (외부 DB 사용)
환경변수 설정:
@@ -308,26 +310,87 @@ MYSQL_HOST=127.0.0.1
MYSQL_PORT=3306
MYSQL_USER=your_user
MYSQL_PASSWORD=your_password
MYSQL_DATABASE=airwatcher
MYSQL_DATABASE=your_database
```
또는 단일 URL 사용:
```bash
DASHBOARD_DB=mysql
MYSQL_URL=mysql://user:password@127.0.0.1:3306/airwatcher
MYSQL_URL=mysql://user:password@db.example.com:3306/your_database
```
추가 서버 환경변수:
- `DASHBOARD_HOST` (기본 `127.0.0.1`)
- `DASHBOARD_PORT` (기본 `3000`)
- `DASHBOARD_POLL_INTERVAL_SEC` (기본 `60`)
- `DASHBOARD_POLL_INTERVAL_SEC` (기본 `3600`, `3600` 미만/비정수 입력 시 서버 시작 에러)
- `DASHBOARD_USERS` (선택, `username:password,username2:password2` 형식. 설정 시 로그인 페이지 + 계정별 세션 인증 활성화)
- `DASHBOARD_ADMIN_USERS` (선택, 전역 제어 권한 계정 목록. 미설정 시 `DASHBOARD_USERS` 첫 번째 계정을 admin으로 간주)
- `DASHBOARD_SESSION_TTL_SEC` (선택, 기본 `604800`초 = 7일)
- `DASHBOARD_REQUIRE_AUTH` (기본: `NODE_ENV=production`이면 `true`, 아니면 `false`)
- `DASHBOARD_API_TOKEN` (`DASHBOARD_REQUIRE_AUTH=true`일 때 필수, API `Authorization: Bearer <token>` 또는 `X-API-Key`로 전달)
- `DASHBOARD_ALLOW_MEMORY_FALLBACK` (기본 `false`, `true`일 때만 MySQL 초기화 실패/설정 누락 시 메모리 저장소 fallback 허용)
- `DASHBOARD_DB_SCHEMA` (선택, `auto|playground`, 기본 `playground`)
- `DASHBOARD_PROJECT_KEY` (선택, 기본 `air-watcher`, playground 스키마에서 프로젝트 네임스페이스 키)
- `LLM_REQUEST_TIMEOUT_MS` (기본 `20000`, LLM 파싱 요청 타임아웃)
참고:
- `DASHBOARD_DB=mysql`인데 MySQL 연결 정보가 없으면 서버가 에러를 반환한다.
- 애플리케이션은 외부 MySQL 연결해 row CRUD만 수행한다.
- 애플리케이션은 DB/테이블 생성이나 마이그레이션을 수행하지 않는다.
- `DASHBOARD_DB=mysql`인데 MySQL 연결 정보가 없으면 서버가 시작 실패한다. (`DASHBOARD_ALLOW_MEMORY_FALLBACK=true`면 메모리 fallback 가능)
- MySQL 초기화 실패도 동일하게 기본은 시작 실패이며, fallback은 명시적으로 허용해야 한다.
- `DASHBOARD_DB`를 비우고 MySQL 환경변수도 없으면 메모리 저장소로 동작한다.
- `CRAWLER_ENDPOINT` 미설정 시 mock 가격으로 동작하므로 실데이터 추적 시 실제 크롤러 API를 연결해야 한다.
- `DASHBOARD_DB_SCHEMA``playground`(또는 `auto`)만 지원한다.
### 7.1.1 계정 분리 + 텔레그램 설정 페이지
- 로그인 페이지: `/login`
- 텔레그램 설정/가이드 페이지: `/setup`
- 계정별로 watch/event가 분리되어, 일반 사용자는 본인 watch만 조회/수정 가능
- 텔레그램은 계정별 `chatId`/`botToken`(선택, 서버 기본 토큰 fallback) 저장 가능
예시:
```bash
DASHBOARD_USERS=alice:alice_pw,bob:bob_pw
DASHBOARD_ADMIN_USERS=alice
```
참고:
- `DASHBOARD_USERS`를 설정하면 브라우저 로그인 기반 인증이 우선 사용된다.
- 토큰 인증(`DASHBOARD_API_TOKEN`)은 기존 자동화/API 호출 용도로 병행 가능하다.
### 7.1.2 단일 Playground DB에 여러 소형 프로젝트 수용
소형 프로젝트를 여러 개 운영한다면 DB를 프로젝트별로 쪼개기보다, 하나의 DB(예: `playground`)에서 `project_key` 네임스페이스로 분리하는 방식이 실용적이다.
- 스키마 파일: `playground_schema.sql`
- 핵심 테이블:
- `projects`: 프로젝트 목록/메타
- `project_documents`: 프로젝트별 문서(JSON) 저장
- `project_events`: 프로젝트별 이벤트 로그
- `project_settings`: 프로젝트별 설정 key-value
적용 예시:
```bash
mysql -u root -p playground < playground_schema.sql
```
Air-Watcher를 playground 스키마로 실행하려면:
```bash
DASHBOARD_DB=mysql
DASHBOARD_DB_SCHEMA=playground
DASHBOARD_PROJECT_KEY=air-watcher
```
Air-Watcher 매핑 권장:
- watch 레코드: `project_documents` (`doc_type='watch'`, `doc_key=<watchId>`)
- 이벤트: `project_events` (`stream='watch_events'`)
- 전역/유저 설정: `project_settings` (`global_controls`, `user_profiles` 등)
### 7.2 Fastify 전환 뼈대
@@ -341,7 +404,7 @@ MYSQL_URL=mysql://user:password@127.0.0.1:3306/airwatcher
DASHBOARD_HOST=127.0.0.1 DASHBOARD_PORT=3000 npm run dashboard:fastify
```
### 7.3 Docker / Compose
### 7.3 Docker / Compose (앱 단독)
Docker 이미지 빌드:
@@ -349,16 +412,20 @@ Docker 이미지 빌드:
docker build -t airwatcher .
```
Docker Compose 기동 (`app + mysql`):
Docker Compose 기동 (`app` only):
```bash
docker compose up --build
docker compose up --build app
```
주요 기본값:
- 앱: `http://127.0.0.1:3000`
- DB 모드: `DASHBOARD_DB=mysql`
- MySQL 컨테이너: `127.0.0.1:3306` (기본 계정 `airwatcher/airwatcher`)
- MySQL은 외부 서버를 사용하며 Compose에서 DB 컨테이너를 띄우지 않는다.
- 인증: `DASHBOARD_REQUIRE_AUTH=true` (토큰 미설정 시 앱 시작 실패)
참고:
- `.env` 또는 쉘 환경변수로 `MYSQL_URL` 또는 `MYSQL_HOST`/`MYSQL_USER`/`MYSQL_DATABASE`를 전달해야 한다.
메모리 모드로 앱만 쓰려면: