문서의 이전 판입니다!
목차
베스트트랙 (Best-track)
1. 개요 (Overview)
베스트트랙은 태풍 종료 후, 예보 현업 상황에서 실시간으로 활용하지 못했던 관측 자료들을 수집하여 충분한 시간을 거쳐 정밀 재분석하여 생산한 최적의 태풍정보입니다. 태풍 분석 정보의 불확실성을 최소화하고, 모든 가용 데이터를 종합하여 도출한 '태풍 분석의 결정체'라 할 수 있습니다.
2. 절차
베스트트랙은 태풍 종료 후 다음과 같은 절차를 통해 생산되고, 확정됩니다.
| 자료 수집 | 베스트트랙 초안 작성 | 태풍예보관 교차검토 | 재분석 검토(2차) - 내외부 전문가2)- | 베스트트랙 확정 |
|---|---|---|---|---|
| 수시 | (당해) 1~2월 | 3~4월 | 5월 | 6월 |
3. 산출물 (Data Products)
태풍의 위치(위‧경도), 중심기압, 최대풍속, 강도 등급, 강풍반경, 폭풍반경 정보를 포함합니다.
3.1 베스트트랙 양식(예시)
| 등급 | 태풍호수 | 날짜(UTC) | 위치 | 강도 | 강풍반경 | 폭풍반경 | 태풍이름 | |||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 년 | 월 | 일 | 시 | 경도(°E) | 위도(°N) | 최대풍속(m/s) | 중심기압(hPa) | 장반경(km) | 단반경(km) | 단반경방향(°) | 장반경(km) | 단반경(km) | 단반경방향(°) | |||
| TS | 2401 | 2024 | 05 | 25 | 12 | 122.2 | 13.3 | 18 | 1000 | 180 | 110 | 270.0 | -999 | -999 | -999.9 | EWINIAR |
② 베스트트랙 세부내용
| 종류 | 자리수 | 세부내용 | |
|---|---|---|---|
| 등급 | 3자리 문자 | TD 열대저압부(Tropical Depression) 중심부근 최대풍속 14 m/s 이상인 열대저압부 |
|
| TS 열대폭풍(Tropical Storm) 중심부근 최대풍속 17 m/s 이상, 25 m/s 미만인 태풍 |
|||
| STS 강한열대폭풍(Severe Tropical Storm) 중심부근 최대풍속 25 m/s 이상, 33 m/s 미만인 태풍 |
|||
| TY 태풍(Typhoon) 중심부근 최대풍속 33 m/s 이상인 태풍 |
|||
| L 온대저기압(Extratropical Cyclone) | |||
| 태풍호수 | 4자리 정수 | 앞 두자리: 태풍 발생 해의 뒤 두자리 수 뒷 두자리: 그 해 발생한 TS이상의 강도를 가진 폭풍의 개수 |
|
| 날짜 | 년 | 4자리 정수 | 년 (年, Year) |
| 월 | 2자리 정수 | 월 (月, Month) | |
| 일 | 2자리 정수 | 일 (日, Day) | |
| 시 | 2자리 정수 | 시 (UTC) | |
| 위치 | 경도 | 5자리 실수 | 단위: 도 (0.0~360.0°) |
| 위도 | 5자리 실수 | 단위: 도 (-90.0~90.0°) | |
| 강도 | 풍속 | 2자리 실수 | 중심부근 최대풍속, 단위: m/s (10분 평균 풍속) 존재하지 않을 시: -9 |
| 기압 | 4자리 정수 | 중심기압, 단위: hPa | |
| 강풍반경 | 장반경 | 4자리 정수 | 강풍(풍속 15 m/s 이상) 장반경, 단위: km 존재하지 않을 시: -999 |
| 단반경 | 4자리 정수 | 강풍(풍속 15 m/s 이상) 단반경, 단위: km 존재하지 않을 시: -999 |
|
| 방향 | 6자리 실수 | 강풍(풍속 15 m/s 이상) 단반경의 방향 단위: 16방위(22.5° 단위, 0~337.5°) 존재하지 않을 시: -999.9 |
|
| 폭풍반경 | 장반경 | 4자리 정수 | 폭풍(풍속 25 m/s 이상) 장반경, 단위: km 존재하지 않을 시: -999 |
| 단반경 | 4자리 정수 | 폭풍(풍속 25 m/s 이상) 단반경, 단위: km 존재하지 않을 시: -999 |
|
| 방향 | 6자리 실수 | 폭풍(풍속 25 m/s 이상) 단반경의 방향 단위: 16방위(22.5° 단위, 0~337.5°) 존재하지 않을 시: -999.9 |
|
| 태풍이름 | 20자리 문자 | 영문 대문자로 표시 | |
4. 베스트트랙 제공 위치
• 기상청 누리집(https://www.kma.go.kr/kma/): 알림‧자료 > 기상간행물 > 국가태풍센터 간행물 > 베스트트랙
• 기상청 API허브(https://apihub.kma.go.kr/): 태풍 > 태풍 베스트트랙
• IBTrACS(International Best Track Archive for Climate Stewardship)
5. 활용방안
소스코드 : typhoon_besttrack_example.py
5.1. 라이브러리 설치 및 기본 설정
태풍 베스트트랙 자료를 조회하고 태풍 중심 위치 및 강풍반경을 시각화하기 위해 필요한 라이브러리를 설치합니다.
pip install requests pandas matplotlib cartopy numpy
import os
from datetime import datetime
import numpy as np
import requests
import pandas as pd
import matplotlib
matplotlib.use("Agg")
import matplotlib.pyplot as plt
from matplotlib import font_manager
from matplotlib.lines import Line2D
from matplotlib.patches import Patch
import cartopy.crs as ccrs
import cartopy.feature as cfeature
from cartopy.geodesic import Geodesic
API 인증키와 API 주소, 조회할 태풍 정보를 설정합니다.
AUTH_KEY = "본인의_API_인증키"
BASE_URL = "https://apihub.kma.go.kr/api/typ01/url/typ_besttrack.php"
YEAR = 2023
TCID = "2311"
TY_NAME = f"Typhoon {TCID}"
HELP = 1
RAW_TEXT_FILE = f"typhoon_besttrack_{YEAR}_{TCID}_raw.txt"
OUTPUT_CSV = f"typhoon_besttrack_{YEAR}_{TCID}.csv"
OUTPUT_PNG = f"typhoon_besttrack_map_{YEAR}_{TCID}.png"
BASE_URL은 (신)기상자료개방포털 > API > 태풍 > 태풍 베스트트랙메뉴의 호출 URL을 사용합니다.
YEAR에는 태풍 발생 연도를 입력합니다.
TCID에는 태풍 번호를 입력합니다.
예를 들어 2023년 11호 태풍은 2311로 입력합니다.
5.2. 태풍 베스트트랙 자료 조회 및 정리
태풍 베스트트랙 API를 호출하여 응답 원문 TEXT를 받아옵니다.
def fetch_besttrack_text(year, tcid):
params = {
"year": year,
"tcid": tcid,
"help": HELP,
"authKey": AUTH_KEY,
}
response = requests.get(BASE_URL, params=params, timeout=60)
response.raise_for_status()
text = response.text
with open(RAW_TEXT_FILE, "w", encoding="utf-8") as f:
f.write(text)
return text
API 응답에는 설명 줄과 실제 데이터 줄이 함께 포함됩니다.
설명 줄은 #으로 시작하므로 제외하고 실제 데이터 줄만 사용합니다.
def extract_data_lines(text):
lines = []
for raw_line in text.splitlines():
line = raw_line.strip()
if not line:
continue
if line.startswith("#"):
continue
lines.append(line)
return lines
베스트트랙 응답 자료의 컬럼은 다음과 같습니다.
COLS = [
"GRADE",
"TYNO",
"YY",
"MM",
"DD",
"HH",
"LON",
"LAT",
"MAX_WS",
"PRES",
"R15",
"R25",
]
응답 텍스트를 pandas DataFrame으로 변환합니다.
def parse_besttrack_text(text):
data_lines = extract_data_lines(text)
rows = []
for line in data_lines:
clean = line.replace(",", " ")
parts = [p for p in clean.split() if p]
if len(parts) < 12:
continue
rows.append(parts[:12])
df = pd.DataFrame(rows, columns=COLS)
return df
숫자형 컬럼과 시간 컬럼을 변환하고 결측값을 처리합니다.
def clean_besttrack_df(df):
numeric_cols = [
"TYNO", "YY", "MM", "DD", "HH",
"LON", "LAT", "MAX_WS",
"PRES", "R15", "R25"
]
for col in numeric_cols:
df[col] = pd.to_numeric(df[col], errors="coerce")
for col in ["MAX_WS", "PRES", "R15", "R25"]:
df.loc[df[col] <= -9, col] = pd.NA
if df["YY"].dropna().max() < 100:
df["YYYY"] = df["YY"].apply(
lambda x: int(2000 + x) if pd.notna(x) else pd.NA
)
else:
df["YYYY"] = df["YY"]
def make_dt(row):
try:
return datetime(
int(row["YYYY"]),
int(row["MM"]),
int(row["DD"]),
int(row["HH"])
)
except Exception:
return pd.NaT
df["datetime"] = df.apply(make_dt, axis=1)
df = df.dropna(subset=["LAT", "LON"]).copy()
df = df.sort_values("datetime").reset_index(drop=True)
return df
5.3. 태풍 중심 위치 및 강풍반경 표출
지도 표출을 위한 기본 지도를 생성합니다.
def setup_map():
fig = plt.figure(figsize=(12, 10))
ax = plt.axes(projection=ccrs.PlateCarree())
ax.add_feature(cfeature.LAND, facecolor="#f2f2f2")
ax.add_feature(cfeature.OCEAN, facecolor="#e6f2ff")
ax.add_feature(cfeature.COASTLINE, linewidth=0.8)
ax.add_feature(cfeature.BORDERS, linewidth=0.5)
ax.gridlines(
draw_labels=True,
linewidth=0.4,
linestyle="--",
alpha=0.5
)
return fig, ax
태풍 중심 위치를 선과 점으로 연결하여 태풍 경로를 표출합니다.
ax.plot(
df["LON"],
df["LAT"],
color="black",
linewidth=1.5,
linestyle="-",
transform=ccrs.PlateCarree()
)
ax.scatter(
df["LON"],
df["LAT"],
s=30,
color="royalblue",
edgecolors="black",
linewidths=0.3,
transform=ccrs.PlateCarree()
)
15m/s 및 25m/s 풍속반경을 원 형태로 표출합니다.
draw_wind_radius(
ax=ax,
lon=row["LON"],
lat=row["LAT"],
radius_value=row["R15"],
edgecolor="orange",
facecolor="gold",
alpha=0.10,
linewidth=0.8
)
draw_wind_radius(
ax=ax,
lon=row["LON"],
lat=row["LAT"],
radius_value=row["R25"],
edgecolor="red",
facecolor="red",
alpha=0.06,
linewidth=1.0
)
태풍 생성 지점, 소멸 지점, 최대세력 지점을 함께 표시합니다.
ax.scatter(
first_row["LON"],
first_row["LAT"],
s=120,
color="limegreen",
edgecolors="black",
marker="o"
)
ax.scatter(
last_row["LON"],
last_row["LAT"],
s=120,
color="black",
edgecolors="white",
marker="X"
)
ax.scatter(
peak_row["LON"],
peak_row["LAT"],
s=180,
color="magenta",
edgecolors="black",
marker="*"
)
최종 태풍 경로 지도는 PNG 파일로 저장합니다.
plt.savefig(
OUTPUT_PNG,
dpi=150,
bbox_inches="tight"
)
전체 실행 코드는 다음과 같습니다.
text = fetch_besttrack_text(YEAR, TCID)
df = parse_besttrack_text(text)
df = clean_besttrack_df(df)
df.to_csv(
OUTPUT_CSV,
index=False,
encoding="utf-8-sig"
)
plot_typhoon_track(df)
실행하면 다음 파일이 생성됩니다.
