Python·DuckDB·World Bank API로 아프리카 경제 데이터 파이프라인 구축

발행: (2026년 5월 23일 PM 09:41 GMT+9)
9 분 소요
원문: Dev.to

출처: Dev.to

모든 데이터 엔지니어가 겪는 고충: 기술적으로 인상적이면서도 실제로 유용한 프로젝트를 찾는 일. 오늘은 AfriData Pipeline을 소개합니다 — 54개 아프리카 국가의 경제 데이터를 추출하고, DuckDB 분석 웨어하우스에 적재한 뒤, 인터랙티브 대시보드로 제공하는 프로덕션 급 ETL 시스템입니다.
유료 API도, 클라우드 서비스도 필요 없습니다. 오직 Python, DuckDB, 그리고 무료 공개 데이터를 사용합니다.

아프리카 경제는 빠르게 성장하고 있지만, 깨끗하고 통합된 경제 데이터를 찾는 일은 의외로 어렵습니다. 세계은행(World Bank)은 16,000개가 넘는 지표를 제공하는 훌륭한 무료 API를 가지고 있지만, 원시 API 응답을 실제로 활용 가능한 형태로 만들려면 꽤 많은 엔지니어링이 필요합니다.

이 프로젝트가 보여주는 내용:

  • 적절한 오류 처리와 재시도를 갖춘 ETL 파이프라인 설계
  • DuckDB에서의 차원 모델링(스타 스키마)
  • 데이터 품질 엔지니어링 — 완전성, 유효성, 최신성에 대한 자동 검사
  • 원시 API부터 인터랙티브 대시보드까지 전 스택 제공

World Bank API v2 → 추출 (httpx) → 변환 (Python) → 적재 (DuckDB)
                                                                ↓
                                                        JSON 내보내기 → 정적 대시보드 (Vercel)

파이프라인은 13,500개의 데이터 포인트(54개 국가 × 10개 지표 × 25년)를 50초 미만에 처리합니다.
다음과 같은 지표들을 선택해 포괄적인 경제 이야기를 구성했습니다:

IndicatorCategoryWhy It Matters
GDP (US$)Economy총 경제 생산량
GDP Growth (%)Economy경제 성장 모멘텀
PopulationDemographics규모 맥락
Inflation (CPI)Economy생활비 압박
UnemploymentLabor고용 시장 건강
Life ExpectancyHealth삶의 질 대리 지표
Internet Users (%)Technology디지털 준비도
Electricity Access (%)Infrastructure개발 기반
Literacy Rate (%)Education인적 자본
FDI Inflows (% GDP)Investment외부 신뢰도

World Bank API v2는 매우 간단합니다 — 인증이 필요 없고, JSON 응답이며, 한 번의 요청에 여러 국가를 배치할 수 있습니다:

import httpx
import time

WB_BASE = "https://api.worldbank.org/v2"
MAX_RETRIES = 3

def extract_indicator(client: httpx.Client, indicator_code: str, 
                      country_codes: str) -> list[dict]:
    url = (f"{WB_BASE}/country/{country_codes}/indicator/{indicator_code}"
           f"?format=json&date=2000:2024&per_page=10000")

    for attempt in range(MAX_RETRIES):
        try:
            resp = client.get(url, timeout=60)
            resp.raise_for_status()
            data = resp.json()
            # World Bank returns [metadata, records]
            if isinstance(data, list) and len(data) == 2:
                return data[1] or []
        except (httpx.HTTPStatusError, httpx.ReadTimeout) as e:
            delay = 2 * (2 ** attempt)
            time.sleep(delay)
    return []

핵심 설계 결정

  • 실패 시 지수 백오프(2 s, 4 s, 8 s)
  • 지표당 단일 요청 — 세미콜론으로 구분된 국가 코드를 사용해 54개 국가를 한 번에 조회
  • 60 초 타임아웃 — 일부 지표는 대용량 페이로드를 반환
  • 지표 간 0.5 s 지연 — 무료 API 사용 정책을 존중

DuckDB는 이 용도에 딱 맞습니다: 초고속 분석, 설정 필요 없음, 단일 포터블 파일.

dim_country ◄──── fact_indicators ────► dim_indicator
     │                  │
     └────────── dim_date ──────────────┘
import duckdb

def create_schema(conn):
    conn.execute("""
        CREATE TABLE IF NOT EXISTS fact_indicators (
            country_key  INTEGER,
            indicator_key INTEGER,
            date_key     INTEGER,
            value        DOUBLE,
            yoy_change   DOUBLE,
            extracted_at TIMESTAMP DEFAULT current_timestamp,
            PRIMARY KEY (country_key, indicator_key, date_key)
        )
    """)
    # Plus dim_country (54 rows), dim_indicator (10 rows), dim_date (25 rows)

