tracks
데이터 품질과 일관성은 집의 기초와 같습니다. 탄탄한 기반이 없으면 그 위에 지어진 모든 것이 무너질 위험이 있습니다. 이때 데이터 검증이 중요한 역할을 합니다. 데이터 검증은 데이터가 정확하고 일관되며 신뢰할 수 있는지 확인하는 데 도움이 됩니다.
Great Expectations는 데이터 문제를 조기에 파악하고, 데이터가 요구되는 품질 기준을 충족하도록 해주는 오픈 소스 데이터 검증 도구입니다.
이 가이드에서는 Great Expectations를 활용한 데이터 검증 과정을 실전 엔드 투 엔드 예제와 함께 단계별로 안내해 드립니다.
Great Expectations란?
Great Expectations(GX)는 현대적 데이터 파이프라인에서 데이터 검증을 관리하고 자동화하는 데 널리 사용되는 오픈 소스 프레임워크입니다.
Python 기반 프레임워크로, 데이터 팀이 데이터의 품질과 일관성을 보장하도록 설계되었습니다. 사용자는 유효한 데이터가 어떤 모습이어야 하는지 설명하는 규칙 또는 테스트인 "기대값(expectations)"을 정의하고, 이 기준을 데이터가 충족하는지 자동으로 검증할 수 있습니다.
Great Expectations의 장점은 다음과 같습니다.
- 데이터 검증 자동화 – Great Expectations는 데이터 검증 과정을 자동화하여 수작업을 줄이고 오류 위험을 최소화합니다. 이를 통해 데이터가 미리 정의된 기준을 지속적으로 충족하도록 보장합니다.
- 데이터 파이프라인과의 통합 – SQL 데이터베이스s, 클라우드 스토리지, ETL 도구 등 다양한 데이터 소스와 플랫폼과 손쉽게 통합되어, 파이프라인의 여러 단계에서 데이터 검증을 수행할 수 있습니다.
- 명확하고 실행 가능한 검증 결과 – 투명한 검증 결과를 제공하여 데이터 품질 문제를 쉽게 파악하고 신속히 해결할 수 있습니다.
- 데이터 문서화 – 데이터 검증 프로세스에 대한 상세하고 접근 가능한 문서를 생성해 팀 간 품질 기준을 일치시키고, 향후 참고 자료로 활용할 수 있습니다.
- 확장성과 유연성 – 오픈 소스 도구로서 높은 커스터마이징이 가능하고 검증 요구에 맞춰 확장할 수 있으며, 다양한 사용 사례에 유연하게 대응할 수 있습니다.
이제 엔드 투 엔드 예제를 살펴보겠습니다!
Great Expectations 설정하기
이 튜토리얼에서는 오픈 소스 버전인 GX Core를 사용해 Pandas DataFrame을 검증하는 방법을 배웁니다. 컨텍스트 설정, Pandas 데이터 소스 등록, 기대값 정의, 배치 검증까지 차례로 진행합니다.
참고: DataLab 노트북을 함께 보면서 따라 하시길 권장합니다. 별도의 Python 스크립트를 만들어도 됩니다.
1. Great Expectations 설치
사전 준비
- Python 3.9 ~ 3.12 설치
- 충돌을 피하기 위해 가상 환경에 Great Expectations를 설치하는 것을 강력히 권장합니다(주의: 가상 환경 설정 방법은 본 문서의 범위를 벗어납니다).
- 샘플 데이터셋
참고: 제공된 DataLab 노트북을 사용하는 경우, 위 사전 준비는 이미 충족되어 있으므로 건너뛰셔도 됩니다.
다음 명령어로 pip를 통해 GX를 설치하세요.
pip install great_expectations
이 명령은 코어 패키지와 필요한 모든 종속 항목을 설치합니다.
2. 데이터 컨텍스트 초기화
Great Expectations는 구성을 관리하기 위해 데이터 컨텍스트가 필요합니다. 구성 저장을 피하기 위해 비영구(ephemeral) 데이터 컨텍스트를 사용합니다.
import great_expectations as gx
# Get the Ephemeral Data Context
context = gx.get_context()
assert type(context).__name__ == "EphemeralDataContext"
첫 번째 데이터 검증 스위트 만들기
GX 설정을 마쳤으니, 이제 데이터 검증 스위트를 만들어 보겠습니다.
1. 데이터 소스 연결 및 데이터 자산 생성
데이터 소스는 Great Expectations를 데이터에 연결하고, 데이터 자산은 특정 데이터 하위 집합(예: 테이블, DataFrame, 파일)을 나타냅니다.
여기서는 inventory_parts_df라는 DataFrame에 연결할 준비를 하겠습니다. 샘플 데이터셋은 제공된 DataLab에 포함되어 있으며, SQL 블록을 실행하면 생성됩니다.

