wing-ops/backend/API.md
htlee fb556fad9e chore: 프로젝트 초기 구성
- frontend: React 19 + Vite 7 + Leaflet + Tailwind + Zustand
- backend: Express + better-sqlite3 + TypeScript
- database: PostgreSQL 초기화 스크립트
- .gitignore: 대용량 참고자료(scat, 참고용) 및 바이너리 파일 제외
- .env.example: API 키 템플릿

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-27 11:06:21 +09:00

199 lines
3.8 KiB
Markdown
Executable File

# Backend API 문서
## 시뮬레이션 API
### POST /api/simulation/run
오일 확산 시뮬레이션을 실행합니다.
#### 요청
```json
{
"model": "OpenDrift", // "KOSPS" | "POSEIDON" | "OpenDrift" | "앙상블"
"lat": 34.7312, // 사고 위도
"lon": 127.6845, // 사고 경도
"duration_hours": 48, // 예측 시간 (시간)
"oil_type": "벙커C유", // 유종
"spill_amount": 100, // 유출량 (kL)
"spill_type": "연속" // 유출 형태
}
```
#### 응답
```json
{
"success": true,
"model": "OpenDrift",
"parameters": {
"lat": 34.7312,
"lon": 127.6845,
"duration_hours": 48,
"oil_type": "벙커C유",
"spill_amount": 100,
"spill_type": "연속"
},
"trajectory": [
{
"lat": 34.7312,
"lon": 127.6845,
"time": 0,
"particle": 0
},
// ... more points
],
"metadata": {
"particle_count": 20,
"time_steps": 49,
"generated_at": "2026-02-16T16:45:00.000Z"
}
}
```
#### 오류 응답
```json
{
"error": "Missing required parameters",
"required": ["model", "lat", "lon", "duration_hours"]
}
```
---
### GET /api/simulation/status/:jobId
시뮬레이션 작업 상태를 확인합니다 (향후 비동기 작업용).
#### 응답
```json
{
"jobId": "abc123",
"status": "completed", // "pending" | "running" | "completed" | "failed"
"progress": 100, // 0-100
"message": "Simulation completed"
}
```
---
## OpenDrift 통합 계획
### 1단계: 환경 설정
```bash
# Python 가상 환경 생성
python3 -m venv venv
source venv/bin/activate # Linux/Mac
# venv\Scripts\activate # Windows
# OpenDrift 설치
pip install opendrift
# 필요한 기상/해양 데이터 라이브러리
pip install netCDF4 xarray
```
### 2단계: 데이터 소스 연동
OpenDrift는 다음 데이터 소스가 필요합니다:
- **바람 데이터**: WindSpeed, WindDirection
- 소스: ERA5, ECMWF, NCEP 등
- 형식: NetCDF (CF-compliant)
- **해류 데이터**: CurrentSpeed, CurrentDirection
- 소스: CMEMS, HYCOM, RTOFS 등
- 형식: NetCDF
- **파고 데이터**: WaveHeight (선택)
- 소스: WaveWatch III
### 3단계: TypeScript에서 Python 호출
```typescript
// backend/src/routes/simulation.ts
import { spawn } from 'child_process'
function runOpenDriftPython(params: SimulationRequest): Promise<ParticlePoint[]> {
return new Promise((resolve, reject) => {
const python = spawn('python3', [
'./src/utils/opendrift_runner.py',
JSON.stringify(params)
])
let stdout = ''
let stderr = ''
python.stdout.on('data', (data) => {
stdout += data.toString()
})
python.stderr.on('data', (data) => {
stderr += data.toString()
console.error('OpenDrift stderr:', data.toString())
})
python.on('close', (code) => {
if (code === 0) {
const result = JSON.parse(stdout)
resolve(result.trajectory)
} else {
reject(new Error(`OpenDrift failed with code ${code}: ${stderr}`))
}
})
})
}
```
### 4단계: 비동기 작업 큐 (선택)
장시간 시뮬레이션의 경우 작업 큐 사용:
```bash
npm install bull redis
```
```typescript
import Queue from 'bull'
const simulationQueue = new Queue('simulation', {
redis: { host: 'localhost', port: 6379 }
})
simulationQueue.process(async (job) => {
const result = await runOpenDriftPython(job.data)
return result
})
```
---
## 레이어 API
### GET /api/layers/tree/all
전체 레이어 트리 구조를 반환합니다.
#### 응답
```json
[
{
"id": "해도",
"name": "해도",
"type": "group",
"children": [
{
"id": "기본해도",
"name": "기본해도",
"type": "layer",
"wmsLayer": "khoa:base_chart"
}
]
}
]
```