콘텐츠로 이동

데이터셋 퍼블리싱 가이드

이 문서는 scripts/publish_to_hf.py 스크립트를 사용하여 공공데이터를 HuggingFace Hub 및 Kaggle에 퍼블리싱하는 전체 과정을 설명합니다.


개요

publish_to_hf.py는 config-driven 방식의 end-to-end 퍼블리싱 스크립트입니다. 하나의 YAML config 파일로 데이터 수집 → 변환 → Parquet 저장 → Dataset Card 생성 → HuggingFace 업로드까지 처리합니다.

이 스크립트는 향후 Builder의 Medallion Architecture(Bronze/Silver/Gold/Exporter/Publisher) 모듈로 분해될 레퍼런스 구현입니다.

[YAML Config] → fetch → transform → write_parquet → generate_card → upload_to_hf / upload_to_kaggle
                  │          │            │                │              │
               Bronze     Silver        Gold           Export         Publish (HF + Kaggle)

사전 준비

1. 환경변수 설정

~/.zshrc (또는 ~/.bashrc)에 다음 환경변수를 추가합니다:

# 공공데이터포털 API 키 (https://www.data.go.kr 에서 발급)
export KPUBDATA_DATAGO_API_KEY="your-api-key"

# HuggingFace API 토큰 (https://huggingface.co/settings/tokens 에서 발급)
export HF_TOKEN="hf_..."

# Kaggle API 인증 (https://www.kaggle.com/settings → API → Create New Token)
export KAGGLE_USERNAME="your-username"
export KAGGLE_KEY="your-api-key"

설정 후 반영:

source ~/.zshrc

Kaggle 대체 인증 방법: ~/.kaggle/kaggle.json 파일에 {"username": "...", "key": "..."} 형태로 저장해도 됩니다. 환경변수가 우선합니다.

2. HuggingFace 토큰 발급

  1. https://huggingface.co/settings/tokens 접속
  2. Create new Access Token 클릭
  3. 설정:
  4. Token type: Fine-grained
  5. Token name: kpubdata-publish (또는 원하는 이름)
  6. User permissions > Repositories: ✅ Write access to contents/settings
  7. Org permissions: 대상 org 선택 후 ✅ Write access to contents/settings
  8. 나머지 권한은 체크 해제
  9. 토큰 생성 후 HF_TOKEN 환경변수에 저장

3. HuggingFace Organization (선택)

org 단위로 데이터셋을 관리하려면:

  1. https://huggingface.co/organizations/new 에서 org 생성
  2. 토큰 발급 시 해당 org에 대한 write 권한 부여

4. Kaggle API 토큰 발급

  1. https://www.kaggle.com/settings 접속
  2. API 섹션에서 Create New Token 클릭
  3. 다운로드된 kaggle.json에서 usernamekey를 환경변수에 설정
  4. 주의: 새 토큰을 발급하면 이전 토큰은 즉시 폐기

Kaggle은 organization을 지원하지 않습니다. 모든 데이터셋은 개인 계정 소속입니다.

5. 의존성 설치

cd kpubdata-builder
uv sync --extra publish

publish extra에는 polars, huggingface-hub, kaggle이 포함됩니다.


사용법

기본 실행 (HuggingFace + Kaggle 모두 업로드)

uv run python scripts/publish_to_hf.py scripts/configs/seoul_apartment_trades.yaml

HuggingFace만 업로드

uv run python scripts/publish_to_hf.py scripts/configs/seoul_apartment_trades.yaml --target hf

Kaggle만 업로드

uv run python scripts/publish_to_hf.py scripts/configs/seoul_apartment_trades.yaml --target kaggle

로컬에서만 파일 생성 (업로드 안 함)

uv run python scripts/publish_to_hf.py scripts/configs/seoul_apartment_trades.yaml --local-only

드라이런 (업로드 시뮬레이션)

uv run python scripts/publish_to_hf.py scripts/configs/seoul_apartment_trades.yaml --dry-run

디버그 로깅

uv run python scripts/publish_to_hf.py scripts/configs/seoul_apartment_trades.yaml -v

CLI 옵션 요약

옵션 설명
config (필수) YAML config 파일 경로
--target 업로드 대상: hf (HuggingFace), kaggle, all (기본값: all)
--dry-run 업로드를 건너뛰고 로컬 파일만 생성 (업로드 시뮬레이션 로그 출력)
--local-only 로컬 파일 생성까지만 실행 (업로드 로직 자체를 건너뜀)
--verbose, -v DEBUG 레벨 로깅 활성화

Config YAML 스키마

Config 파일은 4개의 최상위 섹션으로 구성됩니다.

source — 데이터 수집 설정

source:
  provider: datago          # kpubdata provider 키
  dataset: apt_trade        # dataset 키
  list_all: true            # true면 자동 페이지네이션
  fetch_params:             # 각 항목이 하나의 API 호출
    - LAWD_CD: "11680"
      DEAL_YMD: "202401"
    - LAWD_CD: "11650"
      DEAL_YMD: "202401"