DataLab을 사용하지 않는 경우, 샘플 데이터로 직접 DataFrame을 생성하세요.
이제 데이터 소스와 자산을 생성합니다.
# Add a Pandas Data Source
data_source = context.data_sources.add_pandas(name="inventory_parts")
# Add a Data Asset to the Data Source
data_asset = data_source.add_dataframe_asset(name="inventory_parts_asset")
2. 배치 정의 추가
배치 정의는 검증을 위해 데이터를 식별하고 구성합니다. 여기서는 전체 DataFrame을 대상으로 하는 배치 정의를 추가합니다.
# Define the Batch Definition name
batch_definition_name = "inventory_parts_batch"
# Add the Batch Definition
batch_definition = data_asset.add_batch_definition_whole_dataframe(batch_definition_name)
assert batch_definition.name == batch_definition_name
3. 배치 가져오기
배치는 배치 정의에 연결된 데이터 모음입니다. 데이터를 검증하려면 배치를 가져와 DataFrame(여기서는 inventory_parts_df)과 연결해야 합니다.
# Define the Batch Parameters
batch_parameters = {"dataframe": inventory_parts_df}
# Retrieve the Batch
batch = batch_definition.get_batch(batch_parameters=batch_parameters)
4. 스위트 생성 및 기대값 정의
기대값은 데이터를 검증하기 위한 규칙입니다. 이 예제에서는 다음과 같은 간단한 기대값을 정의합니다.
inventory_id값은 null이 아니어야 합니다.part_num값은 고유해야 합니다.
# Create an Expectation Suite
expectation_suite_name = "inventory_parts_suite"
suite = gx.ExpectationSuite(name=expectation_suite_name)
# Add Expectations
suite.add_expectation(
gx.expectations.ExpectColumnValuesToNotBeNull(column="inventory_id")
)
suite.add_expectation(
gx.expectations.ExpectColumnValuesToBeUnique(column="part_num")
)
# Add the Expectation Suite to the Context
context.suites.add(suite)
사용 가능한 모든 기대값은 Expectation Gallery에서 확인할 수 있습니다. 몇 가지를 더 추가해 보세요!
기대값을 정의하면 GX가 기대값 스위트 구성을 출력합니다.
{
"name": "inventory_parts_suite",
"id": "b2de0b69-0869-4163-8dde-6c09884483f7",
"expectations": [
{
"type": "expect_column_values_to_not_be_null",
"kwargs": {
"column": "inventory_id"
},
"meta": {},
"id": "53d6c42a-d190-412f-a113-783b706531f4"
},
{
"type": "expect_column_values_to_be_unique",
"kwargs": {
"column": "part_num"
},
"meta": {},
"id": "362a2bdc-616d-4b3a-b7f0-c73808caee78"
}
],
"meta": {
"great_expectations_version": "1.2.4"
},
"notes": null
}
스위트에는 다음 정보가 포함됩니다.
- 스위트 이름과 ID: 스위트를 추적하고 관리하기 위한 고유한 이름(
inventory_parts_suite)과 식별자 - 기대값: 각 규칙에는 다음이 포함됩니다.
- 검사 유형(예: 컬럼에 null이 없어야 함, 값이 고유해야 함)
- 검증 대상 컬럼 등 파라미터
- 메타데이터와 각 기대값의 고유 ID로, 추적 및 커스터마이징에 유용합니다.
- 메타데이터: Great Expectations의 버전 정보로, 도구와의 호환성을 보장합니다.
- 노트: 스위트에 대한 설명을 추가할 수 있는 자리(선택 사항)
이 구조화된 출력은 문서이자 재사용 가능한 구성으로서, 데이터셋 검증에 활용되어 기대값이 명확히 정의되고 추적 가능하며 향후 사용 준비가 되었음을 보여 줍니다.
5. 데이터 검증
마지막으로, 배치를 정의된 기대값에 맞춰 검증하고 결과를 평가합니다.
# Validate the Data Against the Suite
validation_results = batch.validate(suite)
# Evaluate the Results
print(validation_results)
검증을 실행하면, Great Expectations는 데이터셋이 정의된 기대값을 충족하는지에 대한 상세 보고서를 제공합니다.
{
"success": false,
"results": [
{
"success": true,
"expectation_config": {
"type": "expect_column_values_to_not_be_null",
"kwargs": {
"batch_id": "inventory_parts-inventory_parts_asset",
"column": "inventory_id"
},
"meta": {},
"id": "53d6c42a-d190-412f-a113-783b706531f4"
},
"result": {
"element_count": 580069,
"unexpected_count": 0,
"unexpected_percent": 0.0,
"partial_unexpected_list": [],
"partial_unexpected_counts": [],
"partial_unexpected_index_list": []
},
"meta": {},
"exception_info": {
"raised_exception": false,
"exception_traceback": null,
"exception_message": null
}
},
{
"success": false,
"expectation_config": {
"type": "expect_column_values_to_be_unique",
"kwargs": {
"batch_id": "inventory_parts-inventory_parts_asset",
"column": "part_num"
},
"meta": {},
"id": "362a2bdc-616d-4b3a-b7f0-c73808caee78"
},
"result": {
"element_count": 580069,
"unexpected_count": 568352,
"unexpected_percent": 97.98006788847535,
"partial_unexpected_list": [
"48379c01",
"paddle",
"11816pr0005",
"2343",
"3003",
"30176",
"3020",
"3022",
"3023",
"30357",
"3039",
"3062b",
"3068b",
"3069b",
"3069b",
"33291",
"33291",
"3795",
"3941",
"3960"
],
"missing_count": 0,
"missing_percent": 0.0,
"unexpected_percent_total": 97.98006788847535,
"unexpected_percent_nonmissing": 97.98006788847535,
"partial_unexpected_counts": [
{
"value": "3069b",
"count": 2
},
{
"value": "33291",
"count": 2
},
{
"value": "11816pr0005",
"count": 1
},
{
"value": "2343",
"count": 1
},
{
"value": "3003",
"count": 1
},
{
"value": "30176",
"count": 1
},
{
"value": "3020",
"count": 1
},
{
"value": "3022",
"count": 1
},
{
"value": "3023",
"count": 1
},
{
"value": "30357",
"count": 1
},
{
"value": "3039",
"count": 1
},
{
"value": "3062b",
"count": 1
},
{
"value": "3068b",
"count": 1
},
{
"value": "3795",
"count": 1
},
{
"value": "3941",
"count": 1
},
{
"value": "3960",
"count": 1
},
{
"value": "48379c01",
"count": 1
},
{
"value": "paddle",
"count": 1
}
],
"partial_unexpected_index_list": [
0,
3,
4,
5,
6,
7,
8,
9,
10,
11,
12,
13,
14,
15,
16,
17,
18,
19,
20,
21
]
},
"meta": {},
"exception_info": {
"raised_exception": false,
"exception_traceback": null,
"exception_message": null
}
}
],
"suite_name": "inventory_parts_suite",
"suite_parameters": {},
"statistics": {
"evaluated_expectations": 2,
"successful_expectations": 1,
"unsuccessful_expectations": 1,
"success_percent": 50.0
},
"meta": {
"great_expectations_version": "1.2.4",
"batch_spec": {
"batch_data": "PandasDataFrame"
},
"batch_markers": {
"ge_load_time": "20241129T122532.416424Z",
"pandas_data_fingerprint": "84a1e1939091fcf54324910def3b89cd"
},
"active_batch_definition": {
"datasource_name": "inventory_parts",
"data_connector_name": "fluent",
"data_asset_name": "inventory_parts_asset",
"batch_identifiers": {
"dataframe": "<DATAFRAME>"
}
}
},
"id": null
}
이 보고서는 데이터의 품질을 상세히 보여 주며, 통과와 실패 항목을 강조합니다. 결과를 간단히 설명하면 다음과 같습니다.
전체 검증: 검증 결과는 부분적으로 성공했습니다. 기대값의 50%가 통과했고 50%가 실패했습니다. 실패는 해결이 필요한 데이터 품질 문제를 의미합니다. 이 경우 한 컬럼이 정의된 규칙을 충족하지 못했습니다.
기대값 1: inventory_id에는 결측값이 없어야 합니다.
- 결과: 통과
- 설명:
inventory_id컬럼의 모든 값이 존재하며 null 또는 결측 항목이 없습니다. 이 컬럼의 데이터 완전성이 좋음을 나타냅니다.
기대값 2: part_num 값은 고유해야 합니다.
- 결과: 실패
- 설명:
part_num컬럼의 97.98%가 중복 값으로, 일부 값만 고유합니다. - 하이라이트:
- 예시 중복 값: "3069b", "33291".
- 중복 발생 빈도와 행 위치를 함께 보여 주어 문제를 더 쉽게 찾아 수정할 수 있습니다.
물론 이는 샘플 데이터셋이며, 검증 결과의 통과와 실패를 모두 확인해 볼 수 있도록 의도적으로 한 항목씩 넣었습니다.
이로써 엔드 투 엔드 데이터 검증을 성공적으로 실행했습니다.
데이터 파이프라인에 Great Expectations 통합하기
운영 환경에서는 검증을 워크플로에 직접 내장해 각 단계에서 데이터 품질을 지속적으로 모니터링해야 합니다.
이 섹션에서는 데이터 파이프라인에 Great Expectations를 통합하는 방법을 살펴봅니다.
이는 개념을 설명하기 위한 예시이며, 여기 포함되지 않은 추가 구성이 필요할 수 있습니다. 최신 문법은 각 도구의 문서를 확인하세요.
ETL 도구와의 통합
Apache Airflow나 Prefect 같은 인기 있는 ETL 도구와 Great Expectations를 통합하는 일은 비교적 간단합니다. ETL 프로세스에 검증 단계를 직접 삽입하면, 다운스트림 분석에 영향을 주기 전에 실시간으로 데이터 문제를 포착하고 해결할 수 있습니다.
자동화된 ETL 워크플로의 일부로 Prefect와 Great Expectations를 연동해 데이터 검증을 실행하는 간단한 예시를 살펴보겠습니다.
from prefect import task, Flow
import great_expectations as ge
# Define a task to run Great Expectations validation
@task
def validate_data():
context = ge.data_context.DataContext()
batch_kwargs = {"path": "path/to/your/datafile.csv", "datasource": "your_datasource"}
batch = context.get_batch(batch_kwargs, suite_name="your_expectation_suite")
results = context.run_validation_operator("action_list_operator", assets_to_validate=[batch])
# Check validation results and raise an alert if validation fails
if not results["success"]:
raise ValueError("Data validation failed!")
# Define your ETL flow
with Flow("ETL_with_GE_Validation") as flow:
validation = validate_data()
# Execute the flow
flow.run()
이 예제에서는 Great Expectations 검증을 실행하는 태스크를 포함한 Prefect 플로우를 정의합니다.
validate_data() 태스크는 Great Expectations 컨텍스트를 로드하고, 데이터 배치를 가져온 뒤 기대값 스위트를 적용합니다.
데이터가 검증 기준을 충족하지 않으면 경고를 발생시켜 워크플로를 중단하고 다운스트림 오류를 방지합니다.
지속적 데이터 검증
유닉스 기반 시스템의 크론 작업이나 Apache Airflow 같은 관리형 서비스를 사용해 검증 작업을 스케줄링할 수 있습니다. 여기서는 데이터 파이프라인 오케스트레이션에 적합한 Airflow를 사용해 검증 실행을 예약하는 방법을 보여 드립니다.
다음은 Airflow DAG(Directed Acyclic Graph)를 설정해 Great Expectations 검증을 매일 실행하는 방법입니다.
from airflow import DAG
from airflow.operators.python_operator import PythonOperator
from datetime import datetime
import great_expectations as ge
# Define the DAG and set the schedule to run daily
default_args = {
'owner': 'airflow',
'start_date': datetime(2024, 1, 1),
'retries': 1,
}
dag = DAG(
'great_expectations_validation',
default_args=default_args,
schedule_interval='@daily', # Runs once a day
)
# Define the function to run the validation
def run_validation():
context = ge.data_context.DataContext()
batch = context.get_batch(batch_kwargs, suite_name="your_expectation_suite")
results = context.run_validation_operator("action_list_operator", assets_to_validate=[batch])
return results
# Set up the task in Airflow
validation_task = PythonOperator(
task_id='run_great_expectations_validation',
python_callable=run_validation,
dag=dag,
)
# Set the task in the DAG
validation_task
이 예제에서는 @daily 주기로 하루 한 번 검증을 실행하도록 DAG를 정의합니다.
run_validation() 함수는 Great Expectations 컨텍스트를 로드하고, 정의된 기대값 스위트를 데이터에 실행하여 검증합니다.
Great Expectations로 데이터 검증할 때의 모범 사례
확장성과 효율성을 위해서는 모범 사례를 따르는 것이 좋으며, Great Expectations를 활용한 데이터 검증도 예외는 아닙니다.
작게 시작하고 반복 개선하기
기초적인 데이터 품질 검사부터 시작해 점차 확장하세요. 처음에는 기본 기대값에 집중하는 것이 좋습니다. 과도한 복잡성을 피하면 통합이 매끄럽고 문제 해결도 쉬워집니다. 데이터셋에 대한 이해가 깊어지면 더 복잡한 검증을 추가할 수 있습니다.
팀 간 협업하기
데이터 품질은 기술적인 이슈에만 국한되지 않습니다. 비즈니스 팀과 협업해 기대값을 정의하고, 구현된 검증이 비즈니스 로직과 목표에 부합하도록 하세요. 이러한 크로스펑셔널 접근은 데이터가 본래 목적에 맞게 활용되고 모든 이해관계자의 요구를 충족하도록 보장합니다.
가능한 부분은 자동화하기
가능한 한 자동화하여 데이터 파이프라인에 데이터 검증을 통합하세요. 자동화된 검증 점검을 도입하면 수동 개입 없이 데이터 품질을 지속적으로 모니터링할 수 있어 효율성이 크게 향상됩니다.
마무리
수고하셨습니다! 이제 Great Expectations에서 데이터를 구성하고 검증하는 방법을 익히셨습니다. 이러한 기법은 워크플로에서 높은 데이터 품질과 투명성을 유지하는 데 도움이 됩니다.
더 실력을 키우고 싶다면 다음 자료를 참고하세요.
- ETL and ELT in Python: 데이터를 효과적으로 변환하고 이동하는 방법을 학습합니다.
- Introduction to Data Quality: 데이터 품질 관리의 기초를 살펴봅니다.
- Cleaning Data in Python: 정확성과 일관성을 보장하기 위한 데이터 정제 기법을 익힙니다.
- Data Quality Dimensions Cheat Sheet: 데이터 품질 차원에 대한 유용한 요약문입니다.
FAQs
Great Expectations는 다른 데이터 검증 도구와 비교해 어떤가요?
Great Expectations는 오픈 소스이며 유연하고, 현대적 데이터 파이프라인과 잘 통합됩니다. 방대한 기대값 라이브러리와 탄탄한 문서화가 강점입니다.
Great Expectations를 사용하려면 Python을 알아야 하나요?
기본적인 Python 지식이 도움이 되지만, Great Expectations는 사용자 친화적인 CLI와 풍부한 문서를 제공하므로 비개발자도 접근할 수 있습니다.
Great Expectations는 어떤 유형의 데이터 소스를 지원하나요?
Great Expectations는 다음을 포함해 폭넓은 데이터 소스를 지원합니다.
- PostgreSQL, MySQL, SQL Server 등의 관계형 데이터베이스
- AWS S3, Google Cloud Storage, Azure Blob Storage 등의 클라우드 스토리지
- CSV, Parquet, Excel 같은 파일 형식
- Apache Spark, Databricks 같은 빅데이터 프레임워크. 적절한 데이터 소스 구성을 통해 쉽게 연결할 수 있습니다.
스트리밍 데이터에도 Great Expectations를 사용할 수 있나요?
Great Expectations는 주로 배치 데이터 검증에 맞춰 설계되었습니다. 스트리밍 데이터 파이프라인을 기본적으로 지원하지는 않지만, Apache Kafka나 Spark Structured Streaming 같은 프레임워크에 주기적으로 스냅샷 또는 마이크로 배치를 검증하는 방식으로 통합할 수 있습니다.
기대값과 검증 결과를 버전 관리할 수 있나요?
네. 기대값과 구성을 YAML 또는 JSON 파일로 저장해 Git 저장소에서 버전 관리할 수 있습니다. 검증 결과는 데이터베이스나 파일 기반 저장소를 설정해 시간에 따른 결과를 추적하고, CI/CD 파이프라인에 통합해 지속적으로 모니터링할 수 있습니다.
Great Expectations는 데이터셋의 스키마 변화를 어떻게 처리하나요?
Great Expectations는 유연한 기대값 프레임워크를 통해 스키마 변화를 처리합니다. 스키마가 변경되면 다음과 같이 대응할 수 있습니다.
expect_table_columns_to_match_set등 기대값을 사용해 컬럼 이름을 동적으로 검증- 새 스키마에 맞춰 기대값 스위트를 수정하거나 새로 생성
- 스키마 추론 도구를 활용해 새로 추가된 컬럼에 대한 기대값을 자동으로 업데이트