사이트 도구


세계기상:gts_전문자료

세계기상 데이터

1. 개요 (Overview)

세계기상기구(WMO) 정보시스템은 전세계 기상기후 데이터를 실시간으로 교환하기 위한 핵심 인프라입니다. 대한민국 기상청(KMA)은 세계적 수준의 기상 기술력을 인정받아, 전세계 오직 15개국만이 보유한 글로벌 정보 서비스 센터인 GISC 서울(Global Information System Contre Seoul)을 운영하고 있습니다. GISC 서울은 기상데이터를 총괄하는 동시에 전 세계를 잇는 기상 데이터의 관문 역할을 수행하며, 다음과 같은 단계를 발전해보고 있습니다.

GTS(Global Telecommunication System): 1960년대부터 운영된 전용망기반의 통신체계입니다. 전 세계 기상 관측자료를 폐쇄형 네트워크를 통해 실시간으로 주고받는 전통적인 통로입니다.

WIS(WMO Information System): GTS를 확장한 통합 정보 시스템입니다. 기상뿐만 아니라 수문, 해양 등 WMO의 모든 데이터를 통합관리하며, GISC서울의 포털을 통해 전 세계 사용자가 데이터를 검색하고 접근할 수 있게 합니다.

WIS2.0: 2025년부터 도입된 차세대 시스템입니다. 클라우드와 인터넷 표준기술(Web API, MQTT등)을 활용하여 고해상도 기상데이터를 더욱 빠르고 개방적으로 공유하는 것을 목표로 합니다.

전문(專文)의 개념: 통신 효율을 극대화하기 위해 약속된 부호와 형식으로 압축된 데이터 메시지입니다.

2. 관측 및 데이터 수집 (Observation & Collection)

GTS는 전 세계 기상 관측 자료를 실시간으로 수집하고 교환하기 위해 구축된 WMO의 중추적인 전용 통신망입니다. 이 시스템은 정해진 규격과 경로를 통해 데이터의 신뢰성과 즉시성을 보장합니다.

2.1 데이터 수집원 (Data Sources)

GTS를 통해 수집되는 관측 자료는 전 지구적 관측 시스템(GOS)으로부터 발생하며, 주요 항목은 다음과 같습니다.

지상 및 해양 관측: 전 세계 기상관측소(ASOS), 해상부이(Buoy), 선박 등에서 측정된 기온, 기압, 풍향/풍속 데이터가 실시간으로 수집됩니다.

고층 및 위성관측: 라디오존데를 이용한 고층기상관측자료와 천리안위성 등 기상위성에서 생산된 방대한 원격 탐사 자료가 포함됩니다.

2.2 수집 메커니즘의 진화

GTS방식: 정해진 경로를 통해 텍스트, 이진형식(BUFR,GRIB)의 데이터를 순차적으로 전달하는 방식

WIS2.0방식: 발행-구독(Publish-Subscribe) 모델을 도입한 MQTT방식, 데이터가 생성되는 즉시 글로벌 서비스(브로커, 캐시)를 통해 사용자에게 알림을 보내고, 사용자가 즉시 데이터를 다운받는 방식

3. 산출물 (Data Products)

수집된 데이터는 가공을 거쳐 다양한 형태의 전문적인 기상 정보로 배포하며, WMO 표준데이터(TAC, BUFR, GRIB)형식을 따릅니다.

TAC(Traditional Alphanumeric Codes) 전문: 사람이 읽을 수 있는 문자/숫자 조합의 고전적 형식입니다.

  • SYNOP: 지상 종관 관측 보고.
  • TEMP: 고층 기상 관측(레윈존데) 보고.
  • METAR/SPECI: 항공기 이착륙을 위한 공항 기상 실황 및 특별 보고.

BUFR(Binary Universal Form for the Representation): WMO가 권장하는 이진 압축 형식으로, 데이터 용량을 획기적으로 줄이면서 다양한 관측 요소를 포함할 수 있습니다. 현재 TAC에서 BUFR로의 전환이 완료 단계에 있습니다.

GRIB(General Regularly-distributed Information in Binary): 수치예보 모델의 격자 데이터를 전송하기 위한 표준 이진 포맷입니다. 기상청의 수치모델 결과물도 이 형식으로 세계에 공유됩니다.

4. 자료의 활용 (Applications)

전 지구 GTS 전문자료는 현대 기상학의 모든 분야에서 '연료'와 같은 역할을 합니다.

수치예보 모델 입력(Data Assimilation): 기상청 전 지구 수치예보 모델(KIM)의 초기값을 생성하기 위해 전 세계의 GTS 자료를 입력합니다. 자료가 많고 정확할수록 예보의 정확도가 기하급수적으로 상승합니다.

