dbt Projects on Snowflake 모범 사례
dbt Projects on Snowflake 모범 사례
이 가이드는 Snowflake에서 dbt를 규모 있게 실행하는 데이터 엔지니어링 팀을 위한 주관적인 모범 사례를 제공해요. 각 섹션은 독립적이라서 팀에 가장 중요한 주제로 바로 이동할 수 있어요.
dbt Projects on Snowflake는 그렇지 않으면 직접 관리해야 할 인프라를 제거해요. 유지 관리할 Python 환경도, 확장할 Airflow 클러스터도, 개발자 머신 간 dbt CLI 버전 드리프트도 없어요. Snowflake가 런타임, 오케스트레이션(태스크를 통해), dbt 버전 관리를 네이티브로 처리해요. 이를 통해 팀은 인프라 운영보다 변환 로직과 데이터 품질에 집중할 수 있어요.
출처: Snowflake 문서
본문
비용 최적화
웨어하우스 컴퓨팅 시간을 줄이는 것은 규모 있게 dbt를 실행하는 팀에게 가장 영향력 큰 모범 사례 중 하나예요. 다음 패턴들이 불필요한 처리를 피하는 데 도움을 줘요.
크고 자주 업데이트되는 테이블에는 증분 모델 사용하기
소스 테이블이 크고 정기적으로 업데이트된다면 전체 테이블 재빌드 대신 증분(incremental) materialization을 사용하세요. 증분 모델은 마지막 실행 이후 변경된 행만 스캔하므로 변환이 일어나기 전에 처리되는 시간 창을 크게 줄여줘요.
마지막 실행 이후 새 행이 없으면 dbt는 여전히 필터 쿼리를 실행해 확인하지만, 병합하거나 삽입할 것이 없으므로 변환 자체는 사실상 건너뛰어요. 가벼운 필터 쿼리만 실행되고 전체 변환은 실행되지 않으므로 웨어하우스 시간의 일부만 소비해요. 이렇게 하면 증분 모델이 이벤트 기반 파이프라인이나 append-only 패턴의 테이블에 특히 비용 효율적이에요.
자주 업데이트되지 않는 작은 테이블의 경우 전체 테이블 materialization이 더 단순하고 보통 똑같이 빠르다는 점을 기억하세요. 스캔 감소가 측정 가능한 이점을 제공하는 곳에서 증분 모델을 사용하세요.
📌 이 페이지에서 설명하는 일부 기능은 가변
live버전을 사용하는 dbt 프로젝트 객체가 필요해요. live 버전 객체를 얻으려면 2026_06 동작 변경 번들에 옵트인하거나, Snowflake 계정 담당자에게 별도의 단일 live 버전 기능을 활성화하도록 요청하세요. 그런 다음 객체를 생성하거나 교체하고, 기존 버전 객체는SYSTEM$MIGRATE_DBT_PROJECT로 마이그레이션하세요. 자세한 내용은 dbt 프로젝트 객체의 단일 가변 live 버전으로의 마이그레이션 문서를 참조하세요.
개발 중 defer to production 사용하기
개발 중 DAG의 일부만 실행할 때도 dbt는 빌드되지 않은 업스트림 모델에 대한 릴레이션이 필요해요. 프로덕션 state와 함께 --defer를 사용해 개발 target에서 업스트림 모델을 재빌드하는 대신, dbt가 이 업스트림 참조를 기존 프로덕션 릴레이션으로 해결하게 하세요.
Snowflake Workspaces는 실행 패널의 Advanced options 아래에 네이티브 defer to production 컨트롤을 제공해요. 이 동작을 구성하려면 개발 중 defer to production 문서를 참조하세요.
Slim CI 사용하기
풀 리퀘스트가 모델 몇 개만 바꿀 때, 자동 컴파일을 활성화한 테스터 dbt 프로젝트 객체를 배포하면 전체 프로젝트가 컴파일돼요. 또한 파이프라인에서 전체 dbt build를 실행하면 전체 프로젝트를 또 다시 컴파일·실행·테스트해요. 함께 보면, 프로젝트가 커질수록 이 추가 작업이 더 많은 웨어하우스 컴퓨팅을 사용해요. Slim CI를 사용해 검증을 변경된 노드와 그 다운스트림 의존성으로 제한하세요:
- 테스터 dbt 프로젝트 객체를
snow dbt deploy --no-auto-compile로 배포해 배포 중 자동 컴파일을 건너뛰어요. --state와 함께--select state:modified+를 전달해 이전 프로덕션 아티팩트 대비 변경된 노드와 그 다운스트림 의존성만 처리해요. 변경되지 않은 노드는 웨어하우스 시간을 소비하지 않아요.--defer를 전달해 빌드되지 않은 업스트림 노드에 대한 참조가 기존 프로덕션 릴레이션으로 해결되게 해요.
프로젝트의 모든 모델과 테스트에 대한 가장 철저한 검증이 필요할 때만 전체 dbt build를 사용하세요. 증분 모델과 Slim CI는 서로 다른 작업을 최적화해요: 증분 모델은 선택된 모델 내에서 변경되지 않은 행을 건너뛰고, Slim CI는 프로젝트 DAG에서 변경되지 않은 노드를 건너뛰어요.
설정과 예시는 Slim CI와 프로덕션 defer에 dbt 아티팩트 사용 문서를 참조하세요.
threads로 병렬 처리 늘리기
dbt_projects_profiles.yml 또는 profiles.yml의 threads 매개 변수를 구성해 단일 실행 내에서 dbt가 동시에 실행하는 모델 수를 제어해요. 대부분의 Snowflake 웨어하우스와 호환되도록 Snowflake는 threads를 8로 설정할 것을 권장해요. 1보다 큰 스레드 수는 독립적인 모델이 병렬로 실행되게 해 주어진 실행의 총 벽시계 시간(wall-clock time)을 줄여요.
my_target:
type: snowflake
threads: 8
# ...
큐잉을 유발하지 않으면서 웨어하우스의 사용 가능한 컴퓨팅 용량과 일치하는 스레드 수를 선택하세요.
비용에 대한 자세한 내용은 dbt Projects on Snowflake 비용 이해 문서를 참조하세요.
dbt 버전 선택
Snowflake는 dbt Core(Python 기반, 1.x 버전)와 dbt Fusion(Rust 기반, 2.x 버전)을 모두 지원해요. 대부분의 팀은 dbt Projects on Snowflake에서 최신 지원 dbt Core 버전(1.11.x)으로 시작하세요. 가장 넓은 Snowflake materialization과 dbt 패키지 지원을 갖췄어요.
프로젝트가 매우 커지거나(모델 5,000개 초과) 성능 개선을 위해 미래 대비를 하고 싶다면 dbt Fusion으로 이동하는 것을 고려하세요. 다음을 염두에 두세요:
- Core에서 Fusion으로 이동할 때 약간의 마이그레이션이 필요해요.
- 오늘날 모든 dbt 패키지가 Fusion과 호환되는 것은 아니에요. 업그레이드 전에 dbt package hub에서 Fusion 호환 배지를 확인하세요.
- 가장 인기 있는 dbt package hub 패키지(
dbt_utils,dbt_expectations,dbt_project_evaluator)는 이미 호환돼요.
지원되는 버전의 전체 목록과 계정 수준 기본값 설정은 dbt Fusion으로 마이그레이션 문서를 참조하세요. Fusion 마이그레이션 지침은 2.0으로 업그레이드 문서를 참조하세요.
오케스트레이션
Snowflake 태스크는 Airflow 같은 외부 오케스트레이터 없이 dbt 프로젝트 실행을 위한 네이티브 스케줄링을 제공해요. 오케스트레이션을 올바르게 설정하려면 권한 모델을 이해하는 것이 중요해요.
실행의 두 역할 모델 이해하기
모든 EXECUTE DBT PROJECT 문에는 두 역할이 관련돼요:
- 호출 역할(calling role):
EXECUTE DBT PROJECT문을 발행하는 세션의 활성 역할(또는 태스크 소유자 역할). 이 역할은 dbt 프로젝트 객체에USAGE권한이 있어야 해요. - 프로필 역할(profile role): 프로젝트의
dbt_projects_profiles.yml또는profiles.yml의 target에 지정된 역할. 프로필 역할은 실행 중 dbt run이 실제로 접근할 수 있는 것(데이터베이스, 스키마, 테이블, 웨어하우스)을 정의해요.
두 역할 모두 웨어하우스에 USAGE가 있어야 해요. 호출 역할은 또한 프로필 역할을 사용할 수 있어야 해요. 실행 중 작업은 두 역할이 공통으로 가진 권한으로 제한돼요.
이 두 역할 모델은 대화형으로 dbt를 실행하든(워크시트에서 사람이 EXECUTE DBT PROJECT를 실행), 예약된 태스크를 통해 실행하든 적용돼요. 차이점은:
- 대화형 실행: 활성 세션 역할이 호출 역할이에요.
- 태스크 실행: 태스크는 태스크 소유자 역할(태스크에
OWNERSHIP이 있는 역할)의 권한으로 시스템 서비스로 실행돼요. 실행에 특정 사용자가 연결되지 않아요.
dbt_projects_profiles.yml 또는 profiles.yml에 역할을 하드코딩하는 대신 env.yml 파일로 이 설정을 단순화할 수 있어요. env.yml에 DBT_CURRENT_ROLE: "{{ select CURRENT_ROLE() }}" 같은 변수를 정의한 다음 프로필 파일에서 role: "{{ env_var('DBT_CURRENT_ROLE') }}"로 참조하세요. 그러면 프로필 역할이 매 실행마다 호출 역할로 해결돼요. 자세한 내용은 dbt Projects on Snowflake용 SQL 환경 변수와 비공개 Git 패키지 사용 문서를 참조하세요.
전용 서비스 계정 사용하기
전용 서비스 계정(예: github_actions_service_user)을 만들고 협소한 권한을 할당한 다음 이 사용자로 태스크를 만들고 소유하게 하세요. 이렇게 하면 다음이 보장돼요:
- 태스크 권한이 한곳에서 거버넌스되고 감사 가능해요.
- 서비스 계정 역할에 필요한 최소 권한만 부여할 수 있어요.
- 퇴사하는 팀원이 프로덕션 스케줄링을 망가뜨리지 않아요.
웨어하우스 구성 정렬하기
단일 오케스트레이션 실행에서 두 웨어하우스를 깨우지 않도록 태스크 정의와 dbt_projects_profiles.yml 또는 profiles.yml의 target에서 같은 웨어하우스를 사용하세요:
-- Task warehouse matches profiles.yml warehouse
CREATE OR ALTER TASK my_db.my_schema.run_dbt_daily
WAREHOUSE = transform_wh
SCHEDULE = '360 minutes'
AS
EXECUTE DBT PROJECT my_db.my_schema.my_project args='build --target prod';
# profiles.yml
prod:
type: snowflake
warehouse: transform_wh
# ...
태스크가 warehouse_a를 사용하는데 프로필 파일이 warehouse_b를 지정하면 한 실행에 두 웨어하우스가 모두 깨어나요.
자동으로 정렬되게 하려면 웨어하우스를 하드코딩하는 대신 env.yml 파일을 사용하세요. env.yml에 DBT_CURRENT_WH: "{{ select CURRENT_WAREHOUSE() }}" 같은 변수를 정의한 다음 프로필 파일에서 warehouse: "{{ env_var('DBT_CURRENT_WH') }}"로 참조하세요. 그러면 프로필 웨어하우스가 매 실행마다 호출 태스크 웨어하우스와 일치해요.
다단계 파이프라인에는 태스크 그래프 사용하기
AFTER 절을 사용해 태스크를 그래프로 연결하세요. 예를 들어 모델이 완료된 후 테스트를 실행해요:
CREATE OR ALTER TASK my_db.my_schema.test_dbt_daily
WAREHOUSE = transform_wh
AFTER my_db.my_schema.run_dbt_daily
AS
EXECUTE DBT PROJECT my_db.my_schema.my_project args='test --target prod';
Snowsight나 SQL로 예약된 태스크를 만들고 관리하는 방법은 Snowflake에서 dbt 프로젝트 객체 실행 스케줄링 문서를 참조하세요.
Apache Airflow 통합을 포함한 오케스트레이션 옵션에 대한 종합적인 개요는 dbt Projects on Snowflake 오케스트레이션 이해 문서를 참조하세요.
실패한 실행에서 복구
run이나 build가 중간에 실패하면 전체 명령을 다시 실행하면 이미 성공한 작업이 반복돼요. dbt retry는 전체 재실행을 피할 수 있지만, 이전 호출을 원래 인수와 선택 항목으로 재생하므로 dbt가 다시 실행하는 리소스를 검토하거나 변경할 수 없어요.
더 많은 제어를 위해 SYSTEM$DBT_GET_LAST_FAILED_RUN_TARGET으로 실패한 실행의 state를 가져온 다음 명시적 결과 셀렉터를 사용하세요:
EXECUTE DBT PROJECT prod_database.dbt_projects.production_project
ARGS = 'run --state ./imports/state --select result:error+'
IMPORTS = (
SYSTEM$DBT_GET_LAST_FAILED_RUN_TARGET('prod_database.dbt_projects.production_project', 'run,build') AS 'state'
);
result:error+ 셀렉터는 오류가 난 리소스와 그 다운스트림 의존성을 다시 실행해요. 실패한 테스트에는 1+result:fail+을 사용해 실패한 테스트, 그 부모 모델, 다운스트림 리소스를 다시 실행해요.
인수나 선택 항목을 바꾸지 않고 이전 호출을 재생하려면 dbt retry를 사용하세요. 프로덕션 오케스트레이션에서는 명시적 결과 셀렉터를 사용해 dbt가 다시 실행할 리소스를 더 제어하세요. 더 많은 예시는 실패한 실행에서 복구 문서를 참조하세요.
지속적 통합과 지속적 배포 (CI/CD)
CI/CD 파이프라인은 dbt 프로젝트의 모든 변경이 프로덕션에 도달하기 전에 검증되도록 보장해요. 공유 파이프라인에서 협업하는 팀에게 필수적이에요.
CI/CD로 프로덕션 배포하기
팀이 프로덕션 dbt 프로젝트 객체에 직접 배포함으로써 CI/CD 검증을 우회하는 경우가 있어요. 일반적인 안티 패턴은:
- 풀 리퀘스트를 만들지 않고 변경 사항을 배포하는 지름길로 Git 스테이지를 사용하기.
- git pull을 한 다음 Workspaces UI로 배포해 Workspaces에서 배포하기.
이 접근 방식들은 dev/staging dbt 프로젝트 객체를 배포하고 테스트할 때 사용해야 해요. 하지만 프로덕션에서는 항상 CI/CD 파이프라인을 통해 배포해야 해요. CI 검증이 없으면:
- 깨진 모델이 감지되지 않은 채 프로덕션에 도달해요.
- 데이터가 이미 손상될 때까지 테스트가 실행되지 않아요.
- 동료가 오류를 잡을 리뷰 게이트가 없어요.
권장되는 CI/CD 패턴
CI 오케스트레이터(GitHub Actions 같은) 안에서 Snowflake CLI를 사용해 모든 배포를 검증 뒤에 게이트하세요:
- 개발자가 풀 리퀘스트를 열어요.
- CI 파이프라인이 트리거되어
snow dbt deploy --no-auto-compile로 테스터 dbt 프로젝트 객체를 만들어요. - 파이프라인이 최신 성공 프로덕션 실행에서 dbt 아티팩트를 가져와 격리된 dev 또는 staging target에서
--state,--defer,--select state:modified+로 변경된 모델과 테스트를 실행해요. - 선택된 모든 모델이 성공적으로 실행되고 선택된 모든 테스트가 통과하면 PR은 머지 가능해요.
- main에 머지하면 별도 파이프라인이 프로덕션 dbt 프로젝트 객체에 배포해요.
이렇게 하면 CI 검증 없이는 어떤 변경도 프로덕션에 도달하지 않아요. 전체 Slim CI 워크플로는 dbt Projects on Snowflake용 Slim CI와 PR별 데이터베이스로 CI/CD 설정 튜토리얼을 참조하세요. 전체 빌드를 실행하는 더 단순한 워크플로는 dbt Projects on Snowflake에서 CI/CD 통합 설정 튜토리얼을 참조하세요.
다중 계정 설정
스테이징과 프로덕션 Snowflake 계정이 분리된 팀에게 CI/CD는 서로 다른 배포 대상을 관리하는 최고의 패턴이에요:
- 풀 리퀘스트 시: 스테이징 계정에 배포하고 테스트해요.
- main에 머지 시: 프로덕션 계정에 배포해요.
Snowflake CLI는 인라인 연결 재정의를 지원하므로 다른 계정을 대상으로 하는 것이 간단해요:
# CI 작업 중, 스테이징 계정에 배포
snow dbt deploy my_project \
--account my_org-staging \
--database analytics_staging \
--role svc_dbt_role \
--warehouse transform_wh \
--default-target staging
# 나중에, CD 작업에서 프로덕션 계정에 배포
snow dbt deploy my_project \
--account my_org-production \
--database analytics_prod \
--role svc_dbt_role \
--warehouse transform_wh \
--default-target prod
PR 수준에서 품질 강제하기
모든 CI 검사가 통과할 때까지 풀 리퀘스트가 main으로 머지되지 못하게 브랜치 보호 규칙을 설정하세요. 이렇게 하면 커밋이 어디서 왔든(Workspaces, 로컬 IDE, 또는 Cortex Code Desktop) 품질이 보장돼요.
환경 변수
환경 변수는 dbt Core에 오랫동안 있었지만, 규모 있게 관리하려면 개별 머신에 존재하고 동기화가 어긋나며 감사할 수 없는 .env 파일을 다뤄야 했어요. env.yml 파일은 Snowflake가 각 dbt Projects on Snowflake 실행 전에 해결하는 단일 Git 버전 관리 구성 파일이에요.
env.yml이 중요한 이유
env.yml 파일은 관리자에게 팀 전체 구성을 관리할 한곳을 줘요:
- 개발자별 스키마:
CURRENT_USER()를 사용해 개발 중 각 엔지니어의 작업을 자동으로 자신의 스키마로 격리해요. - 프로덕션 시간 윈도우: 외부 오케스트레이터 없이 런타임에 시작·종료 타임스탬프를 계산하는 SQL 함수를 사용해요.
- 비공개 패키지용 시크릿:
dbt deps중 비공개 Git 저장소에 인증하기 위해 Snowflake 관리 시크릿을 주입해요. - 한 파일에 여러 환경: dev, staging, prod 구성을 함께 정의해요. 실행 시 활성화할 환경을 선택해요.
동작 방식
env.yml 파일은 dbt Core 실행이 시작되기 전에 실행돼요. Snowflake가 모든 값(SQL 쿼리와 시크릿 포함)을 먼저 해결한 다음 결과 환경 변수를 dbt 실행에 주입해요. 값은 Snowflake 실행 컨텍스트(EXECUTE DBT PROJECT를 실행하는 외부 세션의 역할, 사용자, 웨어하우스)에서 와요.
env_config:
default_environment: dev
environments:
- name: dev
env:
DBT_CURRENT_SCHEMA: "{{ select CURRENT_USER() }}"
DBT_CURRENT_ROLE: "{{ select CURRENT_ROLE() }}"
- name: prod
env:
DBT_DATA_INTERVAL_START: "{{ select (DATE_TRUNC('DAY', CURRENT_TIMESTAMP()) - INTERVAL '1 DAY')::string }}"
DBT_DATA_INTERVAL_END: "{{ select (DATE_TRUNC('DAY', CURRENT_TIMESTAMP()) - INTERVAL '1 SECOND')::string }}"
값은 높은 우선순위부터 해결돼요: EXECUTE DBT PROJECT의 ENV_VARS(또는 CLI의 --env-vars), 그다음 셸 변수(--use-shell-env-vars 사용 시), 그다음 env.yml의 활성 환경.
env.yml 작성, 환경 선택, 비공개 Git 패키지, 전체 참조에 대해서는 dbt Projects on Snowflake용 SQL 환경 변수와 비공개 Git 패키지 사용 문서를 참조하세요.
교차 프로젝트 참조와 공유 매크로
dbt 실무가 성장하면서 팀은 여러 프로젝트에 걸쳐 매크로, 모델, 또는 유틸리티를 공유해야 하는 경우가 많아요. 비공개 Git 패키지는 이를 위한 Snowflake 네이티브 솔루션을 제공해요.
팀이 교차 프로젝트 참조를 사용하는 이유
팀은 코드를 복제하는 대신 공유하기 위해 다른 저장소를 가져와요. 가장 흔한 목적은:
- 유틸리티 매크로 재사용: 커스텀 materialization, 감사·로깅 매크로, 스키마·명명 헬퍼를 매 프로젝트에 복사하는 대신 한곳에서 유지해요.
- 모델, 소스, 시드 정의 재사용: 여러 프로젝트가 기반으로 삼는 표준 소스 정의, 표준 스테이징 모델, 또는 참조 데이터를 다시 정의하지 않고 공유해요.
- 다른 팀의 모델 위에 구축: 다른 팀이 소유하고 유지하는 모델에 의존해요.
dbt Core는 단일 모노레포 또는 별도 저장소에서의 임포트를 모두 지원해요.
동작 방식
비공개 Git 패키지는 dbt deps 중 비공개 Git 저장소에 인증하기 위해 Snowflake 시크릿을 사용해요. 관리자가 시크릿, 네트워크 규칙, 외부 접근 통합을 설정해요. 데이터 엔지니어는 packages.yml에서 비공개 패키지를 참조해요:
packages:
- git: "https://{{env_...')}}@github.com/your-org/dbt-shared-utils.git"
subdirectory: "macros"
# 커밋 ID로 고정; main 같은 브랜치는 권장되지 않습니다.
revision: a1b2c3d4e5f6a7b8c9d0e1f2a3b4c5d6e7f8a9b0
env.yml 파일은 시크릿을 DBT_ENV_SECRET_ 변수로 주입하며, dbt는 패키지 설치 중 인증에 이를 사용해요.
권한과 특권
dbt 프로젝트 객체 권한과 데이터 접근의 분리를 이해하는 것은 규모 있게 dbt를 운영하는 팀에게 중요해요.
배포 역할과 실행 역할 분리하기
일부 팀은 dbt 프로젝트 객체를 관리하는 CI/CD 서비스 사용자가 배포에만 제한되고 프로덕션 데이터를 변환할 수 없길 요구해요. 이 직무 분리(separation of duties) 모델을 위해 CI/CD 파이프라인에서 배포 전용(deploy-only) 역할을 사용하세요. dbt 프로젝트 객체를 만들고 live 버전을 교체하는 데 필요한 권한만 부여해요. 배포가 dbt deps나 dbt compile을 실행하려 하지 않도록 snow dbt deploy --no-auto-compile로 배포하세요.
변환에는 별도의 프로덕션 실행 역할을 사용하세요. dbt_projects_profiles.yml 또는 profiles.yml의 프로덕션 target의 역할로 구성하고, 외부 오케스트레이션의 호출 역할이나 Snowflake 태스크의 태스크 소유자 역할로 같은 역할을 사용하세요. 이 역할에 dbt 프로젝트 객체에 대한 USAGE와 필요한 웨어하우스·데이터 권한을 부여하세요. 자세한 역할·권한 설정은 선택적으로 배포와 실행 분리 문서를 참조하세요.
MONITOR 권한은 데이터 접근을 부여하지 않아요
dbt 프로젝트 객체의 MONITOR 권한은 사용자에게 dbt 프로젝트 객체의 manifest, 실행 기록, 아티팩트에 대한 접근을 줘요. dbt 프로젝트 객체가 만드는 테이블과 뷰를 쿼리할 권한은 부여하지 않아요.
즉, MONITOR가 있는 데이터 엔지니어는:
- dbt DAG에서 모델 정의, 스키마, 혈통을 볼 수 있어요.
- 실행 로그와 실행 기록을 검토할 수 있어요.
- 시스템 함수로 각 실행에서 dbt 아티팩트(
manifest.json,run_results.json,dbt.log)에 접근할 수 있어요. - CoCo를 사용해 배포된 dbt 프로젝트 객체의 파일을 검사하고 프로덕션 실패를 디버깅할 수 있어요.
하지만 별도로 부여된 SELECT 권한이 없으면 프로덕션 테이블을 쿼리할 수 없어요.
데이터 엔지니어링과 데이터 쿼리 분리하기
dbt 파이프라인을 실행하는 권한은 그 출력을 쿼리하는 권한과 분리돼요:
- 데이터 엔지니어링 권한: dbt 프로젝트 객체에 대한
USAGE, dev의 소스 테이블 소유권 또는 접근, 업데이트 배포 능력. - 데이터 쿼리 권한: 파이프라인이 만든 프로덕션 테이블과 뷰에 대한
SELECT.
이 분리는 의도적이에요. 데이터 엔지니어는 dev 스키마나 스테이징 환경에서만 작업을 실행할 수 있고, 전용 서비스 계정이 프로덕션 파이프라인을 실행할 수 있어요. 분석가는 표준 역할 부여를 통해 프로덕션 출력에 대한 접근을 받지, dbt 프로젝트 객체 자체를 통해서는 받지 않아요.
아티팩트는 데이터가 아니라 스키마를 설명해요
manifest.json, run_results.json 같은 dbt 아티팩트는 모델의 스키마(컬럼 이름, 타입, 관계)만 설명해요. 프로젝트가 만드는 테이블과 뷰에 대한 쿼리 접근을 부여하지 않아요. dbt 프로젝트 객체에 MONITOR를 부여하면 그 아티팩트에 접근할 수 있지만, 프로덕션 데이터에 대한 SELECT 권한을 부여하지는 않아요.
전체 권한 참조는 dbt Projects on Snowflake 접근 제어 문서를 참조하세요.
보안
dbt Projects on Snowflake 보안 모범 사례는 자격 증명 노출을 최소화하고 엄격한 접근 경계를 유지하는 데 중점을 둬요.
CI/CD용 OIDC 임시 토큰 사용하기
GitHub Actions 및 다른 CI/CD 플랫폼에서는 장기 서비스 계정 자격 증명 대신 OpenID Connect(OIDC) 인증을 사용하세요. OIDC 사용 시:
- 토큰은 임시적이며 특정 워크플로 실행에 범위가 지정돼요.
- 저장·순환 교체·누출 위험이 있는 시크릿이 없어요.
- OIDC 사용자는 테스터 또는 프로덕션 dbt 프로젝트 객체를 배포·실행하는 데 필요한 권한만 가져요.
이는 Snowflake 자격 증명을 저장소 시크릿으로 저장하는 것보다 상당한 보안 개선이에요. 설정 세부 정보는 CI/CD 튜토리얼의 OIDC 섹션을 참조하세요.
인간 사용자에게 다중 인증 요구하기
dbt 프로젝트 객체를 배포하거나 실행할 수 있는 모든 인간 사용자에게 다중 인증(MFA) 또는 개인 접근 토큰(PAT)을 요구하세요. 이는 자격 증명 손상으로부터 보호하고 권한 있는 엔지니어만 프로덕션 파이프라인을 수정할 수 있도록 보장해요.
출력 테이블은 접근을 자동 부여하지 않아요
dbt 파이프라인이 테이블을 만들거나 업데이트할 때 그 테이블은 파이프라인을 실행한 사용자나 역할에게 자동으로 접근 가능해지지 않아요. 프로덕션 출력에 대한 접근은 관리자의 명시적 GRANT 문이 필요해요.
즉:
- 파이프라인을 실행한다고 결과에
SELECT가 생기지 않아요. - 분석가는 프로덕션 테이블을 쿼리하려면 별도 부여가 필요해요.
- 데이터 엔지니어링 권한과 데이터 쿼리 권한은 격리되어 유지돼요.
이 설계는 보안 경계를 깔끔하게 유지해요: 파이프라인을 빌드하는 능력은 그 출력을 읽는 능력과 분리돼요.
비공개 Git 패키지에는 Snowflake 시크릿 사용하기
비공개 dbt 패키지(공유 매크로, 내부 유틸리티)에 의존하는 팀은 dbt deps 중 비공개 Git 저장소에 인증하기 위해 Snowflake 시크릿을 사용할 수 있어요. 이렇게 하면 Git 토큰을 자격 증명 관리자나 개발자 환경에 저장할 필요가 없어요. 관리자가 읽기 전용 Git 개인 접근 토큰을 담는 Snowflake 시크릿을 만들고, env.yml 파일에서 이를 DBT_ENV_SECRET_ 변수로 참조해요. dbt는 packages.yml에서 패키지를 설치할 때 이 변수로 인증하고, 값이 나타나는 곳마다 마스킹해요. 자세한 내용은 dbt Projects on Snowflake용 SQL 환경 변수와 비공개 Git 패키지 사용 문서를 참조하세요.
하이브리드 개발
규모 있는 엔지니어링 팀에는 기술 수준과 도구 선호도가 다른 개발자들이 있어요. dbt Projects on Snowflake는 여러 개발 워크플로를 지원하므로 팀이 구성원마다 가장 잘 맞는 것을 선택할 수 있어요.
개발 환경 옵션
| 환경 | 가장 적합한 대상 | 핵심 이점 |
|---|---|---|
| Cortex Code Desktop (Snowflake 관리 모드) | 전체 IDE를 선호하는 경험 많은 개발자 | Snowflake 네이티브 dbt 실행이 있는 로컬 IDE 경험 |
| Snowflake Workspaces | 로컬 설정 없이 브라우저 기반 개발을 원하는 팀 | 설치 없음, 협업적, Git 통합 |
| 로컬 IDE + Snowflake CLI | 기존 로컬 dbt Core 워크플로가 있는 팀 | 친숙한 도구, CI/CD로 Snowflake에 배포 |
세 환경 모두 표준 dbt Core를 지원하며 배포 시 같은 결과를 만들어요.
통합 개발-프로덕션 경험을 위해 dbt_projects_profiles.yml 사용하기
자체 호스팅 dbt Core에서 마이그레이션하는 팀은 보통 로컬 워크플로 전체가 의존하는 ~/.dbt/profiles.yml을 이미 갖고 있어요. 이전에는 dbt Projects on Snowflake가 프로젝트 루트의 profiles.yml을 요구했고, dbt Core가 ~/.dbt/보다 프로젝트 디렉터리를 먼저 확인하므로 그 파일이 로컬 실행에도 조용히 주도권을 가졌어요. 팀은 개인 프로필을 덮어쓰거나, 로컬 명령마다 --profiles-dir을 손으로 전달하거나, 모두를 같은 워크플로로 강제해야 했어요.
dbt_projects_profiles.yml 파일이 이를 해결해요:
profiles.yml과 같은 방식으로 작동하지만 dbt Projects on Snowflake 전용이에요.- dbt Projects on Snowflake는 두 파일 이름을 모두 지원해요. 두 파일이 모두 있으면 Snowflake는 배포·컴파일·이후 명령 중
dbt_projects_profiles.yml을 사용하고profiles.yml을 무시해요.dbt_projects_profiles.yml이 없으면 Snowflake는 이전처럼profiles.yml을 사용해요. - 표준 dbt는
dbt_projects_profiles.yml을 인식하지 않아요. 로컬 dbt CLI는profiles.yml만 읽으므로dbt_projects_profiles.yml을 추가해도 개인~/.dbt/profiles.yml을 포함해 누구의 기존 로컬 dbt 워크플로도 방해하지 않아요. - Workspaces, Cortex Code Desktop(Snowflake 관리 모드), 배포된 dbt 프로젝트 객체 전반에서 작동해요. Workspaces와 Cortex Code Desktop에서 프로필 선택기는
dbt_projects_profiles.yml이 있으면 그 target을 표시해요.
하이브리드 팀은 두 워크플로를 나란히 유지할 수 있어요: 일부 엔지니어는 개인 ~/.dbt/profiles.yml로 로컬 dbt CLI를, 다른 사람들은 프로젝트 내 dbt_projects_profiles.yml로 Workspaces나 Cortex Code Desktop을 사용할 수 있어요. 두 그룹 모두 연결을 다시 구성하지 않고 Git 버전 관리되는 프로젝트 하나를 공유하며 로컬과 Snowflake 관리 개발 사이를 전환할 수 있어요. 배포된 dbt 프로젝트 객체도 dbt_projects_profiles.yml을 사용하므로 관리자가 프로덕션 연결 설정을 단일 버전 관리 파일에서 구성할 수 있어요.
팀이 dbt_projects_profiles.yml로 배포한 후 env.yml과 짝을 이뤄 표준 dbt Core가 단독으로는 제공하지 않는 Snowflake의 SQL in YAML 기능을 활용하세요. SQL 함수로 증분 처리용 시간 간격을 계산하고, 오케스트레이션 메타데이터용 컨트롤 테이블을 쿼리하고, 런타임 매개 변수를 검색하도록 저장 프로시저를 호출해요. 두 파일 모두 버전 관리되며 Snowflake는 외부 도구 없이 실행 시 값을 동적으로 해결해요. 자세한 내용은 dbt Projects on Snowflake용 SQL 환경 변수와 비공개 Git 패키지 사용 문서를 참조하세요.
Workspaces에서의 개발에 대한 자세한 내용은 dbt Projects on Snowflake용 Workspaces 문서를, Cortex Code Desktop은 dbt 통합 문서를 참조하세요.
소스와 모델 문서화
잘 문서화된 dbt 프로젝트는 새 엔지니어 온보딩, 실패 디버깅, 규제 감사가 더 쉽게 이뤄져요. dbt는 Snowflake 도구와 통합되는 세 가지 핵심 문서 표면을 제공하며, CoCo가 Snowflake Horizon Catalog를 읽어 기존 메타데이터에서 정확한 문서를 생성함으로써 모두를 가속화할 수 있어요.
소스 문서화 (sources.yml)
sources.yml 파일은 dbt 프로젝트가 의존하는 원시 테이블을 선언하고 Snowsight dbt 프로젝트 객체 세부 정보 페이지로 직접 흐르는 메타데이터를 제공해요. 정의할 핵심 속성:
- 데이터가 어디서 오는지와 소스 시스템이 무엇인지 설명하는 소스 설명.
- 각 테이블이 무엇을 담고 있고 어떤 비즈니스 컨텍스트가 있는지 문서화하는 테이블 설명.
- 다운스트림 소비자를 위해 각 컬럼의 의미를 정의하는 컬럼 설명.
CoCo는 Snowflake Horizon Catalog(테이블 comment, 컬럼 comment, 태그)를 스캔하고 정확한 설명이 이미 채워진 sources.yml을 생성할 수 있어요. 이렇게 하면 수동 발견 작업이 절약되고 문서가 Snowflake 계정에 실제로 있는 것과 동기화되도록 보장돼요.
모델 문서화 (models.yml)
models.yml 파일(때로는 schema.yml이라고도 함)은 프로젝트가 생성하는 모델을 설명해요. 모델 SQL과 함께 이 속성들을 정의하세요:
- 모델이 무엇을 하는지와 누가 소비하는지 설명하는 모델 설명.
- 비즈니스 정의와 예상 데이터 타입이 있는 컬럼 설명.
- 소유권, SLA 기대치, 도메인 태깅, 또는 팀별 관례를 위한 메타 필드.
CoCo는 모델이 생성하는 Snowflake 객체를 읽고 카탈로그 메타데이터에서 모델 문서를 생성할 수 있어요. 파이프라인이 진화하면서 models.yml 파일을 정확하게 유지해요.
프로젝트 개요 유지하기
Snowsight의 dbt 프로젝트 객체 세부 정보 페이지는 프로젝트의 overview docs block을 렌더링해요. dbt가 파싱하는 어떤 .md 파일에나 정의하는 {% docs__overview__ %} 블록이에요. 데이터 프로젝트의 살아있는 README로 사용하세요:
- 프로젝트 목적과 범위.
- 핵심 모델, 그 관계, 데이터 흐름 요약.
- 팀 소유권과 연락처 정보.
- 데이터 갱신 주기와 파이프라인 스케줄.
파이프라인에 큰 구조적 변경(새 도메인, 지원 중단된 모델, 스키마 재구성)이 있을 때 CoCo에게 overview docs block을 재생성하거나 업데이트하도록 요청해 최신 상태로 유지하세요. 이렇게 하면 Snowsight에서 프로젝트를 탐색하는 누구나 파이프라인이 무엇을 하는지와 어떻게 구성되어 있는지에 대한 정확하고 최신의 그림을 얻을 수 있어요.
동시 실행과 대형 프로젝트
dbt 실무가 성숙해지면 효율성과 유지 관리성을 위해 프로젝트를 구조화하는 방법을 이해하는 것이 중요해져요.
팀이 단일 dbt 프로젝트 객체로 시작하는 이유
파이프라인을 단일 dbt 프로젝트 객체에 유지하면 모든 모델에 걸쳐 종단 간 혈통이 보존돼요. 즉 Snowsight의 dbt DAG가 완전한 의존성 그래프를 보여줘서 영향 분석과 디버깅이 간단해져요. 그 통합된 뷰를 유지하면서 서로 다른 태스크 스케줄에서 --select로 파이프라인의 특정 슬라이스를 계속 실행할 수 있어요.
예를 들어 시간에 민감한 모델은 매시간, 전체 파이프라인은 매일 실행하도록 스케줄할 수 있어요:
-- Hourly: only the time-sensitive slice
CREATE OR ALTER TASK my_db.my_schema.hourly_slice
WAREHOUSE = transform_wh
SCHEDULE = '1 hour'
AS
EXECUTE DBT PROJECT my_db.my_schema.my_project
args='run --target prod --select my_model_a my_model_b';
-- Daily: the full pipeline
CREATE OR ALTER TASK my_db.my_schema.daily_full
WAREHOUSE = transform_wh
SCHEDULE = '24 hours'
AS
EXECUTE DBT PROJECT my_db.my_schema.my_project
args='build --target prod';
팀이 단일 프로젝트를 넘어 성장할 때
팀이 성장하면서 효율성을 위해 파이프라인을 논리적 단위(별도 도메인, 팀, 또는 주기)로 나눌 수 있어요. 이때 프로젝트 경계를 넘어 의존성을 유지하는 것이 중요해져요.
한 프로젝트를 동시에 실행하기
데이터 팀은 파이프라인의 독립적인 슬라이스를 서로 다른 주기로 실행해야 하는 경우가 많아요. 같은 dbt 프로젝트 객체를 동시에 실행해 각 슬라이스가 관련 없는 작업을 기다리거나 중복 배포된 객체가 필요하지 않고 최신 상태를 유지하게 하세요.
기본 writeback 동작에서는 동시 실행이 target 및 log 아티팩트를 live 버전의 같은 디렉터리에 쓸 수 있어 실행이 실패할 수 있어요. 그 쓰기가 충돌하지 않게 하려면 격리 패턴 중 하나를 사용하세요:
- 권장: target 및 log 아티팩트를
live버전에 유지할 필요가 없는 실행에는WRITEBACK = FALSE를 설정해요. - writeback이 필요하면 각 실행에 대해 서로 겹치지 않는 별도의
--target-path와--log-path값을 설정해요.
Snowflake는 이 설정과 관계없이 쿼리별 결과 아티팩트와 아카이브를 저장해요. 검색 방법은 프로그래밍 방식으로 dbt 아티팩트와 로그 접근 문서를 참조하세요.
동시 객체 실행은 threads 프로필 설정과 다르다는 점을 기억하세요. 동시 실행은 배포된 객체 하나로 여러 dbt 명령을 실행하지만, threads는 하나의 실행 내에서 병렬 모델 작업을 제어해요. 자세한 내용은 dbt 프로젝트 객체를 동시에 실행 문서를 참조하세요.
파일 제한 고려 사항
dbt 프로젝트 객체는 최대 100,000개의 파일을 지원해요. 이 제한에 근접하는 매우 큰 프로젝트라면 논리적 하위 프로젝트로 분할하는 것을 고려하세요. 프로젝트가 여전히 더 많은 용량을 필요로 한다면 Snowflake 계정 담당자에게 문의하세요.
현재 제한 사항에 대한 자세한 내용은 dbt Projects on Snowflake의 제한 사항, 요구 사항, 고려 사항 문서를 참조하세요.
데이터 품질 테스트
데이터 품질 검사는 dbt 파이프라인에 내장해야지 나중에 덧붙여서는 안 돼요. dbt의 테스트 프레임워크는 모델과 함께 실행되며 품질 검사가 통과하지 못하면 파이프라인을 실패시켜요.
내장 dbt 테스트
모든 dbt 프로젝트는 기본 데이터 무결성을 위해 표준 테스트 유형을 사용해야 해요:
not_null: 중요 컬럼에 null 값이 절대 없도록 보장해요.unique: 기본 키와 비즈니스 키가 고유한지 검증해요.accepted_values: 범주형 컬럼이 예상 값만 포함하는지 확인해요.relationships: 모델 간 참조 무결성을 검증해요.
모델 정의와 함께 schema.yml 파일에 이들을 정의하도록 CoCo에게 요청하세요.
고급 테스트에는 dbt-expectations 사용하기
표현력 있고 자세한 데이터 품질 단언(assertion)이 필요한 팀에게 dbt-expectations 패키지는 dbt의 테스트 기능을 크게 확장해요. 다음과 같은 패턴을 지원해요:
- 테이블 간 행 수 비교.
- 분포 검사(예상 범위 내 값).
- 패턴 매칭과 정규식 검증.
- 교차 컬럼 일관성 검사.
dbt Projects on Snowflake는 전체 dbt deps 지원을 갖추고 있어 dbt-expectations를 포함한 dbt package hub의 어떤 패키지든 설치하고 사용할 수 있어요.
CI/CD에서 테스트 게이트 강제하기
모델과 테스트를 모두 실행하도록 CI/CD 파이프라인을 구성하세요. 완전한 프로젝트 검증에는 전체 dbt build를 사용하거나, Slim CI 워크플로에서 선택된 state:modified+ 그래프를 실행·테스트하세요. 이렇게 하면 다음이 보장돼요:
- CI에서 매 모델 빌드 후 테스트가 실행돼요.
- 실패한 테스트가 풀 리퀘스트의 머지를 차단해요.
- 변경 사항이 프로덕션에 도달하기 전에 데이터 품질이 검증돼요.
테스트는 dbt build의 일부이므로 별도 단계가 필요 없어요.
제3자 패키지
dbt Projects on Snowflake는 전체 dbt deps 지원을 갖추고 있어 dbt package hub의 어떤 패키지든 설치하고 사용할 수 있어요. dbt_utils, dbt_expectations, dbt_project_evaluator 같은 인기 패키지가 포함돼요.
Snowflake 워크스페이스 안이나 dbt 프로젝트 객체 실행 중에 dbt deps를 실행하면 Snowflake가 인터넷에서 패키지를 다운로드하기 위해 네트워크 접근이 필요해요. 이를 허용하도록 dbt 프로젝트 객체에 외부 접근 통합을 구성하세요. 또는 로컬이나 CI/CD 파이프라인에서 dbt deps를 실행하고 dbt_packages/가 이미 포함된 프로젝트를 배포하세요.
패키지 설치·관리 방법에 대한 자세한 내용은 dbt Projects on Snowflake 의존성 이해 문서를 참조하세요.
시맨틱 뷰(Semantic views)
시맨틱 뷰를 dbt 파이프라인 안에 코드화하면 버전 관리되고, 테스트 가능하며, 환경 간 재현 가능함을 보장해요.
Snowflake 시맨틱 뷰 dbt 패키지 사용하기
Snowflake Semantic View dbt Package가 Snowflake UI에서 수동으로 만드는 것보다 dbt에서 시맨틱 뷰를 관리하는 권장 방식이에요. 이 패키지를 사용하면 시맨틱 뷰를 dbt 모델로 정의할 수 있으며, 이는 다음을 의미해요:
- 시맨틱 뷰 정의가 변환 로직과 함께 Git 저장소에 저장돼요.
- 시맨틱 뷰 변경이 모델과 같은 CI/CD 및 리뷰 프로세스를 거쳐요.
- 환경 간(dev, staging, prod) 재현성과 누가 언제 무엇을 바꿨는지에 대한 명확한 감사 추적을 얻어요.
Snowflake 시맨틱 뷰는 Open Semantic Interface(OSI)를 지원하지 않으며 dbt Labs MetricFlow 시맨틱 레이어와 직접 통합되지 않아요. Snowflake Semantic View dbt Package는 Snowflake 플랫폼에서 dbt 파이프라인 내 시맨틱 뷰를 코드화하는 권장 경로예요.
최신 기능용 SQL pass-through
Snowflake Semantic View dbt Package는 SQL pass-through를 사용하므로, dbt package hub의 패키지 버전과 관계없이 최신 Snowflake SQL 기능을 지원해요. 시맨틱 뷰 정의에서 새 Snowflake 기능을 사용하기 위해 패키지 업데이트를 기다릴 필요가 없어요.
시맨틱 뷰 개발·유지 관리에 대한 모범 사례는 시맨틱 뷰 개발·배포 모범 사례 문서를 참조하세요.