반응형

아이스버그 지원 데이터 타입

아이스버그는 구조화된 테이블 형식이지만, 생각보다 다양한 데이터 타입을 지원합니다:

 

기본 데이터 타입:

CREATE TABLE multimedia_content (
    id BIGINT,
    title STRING,
    content_type STRING,
    -- 바이너리 데이터 (이미지, 동영상, 문서 등)
    file_data BINARY,
    -- JSON 형태의 반정형 데이터
    metadata STRING,
    -- 배열과 맵 구조
    tags ARRAY<STRING>,
    properties MAP<STRING, STRING>,
    -- 중첩 구조체
    author STRUCT<name: STRING, email: STRING, department: STRING>,
    created_at TIMESTAMP
) USING ICEBERG

비정형 데이터 처리 방법들

1. 바이너리 데이터 저장

# 이미지나 문서를 바이너리로 저장
import base64

def store_file_in_iceberg(file_path, table_name):
    with open(file_path, 'rb') as f:
        file_content = f.read()
        encoded_content = base64.b64encode(file_content)

    spark.sql(f"""
        INSERT INTO {table_name} VALUES (
            1, 
            'sample_image.jpg', 
            'image/jpeg',
            '{encoded_content.decode()}',
            current_timestamp()
        )
    """)

 

2. JSON/반정형 데이터 저장

# JSON 데이터를 STRING으로 저장 후 쿼리 시 파싱
json_data = {
    "user_id": 123,
    "preferences": {"theme": "dark", "language": "ko"},
    "activity_log": [{"action": "login", "timestamp": "2024-01-01T10:00:00Z"}]
}

spark.sql(f"""
    INSERT INTO user_profiles VALUES (
        123,
        'John Doe',
        '{json.dumps(json_data)}',
        current_timestamp()
    )
""")

# 쿼리 시 JSON 함수 사용
spark.sql("""
    SELECT 
        user_id,
        get_json_object(profile_json, '$.preferences.theme') as theme,
        get_json_object(profile_json, '$.activity_log[0].action') as last_action
    FROM user_profiles
""")

 

3. 복합 데이터 구조 활용

# 스키마 정의
schema = StructType([
    StructField("log_id", LongType()),
    StructField("user_events", ArrayType(StructType([
        StructField("event_type", StringType()),
        StructField("event_data", MapType(StringType(), StringType())),
        StructField("timestamp", TimestampType())
    ]))),
    StructField("session_info", MapType(StringType(), StringType()))
])

# 복잡한 중첩 데이터 저장
complex_data = [
    (1, [
        ("click", {"button": "submit", "page": "checkout"}, datetime.now()),
        ("view", {"page": "product", "product_id": "123"}, datetime.now())
    ], {"browser": "chrome", "device": "mobile"})
]

df = spark.createDataFrame(complex_data, schema)
df.write.format("iceberg").mode("append").saveAsTable("analytics.user_events")

하이브리드 아키텍처 패턴

실무에서는 보통 하이브리드 접근법을 사용합니다:

 

패턴 1: 메타데이터 + 파일 참조

# 큰 파일은 S3에 원본 저장, 메타데이터만 아이스버그에
CREATE TABLE document_registry (
    doc_id BIGINT,
    title STRING,
    doc_type STRING,
    -- 실제 파일의 S3 경로
    file_path STRING,
    file_size BIGINT,
    -- 추출된 텍스트나 메타데이터
    extracted_text STRING,
    tags ARRAY<STRING>,
    upload_date TIMESTAMP
) USING ICEBERG

# 사용 예시
INSERT INTO document_registry VALUES (
    1,
    'Q1 Financial Report',
    'PDF',
    's3://documents/reports/q1-2024.pdf',
    2048576,
    'Revenue increased by 15%...',
    ARRAY('finance', 'quarterly', '2024'),
    current_timestamp()
)

 

패턴 2: 스트리밍 로그 데이터

# 로그 데이터를 구조화하여 저장
CREATE TABLE application_logs (
    log_id BIGINT,
    timestamp TIMESTAMP,
    level STRING,
    service STRING,
    -- 원본 로그 메시지
    raw_message STRING,
    -- 파싱된 구조화 데이터
    parsed_fields MAP<STRING, STRING>,
    -- 에러 스택트레이스 등
    details STRUCT
        error_code: STRING,
        stack_trace: STRING,
        user_id: BIGINT
    >
) USING ICEBERG
PARTITIONED BY (hours(timestamp), level)

 

패턴 3: IoT/센서 데이터

CREATE TABLE sensor_readings (
    device_id STRING,
    timestamp TIMESTAMP,
    sensor_type STRING,
    -- 다양한 센서값을 JSON으로 저장
    readings STRING,  -- JSON: {"temperature": 25.3, "humidity": 60.2, "pressure": 1013.25}
    -- 추가 메타데이터
    location STRUCT<latitude: DOUBLE, longitude: DOUBLE>,
    device_metadata MAP<STRING, STRING>
) USING ICEBERG
PARTITIONED BY (days(timestamp), sensor_type)

한계점과 대안

아이스버그로 처리하기 어려운 경우:

  • 매우 큰 바이너리 파일 (동영상, 고해상도 이미지)
  • 실시간 변경이 잦은 키-값 데이터
  • 그래프 데이터베이스가 필요한 관계형 데이터

이런 경우의 대안:

# 멀티모달 데이터 아키텍처
"""
대용량 파일: S3 직접 저장
├── videos/raw/video_001.mp4
├── images/raw/image_001.jpg

메타데이터: Iceberg 테이블
├── media_catalog (파일 경로, 메타데이터)
├── processing_history (변환 이력)
└── analytics_results (분석 결과)

검색/분석: ElasticSearch, Vector DB
├── 텍스트 검색
├── 이미지 유사도 검색
└── 추천 시스템
"""

 

실제 구현 예시:

def process_multimedia_pipeline():
    # 1. 원본 파일을 S3에 저장
    s3_path = upload_to_s3(file_data, bucket="raw-media")

    # 2. 메타데이터 추출 및 아이스버그 저장
    metadata = extract_metadata(file_data)
    spark.sql(f"""
        INSERT INTO media_catalog VALUES (
            '{file_id}',
            '{s3_path}',
            '{metadata["type"]}',
            {metadata["size"]},
            '{json.dumps(metadata["properties"])}',
            current_timestamp()
        )
    """)

    # 3. 검색용 인덱스 생성
    create_search_index(file_id, metadata)

 

결론적으로, 아이스버그는 완전한 비정형 데이터는 직접 저장하기 어렵지만, JSON, 바이너리, 복합 구조체 등을 통해 상당히 유연한 데이터 저장이 가능합니다. 실무에서는 보통 아이스버그를 메타데이터와 구조화 가능한 부분에는 사용하고, 순수 비정형 데이터는 별도 스토리지와 조합하는 하이브리드 아키텍처를 많이 사용합니다.

반응형

'Data Platform > Iceberg' 카테고리의 다른 글

[Apache Iceberg] 스키마 변경  (0) 2025.06.19
[Apache Iceberg] 매니페스트(Manifest)란?  (0) 2025.06.19
[Apache Iceberg] 사용 방식  (0) 2025.06.19
[Apache Iceberg] Iceberg란?  (6) 2025.06.19

+ Recent posts