왜 위성 추론은 일반 ML과 다른가

보통 ML 모델은 몇 MB 데이터를 넣고 1초 안에 결과를 뽑아요. LLM이 문단 하나 처리하거나, 스마트폰 사진 한 장 분석하는 정도죠. 그런데 지구관측(Earth Observation) 추론은 스케일이 완전히 다릅니다. 하나의 파인튜닝 작업이 테라바이트급 데이터를 옮기면서 몇 시간씩 돌아가요.

입력 데이터도 복잡해요. 여러 스펙트럼 밴드, 센서 타입, 시점(time step)이 뒤섞여 있고, 제공자마다 투영법(projection)과 해상도가 다릅니다. 구름에 가려진 관측값도 많고요. 게다가 출력이 지도라서, 모든 예측값이 주변 지역과 동일한 좌표계에 정밀하게 정렬돼야 합니다.

가장 큰 병목은 데이터 확보 단계예요. 실제로 예측 작업은 모델을 돌리는 시간보다 이미지를 다운로드하고 전처리하는 데 더 많은 시간을 쓰는 경우가 많습니다. 그래서 데이터 파이프라인이 전체 성능을 좌우하죠.

이 글은 AI2(Allen Institute for AI)가 공개한 OlmoEarth 플랫폼 구축 사례를 바탕으로, 대규모 지구관측 시스템 설계의 핵심을 재구성한 것입니다. 근거자료는 OlmoEarth 인프라 블로그에서 확인할 수 있어요.

Distributed server cluster architecture diagram for large-scale geospatial inference pipeline Development Concept Image

핵심 설계: 하드웨어를 작업에 맞춰 쪼개라

가장 중요한 원칙은 **"비싼 GPU한테 잡일 시키지 말자"**예요. 데이터 확보와 전처리가 런타임을 지배한다면, 그 작업을 GPU에 맡기는 순간 가장 비싼 자원이 CPU로도 충분한 일을 하게 됩니다. 그래서 OlmoEarth는 각 작업을 세 단계로 나누고, 각 단계에 맞는 하드웨어 프로파일을 매칭합니다.

단계하드웨어역할
데이터 확보/전처리CPU, 고I/O이미지 fetch, 재투영, 정렬, 정규화 후 고속 로딩 포맷으로 저장
추론GPU모델 forward pass 실행, 최소 가공 출력만 스토리지에 기록
후처리CPU윈도우별 출력 병합, 마스킹/리스케일, Zarr/GeoTIFF/GeoJSON 내보내기

이 구조의 핵심은 멀티프로세스 데이터 로더가 GPU를 계속 먹여주는 동안, 완료된 출력은 곧바로 blob 스토리지로 스트리밍된다는 점이에요. GPU가 노는 시간을 최소화하는 거죠.

파티셔닝: 하나의 요청, 수천 개의 워커

OlmoEarth Run 실행 레이어는 작업 대상 지역을 워커(compute instance) 크기에 맞게 파티션으로 나누고, 다시 모델이 처리할 윈도우로 세분화합니다. 각 윈도우는 독립적인 forward pass로 처리되니까, 지도의 한쪽이 다른 쪽을 기다릴 필요가 없어요.

# 파티셔닝 개념을 단순화한 의사 코드
def run_inference(region, model, workers):
    partitions = split_by_worker_size(region)      # 주(state) 규모 → 수백 개
    tasks = []
    for p in partitions:
        for w in subdivide_into_windows(p):        # 윈도우 단위로 분할
            tasks.append({"window": w, "overlap": True})  # 인접 파티션은 살짝 겹침
    # 파티션은 독립적이므로 수천 인스턴스에 동시 fan-out
    results = parallel_map(tasks, model.forward, max_workers=workers)
    return reconcile_seams(results)  # 겹친 부분 병합해 이음새 제거

실제로 북미 전체 산불 위험 지도를 만들 때 피크 시점에 약 19,600 CPU와 994 GPU를 병렬로 돌렸고, 네트워크 처리량은 168 GB/s를 넘었습니다. 직렬로 계산하면 4,737시간 걸릴 작업을 약 30.5시간으로 줄였으니 155배 속도 향상이죠.

다만 fan-out이 무한정 늘어나진 않아요. 워커를 늘리면 클라우드 쿼터와 부딪히니까, 병렬성은 작업별로 조절하는 노브(knob)입니다. 해상도는 데이터량/연산량과 디테일을, 모델 크기는 GPU 시간과 정확도를, 원본 이미지 캐싱은 스토리지와 반복 실행 속도를 트레이드오프해요.

