Variables와 Params — 런타임 설정 전달하기
Apache Airflow Official Documentation (in-repo snapshot) — Apache Software Foundation core-concepts/variables.rst, core-concepts/params.rst
이 모듈을 다 읽으면
- Variable과 XCom, 그리고 Variable과 Param의 용도 차이를 설명할 수 있다
- Param의 JSON Schema 기반 검증이 schedule 유무에 따라 언제 이루어지는지 설명할 수 있다
- Dag 레벨/태스크 레벨/트리거 시 사용자 지정 Param 사이의 우선순위를 설명할 수 있다
Variable과 Param은 둘 다 Airflow의 런타임 설정 메커니즘이지만 성격이 다르다 — Variable은 전역 키/값 저장소이고, Param은 Dag/태스크 단위로 정의되고 JSON Schema로 검증되는 타입이 있는 파라미터다. 이 모듈은 Variable의 조회 방식과 XCom과의 관계, 그리고 Param의 정의·우선순위·JSON Schema 검증·트리거 UI 폼 자동 생성까지 다룬다.
Variables: 전역 키/값 저장소
Variable은 Airflow의 런타임 설정 개념으로, 전역적이며 태스크에서 조회할 수 있는 일반적인 key/value 저장소다. Airflow UI로 쉽게 설정하거나 JSON 파일로 일괄 업로드할 수 있다. 사용하려면 ``Variable`` 모델을 import해서 ``get``을 호출하면 된다 — ``Variable.get("foo")``로 일반 조회, ``Variable.get("bar", deserialize_json=True)``로 JSON 값 자동 역직렬화, ``Variable.get("baz", default=None)``으로 변수가 없을 때 기본값 반환이 가능하다. ``get_current_context()``로 얻은 Task Context를 통해서도 접근할 수 있으며, ``context["var"]``는 ``var["value"]``(원시 문자열 값)와 ``var["json"]``(구조화된 데이터를 위한 JSON 값) 두 가지 접근 방식을 제공한다. 템플릿에서는 ``{{ var.value.<변수이름> }}``(원시값) 또는 ``{{ var.json.<변수이름> }}``(JSON 자동 역직렬화)로 쓸 수 있다.
Variable은 특정 Airflow Team을 위해 만들어진 것이 아니라면(Multi-Team 환경 설정 시) 전역이다. 전역 Variable은 설치 전체를 아우르는 설정에만 써야 하고, 팀 기반 Variable은 특정 팀에 관련된 설정에 써야 한다. Task/Operator 사이에 데이터를 전달하려면 Variable이 아니라 XCom을 써야 한다. 또한 설정을 최대한 Dag 파일 안에 두어 소스 컨트롤로 버전 관리하는 것이 권장되며, Variable은 정말로 런타임에 의존적인 값에 대해서만 쓰는 것이 좋다.
핵심 포인트
- Variable은 전역(또는 Team 단위) key/value 저장소이며, Variable.get()이나 context["var"]["value"/"json"], 또는 {{ var.value.x }}/{{ var.json.x }} 템플릿으로 접근한다
- Task 간 데이터 전달에는 Variable이 아니라 XCom을 써야 하며, 설정은 가능한 한 Dag 코드에 두고 Variable은 진짜 런타임 의존 값에만 쓰는 것이 권장된다
Params: 타입이 있는 런타임 파라미터
Params는 태스크에 런타임 설정을 제공할 수 있게 해준다. Dag 코드에서 기본 Param을 구성해두고, Dag를 트리거할 때 추가 Param을 제공하거나 Param 값을 덮어쓸 수 있다. ``Param`` 값은 JSON Schema로 검증되며, 스케줄된 Dag Run에서는 기본 Param 값이 쓰인다. 정의된 Param은 수동 트리거 시 사용자 친화적인 UI를 렌더링하는 데도 쓰이며, 사용자가 제공한 값이 검증을 통과하지 못하면 Airflow는 Dag Run을 생성하는 대신 경고를 보여준다.
Dag에 Param을 추가하려면 ``DAG``를 초기화할 때 ``params`` kwarg에, Param 이름을 ``Param`` 객체나 기본값을 나타내는 객체에 매핑하는 딕셔너리를 전달한다(예: ``Param(5, type="integer", minimum=3)``). 태스크 레벨에도 개별적으로 Param을 추가할 수 있다. 우선순위는 '태스크 레벨 Param이 Dag 레벨 Param보다 우선하고, Dag를 트리거할 때 사용자가 제공한 값이 태스크 레벨 Param보다 우선'하는 순서다. Param은 템플릿 문자열 안에서 ``params`` 아래로 참조할 수 있으며(``{{ params.my_int_param + 10 }}``), 기본적으로 템플릿은 문자열을 태스크에 넘겨주지만 ``render_template_as_native_obj=True``를 Dag에 설정하면 Param의 실제 타입(int 등)이 그대로 전달된다 — 다만 이는 Jinja의 native 렌더링을 쓰므로 ``"42"`` 같은 Python 리터럴처럼 보이는 문자열도 변환될 수 있다는 점을 주의해야 한다. 태스크의 ``context`` kwarg를 통해 ``context["params"]["my_int_param"]``으로 접근하는 방법도 있다.
주의할 점으로, Dag 레벨 파라미터는 태스크에 전달되는 '기본값'일 뿐이며, UI 폼이나 CLI로 수동 제공된 값은 DagRun과 TaskInstance의 컨텍스트 안에서만 존재한다. 이는 TaskFlow Dag에서 특히 중요한데, ``with DAG(...) as dag:`` 블록 안의 로직에서 ``dag`` 객체를 통해 수동 제공값에 접근하려 하면 항상 기본값만 보게 되므로, 수동 제공값을 확실히 얻으려면 태스크 안에서 ``params``나 ``ti`` 같은 템플릿 변수를 써야 한다.
핵심 포인트
- Param 우선순위는 '트리거 시 사용자 제공값 > 태스크 레벨 Param > Dag 레벨 Param' 순이며, Dag 객체를 통해 접근하면 항상 기본값만 보이므로 태스크 안에서 params/ti로 접근해야 한다
- render_template_as_native_obj=True를 쓰면 Param이 실제 타입(int 등)으로 전달되지만, 숫자처럼 보이는 문자열이 의도치 않게 변환될 수 있다
JSON Schema 검증과 스케줄 유무에 따른 차이
``Param``은 JSON Schema를 활용하므로 JSON Schema 명세의 전체 기능(``minimum``/``maximum``, ``enum``, ``type``에 리스트를 지정하는 다중 타입, ``format``, ``minLength``/``maxLength`` 등)을 그대로 쓸 수 있다. 예를 들어 ``Param(10, type="integer", minimum=0, maximum=20)``처럼 범위를 제한하거나, ``Param(5, type=["null", "number", "string"])``처럼 여러 타입 중 하나를 허용하거나(단, 필수 Param은 반드시 기본값을 가져야 한다), ``Param("foo", enum=["foo", "bar", 42])``처럼 열거형으로 제한하거나, ``format="idn-email"`` 같은 JSON Schema 포맷을 쓸 수 있다.
검증 시점은 Dag의 ``schedule`` 설정 여부에 따라 달라진다 — Dag에 ``schedule``이 정의되어 있다면 기본값을 가진 Param이 유효해야 하며 이는 Dag 파싱 시점에 검증된다. ``schedule=None``이라면 Param은 Dag 파싱 시점에는 검증되지 않고 Dag를 트리거하는 시점에 검증된다. 이는 Dag 작성자가 기본값을 제공하지 않고 트리거 시점에 사용자가 반드시 유효한 파라미터를 제공하도록 강제하고 싶은 경우에 유용하다.
보안상의 이유로 현재는 커스텀 클래스로부터 파생된 ``Param`` 객체를 사용할 수 없다(향후 Operator ExtraLinks처럼 등록 시스템을 도입할 계획).
핵심 포인트
- schedule이 정의된 Dag는 기본값을 가진 Param이 Dag 파싱 시점에 검증되지만, schedule=None인 Dag는 트리거 시점에만 검증된다
- Param은 JSON Schema를 그대로 활용해 minimum/maximum, enum, 다중 type, format 등 풍부한 제약 조건을 표현할 수 있다
Trigger UI 폼과 런타임 수정 제한
Dag 레벨 Param은 사용자가 UI에서 'Trigger Dag' 버튼을 클릭했을 때 사용자 친화적인 트리거 폼을 렌더링하는 데도 쓰인다(2.6.0에서 추가). Dag에 Param이 정의되어 있지 않으면 트리거 폼 자체가 생략된다. 최상위 Dag Param에 원시 스칼라 값(불리언, 정수, 문자열, 리스트, 딕셔너리)을 쓰면 자동으로 ``Param`` 객체로 박싱되고 ``type``도 자동 감지되어 대응하는 폼 필드 타입으로 렌더링된다. ``Param``의 ``title``·``description``·``description_md`` 속성으로 폼 필드의 라벨과 도움말을 지정할 수 있고, ``type``에 따라 ``string``(텍스트/날짜/시간/기간 피커, ``enum``으로 드롭다운), ``number``/``integer``(숫자 입력), ``boolean``(토글), ``array``(여러 줄 텍스트 또는 다중 선택), ``object``(JSON 입력), ``null``(선택적 필드 표현용) 등 서로 다른 폼 요소가 생성된다. ``section`` 속성으로 필드를 섹션으로 묶을 수 있고(섹션은 기본적으로 접힘), ``const``로 값을 폼에서는 숨기되 제출은 되게 할 수 있다.
``core.dag_run_conf_overrides_params`` 플래그로 Dag를 트리거할 때 Param을 런타임에 수정할 수 있는지 여부를 제어할 수 있다. 이를 ``False``로 설정하면 기본 Param들이 사실상 상수처럼 동작하게 되어, 트리거 시점에 사용자가 값을 덮어쓸 수 없게 된다.
핵심 포인트
- Dag 레벨 Param은 트리거 UI 폼을 자동 생성하는 데 쓰이며, Param이 하나도 없으면 트리거 폼 자체가 생략된다
- core.dag_run_conf_overrides_params를 False로 설정하면 기본 Param 값이 사실상 상수가 되어 트리거 시점 사용자 오버라이드가 막힌다