CHAPTER 03

๐Ÿ“‹ Metadata Management

๋ฉ”ํƒ€๋ฐ์ดํ„ฐ์˜ ์ˆ˜์ง‘, ์ €์žฅ, ๊ด€๋ฆฌ ์ „๋žต

3.1 ๋ฉ”ํƒ€๋ฐ์ดํ„ฐ์˜ 3๊ฐ€์ง€ ์œ ํ˜•

1) ๊ธฐ์ˆ  ๋ฉ”ํƒ€๋ฐ์ดํ„ฐ (Technical Metadata)

๋ฐ์ดํ„ฐ์˜ ๋ฌผ๋ฆฌ์  ๊ตฌ์กฐ์™€ ๊ธฐ์ˆ ์  ํŠน์„ฑ์„ ์„ค๋ช…ํ•ฉ๋‹ˆ๋‹ค.

2) ๋น„์ฆˆ๋‹ˆ์Šค ๋ฉ”ํƒ€๋ฐ์ดํ„ฐ (Business Metadata)

๋ฐ์ดํ„ฐ์˜ ๋น„์ฆˆ๋‹ˆ์Šค ์ปจํ…์ŠคํŠธ์™€ ์˜๋ฏธ๋ฅผ ์„ค๋ช…ํ•ฉ๋‹ˆ๋‹ค.

3) ์šด์˜ ๋ฉ”ํƒ€๋ฐ์ดํ„ฐ (Operational Metadata)

๋ฐ์ดํ„ฐ์˜ ์‚ฌ์šฉ ํŒจํ„ด๊ณผ ์šด์˜ ์ •๋ณด๋ฅผ ์ถ”์ ํ•ฉ๋‹ˆ๋‹ค.

ํ†ตํ•ฉ ๋ฉ”ํƒ€๋ฐ์ดํ„ฐ ์˜ˆ์‹œ:
{
  "technical": {
    "table": "customers",
    "database": "prod_db",
    "schema": "public",
    "columns": [
      {"name": "customer_id", "type": "BIGINT", "pk": true},
      {"name": "email", "type": "VARCHAR(255)", "unique": true}
    ]
  },
  "business": {
    "description": "๊ณ ๊ฐ ์ •๋ณด๋ฅผ ์ €์žฅํ•˜๋Š” ๋ฉ”์ธ ํ…Œ์ด๋ธ”",
    "owner": "data-team@company.com",
    "purpose": "Customer 360 ๋ถ„์„"
  },
  "operational": {
    "last_updated": "2025-12-26T10:00:00Z",
    "query_count_24h": 1547,
    "quality_score": 0.95,
    "popularity_rank": 5
  }
}

3.2 ๋ฉ”ํƒ€๋ฐ์ดํ„ฐ ์ž๋™ ์ˆ˜์ง‘

๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ๋ฉ”ํƒ€๋ฐ์ดํ„ฐ ์ถ”์ถœ

JDBC, ODBC๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ์‹œ์Šคํ…œ์—์„œ ๋ฉ”ํƒ€๋ฐ์ดํ„ฐ๋ฅผ ์ž๋™์œผ๋กœ ์ˆ˜์ง‘ํ•ฉ๋‹ˆ๋‹ค.

# PostgreSQL ์˜ˆ์‹œ
SELECT
    table_schema,
    table_name,
    column_name,
    data_type,
    is_nullable,
    column_default
FROM information_schema.columns
WHERE table_schema NOT IN ('pg_catalog', 'information_schema')
ORDER BY table_schema, table_name, ordinal_position;

์ฃผ์š” ํ”Œ๋žซํผ๋ณ„ ๋ฉ”ํƒ€๋ฐ์ดํ„ฐ API

ํ”Œ๋žซํผ API/๋„๊ตฌ ์ง€์› ๋ฉ”ํƒ€๋ฐ์ดํ„ฐ
AWS Glue Data Catalog API ํ…Œ์ด๋ธ”, ํŒŒํ‹ฐ์…˜, ์Šคํ‚ค๋งˆ
GCP Data Catalog API BigQuery, Cloud Storage
Snowflake INFORMATION_SCHEMA ํ…Œ์ด๋ธ”, ๋ทฐ, ์ปฌ๋Ÿผ, ๊ณ„๋ณด
Databricks Unity Catalog Delta Lake, ๊ณ„๋ณด
dbt manifest.json ๋ชจ๋ธ, ํ…Œ์ŠคํŠธ, ์˜์กด์„ฑ