Cloud-based satellite imagery processing workflow with STAC catalog and COG windowed reads IT Technology Image

주의사항: 화려한 숫자 뒤의 함정들

1. 외부 STAC API를 직접 때리면 안 된다

큰 추론 작업 하나가 수천 개의 메타데이터 쿼리를 동시에 만들어냅니다. ESA나 Microsoft Planetary Computer의 STAC API는 그런 동시성을 감당하도록 설계되지 않았어요. 그래서 OlmoEarth는 자체 메타데이터 인덱스를 유지합니다. AWS Open Data처럼 SNS 알림을 주는 곳은 변경 스트림을 받고, 안 주는 곳은 몇 분 간격으로 폴링하죠. 결과적으로 외부 서비스 요청은 작업 폭발이 아니라 새 이미지 발행 속도에 맞춰 완만하게 흘러갑니다.

2. 실패는 정상이다

이 스케일에서는 실패가 예외가 아니라 기본값이에요. 제공자가 느려지거나 잠깐 죽고, 메타데이터는 있는데 실제 밴드가 없고, 구름 때문에 쓸 만한 관측이 부족하고, 태스크가 그냥 크래시하기도 합니다. 그래서 모든 태스크를 **재진입 가능(reentrant)하고 멱등(idempotent)**하게 설계해서, 그냥 다시 돌리면 안전하게 복구되도록 했어요. 재시도 가능 오류와 치명적 오류를 구분하고, 대체 제공자로 폴백하고, 멈춘 러너를 감지해 재시작하는 모니터링 프로세스도 별도로 둡니다.

3. 데이터 제공자에게 바라는 것

OlmoEarth 팀이 정리한 "지구관측 데이터 발행 모범 사례"는 실무에 바로 쓸 수 있어요.

  • 새 이미지 발행 시 큐 기반 알림 제공
  • 주요 클라우드에 특이한 rate limit 없이 저장
  • range read를 지원하는 클라우드 최적화 포맷(COG, Zarr)으로 제공

이 세 가지만 지켜도 다운스트림 파이프라인 복잡도가 확 줄어듭니다.

국내 환경에 적용한다면: 공공 위성 데이터(아리랑, 천리안 등)를 다룰 때도 이 원칙이 유효해요. 대부분의 국내 데이터 포털은 큐 알림이나 range read를 지원하지 않는 경우가 많아서, 인덱스 레이어를 직접 만들어야 하는 상황이 자주 생깁니다. 이때 COG 변환 파이프라인을 초기에 깔아두면 나중에 후회할 일이 줄어요.

Wildfire risk map visualization generated from continent-scale satellite inference on OlmoEarth platform Dev Environment Setup

결론: 이 아키텍처에서 가져갈 세 가지

  1. 하드웨어 프로파일 분리는 선택이 아니라 필수. CPU/GPU 경계를 명확히 긋지 않으면 비용이 조용히 새어나갑니다.
  2. 인덱스는 외부 서비스의 쿠션이다. 원본 카탈로그를 직접 때리지 말고, 발행 속도에 맞춰 흘러가는 자체 인덱스를 두세요.
  3. 멱등성은 대규모 시스템의 생존 조건. 재시도가 안전하지 않으면 장애 복구는 공포가 됩니다.

OlmoEarth 팀의 로드맵에는 자동 스케줄링, 변화 감지/알림, 임베딩 사전 계산, 멀티 클라우드 지원 등이 포함돼 있어요. 특히 임베딩을 전 지구 규모로 미리 계산해서 원본 이미지 forward pass를 대체하는 방향은, 비용 효율화를 노리는 모든 지구관측 팀이 주목할 만합니다.

함께 보면 좋은 글

다음 단계 학습 방향

  • STAC 스펙과 COG/Zarr 포맷을 직접 다뤄보세요. 데이터 레이어 이해가 전체 설계의 절반입니다.
  • 멱등 태스크 설계 패턴(예: Airflow/Temporal의 재시도 모델)을 학습하면 장애 복구 설계가 쉬워집니다.
  • 관심 있다면 OlmoEarth 모델 자체를 파인튜닝해보며, 플랫폼이 감춰준 복잡도를 체감해보는 것도 좋아요.
본 콘텐츠는 신뢰할 수 있는 출처를 바탕으로 AI 도구를 활용하여 초안이 작성되었으며, 편집자의 검토를 거쳐 발행되었습니다. 전문가의 조언을 대체하지 않습니다.