pre-hook & post-hook
pre-hook & post-hook
모델, 시드, 스냅샷이 빌드되기 전이나 후에 실행할 SQL 문(또는 SQL 문 목록)을 지정하는 설정이에요. dbt가 (아직) 내장 기능으로 제공하지 않는 데이터 플랫폼 특유의 SQL을 실행하고 싶을 때 유용해요.
출처: dbt 공식 문서
본문
모델
이 예시들에서 | 기호는 pre-hooks와 post-hooks의 SQL 문에 대한 두 가지 다른 형식 옵션을 구분해요. 첫 번째 옵션(대괄호 없음)은 단일 SQL 문을 문자열로 받고, 두 번째 옵션(대괄호)은 여러 SQL 문을 문자열 배열로 받아요. SQL-STATEMENT를 여러분의 SQL로 바꿔요.
dbt_project.yml
models:
<resource-path>:
+pre-hook: SQL-statement | [SQL-statement]
+post-hook: SQL-statement | [SQL-statement]
models/<model_name>.sql
{{ config(
pre_hook="SQL-statement" | ["SQL-statement"],
post_hook="SQL-statement" | ["SQL-statement"],
) }}
select ...
models/properties.yml
models:
- name: [<model_name>]
config:
pre_hook: <sql-statement> | [<sql-statement>]
post_hook: <sql-statement> | [<sql-statement>]
시드
이 예시들에서 | 기호는 pre-hooks와 post-hooks의 SQL 문에 대한 두 가지 다른 형식 옵션을 구분해요. 첫 번째 옵션(대괄호 없음)은 단일 SQL 문을 문자열로 받고, 두 번째 옵션(대괄호)은 여러 SQL 문을 문자열 배열로 받아요. SQL-STATEMENT를 여러분의 SQL로 바꿔요.
dbt_project.yml
seeds:
<resource-path>:
+pre-hook: SQL-statement | [SQL-statement]
+post-hook: SQL-statement | [SQL-statement]
seeds/properties.yml
seeds:
- name: [<seed_name>]
config:
pre_hook: <sql-statement> | [<sql-statement>]
post_hook: <sql-statement> | [<sql-statement>]
스냅샷
이 예시들에서 | 기호는 pre-hooks와 post-hooks의 SQL 문에 대한 두 가지 다른 형식 옵션을 구분해요. 첫 번째 옵션(대괄호 없음)은 단일 SQL 문을 문자열로 받고, 두 번째 옵션(대괄호)은 여러 SQL 문을 문자열 배열로 받아요. SQL-STATEMENT를 여러분의 SQL로 바꿔요.
dbt_project.yml
snapshots:
<resource-path>:
+pre-hook: SQL-statement | [SQL-statement]
+post-hook: SQL-statement | [SQL-statement]
snapshots/snapshot.yml
snapshots:
- name: [<snapshot_name>]
config:
pre_hook: <sql-statement> | [<sql-statement>]
post_hook: <sql-statement> | [<sql-statement>]
정의
모델, 시드, 스냅샷이 빌드되기 전이나 후에 실행할 SQL 문(또는 SQL 문 목록)이에요.
pre-hooks와 post-hooks는 SQL 문을 반환하는 매크로도 호출할 수 있어요. 매크로가 실행 시점에만 사용 가능한 값(예: 모델 설정을 사용하거나 다른 리소스에 대한 ref() 호출을 입력으로 사용)에 의존한다면, 매크로 호출을 추가 중괄호 쌍으로 감싸야 해요.
왜 hooks를 쓰나요?
dbt는 필요한 모든 상용구 SQL(DDL, DML, DCL)을 기본 제공 기능으로 제공하는 것을 목표로 해요. 이를 빠르고 간결하게 구성할 수 있어요. 하지만 데이터 플랫폼의 특정 기능에 필요한 SQL이 있어서 dbt가 (아직) 내장 기능으로 제공하지 않는 경우가 있을 수 있어요. 그런 경우 dbt의 컴파일 컨텍스트를 사용해 필요한 정확한 SQL을 작성하고, 이를 pre- 또는 post- hook에 넣어 모델, 시드, 스냅샷 앞이나 뒤에서 실행할 수 있어요.
render 메서드
.render() 메서드는 일반적으로 런타임 중에 Jinja 표현식(예: {{ source(...) }})을 해석하거나 평가하는 데 쓰여요.
--empty 플래그를 사용하면 dbt가 최적화를 위해 ref()나 source() 처리를 건너뛸 수 있어요. 컴파일 오류를 피하고 특정 관계(ref() 또는 source())를 명시적으로 처리하라고 dbt에 알리려면 모델 파일에서 .render() 메서드를 사용해요. 예를 들어:
models.sql
{{ config(
pre_hook = [
"alter external table {{ source('sys', 'customers').render() }} refresh"
]
) }}
select ...
예시
[Redshift] 모델 하나를 S3로 언로드
model.sql
{{ config(
post_hook = "unload ('select from {{ this }}') to 's3:/bucket_name/{{ this }}"
) }}
select ...
[Apache Spark] 테이블 생성 후 분석
dbt_project.yml
models:
jaffle_shop: # this is the project name
marts:
finance:
+post-hook:
# this can be a list
- "analyze table {{ this }} compute statistics for all columns"
# or call a macro instead
- "{{ analyze_table() }}"
참고: Apache Spark의 ANALYZE TABLE 문서
추가 예시
더 심층적인 예시는 여기에 정리해 두었어요.
사용 시 참고 사항
Hooks는 누적돼요
dbt_project.yml과 모델의 config 블록 양쪽에 hooks를 정의하면 두 hooks 집합 모두 모델에 적용돼요.
실행 순서
어떤 hooks의 인스턴스가 여러 개 정의되면 dbt는 다음 순서로 각 hook을 실행해요.
- 의존 패키지의 hooks가 활성 패키지의 hooks보다 먼저 실행돼요.
- 모델 자체 안에 정의된 hooks는
dbt_project.yml에 정의된 hooks보다 나중에 실행돼요. - 특정 컨텍스트 안의 hooks는 정의된 순서대로 실행돼요.
트랜잭션 동작
트랜잭션을 사용하는 어댑터(특히 Postgres나 Redshift)를 쓰고 있다면, hooks가 기본적으로 모델이 생성되는 것과 동일한 트랜잭션 안에서 실행된다는 점을 알아두는 게 좋아요.
hooks를 트랜잭션 밖에서 실행해야 하는 경우가 있을 수 있어요. 예를 들어:
post-hook에서VACUUM을 실행하고 싶은데, 이는 트랜잭션 안에서 실행할 수 없어요. (Redshift 문서)- 실행 시작 시 감사(audit) 테이블에 레코드를 삽입하고 싶은데, 모델 생성이 실패해도 그 문이 롤백되길 원하지 않을 때.
이 동작을 얻으려면 다음 구문 중 하나를 사용할 수 있어요.
- 중요 참고: dbt가 트랜잭션을 지원하지 않는 데이터베이스(예: Snowflake, BigQuery, Spark 또는 Databricks)를 쓰고 있다면 이 구문을 사용하지 마세요.
before_begin과 after_commit 사용하기
설정 블록: before_begin과 after_commit 헬퍼 매크로 사용
models/
{{
config(
pre_hook=before_begin("SQL-statement"),
post_hook=after_commit("SQL-statement")
)
}}
select ...
딕셔너리 사용하기
설정 블록: 딕셔너리 사용
models/
{{
config(
pre_hook={
"sql": "SQL-statement",
"transaction": False
},
post_hook={
"sql": "SQL-statement",
"transaction": False
}
)
}}
select ...
dbt_project.yml 사용하기
dbt_project.yml: 딕셔너리 사용
dbt_project.yml
models:
+pre-hook:
sql: "SQL-statement"
transaction: false
+post-hook:
sql: "SQL-statement"
transaction: false
더 알아보기 (Learn more)
- hooks와 operations — 심층 예시와 operations 같이 보기
- 중괄호 중첩 금지 — 매크로 호출 시 중괄호 처리