# 계산 정확도

## TL;DR

AstroWay API는 **Swiss Ephemeris**를 사용합니다(아스트로딘스트(Astrodienst)의 공식 C 코드로, **astro.com**을 만든 개발사입니다). 이 엔진은 30년 이상 프로 астрологи들이 **Solar Fire($495), Kepler($995), Astro Gold($29.99/월) 및 Janus**에서 사용해 왔습니다. 우리는 이를 WebAssembly로 컴파일하고 REST API 계층으로 감싸서 중개 마진 없이 제공합니다. 모든 기본 계산 엔드포인트는 regression snapshot 테스트로 커버되며, 엔진의 정확도는 **세 가지 독립적인 소스와의 triangulation**과 **NASA 5천년 일식 카탈로그**를 통해 검증되었습니다.

- **행성 위치**: `< 0.1 arcsec` (Astrodienst 공식 swetest CGI와 비교)
- **Placidus 하우스 쿠스피드**: `0.000"` exact match
- **일식**: NASA 일식 카탈로그와 비교 시 `< 1분`
- **ACG 라인**: 적도에서 `< 1.5km` (swetest 기준)
- **일출/일몰**: timeanddate.com과 비교 시 `< 10초`
- **Moon VOC, ingresses, 행성 conjunctions**: 초 단위 정확도

## 엔진

| 컴포넌트 | 값 |
|-----------|----------|
| 라이브러리 | Swiss Ephemeris C 코드 (aloistr/swisseph) |
| 버전 | Astrodienst C 코드 upstream |
| 바인딩 | swisseph-wasm (Node.js용 WebAssembly) |
| Ephemeris | DE431 JPL ephemeris (.se1 파일 사용) |
| 대체재 | Moshier analytical (1800-2399년 외 날짜용) |
| 코드 공유 | app.astroway.info와 `@/core` 공유 — 하나의 엔진, 두 가지 전송 방식 |

## 방법론

정확도는 **triangulation**을 통해 세 가지 독립적인 소스와 비교하여 검증됩니다.

### 1. swetest CGI (레퍼런스)

Astrodienst가 직접 만든 Swiss Ephemeris의 공식 reference-implementation으로, **Astro.com**을 만든 엔진이며 전 세계 수백만 astrologers가 사용합니다. 가장 권위 있는 공개 소스입니다. 우리의 엔진은 **동일**합니다(0.00–0.07 각도 초 drift).

### 2. Kerykeion (Python)

독립적인 Python 라이브러리로, 우리의 WASM이 아닌 `pyswisseph` 바인딩을 사용합니다. 우리의 WASM 계층이 데이터를 왜곡하지 않음을 확인합니다.

### 3. Prokerala API

원격 Swiss Ephemeris API (sidereal Lahiri). 8–17 각도 초의 systematic drift는 Lahiri ayanamsa 공식 버전 차이 때문이며(**엔진의 정확도와는 무관**), Swiss Ephemeris 자체의 오류가 아닙니다.

## Triangulation 결과

| 차트 | swetest(Astrodienst)와 비교 | Kerykeion(Python)과 비교 | Prokerala API와 비교 |
|-------|------------------------------|---------------------------|---------------------|
| Monroe 1926   | **0.00"** | 0.19" | 16.95" (systemic) |
| Diana 1961    | **0.00"** | 0.69" | 8.18" (systemic)  |
| Einstein 1879 | 0.07"     | Kerykeion LMT artifact | 14.96" (systemic) |

## 엔드포인트 수준 Regression 테스트

모든 기본 계산 엔드포인트는 3개의 레퍼런스 차트(Monroe / Diana / Einstein)를 대상으로 **{siteMeta.snapshotCount}개의 snapshot**으로 커버됩니다.

Snapshot suite는 다음을 감지합니다:

- **입력 데이터 매핑 버그** — 잘못된 행성 ID, UT, 하우스 시스템
- **후처리** — 반올림, 단위 변환, 부호 손실
- **기본값 불일치** — mean vs true node, 지구중심 vs местополож기반(topocentric)
- **Schema drift** — 잘못된 형식이 유효성 검사를 통과
- **구식 배포** — 프로덕션 dist가 코드와 일치하지 않음

기본 Tolerance: 모든 숫자 필드에 대해 `5e-5°` (≈0.18 각도 초).

## 상세 벤치마크

### 행성 위치 (열대, swetest와 비교)

| 차트 | 날짜 | 최대 drift |
|-------|------|-----------------|
| Marilyn Monroe  | 1926-06-01 | **0.00"** |
| Princess Diana  | 1961-07-01 | **0.00"** |
| Albert Einstein | 1879-03-14 | 0.07"     |