변환 레이어에서는 각 데이터 포인트에 대해 전년 대비 변화를 계산합니다:

def calculate_yoy(current, previous):
    if current is not None and previous is not None and previous != 0:
        return round(((current - previous) / abs(previous)) * 100, 2)
    return None

이것이 장난감 프로젝트와 프로덕션 프로젝트를 구분하는 포인트입니다. 품질 프레임워크는 세 가지 차원을 평가합니다:

  1. 완전성 — 기대되는 데이터 포인트 중 비null 비율은?

    • Literacy Rate: 18 %만 완전 (데이터가 희박)
    • Population: 100 % 완전 (모든 국가·연도)
  2. 유효성 — 값이 예상 범위 내에 있는가?

    • Life expectancy: 25‑95 년 ✅
    • GDP: $1 M‑$10 T ✅
    • Inflation: -30 % ~ 10 000 % (극심한 인플레이션도 존재) ✅
  3. 신선도 — 최신 데이터는 언제인가?

    • GDP: 2024 ✅
    • Literacy: 2021 ⚠️ (조사 빈도가 낮음)

최종 점수: 95.8/100 — 문해율 데이터가 희박해 완전성 점수가 약간 낮았습니다(조사 기반 지표는 흔히 이런 양상을 보임).

대시보드는 정적 사이트(HTML + Tailwind CSS + Chart.js + Leaflet.js)이며, 사전에 내보낸 JSON 파일을 로드합니다.

주요 기능

  • 🗺️ Choropleth 지도 — 아프리카 국가를 클릭해 지표 전환
  • 📈 국가 비교 — 25년 동안 최대 6개 국가를 비교
  • 🏆 랭킹 테이블 — 지표별 정렬 가능
  • 🌙 다크 모드 — 전체 테마 지원
  • 📱 반응형 — 모바일에서도 작동

대시보드는 파이프라인이 내보낸 네 개의 JSON 파일을 사용합니다:

  • country_profiles.json — 국가별 전체 데이터 (897 KB)
  • rankings.json — 지표별 사전 정렬 랭킹
  • summary_stats.json — 집계 통계
  • quality_report.json — 데이터 품질 투명성 보고서

GitHub Actions 워크플로우가 매일 UTC 06:00에 파이프라인을 실행합니다:

name: Daily ETL Pipeline
on:
  schedule:
    - cron: '0 6 * * *'
  workflow_dispatch:

jobs:
  etl:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-python@v5
        with: { python-version: '3.12' }
      - run: pip install -r requirements.txt
      - run: python -m pipeline.main all
      - run: |
          git config user.name "github-actions[bot]"
          git add dashboard/data/
          git diff --cached --quiet || git commit -m "chore: update data"
          git push

신선한 데이터 → 커밋된 JSON → Vercel 자동 배포 → 최소한의 수동 개입.

무료 API는 과소평가되기 쉽습니다 — 세계은행 API는 깊이가 놀랍습니다. 인증도 없고, 신경 쓸 정도의 레이트 제한도 없으며, 25년 이상의 히스토리를 제공합니다.

DuckDB는 중소 규모 분석 워크로드에 혁신적입니다. 설정 없이 단일 파일만 있으면 13 K+ 행을 밀리초 단위로 분석할 수 있습니다.

데이터 품질은 선택 사항이 아닙니다 — 신뢰할 수 있는 세계은행 데이터라도 누락, 희박한 지표, 예상치 못한 값이 존재합니다. 품질 검사는 파이프라인에 내장해야 합니다, 사후 작업이 아니라.

정적 대시보드는 확장성이 뛰어납니다 — ETL 시점에 JSON을 미리 계산해 두면, 대시보드는 순수 정적 사이트가 됩니다. 백엔드, DB 연결, 서버 비용이 전혀 없습니다. Vercel에 무료로 배포하세요.

스타 스키마는 여전히 유효합니다 — 데이터 레이크와 비정규화 테이블이 대세인 시대에도 차원 모델링은 데이터를 쿼리하기 쉽고 이해하기 쉽게 만들어 줍니다.


직접 해보기

전체 프로젝트는 오픈 소스입니다:
GitHub: hajirufai/afridata-pipeline

스택: Python 3.12, httpx, DuckDB, Chart.js, Leaflet.js, Tailwind CSS

git clone https://github.com/hajirufai/afridata-pipeline.git
cd afridata
0 조회
Back to Blog

관련 글

더 보기 »

내 스킬

프로젝트를 위한 AI 지시문을 만들고, 설치하고, 관리하세요 — 코딩이 필요 없습니다. CREATE 이름을 정하고, 카테고리를 선택하고, 원하는 것을 설명하세요 — 마법사가 자동으로 구성합니다.