UI 커스터마이징

UI 커스터마이징 (Customizing the UI)

Airflow 웹 UI를 커스터마이징하는 방법을 설명하는 문서예요. Dag 홈 페이지 헤더와 페이지 제목을 바꾸고, JSON 테마 구성으로 색·전역 CSS·아이콘을 조정하고, 대시보드에 알림 메시지를 추가하는 방법을 살펴볼게요.

출처: 문서

본문

Dag UI 헤더와 Airflow 페이지 제목 커스터마이징 (Customizing Dag UI Header and Airflow Page Titles)

이제 Airflow에서 Dag 홈 페이지 헤더와 페이지 제목을 커스터마이징할 수 있어요. 이는 다양한 Airflow 설치를 구분하거나 단순히 페이지 텍스트를 수정하는 데 도움이 돼요.

참고 (Note)

커스텀 제목은 페이지 헤더와 페이지 제목 양쪽 모두에 적용돼요.

이 변경을 하려면 다음을 수행해요:

  1. airflow.cfg[api] 섹션 아래에 instance_name 구성 옵션을 추가해요:
[api]

instance_name = "DevEnv"
  1. 또는 환경 변수로 커스텀 제목을 설정할 수 있어요:
AIRFLOW__API__INSTANCE_NAME = "DevEnv"

스크린샷 (Screenshots)

Before

After

UI 테마 커스터마이징 (Customizing UI theme)

UI를 커스터마이징하도록 JSON 구성을 제공할 수 있어요.

중요 (Important)

  • brand, gray, black, white 색상 토큰, globalCss, 그리고 icon(및 icon_dark_mode)으로 네비게이션 아이콘을 커스터마이징할 수 있어요.
  • 모든 최상위 필드(tokens, globalCss, icon, icon_dark_mode)는 선택 사항이에요 — 어떤 조합도 제공할 수 있고, 빈 {}를 제공하면 OSS 기본값을 복원해요.
  • 모든 색상 토큰은 선택 사항이에요 — 다른 것을 제공하지 않고 어떤 부분집합이든 오버라이드할 수 있어요.
  • brandgray는 각각 키 50950의 11-셰이드 스케일을 받아요.
  • blackwhite는 각각 단일 색상인 { "value": "oklch(...)" }을 받아요.
  • OKLCH 색상은 oklch(l c h) 형식을 사용해야 해요. 자세한 내용은 theme를 참고하세요.
  • 세밀한 테마 제어를 위해 커스텀 전역 CSS를 제공할 수도 있어요.

참고 (Note)

brand 색상 팔레트를 수정하면 navbar/sidebar도 수정돼요. gray 수정은 중립 표면과 테두리를 제어해요. blackwhite 수정은 가장 어둡고 가장 밝은 표면 색상을 제어해요.

UI를 커스터마이징하려면 다음을 수행해요:

  1. airflow.cfg[api] 섹션 아래에 theme 구성 옵션을 추가해요:
[api]

theme = {
    "tokens": {
      "colors": {
        "brand": {
          "50": { "value": "oklch(0.971 0.013 17.38)" },
          "100": { "value": "oklch(0.936 0.032 17.717)" },
          "200": { "value": "oklch(0.885 0.062 18.334)" },
          "300": { "value": "oklch(0.808 0.114 19.571)" },
          "400": { "value": "oklch(0.704 0.191 22.216)" },
          "500": { "value": "oklch(0.637 0.237 25.331)" },
          "600": { "value": "oklch(0.577 0.245 27.325)" },
          "700": { "value": "oklch(0.505 0.213 27.518)" },
          "800": { "value": "oklch(0.444 0.177 26.899)" },
          "900": { "value": "oklch(0.396 0.141 25.723)" },
          "950": { "value": "oklch(0.258 0.092 26.042)" }
        }
      }
    }
  }

참고 (Note)

특히 마지막 줄의 공백이 중요해서 여러 줄 값이 제대로 동작해요. 자세한 내용은 configparser 문서에서 확인할 수 있어요.

  1. 또는 환경 변수로 커스텀 테마를 설정할 수 있어요:
AIRFLOW__API__THEME='{
  "tokens": {
    "colors": {
      "brand": {
        "50": { "value": "oklch(0.971 0.013 17.38)" },
        "100": { "value": "oklch(0.936 0.032 17.717)" },
        "200": { "value": "oklch(0.885 0.062 18.334)" },
        "300": { "value": "oklch(0.808 0.114 19.571)" },
        "400": { "value": "oklch(0.704 0.191 22.216)" },
        "500": { "value": "oklch(0.637 0.237 25.331)" },
        "600": { "value": "oklch(0.577 0.245 27.325)" },
        "700": { "value": "oklch(0.505 0.213 27.518)" },
        "800": { "value": "oklch(0.444 0.177 26.899)" },
        "900": { "value": "oklch(0.396 0.141 25.723)" },
        "950": { "value": "oklch(0.258 0.092 26.042)" }
      }
    }
  }
}'