3.3 ์Šคํ‚ค๋งˆ ๊ด€๋ฆฌ

์Šคํ‚ค๋งˆ ๋ณ€๊ฒฝ ๊ฐ์ง€

๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ์Šคํ‚ค๋งˆ๋Š” ์ง€์†์ ์œผ๋กœ ๋ณ€๊ฒฝ๋ฉ๋‹ˆ๋‹ค. ๋ณ€๊ฒฝ ์‚ฌํ•ญ์„ ์ž๋™์œผ๋กœ ๊ฐ์ง€ํ•˜๊ณ  ์ถ”์ ํ•˜๋Š” ๊ฒƒ์ด ์ค‘์š”ํ•ฉ๋‹ˆ๋‹ค.

๋ณ€๊ฒฝ ๊ฐ์ง€ ์ „๋žต:
  1. ํด๋ง (Polling): ์ฃผ๊ธฐ์ ์œผ๋กœ ์Šคํ‚ค๋งˆ๋ฅผ ํ™•์ธํ•˜์—ฌ ๋ณ€๊ฒฝ ๊ฐ์ง€
  2. ์ด๋ฒคํŠธ ๊ธฐ๋ฐ˜: ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ํŠธ๋ฆฌ๊ฑฐ/ํ›„ํฌ ํ™œ์šฉ
  3. CDC (Change Data Capture): ํŠธ๋žœ์žญ์…˜ ๋กœ๊ทธ ๋ชจ๋‹ˆํ„ฐ๋ง

์Šคํ‚ค๋งˆ ๋ฒ„์ „ ๊ด€๋ฆฌ

{
  "schema_version_id": "v5",
  "dataset_id": "customers",
  "timestamp": "2025-12-26T10:00:00Z",
  "changes": [
    {
      "type": "ADD_COLUMN",
      "column": "loyalty_points",
      "data_type": "INTEGER",
      "nullable": true
    },
    {
      "type": "MODIFY_COLUMN",
      "column": "email",
      "old_type": "VARCHAR(200)",
      "new_type": "VARCHAR(255)"
    }
  ],
  "changed_by": "migration-script-v1.5"
}

3.4 ๋ฉ”ํƒ€๋ฐ์ดํ„ฐ ํ’ˆ์งˆ ๊ด€๋ฆฌ

ํ’ˆ์งˆ ํ‰๊ฐ€ ๊ธฐ์ค€

ํ•ญ๋ชฉ ๊ธฐ์ค€ ๋ฐฐ์ 
์„ค๋ช… (Description) 20์ž ์ด์ƒ์˜ ์˜๋ฏธ์žˆ๋Š” ์„ค๋ช… 30์ 
์†Œ์œ ์ž (Owner) ์œ ํšจํ•œ ์ด๋ฉ”์ผ ์ฃผ์†Œ 20์ 
์ปฌ๋Ÿผ ์„ค๋ช… 80% ์ด์ƒ ์ปฌ๋Ÿผ์— ์„ค๋ช… 20์ 
ํƒœ๊ทธ ์ตœ์†Œ 2๊ฐœ ์ด์ƒ์˜ ํƒœ๊ทธ 15์ 
์‹ ์„ ๋„ ์ตœ๊ทผ 30์ผ ์ด๋‚ด ์—…๋ฐ์ดํŠธ 15์ 
ํ’ˆ์งˆ ์ ์ˆ˜ ๊ณ„์‚ฐ:
quality_score = (
    (description_score * 0.3) +
    (owner_score * 0.2) +
    (column_description_score * 0.2) +
    (tags_score * 0.15) +
    (freshness_score * 0.15)
)