국제 항공 및 해상 안전: 전 세계 공항의 METAR 정보를 실시간 확인하여 장거리 비행의 연료 산정 및 비행 경로를 결정합니다. 해상의 부이 및 선박 자료는 선박의 안전 항해(Weather Routing)에 직결됩니다.

기후 변화 감시: 전 지구적 기온 상승 추세 및 이상 기후(엘니뇨, 라니냐 등)를 감시하기 위한 시공간적 연속 데이터셋으로 활용됩니다.

학술 및 산업 연구: 해외 수출입 물류 기업, 글로벌 신재생 에너지 기업 등이 해외 지점의 기후 리스크를 분석하는 데 기초 자료로 사용합니다.

5. 활용방안

5.1. 라이브러리 설치 및 기본 설정

GTS 지상관측 자료 조회 및 기온 비교 그래프 생성을 위한 라이브러리를 설치합니다.

pip install requests pandas matplotlib
import requests
import pandas as pd
import matplotlib
matplotlib.use("Agg")
import matplotlib.pyplot as plt
 
from io import StringIO
from datetime import datetime, timedelta, timezone

API 인증키와 API 주소, 조회할 도시 및 시간 조건을 설정합니다.

AUTH_KEY = "본인의_API_인증키"
 
BASE_URL = "https://apihub.kma.go.kr/api/typ01/url/gts_bufr_syn1.php"
 
STATIONS = {
    "Seoul": 47108,
    "Tokyo": 47662,
    "Beijing": 54511,
}
 
END_TM_UTC = "202211301200"
DTM_HOURS = 24
PLOT_INTERVAL_HOURS = 3
 
OUTPUT_PNG = "gts_temperature_compare.png"

BASE_URL은 (신)기상자료개방포털 > API > 세계기상 > GTS관측 > “GTS 지상관측 조회(BUFR자료를 TAC 형태로 변환)” 메뉴의 호출 URL을 사용합니다.

STATIONS에는 비교할 도시명과 GTS 지점번호를 입력합니다.

END_TM_UTC는 조회 종료시각이며 UTC 기준으로 입력합니다.

5.2. GTS 지상관측 자료 조회 및 정리

API를 호출하여 각 도시의 GTS 지상관측 자료를 조회합니다.

def fetch_station_text(stn_id, tm_str, dtm_hours):
    params = {
        "tm": tm_str,
        "dtm": dtm_hours,
        "stn": stn_id,
        "help": 1,
        "authKey": AUTH_KEY,
    }
 
    response = requests.get(BASE_URL, params=params, timeout=60)
    response.raise_for_status()
 
    return response.text

API 응답에는 설명 줄과 실제 데이터 줄이 함께 포함되어 있습니다.
설명 줄은 #으로 시작하고, 실제 데이터 줄은 숫자로 시작하므로 숫자로 시작하는 줄만 추출합니다.

def extract_data_lines(text):
    data_lines = []
 
    for raw_line in text.splitlines():
        line = raw_line.strip()
 
        if not line:
            continue
 
        if line[0].isdigit():
            data_lines.append(line)
 
    return data_lines

추출한 데이터 줄을 pandas DataFrame으로 변환합니다.
이때 시간 컬럼은 UTC 기준으로 읽은 뒤, 한국시간(KST) 컬럼도 함께 생성합니다.

COLUMNS = [
    "YYMMDDHHMI", "STN", "IW", "IR", "IX", "CH", "VV", "CA",
    "WD", "WS", "TA", "TD", "HM", "PA", "PS", "PT", "PR", "RN",
    "RH", "WC", "WP", "CD", "CL", "CM", "CT", "S19", "TM", "Tm",
    "S33", "S34", "S35", "S36", "S37", "S28", "S29"
]
 
def parse_text_to_dataframe(text):
    data_lines = extract_data_lines(text)
 
    if len(data_lines) == 0:
        return pd.DataFrame()
 
    table_text = "\n".join(data_lines)
 
    df = pd.read_csv(
        StringIO(table_text),
        sep=r"\s+",
        header=None,
        names=COLUMNS,
        engine="python"
    )
 
    for col in COLUMNS:
        if col != "YYMMDDHHMI":
            df[col] = pd.to_numeric(df[col], errors="coerce")
 
    df["datetime_utc"] = pd.to_datetime(
        df["YYMMDDHHMI"].astype(str),
        format="%Y%m%d%H%M",
        errors="coerce"
    )
 
    kst = timezone(timedelta(hours=9))
    df["datetime_utc"] = df["datetime_utc"].dt.tz_localize("UTC")
    df["datetime_kst"] = df["datetime_utc"].dt.tz_convert(kst)
 
    return df

여러 도시의 자료를 조회한 뒤 하나의 DataFrame으로 합칩니다.