### Placidus 하우스 쿠스피드 (swetest와 비교)

| 차트 | drift ASC | drift MC | 최대 쿠스피드 drift |
|-------|-----------|----------|-------------------------|
| Monroe | 0.000" | 0.000" | 0.000" |
| Diana  | 0.000" | 0.000" | 0.000" |

### 일식 (NASA 5천년 카탈로그와 비교)

| 사건 | NASA 최대 | 우리 최대 | Drift |
|-------|----------------|--------------|-------|
| 2025-03-14 Lunar Total  | 06:58 UT | 06:58 UT | 0.8분 |
| 2025-03-29 Solar Partial | 10:47 UT | 10:47 UT | 0.5분 |
| 2025-09-07 Lunar Total  | 18:11 UT | 18:11 UT | 0.8분 |
| 2025-09-21 Solar Partial | 19:41 UT | 19:42 UT | 1.0분 |

### Astro-Cartography (swetest RA 공식과 비교)

모든 MC/IC/ASC/DSC 라인은 올바른 공식 `longitude = RA − GMST`(Kenneth Bowser 표준)를 사용합니다. 기준과의 drift: **적도에서 모든 행성에 대해 < 1.5km**.

### 일출/일몰 (timeanddate.com과 비교)

| 위치 | 날짜 | 매개변수 | Drift |
|---------|------|----------|-------|
| 런던 | 2026-04-15 | 일출 | 0.6초 |
| 런던 | 2026-04-15 | 일몰  | 9초   |

**극지방** (|위도| > 66.5°)은 자동으로 `polarState` + 일반 planetary hours가 정의되지 않음을 알리는 경고를 반환합니다.

### 오비트 아スペクト

AstroWay는 **변동 오비트**를 per-planet으로 사용합니다(두 행성의 MIN 규칙, ZET9 및 astro.com과 동일). 기본 오비트( natal 차트용):

| 아スペクト | Sun | Moon | Inner | Jupiter | Outer |
|--------|-----|------|-------|---------|-------|
| Conjunction | 12°  | 10° | 5° | 8° | 5° |
| Sextile     | 6.5° | 6°  | 5° | 5° | 5° |
| Square      | 10°  | 8°  | 5° | 7° | 5° |
| Trine       | 12°  | 8°  | 5° | 5° | 5° |
| Opposition  | 12°  | 10° | 5° | 8° | 5° |

마이너 아スペクト (36°, 40°, 45°, 72°, 108°, 135°, 144°)은 **기본적으로 비활성화**되어 있습니다. `ALL_ASPECTS`로 명시적으로 활성화할 수 있습니다.

## 극지방 위도

|위도| > 66.5°에서 Placidus / Koch / Regiomontanus 시스템은 수학적으로 정의되지 않습니다. Swiss Ephemeris는 자동으로 Porphyry로 대체하며, 우리의 API는 다음과 같은 경고를 추가합니다:

```json
{
  "system": "P",
  "warning": "위도 68.96° (> 66.5°)에서 Placidus 시스템은 정의되지 않습니다. Swiss Ephemeris가 Porphyry로 대체했습니다..."
}
```

## 지속적인 검증

Regression은 **모든 PR에 대해 CI를 통해 검증**됩니다:

- `api-calc/tests/endpoints/` — {siteMeta.snapshotCount}개의 snapshot (Monroe / Diana / Einstein) + synastry / composite / davison
- `.github/workflows/api-accuracy.yml` — PR 시 자동 실행
- swetest CGI + Kerykeion을 통한 triangulation — 매주
- Dependabot을 통한 upstream Swiss Ephemeris 모니터링

## 알려진 제한 사항

- **범위 외 날짜** (1800년 이전 및 2399년 이후): Moshier analytical 사용, 정확도 ~0.1" (DE431 파일 사용 SWIEPH의 < 0.01"에 비해)
- **True Lilith (id=13) vs Mean Lilith (id=12)**: 최대 12° 차이 — 기본적으로 Mean Lilith (안정적인 동작), True Lilith는 `planetIds: [13]`으로 접근 가능
- **Topocentric vs 지구중심**: 기본적으로 지구중심

## 참고 자료

- Swiss Ephemeris: https://www.astro.com/swisseph/
- swetest CGI: https://www.astro.com/swisseph/swetest.htm
- NASA 일식 카탈로그: https://eclipse.gsfc.nasa.gov/
- Kerykeion: https://github.com/g-battaglia/kerykeion
- Astrodienst: https://www.astro.com/

## 문의

정확성에 대한 질문: support@astroway.info로 차트 데이터와 예상 레퍼런스(astro.com 또는 기타 권위 있는 소스)를 포함하여 문의하세요.