# ์˜ˆ์‹œ:
customers ํ…Œ์ด๋ธ”:
- Description: 30/30 (์™„๋ฒฝํ•œ ์„ค๋ช…)
- Owner: 20/20 (์œ ํšจํ•œ ์†Œ์œ ์ž)
- Column Description: 16/20 (80%)
- Tags: 15/15 (3๊ฐœ ํƒœ๊ทธ)
- Freshness: 15/15 (์–ด์ œ ์—…๋ฐ์ดํŠธ)
= 96/100 = 0.96 (Gold tier)

3.5 ๋ฉ”ํƒ€๋ฐ์ดํ„ฐ ๊ฑฐ๋ฒ„๋„Œ์Šค

์Šน์ธ ์›Œํฌํ”Œ๋กœ์šฐ

์ค‘์š”ํ•œ ๋ฉ”ํƒ€๋ฐ์ดํ„ฐ ๋ณ€๊ฒฝ ์‚ฌํ•ญ์€ ์Šน์ธ ํ”„๋กœ์„ธ์Šค๋ฅผ ๊ฑฐ์ณ์•ผ ํ•ฉ๋‹ˆ๋‹ค.

์›Œํฌํ”Œ๋กœ์šฐ ์˜ˆ์‹œ:
  1. ๋ฐ์ดํ„ฐ ์—”์ง€๋‹ˆ์–ด๊ฐ€ ์ƒˆ ํ…Œ์ด๋ธ”์˜ ๋ฉ”ํƒ€๋ฐ์ดํ„ฐ ์ž‘์„ฑ
  2. ๋ฐ์ดํ„ฐ ๊ฑฐ๋ฒ„๋„Œ์Šค ํŒ€์— ๋ฆฌ๋ทฐ ์š”์ฒญ
  3. ๋ฆฌ๋ทฐ์–ด๊ฐ€ ์„ค๋ช…, ๋ถ„๋ฅ˜, ํƒœ๊ทธ ๊ฒ€ํ† 
  4. ์Šน์ธ ํ›„ ์นดํƒˆ๋กœ๊ทธ์— ๊ฒŒ์‹œ
  5. ๊ด€๋ จ ํŒ€์— ์•Œ๋ฆผ ๋ฐœ์†ก

๋ฉ”ํƒ€๋ฐ์ดํ„ฐ ํ‘œ์ค€

3.6 ๋ฉ”ํƒ€๋ฐ์ดํ„ฐ ๋™๊ธฐํ™”

์‹ค์‹œ๊ฐ„ vs ๋ฐฐ์น˜ ๋™๊ธฐํ™”

๋ฐฉ์‹ ์žฅ์  ๋‹จ์  ์ ํ•ฉํ•œ ๊ฒฝ์šฐ
์‹ค์‹œ๊ฐ„ ์ฆ‰๊ฐ ๋ฐ˜์˜ ๋†’์€ ๋ถ€ํ•˜ ์ค‘์š” ์šด์˜ DB
๋ฐฐ์น˜ (1์‹œ๊ฐ„) ๊ท ํ˜• ์ง€์—ฐ ์žˆ์Œ ๋Œ€๋ถ€๋ถ„์˜ ๊ฒฝ์šฐ
๋ฐฐ์น˜ (์ผ๊ฐ„) ๋‚ฎ์€ ๋ถ€ํ•˜ ํฐ ์ง€์—ฐ ์•„์นด์ด๋ธŒ ๋ฐ์ดํ„ฐ

์ฆ๋ถ„ ๋™๊ธฐํ™”

์ „์ฒด ๋ฉ”ํƒ€๋ฐ์ดํ„ฐ๋ฅผ ๋งค๋ฒˆ ์ˆ˜์ง‘ํ•˜๋Š” ๋Œ€์‹ , ๋ณ€๊ฒฝ๋œ ๋ถ€๋ถ„๋งŒ ์—…๋ฐ์ดํŠธํ•ฉ๋‹ˆ๋‹ค.

# ์ฆ๋ถ„ ๋™๊ธฐํ™” ์ฟผ๋ฆฌ
SELECT *
FROM metadata_changelog
WHERE last_modified > :last_sync_timestamp
ORDER BY last_modified ASC;

