📊 데이터공학

데이터 카탈로그

Data Catalog

데이터 자산 목록화 및 검색. 메타데이터 관리.

상세 설명

데이터 카탈로그(Data Catalog)는 조직 내 모든 데이터 자산을 인벤토리화하고 메타데이터를 관리하는 시스템입니다. 데이터 검색, 이해, 신뢰를 위한 중앙 허브 역할을 하며, 데이터 거버넌스와 셀프 서비스 분석의 핵심 인프라입니다. "어떤 데이터가 있는지, 어디에 있는지, 무엇을 의미하는지, 누가 소유하는지"에 대한 답을 제공합니다.

데이터 카탈로그는 세 가지 유형의 메타데이터를 관리합니다. 첫째, 기술적 메타데이터(Technical Metadata)로 스키마, 데이터 타입, 저장 위치, 파티션 정보 등이 포함됩니다. 둘째, 비즈니스 메타데이터(Business Metadata)로 데이터셋 설명, 태그, 분류, 소유자, 비즈니스 용어집(Glossary) 연결 등이 있습니다. 셋째, 운영 메타데이터(Operational Metadata)로 접근 로그, 사용 빈도, freshness, 품질 점수 등을 추적합니다.

주요 기능으로는 자동 메타데이터 크롤링(데이터베이스, 데이터 레이크, BI 도구에서 스키마 자동 수집), 검색 및 발견(키워드, 태그, 도메인 기반 데이터셋 검색), 데이터 리니지 통합(데이터 흐름 추적과 영향도 분석), 협업 기능(문서화, 평점, 질문/답변, 소유자 지정), 접근 제어(데이터셋별 권한 관리 및 요청 워크플로우) 등이 있습니다.

대표적인 데이터 카탈로그 솔루션으로는 오픈소스인 DataHub(LinkedIn), Amundsen(Lyft), Apache Atlas, 그리고 상용 솔루션인 Alation, Collibra, Informatica가 있습니다. 클라우드 기반으로는 AWS Glue Data Catalog, Google Data Catalog, Azure Purview 등이 있습니다. 데이터 레이크하우스에서는 Unity Catalog(Databricks)가 통합 거버넌스를 제공합니다.

코드 예제

DataHub Python SDK
# DataHub을 활용한 데이터 카탈로그 메타데이터 등록
from datahub.emitter.mce_builder import (
    make_dataset_urn, make_tag_urn, make_term_urn,
    make_user_urn, make_domain_urn
)
from datahub.emitter.rest_emitter import DatahubRestEmitter
from datahub.metadata.schema_classes import (
    DatasetPropertiesClass, SchemaMetadataClass,
    SchemaFieldClass, StringTypeClass, NumberTypeClass,
    OwnershipClass, OwnerClass, OwnershipTypeClass,
    GlobalTagsClass, TagAssociationClass,
    GlossaryTermsClass, GlossaryTermAssociationClass,
    DomainsClass, StatusClass
)
from datahub.emitter.mcp import MetadataChangeProposalWrapper

# DataHub GMS 서버 연결
emitter = DatahubRestEmitter(
    gms_server="http://datahub-gms:8080",
    token="your-access-token"
)

# 1. 데이터셋 URN 생성 (고유 식별자)
dataset_urn = make_dataset_urn(
    platform="snowflake",
    name="analytics.gold.customer_360",
    env="PROD"
)

# 2. 데이터셋 속성 정의 (비즈니스 메타데이터)
properties = DatasetPropertiesClass(
    name="customer_360",
    description="""
    통합 고객 360도 뷰 테이블.
    주문, 행동, CRM 데이터를 결합한 분석용 마트.

    사용 사례:
    - 고객 세그먼테이션
    - LTV 예측 모델 학습
    - 마케팅 캠페인 타겟팅
    """,
    qualifiedName="analytics.gold.customer_360",
    customProperties={
        "refresh_frequency": "hourly",
        "data_owner": "analytics-team",
        "pii_classification": "confidential",
        "row_count": "15,000,000",
        "data_quality_score": "95%"
    }
)

# 3. 스키마 정의 (기술적 메타데이터)
schema = SchemaMetadataClass(
    schemaName="customer_360",
    platform=make_dataset_urn("snowflake", "", "PROD"),
    version=0,
    hash="",
    platformSchema={},
    fields=[
        SchemaFieldClass(
            fieldPath="customer_id",
            type=StringTypeClass(),
            nativeDataType="VARCHAR(50)",
            description="고객 고유 식별자 (UUID)",
            nullable=False,
            isPartOfKey=True
        ),
        SchemaFieldClass(
            fieldPath="email",
            type=StringTypeClass(),
            nativeDataType="VARCHAR(255)",
            description="고객 이메일 주소 (개인정보)",
            nullable=True,
            globalTags=GlobalTagsClass(tags=[
                TagAssociationClass(tag=make_tag_urn("PII")),
                TagAssociationClass(tag=make_tag_urn("Sensitive"))
            ])
        ),
        SchemaFieldClass(
            fieldPath="lifetime_value",
            type=NumberTypeClass(),
            nativeDataType="DECIMAL(18,2)",
            description="고객 생애 가치 (LTV, USD)",
            nullable=True
        ),
        SchemaFieldClass(
            fieldPath="segment",
            type=StringTypeClass(),
            nativeDataType="VARCHAR(20)",
            description="고객 세그먼트 (VIP/Standard/Basic)",
            nullable=False
        ),
        SchemaFieldClass(
            fieldPath="last_activity_date",
            type=StringTypeClass(),
            nativeDataType="DATE",
            description="마지막 활동 일자",
            nullable=True
        )
    ]
)