def collect_all_cities(stations, tm_str, dtm_hours):
    all_frames = []
 
    for city, stn_id in stations.items():
        text = fetch_station_text(stn_id, tm_str, dtm_hours)
        df = parse_text_to_dataframe(text)
 
        if df.empty:
            continue
 
        df = df[df["STN"] == stn_id].copy()
        df["city"] = city
 
        all_frames.append(df)
 
    if len(all_frames) == 0:
        return pd.DataFrame()
 
    result = pd.concat(all_frames, ignore_index=True)
    result = result.sort_values(["city", "datetime_utc"]).reset_index(drop=True)
 
    return result

5.3. 기온 자료 저장 및 그래프 표출

수집한 자료 중 도시명, 지점번호, 시간, 기온만 추출하여 기온 비교용 테이블을 생성합니다.

def build_temperature_table(df):
    out = df[["city", "STN", "datetime_utc", "datetime_kst", "TA"]].copy()
    out = out.sort_values(["datetime_utc", "city"]).reset_index(drop=True)
 
    return out

기온 비교용 자료를 CSV 파일로 저장합니다.

def save_csv(df, filename):
    df.to_csv(filename, index=False, encoding="utf-8-sig")
    print(f"[저장 완료] {filename}")

도시별 기온 변화를 선 그래프로 저장합니다.

def plot_temperature(temp_df):
    plot_df = temp_df.pivot_table(
        index="datetime_kst",
        columns="city",
        values="TA",
        aggfunc="first"
    )
 
    plt.figure(figsize=(12, 6))
 
    for city in plot_df.columns:
        plt.plot(
            plot_df.index,
            plot_df[city],
            marker="o",
            linewidth=2,
            label=city
        )
 
    plt.title("City Temperature Comparison using GTS SYNOP")
    plt.xlabel("Time (KST)")
    plt.ylabel("Temperature (°C)")
    plt.grid(True)
    plt.legend()
    plt.xticks(rotation=45)
    plt.tight_layout()
 
    plt.savefig(OUTPUT_PNG, dpi=150, bbox_inches="tight")
    plt.close()

전체 실행 코드는 다음과 같습니다.

end_tm_str = END_TM_UTC
 
raw_df = collect_all_cities(STATIONS, end_tm_str, DTM_HOURS)
 
temp_df = build_temperature_table(raw_df)
 
save_csv(raw_df, "gts_all_columns_raw.csv")
save_csv(temp_df, "gts_temperature_only.csv")
 
plot_temperature(temp_df)

실행하면 다음 파일이 생성됩니다.

city STN datetime_utc datetime_kst TA
Beijing 54511 2022-11-29 12:00:00+00:00 2022-11-29 21:00:00+09:00 -7.5
Seoul 47108 2022-11-29 12:00:00+00:00 2022-11-29 21:00:00+09:00 1.0
Tokyo 47662 2022-11-29 12:00:00+00:00 2022-11-29 21:00:00+09:00 18.9
Beijing 54511 2022-11-29 15:00:00+00:00 2022-11-30 00:00:00+09:00 -8.2
Seoul 47108 2022-11-29 15:00:00+00:00 2022-11-30 00:00:00+09:00 -1.6
Tokyo 47662 2022-11-29 15:00:00+00:00 2022-11-30 00:00:00+09:00 20.3
Beijing 54511 2022-11-29 18:00:00+00:00 2022-11-30 03:00:00+09:00 -8.5
Seoul 47108 2022-11-29 18:00:00+00:00 2022-11-30 03:00:00+09:00 -4.1
Tokyo 47662 2022-11-29 18:00:00+00:00 2022-11-30 03:00:00+09:00 16.0
Beijing 54511 2022-11-29 21:00:00+00:00 2022-11-30 06:00:00+09:00 -7.9
Seoul 47108 2022-11-29 21:00:00+00:00 2022-11-30 06:00:00+09:00 -6.0
Tokyo 47662 2022-11-29 21:00:00+00:00 2022-11-30 06:00:00+09:00 15.7
Beijing 54511 2022-11-30 00:00:00+00:00 2022-11-30 09:00:00+09:00 -8.6
Seoul 47108 2022-11-30 00:00:00+00:00 2022-11-30 09:00:00+09:00 -6.6
Tokyo 47662 2022-11-30 00:00:00+00:00 2022-11-30 09:00:00+09:00 16.6
Beijing 54511 2022-11-30 03:00:00+00:00 2022-11-30 12:00:00+09:00 -4.0
Seoul 47108 2022-11-30 03:00:00+00:00 2022-11-30 12:00:00+09:00 -4.7
Tokyo 47662 2022-11-30 03:00:00+00:00 2022-11-30 12:00:00+09:00 18.5
Beijing 54511 2022-11-30 06:00:00+00:00 2022-11-30 15:00:00+09:00 -1.4
Seoul 47108 2022-11-30 06:00:00+00:00 2022-11-30 15:00:00+09:00 -2.7