3.7 ๋ฉ”ํƒ€๋ฐ์ดํ„ฐ ์ €์žฅ์†Œ ์•„ํ‚คํ…์ฒ˜

์ €์žฅ์†Œ ์„ ํƒ

์ €์žฅ์†Œ ์šฉ๋„ ์˜ˆ์‹œ
๊ด€๊ณ„ํ˜• DB ๊ตฌ์กฐํ™”๋œ ๋ฉ”ํƒ€๋ฐ์ดํ„ฐ PostgreSQL, MySQL
๋ฌธ์„œ DB ์œ ์—ฐํ•œ ์Šคํ‚ค๋งˆ MongoDB
๊ทธ๋ž˜ํ”„ DB ๊ณ„๋ณด, ๊ด€๊ณ„ Neo4j, JanusGraph
๊ฒ€์ƒ‰ ์—”์ง„ ์ „๋ฌธ ๊ฒ€์ƒ‰ Elasticsearch
๐Ÿ’ก ํ•˜์ด๋ธŒ๋ฆฌ๋“œ ์•„ํ‚คํ…์ฒ˜
๋Œ€๋ถ€๋ถ„์˜ ๋ฐ์ดํ„ฐ ์นดํƒˆ๋กœ๊ทธ๋Š” ์—ฌ๋Ÿฌ ์ €์žฅ์†Œ๋ฅผ ์กฐํ•ฉํ•ฉ๋‹ˆ๋‹ค:
  • PostgreSQL: ๋ฉ”์ธ ๋ฉ”ํƒ€๋ฐ์ดํ„ฐ ์ €์žฅ
  • Neo4j: ๊ณ„๋ณด ๊ทธ๋ž˜ํ”„ ์ €์žฅ
  • Elasticsearch: ๊ฒ€์ƒ‰ ์ธ๋ฑ์Šค
  • Redis: ์บ์‹œ

3.8 ์‹ค์ „ ํŒ

๋ฒ ์ŠคํŠธ ํ”„๋ž™ํ‹ฐ์Šค:
  1. ์ž๋™ํ™” ์šฐ์„ : ์ˆ˜์ž‘์—… ์ตœ์†Œํ™”, ์ž๋™ ์ˆ˜์ง‘ ๊ทน๋Œ€ํ™”
  2. ์ ์ง„์  ๊ฐœ์„ : ์™„๋ฒฝํ•œ ๋ฉ”ํƒ€๋ฐ์ดํ„ฐ๋ฅผ ํ•œ ๋ฒˆ์— ๋งŒ๋“ค๋ ค ํ•˜์ง€ ๋ง๊ฒƒ
  3. ์ธ์„ผํ‹ฐ๋ธŒ ์ œ๊ณต: ๋ฉ”ํƒ€๋ฐ์ดํ„ฐ ์ž‘์„ฑ/๊ฐœ์„  ์‹œ ๋ฆฌ์›Œ๋“œ
  4. ํ’ˆ์งˆ ๋Œ€์‹œ๋ณด๋“œ: ํŒ€๋ณ„ ๋ฉ”ํƒ€๋ฐ์ดํ„ฐ ํ’ˆ์งˆ ์ ์ˆ˜ ๊ณต๊ฐœ
  5. ํ…œํ”Œ๋ฆฟ ์ œ๊ณต: ์ข‹์€ ์„ค๋ช…์˜ ์˜ˆ์‹œ ์ œ๊ณต

3.9 ๋‹ค์Œ ์žฅ ์˜ˆ๊ณ 

๋‹ค์Œ ์žฅ์—์„œ๋Š” Data Lineage Tracking์„ ๋‹ค๋ฃน๋‹ˆ๋‹ค. ๋ฐ์ดํ„ฐ์˜ ํ๋ฆ„์„ ์ถ”์ ํ•˜๊ณ  ๊ณ„๋ณด ๊ทธ๋ž˜ํ”„๋ฅผ ๊ตฌ์ถ•ํ•˜๋Š” ๋ฐฉ๋ฒ•์„ ๋ฐฐ์šฐ๊ฒŒ ๋ฉ๋‹ˆ๋‹ค.