필드 타입 필수 설명
provider str kpubdata의 provider 이름
dataset str kpubdata의 dataset 이름
list_all bool trueds.list_all() 사용 (자동 페이지네이션)
fetch_params list[dict] API 호출 파라미터 목록. 각 항목이 별도 호출, 결과는 합산

transform — 데이터 변환 설정

transform:
  column_mapping:
    sggCd: district_code     # raw 필드명 → clean 컬럼명
    dealAmount: deal_amount_10k_krw

  dtypes:
    district_code: str
    deal_amount_10k_krw: int_comma    # "82,500" → 82500

  derived:
    - name: deal_date
      expr: "concat_date(deal_year, deal_month, deal_day)"
      dtype: str

  filters:
    - "deal_amount_10k_krw > 0"
필드 타입 필수 설명
column_mapping dict[str, str] raw API 필드 → clean 컬럼 이름 매핑. 매핑되지 않은 컬럼은 제거됨
dtypes dict[str, str] 타입 캐스팅. 지원: int, float, str, int_comma
derived list[dict] 파생 컬럼 정의
filters list[str] 행 필터 표현식

지원하는 타입 (dtypes)

타입 설명 예시
str 문자열 변환 "11680""11680"
int 정수 변환 (null-safe) "2024"2024, "-"null
float 실수 변환 (null-safe) "84.5"84.5, ""null
int_comma 콤마 제거 후 정수 변환 "82,500"82500

null-safe 처리: 빈 문자열(""), "-", "N/A", "null", "None"은 자동으로 null로 변환됩니다.

파생 컬럼 (derived)

표현식 설명 예시
concat_date(y, m, d) 날짜 문자열 조합 (zero-padded) concat_date(deal_year, deal_month, deal_day)"2024-01-15"
format(fmt, col1, col2, ...) Polars pl.format() 사용 format("{}-{}", year, month)"2024-01"

필터 표현식 (filters)

"컬럼명 연산자 값" 형태의 문자열. 지원 연산자: >, <, >=, <=, ==, !=

filters:
  - "deal_amount_10k_krw > 0"
  - "floor >= 1"

모든 필터를 동시에 만족하는 행만 유지됩니다 (AND 조건).

output — 출력 설정

output:
  hf_repo: "kpubdata/seoul-apartment-trades"
  kaggle_slug: "yschoe/seoul-apartment-trades"
  parquet_filename: "data/train.parquet"
  staging_dir: "./staging/seoul-apartment-trades"
필드 타입 필수 설명
hf_repo str HuggingFace 레포 ID (org/dataset-name)
kaggle_slug str Kaggle 데이터셋 슬러그 (username/dataset-name). 없으면 Kaggle 업로드 건너뜀
parquet_filename str staging 내 parquet 파일 경로
staging_dir str 로컬 staging 디렉토리 (스크립트 실행 위치 기준 상대경로)

card — Dataset Card 설정

card:
  title: "Korean Apartment Trades (아파트매매 실거래가)"
  description: |
    Real transaction prices for apartment sales...
  license: "cc-by-4.0"
  language:
    - ko
  tags:
    - real-estate
    - tabular
  features:
    - name: district_code
      description: "시군구 코드 (5-digit administrative district code)"
필드 타입 필수 설명
title str 데이터셋 제목
description str 데이터셋 설명
license str 라이선스 (기본값: cc-by-4.0)
language list[str] 언어 코드 (기본값: ["ko"])
tags list[str] HuggingFace 태그
features list[dict] 피처별 이름과 설명. Dataset Card의 Features 테이블에 렌더링됨

스크립트 내부 구조

스크립트의 각 함수는 Builder의 Medallion Architecture stage에 1:1 대응됩니다.

함수                          → Builder Stage     설명
──────────────────────────────────────────────────────────────
load_config()                 → (설정)            YAML config 로드 및 검증
fetch_records()               → Bronze            kpubdata Client로 raw 데이터 수집
transform_records()           → Silver            Polars 기반 컬럼 매핑, 타입 변환, 필터링
  ├── _cast_column()                              null-safe 타입 캐스팅
  ├── _nullify_tokens()                           빈값/"-"/"N/A" → null 변환
  ├── _add_derived_column()                       파생 컬럼 생성
  └── _apply_filter()                             비교 필터 적용
write_parquet()               → Gold              Parquet 패키징
generate_dataset_card()       → Export            HF Dataset Card (README.md) 생성
  ├── _build_features_table()                     피처 설명 마크다운 테이블
  ├── _build_sample_table()                       샘플 데이터 테이블
  └── _build_stats_section()                      수치 컬럼 통계
upload_to_hf()                → Publish           whitelist 기반 HF Hub 업로드
upload_to_kaggle()            → Publish           dataset-metadata.json 생성 + Kaggle API 업로드
  └── _map_kaggle_license()                       HF→Kaggle 라이선스 매핑
main()                        → CLI               argparse 기반 진입점 (--target hf|kaggle|all)

업로드 보안