스크린샷 (Screenshots)

Light Mode

Dark Mode

  1. Airflow UI에 커스텀 CSS 규칙을 추가하려면 테마 구성에 globalCss 키를 포함할 수 있어요. 자세한 정보는 https://chakra-ui.com/docs/theming/customization/global-css
AIRFLOW__API__THEME='{
  "tokens": {
    "colors": {
      "brand": {
        "50": { "value": "oklch(0.971 0.013 17.38)" },
        "100": { "value": "oklch(0.936 0.032 17.717)" },
        "200": { "value": "oklch(0.885 0.062 18.334)" },
        "300": { "value": "oklch(0.808 0.114 19.571)" },
        "400": { "value": "oklch(0.704 0.191 22.216)" },
        "500": { "value": "oklch(0.637 0.237 25.331)" },
        "600": { "value": "oklch(0.577 0.245 27.325)" },
        "700": { "value": "oklch(0.505 0.213 27.518)" },
        "800": { "value": "oklch(0.444 0.177 26.899)" },
        "900": { "value": "oklch(0.396 0.141 25.723)" },
        "950": { "value": "oklch(0.258 0.092 26.042)" }
      }
    }
  },
  "globalCss": {
    "button": {
      "text-transform": "uppercase"
    }
  }
}'

gray, black, white 토큰 커스터마이징 (Customizing gray, black, and white tokens)

brand와 무관하게 중립 팔레트와 표면 색상을 오버라이드할 수 있어요. gray는 테두리와 중립 UI 요소를 제어하고, blackwhite는 가장 어둡고 가장 밝은 표면 배경을 제어해요. 모든 필드는 선택 사항이에요 — 변경하려는 토큰만 제공하면 돼요.

AIRFLOW__API__THEME='{
  "tokens": {
    "colors": {
      "gray": {
        "50":  { "value": "oklch(0.975 0.002 264.0)" },
        "100": { "value": "oklch(0.950 0.003 264.0)" },
        "200": { "value": "oklch(0.880 0.005 264.0)" },
        "300": { "value": "oklch(0.780 0.008 264.0)" },
        "400": { "value": "oklch(0.640 0.012 264.0)" },
        "500": { "value": "oklch(0.520 0.015 264.0)" },
        "600": { "value": "oklch(0.420 0.015 264.0)" },
        "700": { "value": "oklch(0.340 0.012 264.0)" },
        "800": { "value": "oklch(0.260 0.009 264.0)" },
        "900": { "value": "oklch(0.200 0.007 264.0)" },
        "950": { "value": "oklch(0.145 0.005 264.0)" }
      },
      "black": { "value": "oklch(0.220 0.025 288.6)" },
      "white": { "value": "oklch(0.985 0.002 264.0)" }
    }
  }
}'

아이콘 (SVG 전용) (Icon (SVG-only))

theme 구성에 icon 키(그리고 다크 컬러 모드용으로 선택적으로 icon_dark_mode)를 제공해서 네비게이션 바의 기본 Airflow 아이콘을 바꿀 수 있어요. 값은 절대 http(s) URL이거나 /로 시작하는 앱 상대 경로여야 하고, .svg 파일을 가리켜야 해요.

[api]

theme = {
    "tokens": {
      "colors": {
        "brand": {
          "50": { "value": "oklch(0.971 0.013 17.38)" },
          "100": { "value": "oklch(0.936 0.032 17.717)" },
          "200": { "value": "oklch(0.885 0.062 18.334)" },
          "300": { "value": "oklch(0.808 0.114 19.571)" },
          "400": { "value": "oklch(0.704 0.191 22.216)" },
          "500": { "value": "oklch(0.637 0.237 25.331)" },
          "600": { "value": "oklch(0.577 0.245 27.325)" },
          "700": { "value": "oklch(0.505 0.213 27.518)" },
          "800": { "value": "oklch(0.444 0.177 26.899)" },
          "900": { "value": "oklch(0.396 0.141 25.723)" },
          "950": { "value": "oklch(0.258 0.092 26.042)" }
        }
      }
    },
    "icon": "/static/company-icon.svg",
    "icon_dark_mode": "/static/company-icon-dark.svg"
  }

참고 (Note)

  • SVG 아이콘만 지원돼요.
  • 아이콘 로드에 실패하면 Airflow는 기본 아이콘으로 폴백해요.
  • 아이콘 크기는 UI가 제어하며 테마로 구성할 수 없어요.

대시보드 알림 메시지 추가하기 (Adding Dashboard Alert Messages)

Airflow 대시보드에 추가 알림 메시지를 표시할 수 있어요. 설정 문제에 대한 경고, 최종 사용자에게 변경 사항 공지, 실시간 상태 정보 제공에 유용할 수 있어요. 대시보드 알림은 정적 콘텐츠와 동적 콘텐츠를 모두 지원해요.

