Skip to main content

1. 왜 Lakebase + Apps 배포가 중요한가

기존 OLTP 웹 애플리케이션은 RDS, Cloud SQL 등 외부 데이터베이스를 사용하고, 분석이 필요할 때마다 별도의 ETL 파이프라인으로 데이터를 Lakehouse로 이동시켜야 했습니다. 이 방식은 다음과 같은 문제를 야기합니다.
  • 데이터 사일로 (Data Silo): 운영 DB와 분석 플랫폼이 분리되어 실시간 분석이 어렵습니다.
  • ETL 복잡도: 데이터 이동 파이프라인 유지·관리 비용이 발생합니다.
  • 보안 경계 분산: 별도 DB의 IAM/시크릿 관리가 추가됩니다.
  • 거버넌스 공백: Unity Catalog 혜택(데이터 계보, 접근 제어)을 운영 DB 데이터에 적용하기 어렵습니다.
Databricks Apps + Lakebase 조합은 이 문제를 근본적으로 해결합니다.
이점설명
단일 플랫폼앱 서빙, OLTP 스토리지, 분석이 하나의 Databricks 워크스페이스에서 처리됩니다
자동 동기화 (Data Sync)Lakebase 트랜잭션 데이터가 Delta Lake로 자동 반영됩니다
통합 거버넌스Unity Catalog로 운영 데이터에도 행/열 수준 접근 제어가 적용됩니다
OAuth 통합 인증별도 인증 서버 없이 Databricks OAuth 2.0으로 앱과 DB를 함께 보호합니다
비용 단순화외부 DB 인스턴스 비용 없이 Databricks DBU 기반으로 과금이 통합됩니다

2. 배포 아키텍처

전체 구성도

구성 요소역할연결 방식
End User / Browser최종 사용자 접근HTTPS (Databricks 관리형 도메인)
Databricks Apps (Streamlit / FastAPI)웹 앱 호스팅psycopg2 / SQLAlchemy로 Lakebase 연결
Databricks Identity (SSO)OAuth 2.0 인증앱 접근 시 자동 인증 처리
Lakebase (OLTP DB)PostgreSQL 운영 데이터베이스Apps에서 읽기/쓰기
Delta Lake / Unity Catalog분석 레이어Lakebase에서 Data Sync로 자동 반영

