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

3.8 KiB
Executable File

Backend API 문서

시뮬레이션 API

POST /api/simulation/run

오일 확산 시뮬레이션을 실행합니다.

요청

{
  "model": "OpenDrift",        // "KOSPS" | "POSEIDON" | "OpenDrift" | "앙상블"
  "lat": 34.7312,               // 사고 위도
  "lon": 127.6845,              // 사고 경도
  "duration_hours": 48,         // 예측 시간 (시간)
  "oil_type": "벙커C유",         // 유종
  "spill_amount": 100,          // 유출량 (kL)
  "spill_type": "연속"           // 유출 형태
}

응답

{
  "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"
  }
}

오류 응답

{
  "error": "Missing required parameters",
  "required": ["model", "lat", "lon", "duration_hours"]
}

GET /api/simulation/status/:jobId

시뮬레이션 작업 상태를 확인합니다 (향후 비동기 작업용).

응답

{
  "jobId": "abc123",
  "status": "completed",        // "pending" | "running" | "completed" | "failed"
  "progress": 100,              // 0-100
  "message": "Simulation completed"
}

OpenDrift 통합 계획

1단계: 환경 설정

# 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 호출

// 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단계: 비동기 작업 큐 (선택)

장시간 시뮬레이션의 경우 작업 큐 사용:

npm install bull redis
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

전체 레이어 트리 구조를 반환합니다.

응답

[
  {
    "id": "해도",
    "name": "해도",
    "type": "group",
    "children": [
      {
        "id": "기본해도",
        "name": "기본해도",
        "type": "layer",
        "wmsLayer": "khoa:base_chart"
      }
    ]
  }
]