매핑 가능한 데이터 타입, 템플릿 필드와의 상호작용, 매핑 상한과 빈 매핑 처리
Apache Airflow Official Documentation (in-repo snapshot) — Apache Software Foundation authoring-and-scheduling/dynamic-task-mapping.rst - What data types can be expanded?, How do templated fields and mapped arguments interact?, Placing limits on mapped tasks, Automatically skipping zero-length maps (약 603-709줄)
이 모듈을 다 읽으면
- 매핑 가능한 XCom 데이터 타입과 실패 조건(UnmappableXComTypePushed)을 설명할 수 있다
- 템플릿 필드가 매핑되면 왜 템플릿 치환이 되지 않는지 설명할 수 있다
- max_map_length와 max_active_tis_per_dag 두 제한의 적용 범위 차이를 설명할 수 있다
매핑 대상은 dict 또는 list(혹은 이를 담은 XCom)만 가능하며, 템플릿 필드도 매핑되면 템플릿 치환 없이 원문 그대로 전달되고, max_map_length는 expand가 만들 수 있는 태스크 총 개수를, max_active_tis_per_dag는 동시에 실행 가능한 매핑 태스크 복사본 수를 제한하며, 빈 리스트로 매핑하면 해당 태스크는 SKIPPED로 처리된다.
매핑 가능한 데이터 타입
현재로서는 dict, list, 또는 태스크 결과로 XCom에 저장된 이 두 타입에 대해서만 매핑할 수 있다.
업스트림 태스크가 매핑 불가능한 타입을 반환하면 매핑 태스크는 런타임에 `UnmappableXComTypePushed` 예외로 실패한다 - 예를 들어 업스트림이 순수 문자열을 반환하는 것은 허용되지 않으며, 반드시 list나 dict여야 한다.
핵심 포인트
- 매핑 대상으로 쓸 수 있는 타입은 현재 dict, list, 또는 XCom에 저장된 이 두 타입뿐이며, 업스트림이 매핑 불가능한 타입(예: 순수 문자열)을 반환하면 런타임에 UnmappableXComTypePushed 예외로 실패한다
템플릿 필드와 매핑의 상호작용
오퍼레이터의 어떤 인자든 매핑될 수 있으며, 원래 템플릿 처리 대상이 아닌 인자도 매핑할 수 있다.
하지만 어떤 필드가 템플릿 처리 대상으로 표시되어 있는 *동시에* 매핑도 된다면, 그 필드는 템플릿 치환이 **되지 않는다**. 예를 들어 매핑된 리스트에 `"{{ ds }}"`라는 문자열을 담아 넘기면, 실제 날짜값이 아니라 `{{ ds }}`라는 원문 그대로가 출력된다.
값을 실제로 보간하고 싶다면, 직접 `task.render_template`을 호출하거나 다른 방식으로 보간해야 한다 - 예를 들어 함수 인자 기본값을 `ds=None`으로 선언해 컨텍스트 값을 받게 하거나, `**context`로 전체 컨텍스트를 받아 `context["task"].render_template("{{ ds }}", context)`처럼 명시적으로 렌더링할 수 있다.
핵심 포인트
- 어떤 오퍼레이터 인자든 매핑될 수 있지만, 원래 템플릿 처리 대상으로 표시된 필드라도 매핑되면 템플릿 치환이 되지 않고 {{ ds }} 같은 원문이 그대로 전달된다
- 값을 실제로 보간하고 싶다면 task.render_template을 직접 호출하거나, 함수 인자 기본값(ds=None)이나 **context로 컨텍스트 값을 받아 직접 채워야 한다
매핑 태스크 개수/동시성 제한
태스크에 걸 수 있는 제한은 두 가지다 - 확장의 결과로 생성될 수 있는 매핑 태스크 인스턴스의 개수, 그리고 그 매핑 태스크가 동시에 실행될 수 있는 개수.
먼저 매핑 태스크 개수를 제한하는 `[core] max_map_length` 설정이 있다 - 이는 `expand`가 만들 수 있는 태스크의 최대 개수이며 기본값은 1024다. 소스 태스크(위 예의 `make_list`)가 이보다 긴 리스트를 반환하면, 그 소스 태스크 자체가 실패한다.
다음은 매핑 태스크의 동시 실행 복사본 수를 제한하는 것이다 - 큰 매핑 태스크가 사용 가능한 러너 슬롯을 전부 소비하지 않길 원한다면 태스크에 `max_active_tis_per_dag` 설정을 써서 동시에 실행 가능한 개수를 제한할 수 있다. 다만 이 제한은 이 특정 DagRun에만 적용되는 것이 아니라, 그 태스크의 모든 활성 DagRun에 걸쳐 적용된다는 점에 유의해야 한다.
핵심 포인트
- [core] max_map_length(기본 1024)는 expand가 만들 수 있는 태스크 인스턴스 총 개수의 상한이며, 초과하는 리스트를 반환한 소스 태스크 자체가 실패한다
- max_active_tis_per_dag는 매핑 태스크의 동시 실행 복사본 수를 제한하지만, 이 제한은 해당 태스크의 현재 DagRun뿐 아니라 모든 활성 DagRun에 걸쳐 적용된다는 점에 주의해야 한다
빈 매핑의 자동 스킵
입력이 비어 있으면(길이 0), 새 태스크가 하나도 생성되지 않고 그 매핑 태스크는 `SKIPPED`로 표시된다.
이는 Dag가 실행 시점에 처리할 작업을 스스로 발견하는 상황에서 유용하다 - 예를 들어 스캔 후 복구 작업을 하는 Dag는 복구할 것을 찾지 못하면 빈 리스트를 반환할 수 있고, 이 경우 매핑 태스크가 스킵되며, 다운스트림 요약 태스크가 스킵된 업스트림을 허용하는 트리거 규칙(예: `TriggerRule.NONE_FAILED`)을 쓰면 이 런을 여전히 성공한 무동작(no-op)으로 처리할 수 있다.
핵심 포인트
- 매핑 입력이 빈 리스트이면 태스크 인스턴스가 하나도 생성되지 않고 해당 매핑 태스크는 SKIPPED로 표시된다
- 다운스트림 요약 태스크가 TriggerRule.NONE_FAILED처럼 스킵된 업스트림을 허용하는 트리거 규칙을 쓰면, 할 일 없음도 정상적인 무동작(no-op) 성공으로 처리할 수 있다