OAuth 인증 흐름 (Authentication Flow)

  1. 사용자가 앱 URL(https://<workspace>.azuredatabricks.net/apps/<app-name>)에 접근합니다.
  2. Databricks Apps 런타임이 Databricks OAuth 2.0으로 사용자를 인증합니다.
  3. 앱 컨테이너 내부에서 DATABRICKS_TOKEN 환경 변수가 자동 주입됩니다.
  4. 앱 코드가 해당 토큰을 사용해 Lakebase에 연결합니다 (generate_lakebase_credential() API 활용).
  5. 모든 DB 접근이 사용자 신원과 연결된 단기 자격증명 (Short-lived Credential)으로 이루어집니다.
핵심: 앱 코드에 장기 비밀번호(Long-lived Password)를 하드코딩할 필요가 없습니다. Databricks가 자격증명 생명주기를 전적으로 관리합니다.

3. app.yaml 설정

app.yaml은 Databricks Apps의 배포 명세 파일입니다. 앱 실행 명령, 환경 변수, 필요 리소스를 선언합니다.

기본 구조 예시 (Streamlit + Lakebase)

# app.yaml — Databricks Apps 배포 설정
command:
  - "streamlit"
  - "run"
  - "app.py"
  - "--server.port=8501"
  - "--server.address=0.0.0.0"

# 리소스 선언 — Databricks가 자동으로 자격증명을 주입합니다
resources:
  - name: "lakebase-instance"
    description: "운영 Lakebase PostgreSQL 인스턴스"
    databricks_resource_type: "databricks-lakebase-database"
    # Lakebase 인스턴스 이름 (Databricks Console에서 확인)
    instance_id: "${var.lakebase_instance_id}"

  - name: "sql-warehouse"
    description: "분석용 SQL Warehouse"
    databricks_resource_type: "databricks-sql-warehouse"
    warehouse_id: "${var.warehouse_id}"

# 환경 변수 설정
env:
  - name: LAKEBASE_HOST
    valueFrom:
      resourceRef:
        resourceName: "lakebase-instance"
        fieldPath: "host"
  - name: LAKEBASE_PORT
    value: "5432"
  - name: LAKEBASE_DBNAME
    value: "shop_db"
  - name: APP_ENV
    value: "production"
  - name: LOG_LEVEL
    value: "INFO"
  # 시크릿은 Databricks Secrets에서 참조합니다
  - name: APP_SECRET_KEY
    valueFrom:
      secretRef:
        secretName: "app-secrets"
        key: "secret_key"

FastAPI를 사용하는 경우

# app.yaml — FastAPI 배포
command:
  - "uvicorn"
  - "main:app"
  - "--host=0.0.0.0"
  - "--port=8000"
  - "--workers=2"

resources:
  - name: "lakebase-instance"
    databricks_resource_type: "databricks-lakebase-database"
    instance_id: "${var.lakebase_instance_id}"

env:
  - name: DATABASE_URL
    value: "postgresql://${LAKEBASE_USER}:${LAKEBASE_PASSWORD}@${LAKEBASE_HOST}:5432/app_db"
  - name: POOL_SIZE
    value: "10"
  - name: MAX_OVERFLOW
    value: "20"

4. 배포 방법

4-1. Databricks CLI를 사용한 직접 배포

# Databricks CLI 설치
pip install databricks-cli

# 워크스페이스 인증 설정
databricks configure --token

# 앱 생성 (최초 1회)
databricks apps create my-lakebase-app \
  --description "Lakebase 기반 쇼핑몰 앱"

# 앱 배포 (소스 디렉터리 기준)
databricks apps deploy my-lakebase-app \
  --source-code-path ./my-app

# 배포 상태 확인
databricks apps get my-lakebase-app

# 앱 로그 실시간 확인
databricks apps logs my-lakebase-app --follow

4-2. Databricks Asset Bundles (DAB) 를 사용한 배포

Asset Bundles는 앱, Job, Pipeline 등 Databricks 리소스를 코드로 관리(IaC)하는 방식입니다.
# databricks.yml — Asset Bundle 설정
bundle:
  name: lakebase-app-bundle

variables:
  lakebase_instance_id:
    description: "Lakebase 인스턴스 ID"
  warehouse_id:
    description: "SQL Warehouse ID"

targets:
  dev:
    mode: development
    workspace:
      host: https://adb-xxxx.azuredatabricks.net
    variables:
      lakebase_instance_id: "dev-instance-id"
      warehouse_id: "dev-warehouse-id"

  prod:
    mode: production
    workspace:
      host: https://adb-yyyy.azuredatabricks.net
    variables:
      lakebase_instance_id: "prod-instance-id"
      warehouse_id: "prod-warehouse-id"

resources:
  apps:
    lakebase_app:
      name: "my-lakebase-app"
      description: "Lakebase 기반 운영 앱"
      source_code_path: ./app
# 개발 환경 배포
databricks bundle deploy --target dev

# 프로덕션 환경 배포
databricks bundle deploy --target prod

4-3. GitHub Actions CI/CD 연동

# .github/workflows/deploy.yml
name: Deploy Databricks App

on:
  push:
    branches: [main]
  pull_request:
    branches: [main]

jobs:
  deploy:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4

      - name: Install Databricks CLI
        run: pip install databricks-cli

      - name: Deploy to Production
        env:
          DATABRICKS_HOST: ${{ secrets.DATABRICKS_HOST }}
          DATABRICKS_TOKEN: ${{ secrets.DATABRICKS_TOKEN }}
        run: |
          databricks bundle deploy --target prod

5. 환경 분리 (Environment Isolation)

프로덕션 데이터 오염을 방지하기 위해 환경별로 독립된 Lakebase 인스턴스를 사용하는 것이 원칙입니다.
환경Lakebase 인스턴스용도
devlakebase-dev개발자 로컬 테스트, 스키마 변경 실험
staginglakebase-stagingQA 테스트, 성능 검증, 마이그레이션 리허설
prodlakebase-prod실제 운영, 고가용성, 백업 필수

환경별 연결 설정 예시 (Python)

# config.py — 환경별 DB 연결 설정
import os

APP_ENV = os.getenv("APP_ENV", "dev")

DB_CONFIG = {
    "dev": {
        "host": os.getenv("LAKEBASE_DEV_HOST"),
        "dbname": "app_dev",
        "pool_size": 3,
        "max_overflow": 5,
    },
    "staging": {
        "host": os.getenv("LAKEBASE_STAGING_HOST"),
        "dbname": "app_staging",
        "pool_size": 5,
        "max_overflow": 10,
    },
    "production": {
        "host": os.getenv("LAKEBASE_PROD_HOST"),
        "dbname": "app_prod",
        "pool_size": 20,
        "max_overflow": 40,
    },
}

current_config = DB_CONFIG[APP_ENV]
주의: 스테이징 환경에 프로덕션 데이터를 복사할 때는 반드시 개인정보(PII)를 마스킹(Masking)하세요.

6. 스케일링과 성능 (Scaling & Performance)

Lakebase 인스턴스 사이징 가이드

규모vCPURAM적합한 동시 접속 수
소규모 (Small)28 GB~50
중간 (Medium)416 GB~200
대규모 (Large)832 GB~500
초대규모 (XLarge)1664 GB~1,000+

연결 풀링 (Connection Pooling) 설정

# database.py — SQLAlchemy 연결 풀 설정
from sqlalchemy import create_engine
from sqlalchemy.pool import QueuePool
import os

def get_engine():
    db_url = (
        f"postgresql+psycopg2://{os.getenv('LAKEBASE_USER')}:"
        f"{os.getenv('LAKEBASE_PASSWORD')}@"
        f"{os.getenv('LAKEBASE_HOST')}:5432/"
        f"{os.getenv('LAKEBASE_DBNAME')}"
    )
    return create_engine(
        db_url,
        poolclass=QueuePool,
        pool_size=int(os.getenv("POOL_SIZE", 10)),      # 기본 유지 연결 수
        max_overflow=int(os.getenv("MAX_OVERFLOW", 20)), # 최대 초과 허용 연결 수
        pool_timeout=30,       # 풀에서 연결을 기다리는 최대 시간 (초)
        pool_recycle=1800,     # 연결 재활용 주기 (초) — 장시간 유휴 연결 방지
        pool_pre_ping=True,    # 연결 유효성 사전 확인 (Dead Connection 방지)
        connect_args={
            "connect_timeout": 10,
            "application_name": "databricks-app",
            "sslmode": "require",  # SSL 필수 (보안)
        },
    )

# 앱 시작 시 엔진 1회 초기화
engine = get_engine()

Auto-scaling 고려 사항

  • Databricks Apps는 자체적으로 요청 기반 스케일링 을 지원합니다.
  • 앱 인스턴스가 늘어날수록 DB 연결 수도 증가합니다. pool_size × 앱 인스턴스 수가 Lakebase 최대 연결 수를 초과하지 않도록 설계하세요.
  • 고트래픽 환경에서는 PgBouncer 또는 Lakebase 내장 연결 관리자를 활용하는 것을 권장합니다.

모니터링, 트레이드오프 분석, 베스트 프랙티스, 운영 체크리스트는 Lakebase Apps 모니터링과 운영 페이지에서 이어집니다.