왜 커스텀 모델 배포가 필요한가?
Databricks Model Serving은 등록된 MLflow 모델을 REST API 엔드포인트로 배포하는 관리형 서비스입니다. Foundation Model API (FMAPI) 가 제공하는 사전 학습 모델(llama, mixtral 등)로 충분하지 않은 경우, 커스텀 모델 배포가 필요합니다.Foundation Model API vs. 커스텀 모델 배포
| 구분 | Foundation Model API | 커스텀 모델 배포 |
|---|---|---|
| 모델 제어 | Databricks가 제공하는 모델만 사용 | 직접 학습/파인튜닝한 모델 사용 가능 |
| 전처리/후처리 | 불가 (입출력 형식 고정) | 완전한 자유도 |
| 비용 | 토큰당 종량제 (Pay-per-token) | 인스턴스 시간당 과금 |
| 운영 복잡도 | 낮음 (인프라 자동 관리) | 높음 (의존성, 스케일링 직접 설정) |
| 레이턴시 | 공유 인프라 (변동 가능) | 전용 인스턴스 (예측 가능) |
| 규정 준수 | 데이터가 외부 모델 통과 | 워크스페이스 내부에서 처리 |
커스텀 배포가 필요한 경우
| 사용 사례 | 설명 |
|---|---|
| 전후처리 파이프라인 | 입력 데이터 정규화, 피처 엔지니어링, 출력 후처리가 필요한 경우 |
| 파인튜닝 모델 | 도메인 특화 데이터로 Fine-tuning한 모델을 배포해야 하는 경우 |
| 자체 학습 모델 | 사내 데이터로 처음부터 학습한 ML/DL 모델 |
| 앙상블 모델 | 여러 모델의 예측을 결합해야 하는 경우 |
| 외부 라이브러리 의존 | 표준 MLflow flavor에 없는 프레임워크를 사용하는 경우 |
| 비즈니스 로직 포함 | 예측값에 규칙 기반 로직을 적용해야 하는 경우 |
| GPU 추론 | 대규모 딥러닝 모델을 GPU로 서빙해야 하는 경우 |
| 데이터 거버넌스 | 입력 데이터가 외부 서비스로 나가면 안 되는 경우 |
모델 서빙 엔드포인트 (Model Serving Endpoint) 란 학습된 ML 모델을 REST API로 노출하여, 애플리케이션에서 실시간으로 예측을 요청할 수 있게 해주는 서비스입니다. Databricks에서는 인프라 관리, 오토스케일링, 모니터링을 자동으로 처리합니다.
배포 가능한 모델 유형
| 배포 유형 | 설명 | 포함 모델 |
|---|---|---|
| 표준 Flavor | 기본 제공 MLflow Flavor를 사용합니다 | sklearn, xgboost, lightgbm, spark |
| 커스텀 PyFunc | mlflow.pyfunc.PythonModel을 상속하여 자유로운 추론 로직을 구현합니다 | 전처리/후처리, 멀티모델 앙상블 등 |
| 외부 모델 | 외부 LLM 제공사를 프록시합니다 | OpenAI, Anthropic, Cohere |
| 모델 유형 | 특징 | 적합한 경우 |
|---|---|---|
| 표준 MLflow Flavor | mlflow.sklearn, mlflow.xgboost 등으로 저장한 모델 | 단순 predict 호출로 충분한 경우 |
| 커스텀 PyFunc | mlflow.pyfunc.PythonModel을 상속하여 자유로운 추론 로직 구현 | 전후처리, 앙상블, 비즈니스 로직이 필요한 경우 |
| 외부 모델 (External Models) | OpenAI, Anthropic 등 외부 API를 Databricks 엔드포인트로 프록시 | 외부 LLM API에 거버넌스/레이트 리밋을 적용할 때 |
모델 시그니처 정의 (Model Signature)
모델 시그니처 (Model Signature) 는 모델의 입력/출력 스키마를 명시적으로 정의합니다. 시그니처가 있으면 서빙 시 입력 데이터 유효성 검사가 자동으로 수행되어 오류를 조기에 감지할 수 있습니다.시그니처 없이 배포하면 입력 형식 오류가 서빙 환경에서 런타임에 발생합니다.input_example과 함께signature를 항상 명시하는 것을 권장합니다.
PyFunc 커스텀 모델 작성법
mlflow.pyfunc.PythonModel을 상속하면 load_context()와 predict() 메서드를 직접 구현하여 자유로운 추론 로직을 만들 수 있습니다.
기본 구조
커스텀 모델 저장 및 등록
의존성 관리 주의:conda_env또는pip_requirements를 명시하지 않으면, 로컬 환경의 패키지 버전이 서빙 환경과 달라 오류가 발생할 수 있습니다. 반드시 학습에 사용한 주요 라이브러리 버전을 명시하십시오.
실전 패턴
패턴 1: 앙상블 모델 (Ensemble)
여러 모델의 예측을 결합하여 최종 예측을 만드는 패턴입니다. 각 모델을 개별 artifact로 저장하고load_context()에서 한꺼번에 로드합니다.
패턴 2: 파인튜닝 임베딩 모델 (Fine-tuned Embedding)
Hugging Face 모델을 파인튜닝한 후 커스텀 전처리와 함께 배포하는 패턴입니다.패턴 3: 비즈니스 룰 결합 모델
ML 예측에 규칙 기반 로직을 결합하는 패턴입니다.엔드포인트 생성
방법 1: SDK (MLflow Deployments)
방법 2: Databricks SDK
방법 3: REST API
워크로드 크기 옵션
| 워크로드 크기 | 동시 요청 수 (대략) | 적합한 사용 사례 |
|---|---|---|
| Small | 최대 4 동시 요청 | 개발/테스트, 저트래픽 |
| Medium | 최대 16 동시 요청 | 중간 트래픽 프로덕션 |
| Large | 최대 64 동시 요청 | 고트래픽 프로덕션 |
GPU 서빙 설정
딥러닝 모델이나 대규모 모델은 GPU 서빙이 필요합니다.| GPU 워크로드 타입 | GPU 종류 | 적합한 모델 |
|---|---|---|
GPU_SMALL | T4 (16GB) | 소규모 딥러닝 모델, 임베딩 모델 |
GPU_MEDIUM | A10G (24GB) | 중규모 트랜스포머, 이미지 모델 |
GPU_LARGE | A100 (80GB) | 대규모 LLM, 파인튜닝된 Foundation Model |
트래픽 분할 및 A/B 테스트
하나의 엔드포인트에 여러 모델 버전을 동시에 배포하고, 트래픽 비율을 조절하여 A/B 테스트 를 수행할 수 있습니다.| 구성 요소 | 트래픽 비율 | 설명 |
|---|---|---|
| 클라이언트 요청 | 100% | 엔드포인트(fraud-detection)로 전송됩니다 |
| 모델 v3 (현재 프로덕션) | 80% | 현재 안정된 프로덕션 모델입니다 |
| 모델 v4 (챌린저) | 20% | 성능을 검증 중인 새 버전 모델입니다 |
| 응답 | - | 두 모델의 응답이 클라이언트에 반환됩니다 |
블루-그린 배포: 새 모델 버전을 100% 트래픽으로 전환하면서도 이전 버전을 유지하는 방식입니다. 문제 발생 시 즉시 이전 버전으로 롤백할 수 있습니다.
모니터링 (Monitoring)
Inference Table (추론 로그 테이블)
Inference Table 은 엔드포인트의 모든 요청/응답을 Unity Catalog 테이블에 자동으로 저장합니다. 모델 드리프트 감지, 디버깅, 감사 로그 목적으로 활용합니다.엔드포인트 메트릭 확인
콜드 스타트 최적화
콜드 스타트 (Cold Start) 는scale_to_zero_enabled=True 설정 시 트래픽이 없다가 첫 요청이 들어올 때 컨테이너를 다시 시작하는 지연 시간입니다. 일반적으로 30초~5분이 소요됩니다.
| 전략 | 방법 | 트레이드오프 |
|---|---|---|
| Scale-to-zero 비활성화 | scale_to_zero_enabled=False | 비용 증가, 콜드 스타트 없음 |
| Provisioned Concurrency | 최소 인스턴스 수 설정 | 비용 증가, 항상 warm 상태 |
| 모델 경량화 | ONNX 변환, 양자화 (Quantization) | 로드 시간 단축 |
| 의존성 최소화 | 불필요한 패키지 제거 | 컨테이너 빌드/로드 속도 향상 |
load_context() 최적화: 무거운 초기화(모델 로드, 토크나이저 초기화 등)는 반드시load_context()에서 수행하고predict()에서는 수행하지 마십시오.load_context()는 인스턴스 시작 시 한 번만 실행되지만,predict()는 매 요청마다 실행됩니다.
비용 관리
커스텀 모델 서빙은 인스턴스 가동 시간 기준으로 과금됩니다. Foundation Model API의 토큰 기반 과금과 다른 비용 구조를 갖습니다.| 비용 요소 | 설명 | 절감 방법 |
|---|---|---|
| 인스턴스 크기 | Small < Medium < Large 순으로 과금 | 실제 트래픽에 맞는 크기 선택 |
| Scale-to-zero | 트래픽 없을 때 인스턴스 종료 | 개발/비업무 시간에 활성화 |
| GPU 비용 | CPU 대비 5~10배 비용 | 실제 GPU 필요 여부 사전 검증 |
| Inference Table 저장 | Delta Lake 스토리지 비용 | 보존 기간 설정 (TBLPROPERTIES) |
실습: 모델 서빙 엔드포인트 생성 및 호출
엔드포인트 호출 방법
베스트 프랙티스와 흔한 실수
베스트 프랙티스
| 항목 | 권장 사항 |
|---|---|
| 시그니처 필수 정의 | infer_signature()로 항상 입출력 스키마를 명시합니다 |
| 의존성 버전 고정 | scikit-learn==1.4.0처럼 정확한 버전을 pip_requirements에 명시합니다 |
| load_context 최적화 | 모델 로드 등 무거운 작업은 load_context()에서 처리합니다 |
| input_example 제공 | log_model() 시 실제 샘플 데이터를 input_example로 제공합니다 |
| Inference Table 활성화 | 프로덕션에서는 항상 auto_capture_config를 활성화합니다 |
| 환경별 scale_to_zero | 개발은 True, 프로덕션은 False로 설정합니다 |
흔한 실수
| 실수 | 증상 | 해결 방법 |
|---|---|---|
| 의존성 미명시 | ModuleNotFoundError 발생 | pip_requirements에 모든 패키지 버전 명시 |
| 모델 크기 초과 | 엔드포인트 PENDING 상태에서 멈춤 | 커스텀 모델 크기는 일반적으로 수 GB 이하 권장 |
| predict()에서 무거운 로드 | 요청마다 수 초 지연 | 초기화 로직을 load_context()로 이동 |
| 시그니처 불일치 | 400 Bad Request 오류 | 요청 형식을 input_example과 동일하게 맞춤 |
| 타임아웃 미고려 | 기본 타임아웃(60초) 초과 오류 | 모델 최적화 또는 비동기 처리 패턴 도입 |
| GPU 없이 GPU 모델 실행 | CUDA 오류 발생 | workload_type="GPU_SMALL" 이상으로 설정 |
| scale_to_zero + 저레이턴시 | 첫 요청 30초~수 분 지연 | 프로덕션에서는 scale_to_zero_enabled=False |
트러블슈팅
자주 발생하는 문제와 해결 방법
| 증상 | 원인 | 해결 방법 |
|---|---|---|
엔드포인트가 PENDING 상태에서 멈춤 | 모델 로드 실패 또는 의존성 문제 | 엔드포인트 이벤트 로그 확인. conda_env에 정확한 패키지 버전 명시 |
ModuleNotFoundError | 서빙 환경에 필요한 패키지 미설치 | pip_requirements 또는 conda_env에 모든 의존성 추가 |
| 입력 스키마 불일치 | 요청 데이터의 컬럼명/타입이 모델 시그니처와 다름 | input_example과 동일한 형식으로 요청. 모델 시그니처 확인 |
| Scale-to-zero 후 첫 요청 느림 | Cold Start (컨테이너 부팅 시간) | 프로덕션에서는 scale_to_zero_enabled=False 사용 |
| 메모리 부족 (OOM) | 모델 크기 대비 워크로드 크기가 작음 | workload_size를 Medium/Large로 변경 |
| GPU 할당 실패 | GPU 리소스 부족 | 다른 GPU 타입 시도 또는 워크스페이스 관리자에 문의 |
엔드포인트 상태 확인
프로덕션 배포 체크리스트:
- 모델 시그니처(input/output schema)가 올바른지 확인
pip_requirements에 모든 의존성과 정확한 버전을 명시- Scale-to-zero 비활성화 (지연 시간 민감한 경우)
- Inference Table을 활성화하여 요청/응답 로깅
- 엔드포인트 모니터링 알림 설정
정리
| 항목 | 핵심 포인트 |
|---|---|
| 커스텀 vs FMAPI | 파인튜닝 모델, 전후처리, 데이터 거버넌스가 필요하면 커스텀 배포를 선택합니다 |
| 모델 시그니처 | infer_signature()로 입출력 스키마를 명시하여 런타임 오류를 사전 방지합니다 |
| 커스텀 PyFunc | PythonModel을 상속하여 전처리/후처리/앙상블 등 자유로운 추론 로직을 구현합니다 |
| 엔드포인트 생성 | SDK, REST API, UI 세 가지 방법으로 생성할 수 있습니다 |
| 트래픽 분할 | A/B 테스트와 블루-그린 배포로 안전하게 모델을 교체합니다 |
| GPU 서빙 | workload_type으로 T4/A10G/A100 등 GPU를 선택합니다 |
| 콜드 스타트 | 프로덕션에서는 scale_to_zero_enabled=False로 지연 시간을 예측 가능하게 유지합니다 |
| 모니터링 | Inference Table에서 요청/응답을 SQL로 분석하고, 레이턴시와 에러율을 추적합니다 |
| 비용 관리 | 환경별 workload_size와 scale_to_zero 설정으로 불필요한 비용을 절감합니다 |
| 의존성 관리 | conda_env 또는 pip_requirements에 정확한 버전을 명시하는 것이 핵심입니다 |