# 4. 소유권 설정
ownership = OwnershipClass(
    owners=[
        OwnerClass(
            owner=make_user_urn("analytics_lead"),
            type=OwnershipTypeClass.DATAOWNER
        ),
        OwnerClass(
            owner=make_user_urn("data_steward"),
            type=OwnershipTypeClass.BUSINESS_OWNER
        )
    ]
)

# 5. 비즈니스 용어집(Glossary) 연결
glossary_terms = GlossaryTermsClass(
    terms=[
        GlossaryTermAssociationClass(
            urn=make_term_urn("Customer Analytics")
        ),
        GlossaryTermAssociationClass(
            urn=make_term_urn("Marketing Data")
        )
    ],
    auditStamp={"time": 0, "actor": "urn:li:corpuser:admin"}
)

# 6. 도메인 할당
domains = DomainsClass(
    domains=[make_domain_urn("Marketing")]
)

# 7. 태그 추가
global_tags = GlobalTagsClass(
    tags=[
        TagAssociationClass(tag=make_tag_urn("Gold")),
        TagAssociationClass(tag=make_tag_urn("Certified")),
        TagAssociationClass(tag=make_tag_urn("Production"))
    ]
)

# 8. 메타데이터 발행
mcps = [
    MetadataChangeProposalWrapper(entityUrn=dataset_urn, aspect=properties),
    MetadataChangeProposalWrapper(entityUrn=dataset_urn, aspect=schema),
    MetadataChangeProposalWrapper(entityUrn=dataset_urn, aspect=ownership),
    MetadataChangeProposalWrapper(entityUrn=dataset_urn, aspect=glossary_terms),
    MetadataChangeProposalWrapper(entityUrn=dataset_urn, aspect=domains),
    MetadataChangeProposalWrapper(entityUrn=dataset_urn, aspect=global_tags),
]

for mcp in mcps:
    emitter.emit(mcp)

print(f"Dataset registered: {dataset_urn}")

# 9. GraphQL로 메타데이터 검색
import requests

query = """
query {
    search(input: {
        type: DATASET,
        query: "customer",
        start: 0,
        count: 10
    }) {
        searchResults {
            entity {
                urn
                ... on Dataset {
                    name
                    description
                    platform { name }
                }
            }
        }
    }
}
"""

response = requests.post(
    "http://datahub-gms:8080/api/graphql",
    json={"query": query},
    headers={"Authorization": "Bearer your-token"}
)
print(response.json())

실무 대화

분석가: 마케팅 분석에 쓸 고객 데이터가 어디 있는지 모르겠어요. DW 테이블이 너무 많아서 찾기가 힘들어요.
데이터 엔지니어: 데이터 카탈로그에서 "customer" 검색해보세요. gold.customer_360 테이블이 통합 고객 뷰에요. 소유자, 스키마 설명, 사용 예제가 다 문서화되어 있어요.
분석가: 이 데이터 신뢰할 수 있나요? 최신 데이터인지 어떻게 알 수 있죠?
데이터 엔지니어: 카탈로그에 freshness 지표와 데이터 품질 점수가 있어요. 95% 품질 점수에 hourly 업데이트 되고, 리니지 탭에서 원천 시스템도 확인 가능해요.
면접관: 데이터 카탈로그의 가치는 무엇인가요?
지원자: 데이터 검색 시간 단축, 중복 데이터셋 방지, 데이터 품질 가시성, 규정 준수 지원입니다. Airbnb 사례에서는 데이터 발견 시간을 90% 단축했다고 합니다. 셀프 서비스 분석의 필수 인프라입니다.
면접관: 메타데이터를 최신 상태로 유지하는 방법은?
지원자: 자동 크롤링으로 기술적 메타데이터를 수집하고, CI/CD 파이프라인에 메타데이터 발행을 통합합니다. 비즈니스 메타데이터는 코드 리뷰에 문서화를 포함시키고, 데이터 스튜어드가 주기적으로 검토합니다.
개발자: dbt 모델마다 DataHub에 메타데이터 발행하려면 어떻게 해야 하나요?
시니어: dbt-datahub 패키지를 쓰면 돼. dbt run 후에 자동으로 모델 설명, 컬럼 정보, 리니지가 DataHub에 반영돼. meta 필드에 owner, tags도 정의할 수 있어.
개발자: PII 컬럼에 자동으로 태그 붙이는 방법이 있나요?
시니어: DataHub의 Classification 기능을 써. 정규식 패턴(email, ssn 등)으로 PII를 자동 탐지하고 태그를 붙여줘. 거버넌스 정책과 연동해서 접근 제어도 가능해.

주의사항

  • 메타데이터가 최신 상태가 아니면 신뢰를 잃습니다. 자동 크롤링과 CI/CD 연동을 필수로 설정하세요.
  • 비즈니스 메타데이터(설명, 태그)는 수동 입력이 필요합니다. 문서화를 코드 리뷰 프로세스에 포함시키세요.
  • 사용자 채택률이 낮으면 무용지물입니다. 교육과 온보딩을 충분히 제공하세요.
  • 데이터 파이프라인(dbt, Airflow)과 통합하면 메타데이터가 자동으로 동기화됩니다.
  • 비즈니스 용어집(Glossary)을 먼저 정의하면 일관된 데이터 이해가 가능합니다.

더 배우기