upload_to_hf()는 staging 디렉토리 전체를 업로드하지 않습니다. 임시 .hf_upload/ 디렉토리에 다음 파일만 복사 후 업로드합니다:

  • README.md (dataset card)
  • data/*.parquet (데이터 파일)

업로드 완료 후 .hf_upload/ 디렉토리는 자동 삭제됩니다.


제공되는 Config 파일

seoul_apartment_trades.yaml

국토교통부 아파트매매 실거래가 데이터. 서울 25개구 전체, 2020-01~2024-12 (60개월). 거래가격(deal_amount_10k_krw)을 타겟 변수로 하는 tabular regression / time-series 벤치마크.

  • 소스: data.go.kr MOLIT 아파트 실거래가 API
  • 지역: 서울 25개구 전체
  • 기간: 2020년 1월 ~ 2024년 12월 (60개월)
  • API 호출: 1,500회 (25개구 × 60개월)
  • 예상 레코드: ~250,000건
  • HF 레포: kpubdata/seoul-apartment-trades

korea_base_rate.yaml

한국은행 기준금리 데이터. config-driven 재사용성 검증용.

  • 소스: BOK 기준금리 API
  • HF 레포: kpubdata/korea-base-rate

새 데이터셋 추가하기

  1. scripts/configs/ 에 새 YAML config 파일 생성
  2. 위 스키마에 맞춰 source, transform, output, card 섹션 작성
  3. --local-only로 먼저 로컬 테스트:
    uv run python scripts/publish_to_hf.py scripts/configs/my_new_dataset.yaml --local-only -v
    
  4. staging 디렉토리에서 parquet과 README.md 확인
  5. 문제없으면 실행:
    uv run python scripts/publish_to_hf.py scripts/configs/my_new_dataset.yaml
    

Config 작성 팁

  • column_mapping에 포함되지 않은 raw 필드는 자동으로 제거됩니다.
  • fetch_params의 각 항목은 별도의 API 호출이 됩니다. 여러 지역/기간을 조합하려면 항목을 추가하세요.
  • list_all: true를 사용하면 페이지네이션을 자동으로 처리합니다.
  • int_comma 타입은 "82,500" 같은 콤마가 포함된 숫자 문자열을 처리합니다.
  • 파생 컬럼은 타입 캐스팅 이후에 계산되므로, 참조하는 컬럼이 올바른 타입인지 확인하세요.

트러블슈팅

No records fetched 에러

  • KPUBDATA_DATAGO_API_KEY 환경변수가 올바르게 설정되었는지 확인
  • fetch_params의 파라미터 값이 API 스펙에 맞는지 확인 (예: LAWD_CD는 5자리 시군구 코드)

huggingface_hub not installed 에러

uv sync --extra publish

HF 업로드 401/403 에러

  • HF_TOKEN 환경변수 확인
  • 토큰에 대상 org/repo에 대한 write 권한이 있는지 확인
  • Fine-grained 토큰의 경우 Org permissions에서 대상 org 선택 필요

Polars 타입 캐스팅 실패

  • 원본 데이터에 빈 문자열, "-", "N/A" 등이 포함되어 있을 수 있습니다 → int/float 타입은 자동으로 null-safe 처리됩니다
  • 콤마가 포함된 숫자 필드는 int_comma 타입을 사용하세요

Kaggle 업로드 401 에러

  • KAGGLE_USERNAMEKAGGLE_KEY 환경변수 확인
  • 또는 ~/.kaggle/kaggle.json 파일 존재 여부 확인
  • Kaggle 토큰을 재발급하면 이전 토큰이 즉시 폐기됨. 새 토큰으로 환경변수/파일 모두 갱신 필요

Kaggle dataset_view AttributeError

  • kaggle SDK 1.6+ 에서 dataset_view() 메서드가 제거됨
  • 스크립트는 dataset_list(mine=True, search=slug) 방식으로 데이터셋 존재 여부를 판별

Kaggle organization 미지원

  • Kaggle은 HuggingFace와 달리 organization 계정을 지원하지 않음
  • 모든 데이터셋은 개인 계정 소속 (username/dataset-name)
  • kaggle_slughf_repo와 다른 namespace를 가질 수 있음

Builder 모듈 분해 가이드

이 스크립트는 학생들이 Builder의 Medallion Architecture 모듈로 분해하는 레퍼런스입니다.

스크립트 함수 분해 대상 모듈 디렉토리
fetch_records() Bronze stage src/kpubdata_builder/stages/bronze/
transform_records() Silver stage (Polars engine) src/kpubdata_builder/stages/silver/, tabular/
write_parquet() Gold stage src/kpubdata_builder/stages/gold/
generate_dataset_card() HF Layout Exporter src/kpubdata_builder/exporters/
upload_to_hf() HF Publisher src/kpubdata_builder/publishers/
upload_to_kaggle() Kaggle Publisher src/kpubdata_builder/publishers/
Config YAML BuildSpec model src/kpubdata_builder/spec.py

참고 이슈: #50, #8, #9, #10, #28, #37, #40