기본 정적 알림 (Basic Static Alerts)

웹서버를 재시작할 때까지 일정하게 유지되는 정적 알림 메시지를 추가하려면:

  1. airflow_local_settings.py 파일을 만들어 $PYTHONPATH 또는 $AIRFLOW_HOME/config 폴더에 두세요. (Airflow는 초기화될 때 $AIRFLOW_HOME/configPYTHONPATH에 추가해요.)
  2. airflow_local_settings.py에 다음 내용을 추가해요:

참고: 로컬 설정을 구성하는 방법에 대한 자세한 내용은 로컬 설정 구성을 참고하세요.

from airflow.api_fastapi.common.types import UIAlert

DASHBOARD_UIALERTS = [
    UIAlert("Welcome to Airflow", category="info"),
]
  1. Airflow webserver를 재시작하면 대시보드에 알림 메시지가 표시되는 것을 볼 수 있어요.

알림 카테고리 (Alert Categories)

알림 메시지의 카테고리를 제어할 수 있어요. 사용 가능한 카테고리는 다음과 같아요:

  • "info" (기본값) - 파란색 정보 알림
  • "warning" - 노란색 경고 알림
  • "error" - 빨간색 오류 알림
from airflow.api_fastapi.common.types import UIAlert

DASHBOARD_UIALERTS = [
    UIAlert(text="Welcome to Airflow.", category="info"),
    UIAlert(text="Airflow server downtime scheduled for tomorrow at 10:00 AM.", category="warning"),
    UIAlert(text="Critical error detected!", category="error"),
]

알림의 Markdown 콘텐츠 (Markdown Content in Alerts)

더 풍부한 형식을 위해 알림 메시지에 Markdown을 포함할 수 있어요. 다음 예시에서는 링크가 포함된 heading 2 알림 메시지를 보여줘요:

from airflow.api_fastapi.common.types import UIAlert

DASHBOARD_UIALERTS = [
    UIAlert(text="## Visit [airflow.apache.org](https://airflow.apache.org)", category="info"),
]

동적 대시보드 알림 (Dynamic Dashboard Alerts)

대시보드 알림은 대시보드 페이지가 새로고침될 때마다 업데이트되는 동적 콘텐츠를 지원해요. 이렇게 하면 웹서버 재시작 없이 실시간 상태 업데이트가 가능해요. 동적 알림은 iterable 객체의 인스턴스로 정의해야 해요. 권장 방식은 list를 서브클래스화하고, Airflow가 알림을 반복할 때마다 새 알림을 생성하는 커스텀 __iter__ 메서드를 구현하는 클래스를 만드는 것이에요.

참고 (Note)

동적 알림을 구현할 때는 대시보드 로드 시간에 영향을 주지 않도록 알림 생성 로직을 가볍게 유지하는 것이 중요해요. 비용이 큰 작업에는 결과 캐싱을 고려하고, 알림 생성이 UI를 깨뜨리지 않도록 예외를 우아하게 처리하세요.

동적 알림은 특히 이런 경우에 유용해요:

  • 실시간 알림 (Real-time notifications): 현재 상태 업데이트나 공지를 표시
  • 배포 알림 (Deployment notifications): 현재 배포 상태, 빌드 진행, GitOps 상태 표시
  • 임시 유지보수 알림 (Temporary maintenance alerts): 진행 중인 유지보수나 이슈에 대한 시간 민감 정보 제공
  • 환경별 경고 (Environment-specific warnings): 현재 환경 조건에 따라 다른 알림 표시
  • 외부 서비스 상태 (External service status): 의존 서비스 또는 API의 가용성 표시

동적 알림 만들기 (Creating Dynamic Alerts)

동적 알림을 만들려면 DASHBOARD_UIALERTSlist를 서브클래스화하고 __iter__ 메서드를 구현하는 클래스의 인스턴스로 정의해요. UI는 이 메서드가 생성하는 UIAlert 인스턴스를 반복하고 대시보드 페이지의 알림으로 노출해요.

아래 예시는 알림을 동적으로 생성하는 로직을 어떻게 적용할 수 있는지 보여줘요. 더 실용적인 유스케이스는 API, 데이터베이스 쿼리, 파일에서 생성되는 알림을 포함할 수 있어요.

import random
from airflow.api_fastapi.common.types import UIAlert

class DynamicAlerts(list):
    def __iter__(self):
        # This method is called each time Airflow iterates over DASHBOARD_UIALERTS
        # Example: Flip a coin
        if random.choice([True, False]):
            yield UIAlert("Heads!", category="info")
        else:
            yield UIAlert("Tails!", category="warning")

# Create an instance of the class
DASHBOARD_UIALERTS = DynamicAlerts()

더 알아보기 (Learn more)