데이터셋 퍼블리싱 가이드¶
이 문서는 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 토큰 발급¶
- https://huggingface.co/settings/tokens 접속
- Create new Access Token 클릭
- 설정:
- Token type: Fine-grained
- Token name:
kpubdata-publish(또는 원하는 이름) - User permissions > Repositories: ✅ Write access to contents/settings
- Org permissions: 대상 org 선택 후 ✅ Write access to contents/settings
- 나머지 권한은 체크 해제
- 토큰 생성 후
HF_TOKEN환경변수에 저장
3. HuggingFace Organization (선택)¶
org 단위로 데이터셋을 관리하려면:
- https://huggingface.co/organizations/new 에서 org 생성
- 토큰 발급 시 해당 org에 대한 write 권한 부여
4. Kaggle API 토큰 발급¶
- https://www.kaggle.com/settings 접속
- API 섹션에서 Create New Token 클릭
- 다운로드된
kaggle.json에서username과key를 환경변수에 설정 - 주의: 새 토큰을 발급하면 이전 토큰은 즉시 폐기됨
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 | true면 ds.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
새 데이터셋 추가하기¶
scripts/configs/에 새 YAML config 파일 생성- 위 스키마에 맞춰
source,transform,output,card섹션 작성 --local-only로 먼저 로컬 테스트:uv run python scripts/publish_to_hf.py scripts/configs/my_new_dataset.yaml --local-only -v- staging 디렉토리에서 parquet과 README.md 확인
- 문제없으면 실행:
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_USERNAME과KAGGLE_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_slug은hf_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