dbt 테스트가 어떻게 SQL을 생성하고 데이터 유효성을 검증하는지 내부 동작 원리를 깊이 있게 파헤칩니다. PM/기획자를 위한 dbt 테스트 심층 가이드로, 데이터 품질 관리의 핵심을 잡으세요.
안녕하세요! 데이터 기반 의사결정을 위해 밤낮으로 애쓰시는 기획자/PM님들, 그리고 데이터에 대한 깊은 이해를 갈망하시는 모든 분들께 반가운 인사를 드립니다. 오늘은 데이터 파이프라인의 필수 도구로 자리 잡은 dbt(data build tool)의 테스트 프레임워크에 대해 이야기해 볼까 해요. 특히, "dbt 테스트가 대체 어떻게 내 데이터를 검증하는 거지?"라는 근본적인 질문에 대한 답을 찾아 떠나는 여정이 될 겁니다.
혹시 이런 경험 없으신가요? 야심 차게 구축한 대시보드의 핵심 지표가 어느 날 갑자기 이상한 값을 보여주거나, 중요한 보고서의 데이터가 엉망진창이 되는 사태를 말이죠. 그런데 더 답답한 건, "분명히 dbt 테스트는 다 통과했다"는 개발팀의 답변이었을 때입니다. '테스트는 통과했는데 데이터는 왜 틀리지?'라는 의문이 머릿속을 떠나지 않을 때가 많으실 텐데요. 오늘은 그 미스터리를 함께 풀어보고, dbt 테스트를 더 현명하게 활용하는 방법을 알아보려 합니다.
dbt 테스트는 단순한 '통과/실패'를 넘어, 내부적으로 SQL 쿼리를 생성하고 실행하면서 데이터를 검증합니다. 이 내부 동작 원리를 이해하는 것이야말로, 우리가 진정으로 신뢰할 수 있는 데이터 파이프라인을 구축하고 데이터 품질을 보장하는 첫걸음이거든요. PM/기획자로서 dbt 테스트의 '마법' 뒤에 숨겨진 '과학'을 이해한다면, 개발팀과의 소통도 훨씬 원활해지고, 더 견고한 데이터 전략을 세울 수 있을 거예요. 자, 그럼 함께 dbt 테스트의 심장부를 들여다볼까요?
📑 목차
- "dbt 테스트 통과했는데, 왜 데이터는 엉망이죠?" PM의 답답한 현실
- 문제 발생: "분명히 테스트는 성공인데..." 신뢰할 수 없는 데이터의 그림자
- 원인 분석: dbt 테스트, 그 마법 뒤에 숨겨진 SQL의 비밀
- Generic 테스트: 편리함 속에 감춰진 '일반적인' 함정
- Singular 테스트: 맞춤형 검증, 그러나 '의도대로' 동작하는가?
- 해결 과정: dbt 테스트의 심장을 들여다보는 여정
- Generic 테스트의 SQL 생성 원리 파헤치기
- Singular 테스트: 원하는 검증 SQL 직접 설계하고 검토하기
- 교훈: PM을 위한 dbt 테스트 전략: '통과'를 넘어 '신뢰'로
- 데이터 유효성 검사, 이제 '어떤 SQL'이 실행되는지 물어보세요
- 테스트 설계는 곧 비즈니스 로직 설계: PM의 적극적인 참여
- Generic vs Singular: 최적의 조합으로 견고한 데이터 파이프라인 구축
- 마무리: dbt 테스트, 당신의 데이터 품질을 위한 강력한 동반자
Image by Dewesoft on Pixabay
"dbt 테스트 통과했는데, 왜 데이터는 엉망이죠?" PM의 답답한 현실
지금부터 가상의 시나리오를 하나 설정해볼게요. 여러분은 온라인 쇼핑몰의 핵심 서비스 기획자(PM)입니다. 고객 행동을 분석하고 마케팅 캠페인을 최적화하기 위해 '일일 구매 전환율'을 보여주는 대시보드를 구축했어요. 이 대시보드는 dbt를 통해 생성된 daily_customer_purchases라는 핵심 데이터 모델에 기반하고 있습니다. 이 모델은 고객의 주문 정보, 상품 정보, 결제 상태 등을 집계하여 일별 구매 현황을 보여주죠.
초기에는 모든 것이 순조로웠습니다. 개발팀은 dbt 모델을 만들고, 데이터 유효성 검사를 위해 여러 테스트를 추가했다고 보고했어요. customer_id는 not_null이고 unique하다는 테스트, order_amount는 0보다 커야 한다는 테스트 등, 기본적인 데이터 무결성을 위한 장치들이 잘 마련된 것처럼 보였습니다. '테스트가 다 통과했으니 데이터는 믿을 수 있겠지!'라고 생각했죠. 그런데 어느 날, 대시보드의 '일일 구매 전환율'이 평소보다 2배 이상 급증하는 현상을 발견하게 됩니다. 일시적인 이벤트 효과인가 싶었지만, 마케팅팀에서는 그런 이벤트는 없었다고 하네요. '혹시 데이터에 문제가 생긴 건 아닐까?'라는 불길한 예감이 스쳤죠.
문제 발생: "분명히 테스트는 성공인데..." 신뢰할 수 없는 데이터의 그림자
여러분은 곧바로 데이터 엔지니어에게 문의했습니다. 엔지니어는 "dbt 테스트는 모두 초록불(Passed)입니다. 데이터 파이프라인에는 문제가 없어요."라고 답했어요. 하지만 대시보드의 지표는 여전히 비정상적인 값을 가리키고 있었죠. 심층 분석 결과, 다음과 같은 심각한 데이터 불일치 문제가 발견되었습니다.
- 중복 주문 ID:
daily_customer_purchases모델의order_id컬럼에서 동일한 주문 ID가 여러 번 나타나는 현상이 발견되었습니다. 분명unique테스트를 통과했는데 말이죠. 이로 인해 특정 주문이 여러 번 집계되어 총 구매 금액과 전환율이 부풀려졌습니다. - 결제 상태 불일치: '결제 완료' 상태여야 하는 주문 중 일부가 실제로는 '결제 실패'이거나 '환불' 상태임에도 불구하고, 모델에서는 '결제 완료'로 잘못 분류되어 있었습니다. 이는 상위 시스템의 데이터 연동 문제였는데, dbt 테스트는 이를 잡아내지 못했어요.
- 특정 상품의 과도한 판매량: 특정 프로모션 상품의 판매량이 비정상적으로 높게 집계되어 있었습니다. 이 역시
order_amount가 양수라는 기본적인 테스트는 통과했지만, 실제 비즈니스 로직과는 동떨어진 수치였죠.
이러한 문제들로 인해 대시보드는 신뢰도를 잃었고, 마케팅 캠페인 전략은 혼란에 빠졌습니다. 'dbt 테스트가 왜 이런 문제를 잡아내지 못했을까?' '테스트는 도대체 뭘 검증했던 거지?'라는 질문이 꼬리에 꼬리를 물었죠. 단순히 '테스트 통과' 여부만으로는 데이터의 진정한 유효성을 판단할 수 없다는 뼈아픈 교훈을 얻게 된 순간이었습니다.
원인 분석: dbt 테스트, 그 마법 뒤에 숨겨진 SQL의 비밀
왜 이런 문제가 발생했을까요? 가장 큰 원인은 dbt 테스트가 내부적으로 어떻게 동작하는지, 즉 어떤 SQL을 생성하고 실행하는지에 대한 이해 부족 때문입니다. dbt 테스트는 결코 마법이 아니거든요. 결국 우리의 데이터를 대상으로 특정 SQL 쿼리를 실행하고, 그 결과가 기대하는 바와 다를 때 '실패'를 알리는 아주 논리적인 과정입니다.
Generic 테스트: 편리함 속에 감춰진 '일반적인' 함정
우리가 가장 흔하게 사용하는 not_null, unique, accepted_values 같은 테스트들을 Generic 테스트라고 부릅니다. 이 테스트들은 dbt에서 미리 정의된 템플릿 형태로 제공되기 때문에, YAML 파일에 몇 줄만 추가하면 쉽게 적용할 수 있죠. 너무나 편리해서 많은 분들이 그 내부 동작 원리에 대해서는 깊이 생각하지 않는 경우가 많습니다.
Generic 테스트는 사실 Jinja 템플릿 엔진과 함께 작동합니다. 우리가 YAML 파일에 정의한 테스트 구문은 Jinja 템플릿을 통해 특정 SQL 쿼리로 변환됩니다. 그리고 이 SQL 쿼리가 데이터베이스에 직접 실행되어 데이터를 검증하는 방식이에요. 문제는 이 "미리 정의된 SQL"이 우리의 특정 비즈니스 로직이나 엣지 케이스를 완벽하게 포괄하지 못할 수 있다는 점입니다.
예를 들어, order_id에 대한 unique 테스트는 단순히 해당 컬럼에 중복 값이 있는지를 확인하는 SQL을 생성합니다. 하지만 만약 상위 시스템에서 동일한 주문 ID가 '환불' 후 '재결제'되면서 두 번 들어왔다면 어떨까요? dbt의 unique 테스트는 이를 '다른 주문'으로 인식하지 못하고, 단순히 '중복된 ID'로만 판단하여 문제를 잡아내지 못할 수도 있습니다. 즉, "중복은 없지만 비즈니스적으로는 잘못된" 상황을 놓칠 수 있다는 의미죠. PM의 관점에서는 "분명히 유니크하다고 했는데 왜 중복 문제가 발생했지?"라는 의문이 생길 수밖에 없는 지점입니다.
Singular 테스트: 맞춤형 검증, 그러나 '의도대로' 동작하는가?
Singular 테스트는 Generic 테스트와 달리, 우리가 직접 SQL 쿼리를 작성하여 데이터를 검증하는 방식입니다. .sql 파일 형태로 모델과 함께 관리되며, 특정 비즈니스 규칙이나 복잡한 데이터 조건을 검증하는 데 주로 사용됩니다. 예를 들어, '상품 가격은 항상 0보다 커야 하고, 할인율은 100%를 넘을 수 없다'와 같은 복잡한 규칙을 검증할 때 유용하죠.
Singular 테스트는 Generic 테스트의 한계를 극복할 수 있는 강력한 도구이지만, 여기에도 함정이 있습니다. 바로 "내가 의도한 대로 SQL이 정확하게 데이터를 검증하고 있는가?"에 대한 질문입니다. 개발자가 작성한 SQL이 PM이 생각하는 비즈니스 로직과 미묘하게 다를 수 있거든요. 특히, 복잡한 로직일수록 SQL 문 하나하나가 비즈니스 규칙의 어떤 부분을 커버하고, 어떤 엣지 케이스를 놓칠 수 있는지 정확히 파악하기 어렵습니다. 만약 SQL 쿼리 자체가 특정 오류 조건을 놓치도록 설계되었다면, 테스트는 항상 '통과'하겠지만 실제 데이터는 여전히 '오류' 상태에 머무르게 되는 거죠. 이것이 바로 '테스트는 통과했지만 데이터는 엉망인' 상황의 또 다른 주범이 됩니다.
결국, dbt 테스트의 문제는 테스트 자체의 기능 부족이 아니라, 테스트가 생성하고 실행하는 SQL 쿼리의 한계나 우리의 기대와의 불일치에서 비롯된다는 것을 알 수 있습니다. PM/기획자로서 우리는 이 SQL의 '정체'를 파악하고, 우리의 데이터 품질 요구사항이 SQL에 정확히 반영되도록 적극적으로 소통해야 합니다.
Image by analogicus on Pixabay
해결 과정: dbt 테스트의 심장을 들여다보는 여정
데이터 문제의 근본 원인이 dbt 테스트가 생성하고 실행하는 SQL에 있다는 것을 알았다면, 이제 해결책은 명확합니다. 바로 dbt 테스트의 '심장'인 SQL 쿼리를 직접 들여다보는 것입니다. PM/기획자라도 이 과정을 이해하면 개발팀과 훨씬 심도 있는 대화를 나눌 수 있고, 데이터 품질 관리 프로세스 전반에 대한 통찰력을 얻을 수 있습니다.
Generic 테스트의 SQL 생성 원리 파헤치기
Generic 테스트는 dbt에 내장된 매크로(macro)와 Jinja 템플릿을 통해 SQL을 생성합니다. dbt compile 명령어를 사용하면 실제로 어떤 SQL이 생성되는지 확인할 수 있어요. 몇 가지 대표적인 Generic 테스트를 예시로 살펴볼까요?
1. not_null 테스트
모델의 특정 컬럼에 NULL 값이 없는지 확인하는 가장 기본적인 테스트입니다. YAML 파일에서는 이렇게 정의하죠.
# models/my_model.yml
version: 2
models:
- name: daily_customer_purchases
columns:
- name: customer_id
tests:
- not_null
이 정의는 dbt compile을 통해 다음과 유사한 SQL 쿼리로 변환됩니다. (실제 생성되는 SQL은 데이터베이스 종류 및 dbt 버전에 따라 약간 다를 수 있습니다.)
-- Generated SQL for not_null test
select
count(*)
from <YOUR_SCHEMA>.daily_customer_purchases -- 실제 스키마와 테이블 이름
where customer_id is null
동작 원리: 이 SQL은 customer_id가 NULL인 행의 개수를 셉니다. 만약 count(*)의 결과가 0보다 크면, 테스트는 실패하게 됩니다. 간단하죠? PM 관점에서는 '고객 ID가 꼭 있어야 하는가?'라는 비즈니스 요구사항이 이 한 줄의 SQL로 구현된 것이라고 이해할 수 있습니다.
2. unique 테스트
컬럼에 중복 값이 없는지 확인하는 테스트입니다.
# models/my_model.yml
version: 2
models:
- name: daily_customer_purchases
columns:
- name: order_id
tests:
- unique
이 정의는 대략 이런 SQL 쿼리로 변환됩니다.
-- Generated SQL for unique test
select
order_id
from <YOUR_SCHEMA>.daily_customer_purchases
group by order_id
having count(*) > 1
동작 원리: order_id를 기준으로 그룹화하고, 각 그룹의 개수가 1보다 큰 경우(즉, 중복된 경우) 해당 order_id를 반환합니다. 이 SQL이 반환하는 행이 하나라도 있다면 테스트는 실패합니다. 앞서 발생했던 '중복 주문 ID' 문제는 이 SQL이 해당 데이터를 찾아내지 못했거나, 비즈니스적으로는 중복이지만 기술적으로는 중복이 아닌 것으로 판단될 만한 특정 조건이 있었을 수 있다는 단서를 제공합니다.
3. accepted_values 테스트
컬럼 값이 특정 목록 내에 있는지 확인하는 테스트입니다.
# models/my_model.yml
version: 2
models:
- name: daily_customer_purchases
columns:
- name: payment_status
tests:
- accepted_values:
values: ['paid', 'refunded', 'failed']
이 정의는 다음과 같은 SQL로 변환될 수 있습니다.
-- Generated SQL for accepted_values test
select
payment_status
from <YOUR_SCHEMA>.daily_customer_purchases
where payment_status not in ('paid', 'refunded', 'failed')
동작 원리: payment_status 컬럼의 값이 정의된 목록 ('paid', 'refunded', 'failed')에 포함되지 않는 모든 행을 반환합니다. 이 SQL이 반환하는 행이 있다면 테스트는 실패합니다. PM은 '결제 상태가 이 셋 중 하나여야 한다'는 비즈니스 규칙이 SQL로 어떻게 구현되는지 명확히 볼 수 있는 거죠.
이처럼 dbt compile을 통해 실제 SQL을 확인하는 것은 dbt 테스트의 범위와 한계를 명확히 이해하는 데 매우 중요합니다. PM은 이 SQL을 보고, '과연 이 SQL이 내가 생각하는 모든 예외 상황을 잡아낼 수 있을까?'라는 질문을 던져야 합니다.
Singular 테스트: 원하는 검증 SQL 직접 설계하고 검토하기
Generic 테스트로 커버하기 어려운 복잡한 비즈니스 로직이나 특정 엣지 케이스는 Singular 테스트를 통해 직접 SQL을 작성하여 검증해야 합니다. Singular 테스트는 보통 models/tests/ 디렉토리 안에 .sql 파일로 저장됩니다.
예를 들어, '주문 금액은 항상 0보다 커야 한다'는 일반적인 규칙 외에, '특정 프로모션 상품의 할인율은 50%를 초과할 수 없다'와 같은 복잡한 규칙을 검증하고 싶을 때 Singular 테스트를 사용합니다. 앞서 발생했던 '특정 상품의 과도한 판매량' 문제의 원인이 '음수 금액' 때문이었다면, 다음과 같은 Singular 테스트를 작성할 수 있습니다.
-- models/tests/assert_order_amount_is_positive.sql
select
order_id,
order_amount
from {{ ref('daily_customer_purchases') }}
where order_amount <= 0
동작 원리: 이 SQL은 daily_customer_purchases 모델에서 order_amount가 0 이하인 모든 주문을 찾아냅니다. 이 쿼리가 반환하는 행이 하나라도 있다면 테스트는 실패합니다. 만약 이 테스트가 성공했다면, '음수 금액'은 문제가 아니라는 뜻이 되므로, PM은 다른 원인을 찾아야겠죠.
Singular 테스트의 핵심은 PM이 '어떤 조건의 데이터가 문제라고 생각하는지'를 명확히 정의하고, 개발팀과 함께 그 조건을 정확한 SQL 쿼리로 변환하는 과정입니다. PM은 비즈니스 전문가로서 문제 정의에 참여하고, 개발자는 이를 기술적으로 구현합니다. 그리고 구현된 SQL이 PM의 의도와 일치하는지 함께 검토하는 것이 매우 중요합니다. 이 과정을 통해 '우리가 잡아내고자 하는 문제는 무엇이고, 이 SQL이 그것을 어떻게 찾아낼 것인가'에 대한 투명성을 확보할 수 있습니다.
Image by Alexandra_Koch on Pixabay
교훈: PM을 위한 dbt 테스트 전략: '통과'를 넘어 '신뢰'로
이제 우리는 dbt 테스트가 단순한 '마법'이 아니라, 내부적으로 SQL을 생성하고 실행하는 '과학'이라는 것을 이해했습니다. 이러한 이해를 바탕으로, PM/기획자로서 데이터 품질을 관리하고 신뢰할 수 있는 데이터 파이프라인을 구축하기 위한 몇 가지 중요한 교훈을 얻을 수 있습니다.
데이터 유효성 검사, 이제 '어떤 SQL'이 실행되는지 물어보세요
가장 중요한 교훈은 바로 '테스트 통과 여부' 그 이상을 바라보는 시야입니다. 앞으로 개발팀과 데이터 품질에 대해 논의할 때, 단순히 "dbt 테스트는 다 통과했습니다"라는 답변에 만족하지 마세요. 대신 이렇게 질문해 보세요.
- "이
unique테스트는 어떤 SQL로 변환되나요? 저희가 우려하는 A라는 상황도 이 SQL로 잡아낼 수 있을까요?" - "이 Singular 테스트의 SQL은 어떤 비즈니스 로직을 검증하고 있나요? 저희가 놓치고 있는 엣지 케이스는 없을까요?"
이 질문들은 단순히 개발팀을 의심하는 것이 아니라, 데이터 유효성 검증 로직에 대한 투명성을 확보하고, PM이 가진 비즈니스 도메인 지식을 테스트 설계에 효과적으로 반영하기 위한 건설적인 대화의 시작입니다. dbt compile 명령어를 통해 생성된 SQL을 함께 검토하는 시간을 가지면, 서로의 이해도를 높이고 잠재적인 데이터 문제를 미리 발견할 수 있습니다.
테스트 설계는 곧 비즈니스 로직 설계: PM의 적극적인 참여
dbt 테스트는 단순한 기술적 검증 도구가 아닙니다. 이는 곧 '우리가 생각하는 올바른 데이터는 어떤 모습인가?'라는 비즈니스 로직을 코드화하는 과정과 같습니다. 따라서 테스트 설계는 개발팀만의 영역이 아니라, 비즈니스 규칙과 요구사항을 가장 잘 아는 PM의 적극적인 참여가 필수적입니다.
- 테스트 케이스 정의: 어떤 데이터가 '유효하지 않은' 것인지, 어떤 비즈니스 규칙이 위반되었을 때 '문제'로 간주해야 하는지 PM이 구체적으로 정의해야 합니다.
- 엣지 케이스 발굴: 일반적인 상황 외에, 발생 가능성이 희박하지만 치명적인 엣지 케이스(예: 환불 후 재결제 시 중복 주문 ID 발생)를 발굴하여 테스트에 반영할 수 있도록 개발팀에 아이디어를 제공해야 합니다.
- SQL 로직 검토: Singular 테스트의 경우, 개발자가 작성한 SQL이 PM이 정의한 비즈니스 로직을 정확히 반영하는지 함께 검토하는 시간을 가지세요.
이러한 과정을 통해 PM은 단순한 데이터 소비자에서 벗어나, 데이터 품질을 능동적으로 설계하고 관리하는 데이터 거버넌스의 핵심 주체로 거듭날 수 있습니다.
Generic vs Singular: 최적의 조합으로 견고한 데이터 파이프라인 구축
Generic 테스트와 Singular 테스트는 각각의 장단점이 명확합니다. 이 둘을 적절히 조합하여 사용하는 것이 가장 견고한 데이터 파이프라인을 구축하는 방법입니다.
| 구분 | Generic 테스트 | Singular 테스트 |
|---|---|---|
| 장점 |
|
|
| 단점 |
|
|
| 적합한 상황 |
|
|
PM은 데이터의 중요도와 복잡성에 따라 어떤 유형의 테스트를 적용할지 개발팀과 함께 전략적으로 논의해야 합니다. 기본적인 무결성은 Generic 테스트로 빠르게 커버하고, 비즈니스 핵심 지표에 영향을 미치는 중요 로직이나 엣지 케이스는 Singular 테스트로 심층적으로 검증하는 것이죠.
마무리: dbt 테스트, 당신의 데이터 품질을 위한 강력한 동반자
오늘은 dbt 테스트 프레임워크의 내부 동작 원리를 깊이 파헤쳐 봤습니다. dbt 테스트는 단순한 '통과/실패' 알림판이 아니라, 우리의 데이터에 대해 특정 SQL 쿼리를 실행하고 그 결과를 바탕으로 유효성을 판단하는 정교한 도구라는 것을 알게 되셨을 거예요.
PM/기획자로서 dbt 테스트의 SQL 생성 원리를 이해하는 것은 데이터를 맹목적으로 신뢰하는 것을 넘어, 데이터의 진정한 품질을 보장하고 데이터 기반 의사결정의 신뢰도를 높이는 데 결정적인 역할을 합니다. 이제 "dbt 테스트 통과했는데, 왜 데이터는 엉망이죠?"라는 답답함 대신, "이 테스트는 어떤 SQL로 데이터를 검증하고 있나요?"라고 질문하며 데이터 품질에 대한 주도적인 역할을 수행할 수 있게 되셨기를 바랍니다.
dbt 테스트는 여러분의 데이터 파이프라인을 더욱 견고하게 만들고, 데이터 신뢰도를 한 차원 높여줄 강력한 동반자입니다. 이 도구를 올바르게 이해하고 활용하여, 여러분의 비즈니스가 언제나 정확하고 신뢰할 수 있는 데이터 위에서 성장할 수 있기를 응원합니다!
오늘 다룬 내용에 대해 궁금한 점이나, 실제 프로젝트에서 겪었던 dbt 테스트 관련 경험이 있다면 댓글로 자유롭게 공유해주세요. 함께 배우고 성장하는 기회가 되기를 바랍니다!
📌 함께 읽으면 좋은 글
- [테스트 QA] 외부 API 의존성 테스트, 7가지 핵심 질문: Record/Replay vs Explicit Mocking 전략 가이드
- [데이터 엔지니어링] SQL 재귀 CTE, 무작정 쓰면 망합니다: 계층형 데이터 처리의 숨겨진 함정과 최적화 전략
- [클라우드 인프라] 수백만 원 절감! S3 스토리지 비용 최적화, Intelligent-Tiering vs. 수동 티어링 심층 비교
이 글이 도움이 되셨다면 공감(♥)과 댓글로 응원해 주세요!
궁금한 점이나 다루었으면 하는 주제가 있다면 댓글로 남겨주세요.
'데이터 엔지니어링' 카테고리의 다른 글
| 기업 셀프서비스 BI, 데이터 거버넌스로 성공시키는 실전 전략 (0) | 2026.07.20 |
|---|---|
| Metabase/Superset 느려지는 진짜 이유: 대시보드 로딩 지연, 캐싱만으론 부족합니다 (0) | 2026.07.18 |
| 데이터 분석 보고서가 지연될 때, Spark Catalyst Optimizer는 어떤 마법을 부릴까? (0) | 2026.07.17 |
| SQL 재귀 CTE, 무작정 쓰면 망합니다: 계층형 데이터 처리의 숨겨진 함정과 최적화 전략 (0) | 2026.07.13 |
| 데이터 레이크하우스 전환: 성공을 위한 5가지 핵심 체크리스트 (1) | 2026.07.11 |