Star/Snowflake schema와 wide table tradeoff
스키마 설계는 쿼리 방식과 분리할 수 없다
분석 모델링에서 grain, fact, dimension을 정의했다면 다음 결정은 "이 요소들을 어떤 스키마 구조로 조합할 것인가"다. 크게 세 가지 선택지가 있다. Star schema, Snowflake schema, Wide(flat) table이다.
이 선택은 순수하게 기술적인 것처럼 보이지만 실제로는 "누가 이 데이터를 어떻게 쿼리하는가"에 대한 판단이다. 분석가가 SQL을 직접 쓰는지, BI 도구가 자동으로 조인하는지, 컬럼형 저장소가 어떻게 동작하는지에 따라 최적의 선택이 달라진다.
1. Star Schema: 단순한 구조, 직관적인 쿼리
Star schema는 하나의 사실 테이블이 중심에 위치하고 여러 차원 테이블이 직접 연결된 구조다. 차원 테이블은 정규화하지 않는다. 지역 차원이 있다면 국가, 지역, 도시를 별도 테이블로 나누지 않고 하나의 dim_location 테이블에 모두 넣는다.
1.1 Star Schema의 장점
조인이 단순하다. 사실 테이블과 차원 테이블 사이의 조인이 최대 1단계다. 분석가가 SQL을 작성할 때 조인 경로가 직관적이고, BI 도구가 자동으로 관계를 인식하기 쉽다.
쿼리 성능이 예측 가능하다. 조인 깊이가 일정하므로 쿼리 옵티마이저가 최적화하기 쉽다. 특히 컬럼형 저장소(BigQuery, Snowflake, ClickHouse, Redshift)에서 사실 테이블을 스캔하고 차원을 조인하는 패턴이 잘 최적화된다.
분석가 접근성이 높다. 테이블 수가 적고 관계가 단순하므로 데이터를 처음 접하는 팀원도 구조를 빠르게 파악할 수 있다.
1.2 Star Schema의 단점
차원 테이블에 중복이 생긴다. 지역 계층(도시, 주, 국가)이 dim_location에 비정규화되어 있으면, 국가명이 바뀔 때 여러 행을 업데이트해야 한다. OLTP에서는 정규화로 피하던 갱신 이상이 발생할 수 있다.
저장 공간이 더 필요하다. 비정규화된 텍스트 속성이 중복 저장되어 차원 테이블 크기가 커진다. 하지만 현대의 컬럼형 저장소에서는 압축으로 이 차이가 크게 줄어든다.
2. Snowflake Schema: 정규화된 차원, 복잡한 조인
Snowflake schema는 Star schema에서 차원 테이블을 추가로 정규화한 구조다. dim_location 하나에 담겨 있던 도시·주·국가 정보를 dim_city, dim_state, dim_country로 분리한다. 차원이 계층 구조를 가지면 각 수준마다 별도 테이블이 생긴다.
location_key (PK)
city_name
state_name
country_name
region
수천 개 도시 행에 반복 저장
city_key (PK)
city_name
state_key (FK)
state_key (PK)
state_name
country_key (FK)
country_key (PK)
country_name
region
한 번만 저장됨 → 갱신 이상 없음
2.1 Snowflake Schema의 장점
데이터 중복이 없다. 국가명처럼 여러 하위 계층이 공유하는 값을 한 곳에만 저장한다. 갱신 이상이 없고 데이터 일관성이 높다.
차원 계층이 명시적이다. 도시→주→국가 계층이 외래 키 관계로 명확하게 표현된다. 계층 구조가 복잡하고 깊을수록 이점이 두드러진다.
2.2 Snowflake Schema의 단점
쿼리가 복잡해진다. "국가별 매출"을 조회하려면 fct_sales → dim_location → dim_city → dim_state → dim_country까지 연결해야 한다. 분석가가 직접 SQL을 쓸 때 조인 실수가 발생하기 쉽다.
성능 우위가 불분명하다. 데이터 중복 감소로 저장 공간을 절약하지만, 조인 단계가 늘어나므로 쿼리 성능이 반드시 좋아지지는 않는다. 컬럼형 저장소에서는 압축 덕분에 중복 저장 비용이 낮으므로 Star schema의 단점이 더 작아진다.
실무에서의 위치. Snowflake schema는 데이터 웨어하우스 레이어에서보다는 staging/ODS(Operational Data Store) 레이어에 더 어울린다. 분석 레이어(mart)는 Star schema나 wide table로 제공하고, 그 기반이 되는 저장 계층을 정규화하는 방식이 일반적이다.
3. Wide Table (One Big Table): 현대 컬럼형 저장소의 현실적 선택
Wide table(또는 One Big Table, OBT)은 사실과 차원을 미리 조인해서 하나의 비정규화 테이블로 만드는 전략이다. 분석가는 조인 없이 이 테이블 하나에서 모든 컬럼을 쓸 수 있다.
-- Wide table 예시: 사전 조인된 주문 분석 테이블
CREATE TABLE wide_orders AS
SELECT
o.order_id,
o.order_date,
o.amount,
-- 고객 차원 (비정규화)
c.customer_name,
c.customer_tier,
c.customer_city,
c.customer_country,
-- 상품 차원 (비정규화)
p.product_name,
p.product_category,
p.product_brand,
-- 날짜 차원 (비정규화)
d.year,
d.quarter,
d.month,
d.weekday
FROM fct_orders o
JOIN dim_customer c ON o.customer_key = c.customer_key AND c.is_current
JOIN dim_product p ON o.product_key = p.product_key
JOIN dim_date d ON o.date_key = d.date_key;3.1 Wide Table이 잘 작동하는 조건
컬럼형 저장소의 특성. BigQuery, Snowflake, ClickHouse, Redshift는 컬럼 단위로 데이터를 저장하고 압축한다. 쿼리가 50개 컬럼 중 5개만 읽는다면, 나머지 45개는 디스크에서 전혀 읽지 않는다. 이 특성 덕분에 "컬럼이 많아도 안 읽으면 비용이 없다"는 원칙이 성립한다.
조인 비용 절감. 컬럼형 저장소에서도 대규모 테이블 간 조인은 비용이 높다. 특히 고카디널리티 FK 조인은 셔플(shuffle)을 유발한다. Wide table은 이 조인 비용을 쿼리 시점이 아닌 테이블 생성 시점으로 옮긴다.
분석가 편의. SQL에 익숙하지 않은 분석가나 BI 도구 사용자는 조인 없이 필요한 컬럼을 바로 선택할 수 있다. 셀프서비스 분석에서 진입 장벽이 낮아진다.
3.2 Wide Table의 한계
갱신이 어렵다. 차원이 변경되면 수백만~수십억 행을 재생성해야 한다. SCD Type 2처럼 "당시 값"을 유지하려면 복잡한 로직이 필요하다.
컬럼 수 제한. 일부 시스템은 컬럼 수에 제한이 있고, 컬럼이 매우 많으면 스키마 관리가 어려워진다.
일관성 위험. 같은 개념(예: "고객 등급")이 여러 wide table에 중복되면 정의가 달라지는 문제가 발생한다. Semantic layer나 metric layer로 이를 보완해야 한다.
4. 세 가지 스키마의 종합 비교
BI 도구 기반 셀프서비스
분석 레이어(mart)
조인이 예측 가능해야 할 때
conformed dimension 재사용
차원 테이블 비정규화로
갱신 이상 가능
→ SCD로 관리 필요
계층이 복잡한 차원
staging/ODS 레이어
데이터 중복이 엄격히 금지될 때
차원 테이블이 자주 변경될 때
분석 레이어에서는 조인 복잡성
→ 뷰(View)로 단순화 권고
컬럼형 저장소(BigQuery 등)
셀프서비스 분석 말단
특정 도메인 집중 분석
BI 도구 직접 연결 mart
차원 변경 시 전체 재생성
정의 불일치 위험
→ metric layer 보완 필요
| 기준 | Star | Snowflake | Wide Table |
|---|---|---|---|
| 조인 복잡도 | 낮음 (1단계) | 높음 (다단계) | 없음 |
| 저장 중복 | 중간 | 낮음 | 높음 |
| 쿼리 성능 (컬럼형 저장소) | 좋음 | 보통 | 매우 좋음 (조인 없음) |
| 갱신 용이성 | 보통 | 좋음 | 낮음 |
| 분석가 접근성 | 높음 | 낮음 | 매우 높음 |
| SCD 지원 | 자연스러움 | 자연스러움 | 복잡함 |
5. 현대 데이터 스택에서의 실전 조합
순수한 이론적 선택보다 현장에서 더 중요한 것은 레이어별 전략이다. dbt 커뮤니티가 제안하는 모델링 레이어 패턴은 각 레이어마다 다른 전략을 쓴다.
Staging 레이어는 원천 데이터를 1:1로 정제한다. 정규화 구조를 유지하고 컬럼 이름·타입 표준화에 집중한다.
Intermediate 레이어는 비즈니스 개념을 모델링한다. Conformed dimension을 정의하고 사실 테이블을 구성하는 Star schema가 이 레이어에 어울린다.
Mart 레이어는 분석가와 BI 도구가 직접 사용하는 계층이다. 특정 도메인(매출, 마케팅, 고객 LTV)에 집중된 wide table이나 Star schema 뷰를 제공한다.
이 레이어 분리는 "어느 스키마가 더 좋은가"가 아니라 "각 레이어의 목적에 맞는 스키마를 사용하라"는 실용주의적 접근이다.
6. Galaxy Schema와 기타 변형
Galaxy Schema(Fact Constellation)는 여러 사실 테이블이 conformed dimension을 공유하는 구조다. 예를 들어 fct_orders와 fct_returns가 동일한 dim_customer, dim_product, dim_date를 참조한다. "주문과 반품을 함께 분석"하는 cross-fact 쿼리가 가능해진다.
Galaxy schema는 대형 데이터 웨어하우스에서 자연스럽게 등장하는 패턴이다. 핵심은 conformed dimension의 정의를 조직 전체가 공유하는 것이다.
7. Semantic Layer와 스키마 선택의 관계
현대 데이터 스택에서 Looker(LookML), MetaBase, Cube.js 같은 semantic layer 도구는 스키마 선택의 유연성을 높인다. 물리적 테이블 구조가 Star schema든 wide table이든 관계없이, semantic layer에서 메트릭 정의·조인 관계·집계 규칙을 선언하면 BI 도구는 이를 기반으로 쿼리를 자동 생성한다.
이 접근에서 물리적 스키마는 성능과 갱신 편의성 기준으로 선택하고, 분석가가 보는 논리적 구조는 semantic layer가 제공한다. 결과적으로 "어느 스키마가 분석하기 쉬운가"라는 질문이 덜 중요해지고, "어느 스키마가 갱신하기 쉽고 성능이 좋은가"가 더 중요해진다.
마무리
Star, Snowflake, Wide table 중 하나가 항상 옳은 선택은 아니다. 컬럼형 저장소가 보편화된 현재, 저장 중복 비용은 과거보다 훨씬 낮아졌고 조인 비용은 여전히 유의미하다. 그 균형점에서 레이어별로 적절한 전략을 조합하는 것이 현실적인 해법이다.
다음 편에서는 이 스키마들 위에서 메트릭을 일관되게 정의하는 Metric Layer 설계 문제, 즉 "팀마다 '매출'의 정의가 다른 문제를 어떻게 해결할 것인가"를 다룬다.
References
- Ralph Kimball, Margy Ross, The Data Warehouse Toolkit (3rd ed.): https://www.kimballgroup.com/data-warehouse-business-intelligence-resources/books/data-warehouse-dw-toolkit/
- dbt Labs, "Modeling Guide — marts, intermediate, staging": https://docs.getdbt.com/guides/best-practices/how-we-structure/1-guide-overview
- Kimball Group, "Star Schema vs Snowflake Schema": https://www.kimballgroup.com/2003/01/its-the-business-process-stupid/
- Trino Blog, "When to use a wide table vs star schema": https://trino.io/blog/2021/10/21/one-big-table.html
- Databricks Engineering Blog, "Delta Lake: one Big Table vs Star Schema": https://www.databricks.com/blog/2020/08/27/databricks-delta-lake-the-foundation-for-your-data-lakehouse.html
- ClickHouse Docs, "Denormalization vs joins": https://clickhouse.com/docs/en/optimize/sparse-primary-indexes
- dbt discourse, "Star Schema vs OBT": https://discourse.getdbt.com/t/one-big-table-or-many-small-tables/5231
- Fivetran Blog, "Star Schema vs Snowflake Schema": https://www.fivetran.com/blog/star-schema-vs-snowflake-schema