로컬 초경량 프로젝트 (DBT, DuckDB)

우상욱·2024년 3월 3일
0

DBT

목록 보기
16/16

DBT를 배웠으니, 이제 로컬에서 한번 가볍게 데이터 파이프라인을 만들어보겠습니다. 물론, 스케줄링이 붙지않아 자동화되지 않겠지만, 추후에 에어플로우와 함께 프로젝트를 진행해보겠습니다.

프로젝트


1. 가상환경 생성

conda create --name dbt python=3.9
conda activate 

2. DBT, DuckDB 설치

python -m pip install dbt-core==1.6
python -m pip install dbt-duckdb==1.6 # duckdb도 설치됨

3. dbt init

dbt init

4. 설정 파일 수정

프로젝트의 이름과 프로필 명을 반드시 다르게 해줍니다. 여기서는 woody_dbt_duckdb, 그리고 dbt_duckdb가 다른 것을 볼 수 있습니다.

  • dbt_project.yml
name: 'woody_dbt_duckdb'
version: '1.0.0'
config-version: 2
profile: 'dbt_duckdb'

model-paths: ["models"]
analysis-paths: ["analyses"]
test-paths: ["tests"]
seed-paths: ["seeds"]
macro-paths: ["macros"]
snapshot-paths: ["snapshots"]

clean-targets:
  - "target"
  - "dbt_packages"

models:
  woody_dbt_duckdb:
    silver:
      schema: silver
      materialized: table
    gold:
      schema: gold
      materialized: table
  • profiles.yml
dbt_duckdb:
  outputs:
    dev:
      type: duckdb
      path: dbt.duckdb
  target: dev

설정을 마쳤으면, 확인을 위해 dbt run 커맨드로 확인합니다.

5. Source 생성

Source는 DBT에선 Extract, Load가 이미 된 데이터로, 이미 웨어하우스에 로드되어 있는 데이터셋입니다. DuckDB에서 진행하고 있으니, 가볍게 공공데이터 csv 파일을 가지고 만들어보겠습니다.

# 터미널에서 덕디비 실행
duckdb dbt.duckdb

# 브론즈 스키마 생성
create schema bronze

# csv 카피 및 테이블 생성
CREATE TABLE bronze.seoul_bronze AS SELECT * FROM read_csv_auto('/Users/woody/Myspace/dbt-project/dbt_duckdb/data/seoul_raw.csv');
  • bronze 스키마를 만들었고, 이 bronze 스키마에 seoul_bronze라는 테이블을 만들었습니다.

  • 컬럼이 약 120개 정도 되고, 저희는 silver 레이어에서, 특정 컬럼만 사용할 것이니, 해당 부분을 가공하는 silver model을 만들어보겠습니다.

6. 가공 테이블 생성(Silver)

먼저 models의 silver 폴더에서, schema.yml 파일을 수정합니다.

version: 2
models:
  - name: silver.seoul_silver
    description: "서울시 소득별 및 이동현황 중간 가공 데이터"
sources:
  - name: bronze
    description: "원본 데이터"
    tables:
      - name: seoul_bronze
        description : "서울시 소득별 및 이동현황 RAW 데이터"

sources는 방금 만든 bronze 스키마의 seoul_bronze를 사용할 것이고, 이 소스를 사용해서, 데이터를 가공합니다. 가공 로직은 seoul_silver.sql에 담습니다. sourcesname에는 스키마가 들어갔지만, model은 바로 name에 스키마와 테이블명이 모두 사용됩니다.

with source_data as (
    select
        자치구명,
        datepart('year', today()) - 생년월일 as 나이,
        직업군,
        세대주여부,
        CAST(추정연소득 AS FLOAT) as 추정연소득,
        순자산평가금액,
        nullif(평균_통화량, 'NA') as 평균_통화량
    from {{ source('bronze', 'seoul_bronze') }}
    where 추정연소득 != 'NA'
)
select *
from source_data

{{ source('bronze', 'seoul_bronze') }} 이 부분은 소스의 스키마와 테이블명을 진자템플릿으로 가져오는 부분입니다. 그럼 이렇게 작업을 하고 dbt run을 해봅니다.

DuckDB에서 확인해보면, 테이블이 잘 생성된 것을 볼 수 있습니다. 스키마가 main_silver인 것을 볼 수 있는데, duckdb-dbt는 models의 경우 main을 추가로 앞에 붙여서 스키마를 생성합니다.

7. 최종 테이블 생성(Gold)

최종 Gold Layer도 크게 다르지 않습니다. 다만 ref 를 이용해서, 실버에 있는 테이블을 참조합니다. 먼저 schema.yml 파일에 저장합니다. 여기선 참조할 source가 없기 때문에, 이렇게 구현합니다.


version: 2

models:
  - name: gold.seoul_gold
    description: "서울시 소득별 및 이동현황 최종 마트1"

그 다음은 seoul_gold.sql 파일을 생성합니다.

with source_data as (
    select
        자치구명,
        avg(추정연소득) as 평균연소득
    from {{ ref('seoul_silver') }}
    group by 자치구명
    order by 평균연소득 desc
)
select *
from source_data

refseoul_silver 스키마를 이용해서, 자치구별 평균 연소득을 구해서 테이블을 생성합니다. 그럼 이렇게 작업을 하고 dbt run을 해봅니다.

Duckdb를 확인해보면, gold 스키마에 데이터가 잘 생성된 것을 확인할 수 있습니다.

dbt docs


  1. 문서를 확인해보기 위해서, dbt docs generate 명령어로 문서를 만들어봅니다.
  2. 문서가 잘 만들어졌다면, 서버를 실행합니다. dbt docs serve
  3. 접속해서 확인합니다.

프로젝트의 구조와 dbt 프로젝트 내에서 사용중인 데이터베이스의 테이블들을 깔끔하게 볼 수 있습니다.

또한 seoul_silver를 클릭해서, 우측 하단의 초록색 동그라미를 클릭해보면, data lineage를 정확히 확인할 수 있습니다. 업스트림에서 다운스트림으로 이어지는, 데이터 계보를 확인 할 수 있고,

테이블에 대한 정보를 조금 더 보기 쉽게 볼 수 있습니다.

DBT build


production 환경에서는 반드시 dbt build를 통해서, 모든 변경사항에 대해서 오류가 없는지 확인하고 모든 실행을 합니다. 여기에는 dbt run, dbt seed, dbt test, dbt snapshot 모든 것들이 포함됩니다. 저희도 기분 낼겸 한번 커맨드를 실행해보겠습니다.

dbt build

이외에도


  • 이 외에도, 변하지 않는 마스터 테이블 같은 느낌의 dbt seed를 활용해서, 데이터 가공 로직에 추가할 수 있습니다.
  • 다양한 방식의 dbt test를 통해서, 데이터의 무결성을 보장할 수 있습니다.
  • dbt snapshot을 통해서 데이터의 변경사항을 컬럼단위로 관리할 수 있습니다.

이 모든 것들은, 에어플로우 스터디가 마치는 대로, 하나의 프로젝트로 소개해드리도록 하겠습니다. 감사합니다:)

profile
데이터엔지니어

0개의 댓글