1. Great Expectations란?
Great Expectations(GX)는 데이터 품질 검증, 문서화, 프로파일링을 위한 오픈소스 Python 프레임워크입니다. 데이터 파이프라인의 신뢰성을 확보하기 위해 Expectations(기대치)라는 선언적 테스트를 정의하고 실행합니다.
📝 데이터 계약 정의
컬럼 유형, 값 범위, 유일성, NULL 허용 여부 등 데이터에 대한 명시적인 계약을 코드로 정의합니다. 이는 팀 간 데이터 사양을 공유하는 단일 진실 공급원 역할을 합니다.
🔍 자동화된 검증
정의된 Expectations를 배치 데이터, 스트리밍 데이터, 또는 데이터베이스에 대해 자동으로 실행하여 품질 문제를 조기에 발견합니다. CI/CD 파이프라인에 통합 가능합니다.
📊 데이터 문서화
검증 결과를 자동으로 문서화하여 데이터 라인지와 신뢰도를 시각적으로 보여줍니다. 데이터 드리프트 감지와 프로파일링 리포트 생성 기능을 포함합니다.
2. 왜 써야 하는가?
데이터 품질 관리를 위한 기존 접근법과의 비교를 통해 GX의 가치를 확인할 수 있습니다.
| 도구/접근법 | 장점 | 단점 | GX 차별점 |
|---|---|---|---|
| 수동 SQL 검증 | 간단한 쿼리로 빠른 확인 가능 | 반복 작업, 문서화 부재, 자동화 어려움 | 코드 기반 자동화, 재사용 가능한 테스트 |
| 단위 테스트(pytest) | 익숙한 테스트 프레임워크 | 데이터 특화 기능 부족, 대용량 데이터 비효율 | 데이터 최적화 검증기, 풍부한 Expectation 라이브러리 |
| 상용 데이터 품질 도구 | 통합 UI, 엔터프라이즈 기능 | 높은 비용, 벤더 종속, 유연성 낮음 | 오픈소스, 커뮤니티 기반, 코드 우선 접근 |
| Great Expectations | 선언적 테스트, 자동 문서화, 오픈소스 | 학습 곡선, 초기 설정 필요 | 표준화된 데이터 계약, 협업 용이성 |
핵심 가치: GX는 단순한 테스트 도구를 넘어 데이터 팀 간의 커뮤니케이션 도구입니다. Expectations는 실행 가능한 데이터 사양서 역할을 하여 데이터 소비자와 생산자 간의 오해를 줄입니다.
3. 핵심 개념
GX의 아키텍처는 데이터 소스, Expectations, 검증 실행, 결과 처리를 중심으로 구성됩니다.
주요 컴포넌트
- Data Context: 프로젝트의 루트 설정 객체. 구성 파일(
great_expectations.yml)로 관리. - Datasource: Pandas, Spark, SQLAlchemy 등 데이터 소스에 대한 연결.
- Expectation: "이 컬럼의 값은 NULL이 아니어야 한다"와 같은 단일 검증 규칙.
- Expectation Suite: 관련 Expectations의 집합. 일반적으로 하나의 테이블이나 데이터셋에 매핑.
- Batch: 검증할 데이터의 단위 (예: 특정 날짜의 파티션).
- Validator: Batch에 Expectation Suite를 실행하는 객체.
- Checkpoint: Datasource, Batch Request, Expectation Suite를 묶어 반복 실행을 자동화.
- Data Docs: Expectations와 검증 결과를 HTML로 생성한 정적 사이트.
4. 퀵스타트
로컬 환경에서 Pandas DataFrame을 이용해 첫 번째 검증을 실행해봅니다.
4.1 설치
# 기본 설치 (Pandas 기반)
pip install great_expectations
# Spark 지원이 필요한 경우
pip install "great_expectations[spark]"
# PostgreSQL, Redshift 등 SQL 지원
pip install "great_expectations[sql]"
4.2 프로젝트 초기화
# GX 프로젝트 구조 생성
great_expectations init
이 명령어는 great_expectations/ 디렉토리를 생성하고 기본 설정 파일들을 준비합니다.
4.3 첫 번째 Expectation 생성 및 실행
import great_expectations as gx
import pandas as pd
# 1. Data Context 로드
context = gx.get_context()
# 2. 샘플 데이터 생성
df = pd.DataFrame({
"user_id": [101, 102, 103, 104, 105],
"age": [25, 32, 28, 45, 22],
"email": [
"alice@example.com",
"bob@example.com",
"charlie@example.com",
"david@example.com",
"eve@example.com"
],
"signup_date": pd.to_datetime([
"2025-01-10", "2025-01-11", "2025-01-11",
"2025-01-12", "2025-01-13"
])
})
# 3. GX 데이터셋으로 변환 (Pandas)
batch = context.data_sources.pandas_default.read_dataframe(df)
# 4. Expectation Suite 생성
suite = context.add_expectation_suite("my_first_suite")
# 5. Expectations 정의
# 컬럼 존재 여부
batch.expect_column_to_exist("user_id")
batch.expect_column_to_exist("age")
# 값 범위 검증 (나이는 18세 이상 100세 미만)
batch.expect_column_values_to_be_between(
column="age",
min_value=18,
max_value=100
)
# 고유성 검증 (user_id는 중복되지 않아야 함)
batch.expect_column_values_to_be_unique("user_id")
# 이메일 형식 검증
batch.expect_column_values_to_match_regex(
column="email",
regex=r"^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$"
)
# 6. 검증 실행
results = batch.validate(expectation_suite=suite)
# 7. 결과 확인
print(f"성공한 Expectations: {results.success_count}")
print(f"실패한 Expectations: {results.failure_count}")
if not results.success:
for result in results.results:
if not result.success:
print(f"실패: {result.expectation_config.expectation_type}")
print(f" - 컬럼: {result.expectation_config.kwargs.get('column')}")
print(f" - 메시지: {result.result.get('partial_unexpected_list', 'N/A')}")
실행 결과 예시: 위 데이터는 모든 검증을 통과해야 합니다. 만약 age 컬럼에 17이 있다면 expect_column_values_to_be_between Expectation이 실패합니다.
5. 핵심 설정 레퍼런스
great_expectations.yml의 주요 설정 항목입니다.
| 섹션 | 키 | 기본값 / 예시 | 설명 |
|---|---|---|---|
| datasources | pandas_default | class_name: PandasDatasource | Pandas DataFrame을 위한 데이터 소스 |
| spark_local | class_name: SparkDFDatasource | 로컬 Spark 세션 사용 | |
| postgresql_dev | class_name: SqlAlchemyDatasource connection_string: postgresql://... |
PostgreSQL 연결 | |
| expectations_store | class_name | ExpectationsStore | Expectation Suite 저장소 (로컬 파일, S3 등) |
| validations_store | class_name | ValidationsStore | 검증 결과 저장소 |
| data_docs_sites | local_site | site_index_builder: class_name: DefaultSiteIndexBuilder |
Data Docs 생성 설정 (로컬, S3, GCS 호스팅) |
| anonymous_usage_statistics | enabled | true (개발 시 false 권장) | 익명 사용 통계 전송 여부 |
주의: 프로덕션 환경에서는 anonymous_usage_statistics.enabled를 false로 설정하고, 저장소(Store)를 파일 시스템이 아닌 S3, GCS, 데이터베이스와 같은 지속성 있는 저장소로 구성하세요.
6. 실무 팁 & 트러블슈팅
자주 겪는 문제와 해결책
🚫 성능 이슈 (대용량 데이터)
증상: Spark나 대용량 Pandas DataFrame 검증 시 속도가 매우 느림.
해결:
- Spark 사용 시
spark_config튜닝. - 샘플링 적용:
batch.expect_...대신batch.expect_column_values_to_be_between(..., mostly=0.95)로 95%만 검증. - 필요한 컬럼만 선택하여 검증.
🔗 데이터 소스 연결 실패
증상: SQL 데이터베이스 연결 시 타임아웃 또는 인증 오류.
해결:
great_expectations.yml의connection_string재확인.- 네트워크/방화벽 설정 점검.
- SQLAlchemy 드라이버 버전 호환성 확인 (e.g.,
psycopg2-binaryfor PostgreSQL).
📁 Data Docs 생성 안 됨
증상: great_expectations docs build 실행 후 HTML이 생성되지 않음.
해결:
great_expectations.yml의data_docs_sites설정 확인.- 출력 디렉토리(
great_expectations/uncommitted/data_docs/) 권한 확인. context.build_data_docs()를 Python 코드에서 직접 실행해보기.
🔄 CI/CD 통합 실패
증상: Jenkins/GitHub Actions에서 GX 검증 실패 시 파이프라인이 중단되지 않음.
해결:
- Checkpoint 실행 후 반환된
CheckpointResult의success속성을 명시적으로 확인하고 실패 시 exit code 1을 반환하도록 스크립트 작성. - Airflow 오퍼레이터 사용 시
gx.checkpoint.run()의 결과를 처리하는 로직 추가.
실무 팁
- 점진적 도입: 모든 컬럼에 대한 Expectations를 한 번에 정의하지 말고, 가장 중요한 비즈니스 규칙(예: 주문 금액 > 0)부터 시작하세요.
- 프로파일링 활용:
batch.profile()또는great_expectations profileCLI 명령어로 데이터를 탐색한 후 자동 생성된 Expectations를 기반으로 시작하세요. - 커스텀 Expectations: 빌트인 Expectations로 부족할 경우
@batch.expectation데코레이터를 사용해 Python 함수를 커스텀 Expectation으로 등록할 수 있습니다. - 버전 관리: Expectation Suite JSON 파일을 Git으로 관리하여 변경 이력을 추적하세요.
7. 참고 자료
- 📘 공식 문서 - 개념, 튜토리얼, API 레퍼런스
- 🐙 GitHub 저장소 - 소스 코드, 이슈, 컨트리뷰션 가이드
- 🔍 Expectations 갤러리 - 사용 가능한 모든 Expectations 목록
- 💬 공식 포럼 - 커뮤니티 질문과 답변
- 추천 학습 경로: 공식 문서의 "Tutorials" → "Core concepts" → "Deployment patterns" 순서로 진행.