왜 피처 테이블 관리가 중요한가?
머신러닝 프로젝트에서 데이터 과학자들이 가장 많은 시간을 보내는 단계는 피처 엔지니어링(Feature Engineering) 입니다. 문제는 각자가 만든 피처가 노트북 곳곳에 흩어져 있어, 재사용이 어렵고 일관성이 깨지기 쉽다는 것입니다.| 문제 | 설명 |
|---|---|
| 중복 작업 | 동일한 피처를 여러 팀이 각자 계산합니다 (예: “고객 30일 평균 거래 금액”) |
| 학습-서빙 불일치 | 학습 시 계산한 피처와 온라인 서빙 시 계산한 피처가 다릅니다 (Training-Serving Skew) |
| 버전 관리 부재 | 피처 정의가 바뀌어도 이전 버전을 추적할 수 없습니다 |
| 발견 불가 | 다른 팀이 만든 유용한 피처가 있는지 알 수 없습니다 |
💡 피처 테이블(Feature Table) 이란 ML 학습에 사용되는 피처들을 기본 키(Primary Key) 와 함께 저장한 Delta 테이블입니다. Unity Catalog에 등록되어 검색, 공유, 리니지 추적이 가능합니다. Databricks Feature Engineering은 이러한 피처 테이블을 체계적으로 생성, 관리, 조회하는 프레임워크입니다.
핵심 개념
| 단계 | 작업 | 설명 |
|---|---|---|
| 1 | 원본 데이터 | 트랜잭션, 로그 등의 소스 데이터입니다 |
| 2 | 피처 계산 | 집계, 변환을 수행하여 피처를 생성합니다 |
| 3 | 피처 테이블 (Unity Catalog) | 피처를 중앙 저장소에 관리합니다 (핵심) |
| 4a | 학습 데이터 생성 | FeatureLookup으로 학습 데이터를 구성합니다 |
| 4b | 온라인 서빙 | Online Store에서 실시간 피처를 제공합니다 |
| 5 | 모델 학습 | 학습 데이터로 모델을 학습합니다 |
| 6 | 모델 배포 | 배포된 모델이 Online Store에서 피처를 조회합니다 |
피처 테이블 vs 일반 Delta 테이블
| 특성 | 일반 Delta 테이블 | 피처 테이블 |
|---|---|---|
| 기본 키 | 선택 사항 | 필수 (Lookup에 사용) |
| 타임스탬프 키 | 없음 | 선택 (Point-in-time lookup용) |
| 자동 리니지 | 테이블 레벨만 | 피처 → 모델 → 서빙까지 추적 |
| 온라인 스토어 동기화 | 수동 | 자동 퍼블리시 지원 |
| Feature UI | 표시 안 됨 | Feature 탭에서 검색/탐색 가능 |
| 서빙 시 자동 조회 | 불가 | 모델 배포 시 자동 피처 조회 |
피처 테이블 생성
FeatureEngineeringClient 사용
타임스탬프 키가 있는 피처 테이블
시계열 피처에는 타임스탬프 키 를 추가하여 Point-in-time Lookup을 지원합니다.피처 명명 규칙 및 조직화
체계적인 피처 관리를 위해 일관된 명명 규칙 을 정하는 것이 중요합니다.추천 명명 규칙
| 구분 | 규칙 | 예시 |
|---|---|---|
| 테이블 이름 | {entity}_features 또는 {entity}_{domain}_features | customer_features, product_behavior_features |
| 피처 이름 | {집계방법}_{대상}_{기간} | avg_amount_30d, count_transactions_7d |
| 타임스탬프 키 | timestamp 또는 event_time | timestamp |
| 기본 키 | 엔티티의 고유 식별자 | customer_id, product_id |
카탈로그 구조
| 카탈로그/스키마 | Feature Table | 설명 |
|---|---|---|
| catalog > ml_features | customer_features | 고객 정적 피처 |
| customer_hourly_features | 고객 시간대별 피처 | |
| product_features | 상품 피처 | |
| merchant_features | 가맹점 피처 | |
| customer_product_features | 고객-상품 교차 피처 |
💡 피처 검색: Unity Catalog에 등록된 피처 테이블은 Databricks UI의 Feature 탭에서 검색하고 메타데이터(설명, 태그, 리니지)를 확인할 수 있습니다. 팀 간 피처 공유에 매우 유용합니다.
FeatureLookup 상세
FeatureLookup은 피처 테이블에서 원하는 피처를 기본 키로 조인하여 가져오는 메커니즘입니다. 학습 데이터를 만들 때 라벨 데이터에 피처를 결합하는 핵심 도구입니다.
기본 사용법
FeatureLookup이 모델에 기록되는 원리
| 단계 | 작업 | 설명 |
|---|---|---|
| 1 | fe.create_training_set() | Training Set을 생성합니다 (피처 조회 메타데이터 포함) |
| 2 | 모델 학습 | sklearn, XGBoost 등으로 모델을 학습합니다 |
| 3 | fe.log_model() | 모델을 로깅합니다 |
| 4 | MLflow 저장 | 모델 + 피처 메타데이터를 MLflow에 저장합니다 |
| 5 | 서빙 시 자동 조회 | 서빙 시 자동으로 피처 테이블에서 피처를 조회합니다 |
💡 핵심 원리: fe.log_model()로 모델을 저장하면, 어떤 피처 테이블에서 어떤 피처를 사용했는지가 모델에 기록됩니다. 서빙 시에는 기본 키만 전달하면 나머지 피처는 자동으로 피처 테이블에서 조회됩니다.
Point-in-time Lookups
시계열 데이터에서는 미래 데이터 누수(Data Leakage) 를 방지하기 위해 Point-in-time Lookup이 필수적입니다. 이벤트 발생 시점 기준으로 그 시점까지 알 수 있었던 피처만 가져옵니다.💡 데이터 누수(Data Leakage) 란 학습 시에는 알 수 없는 미래 데이터가 피처로 포함되는 것을 말합니다. 예를 들어, 화요일에 발생한 거래의 사기 여부를 예측할 때 수요일의 피처 값을 사용하면 실제 서빙 환경과 달라집니다.
Point-in-time Lookup 동작 원리
| 라벨 데이터 | 피처 테이블 | 결과 |
|---|---|---|
| customer_id=A, event_time=14:00 | customer_id=A, timestamp=13:00, count=5 | count=5 (13:00 피처 사용) |
| customer_id=A, event_time=14:00 | customer_id=A, timestamp=15:00, count=8 | 사용 안 함(미래 데이터) |
| customer_id=A, event_time=16:00 | customer_id=A, timestamp=15:00, count=8 | count=8 (15:00 피처 사용) |
온라인 vs 오프라인 스토어
| 특성 | 오프라인 스토어 | 온라인 스토어 |
|---|---|---|
| 저장소 | Delta 테이블 (Unity Catalog) | DynamoDB, Azure Cosmos DB 등 |
| 지연 시간 | 초~분 단위 | 밀리초 단위 |
| 용도 | 배치 학습, 분석, 백필 | 실시간 추론 서빙 |
| 데이터 크기 | 수십 TB까지 | 최신 스냅샷만 저장 |
| 비용 | 상대적으로 저렴 | 읽기 처리량에 따라 증가 |
온라인 스토어 퍼블리시
실습: 피처 테이블 전체 워크플로
다음은 피처 생성부터 모델 학습, 서빙까지의 전체 워크플로입니다.피처 테이블 업데이트
기존 피처 테이블에 새로운 데이터를 추가하거나 갱신할 수 있습니다.⚠️ 주의:overwrite모드는 기존 데이터를 완전히 교체합니다. 점진적 업데이트에는 반드시merge모드를 사용하십시오.
모범 사례 및 안티패턴
모범 사례
| 항목 | 권장 사항 |
|---|---|
| 기본 키 설계 | 비즈니스 엔티티의 고유 식별자를 사용합니다 (customer_id, product_id) |
| 피처 분리 | 도메인별로 별도의 피처 테이블을 만듭니다 (고객, 상품, 가맹점 등) |
| 설명 추가 | description과 tags를 반드시 작성하여 팀 간 검색이 가능하게 합니다 |
| Point-in-time | 시계열 피처에는 반드시 타임스탬프 키를 포함합니다 |
| 스케줄 갱신 | Databricks Jobs로 피처 테이블을 정기적으로 갱신합니다 |
| 테스트 | 피처 계산 로직에 대한 단위 테스트를 작성합니다 |
안티패턴
| 안티패턴 | 문제점 | 개선 방법 |
|---|---|---|
| 거대한 단일 테이블 | 하나의 테이블에 수백 개 피처를 넣으면 관리와 갱신이 어렵습니다 | 도메인별로 분리하고 FeatureLookup으로 결합합니다 |
| 노트북에서 직접 조인 | 피처 조회 로직이 모델에 기록되지 않아 서빙 시 불일치가 발생합니다 | 반드시 FeatureLookup + fe.log_model()을 사용합니다 |
| 타임스탬프 없는 시계열 피처 | 미래 데이터 누수로 모델 성능이 과대평가됩니다 | timestamp_keys를 추가하고 timestamp_lookup_key를 사용합니다 |
| 피처 이름에 버전 포함 | avg_amount_v2, avg_amount_v3 등은 혼란을 초래합니다 | 테이블 자체를 버전 관리하거나, Delta 테이블의 시간 여행을 활용합니다 |
| 수동 피처 복사 | 피처를 CSV로 내보내 다른 프로젝트에서 사용하면 일관성이 깨집니다 | Unity Catalog의 권한 설정으로 테이블을 직접 공유합니다 |
정리
| 항목 | 핵심 포인트 |
|---|---|
| 피처 테이블 | 기본 키 + 피처를 Delta 테이블로 관리하여 재사용성과 일관성을 확보합니다 |
| FeatureLookup | 라벨 데이터에 피처를 자동으로 결합하고, 메타데이터를 모델에 기록합니다 |
| Point-in-time | 타임스탬프 키로 미래 데이터 누수를 방지합니다 |
| 온라인/오프라인 | 오프라인은 학습용, 온라인은 실시간 서빙용으로 동일한 피처를 이중 저장합니다 |
| fe.log_model() | 피처 조회 정보가 모델에 포함되어, 서빙 시 기본 키만으로 예측이 가능합니다 |
| 명명 규칙 | 일관된 테이블/피처 명명과 설명으로 팀 간 피처 공유를 촉진합니다 |