오늘은 원티드랩에서 데이터 마트를 설립한 배경과 과정에 대한 글이 있어 이를 리뷰하고자 한다. 이전 직장에서 데이터 마트를 만들 때는 기존 대시보드를 바탕으로 만들었었다. 대시보드를 주로 이용하는 사업부와 미팅을 거치며 어떤 식으로 보완되면 좋은지 니즈를 파악하고 마트를 구성했다. 원티드랩에서는 어떻게 데이터 마트를 설계하는지 알아보자.
기술 블로그 출처
데이터 마트 구조화 요약
- ERD 작성
- 코드작업
- 확장성, 독립성, 품질 고려
- 관리방식
- 컬럼명 규칙
데이터 마트
데이터 마트란, 운영상 생성된 데이터를 변환, 집계하여 분석을 위해 운영 데이터를 가공한 데이터셋을 의미한다. 주로 데이터 웨어하우스의 하위 집합으로 사용되며, 데이터 웨어하우스에서 전체적인 기업 데이터를 중앙 집중화하여 보관하는 것과 달리, 데이터 마트는 특정한 주제나 부서, 사용자의 요구에 맞추어 구성된다.
원티드랩은 이미 구글 빅쿼리로 DW를 운영하고 있는데, 구글 빅쿼리는 SQL 기반의 스키마를 사용하여 데이터를 관리할 수 있다. 데이터 팀은 운영 데이터를 모두 구글 빅쿼리에 저장하고 필요한 테이블과 컬럼을 자주 사용하는 팀원들을 위해 뷰테이블로 구조화해 둔다고 한다.
원티드랩은 기업과 유저 단 데이터를 모두 보유하고 있어 세부 데이터를 처음부터 이해하기 어려웠으나 이미 만들어진 뷰테이블 코드를 분석하며 사용빈도가 높은 테이블과 컬럼들을 먼저 파악하기 시작했다.
1. ERD 작성
draw.io를 사용하여 데이터 웨어하우스의 뷰테이블을 기반으로 ERD를 작성하고 테이블 간의 관계를 파악했다. 이를 통해 테이블 간의 관계를 이해하고, 데이터의 흐름과 구조를 시각화 했다.
기업이 빠르게 성장해 모델링 및 운영에만 집중해야 하기 때문에 내부 인프라 사용성까지 챙기기 어려웠다. 그러나 테이블 구조화 뿐만 아니라 각 테이블과 컬럼들의 설명이 좀 더 보완되어야 구성원들이 잘 이해하고 사용할 수 있다고 생각했다. 따라서 아래의 정보들을 토대로 데이터 마트의 작업 우선순위를 결정했다.
- Key값: Primary Key, Foriegn Key 등
- Mapping Cardinality
- 컬럼의 타입
* Mapping Cardinality: 데이터 모델링에서 한 엔터티와 다른 엔터티 간의 관계를 설명하는 데 사용되는 개념이다. 이는 한 엔터티의 레코드와 다른 엔터티의 레코드 사이의 관계를 나타낸다.
- One-to-One (1:1): 한 엔터티의 각 레코드가 다른 엔터티의 하나의 레코드와 관련이 있음
- One-to-Many (1:N): 한 엔터티의 각 레코드가 다른 엔터티의 여러 레코드와 관련이 있음
- Many-to-Many (N:N): 한 엔터티의 여러 레코드가 다른 엔터티의 여러 레코드와 관련이 있음
2-1. 고려한 점
데이터 마트를 관리할 때 가장 중요하게 생각한 부분은 확장성, 독립성, 품질이다.
- 확장성
- 시스템이 증가하는 데이터양과 요구사항에 대해 유연하게 대응할 수 있는 능력
- 같은 성격의 컬럼들을 테이블 단위로 묶어 추가/수정 할 수 있게 구현했다.
- 예를 들어, User 테이블에는 온전히 유저 정보만 추가될 수 있게 그룹화 진행
- 독립성
- 데이터의 중복을 최소화하고, 각 테이블이 독립적으로 관리될 수 있는 능력
- 테이블 간 PK 외에는 중복되는 컬럼이 없도록 설계하고, 1:N 관계가 아니라면 독립적인 하나의 행만 가질 수 있도록 json 타입이나 python 코드로 컬럼을 새로 추가했다.
- 예를 들어, User 테이블에 작성한 이력서 정보나 지원한 회사 정보는 별도 테이블로 구현
- 품질
- 정확성, 일관성, 유효성 등을 보장하는 능력
- 컬럼 기준에 대한 현황을 파악하고 최대한 쿼리 작성에 편리하도록 설계
- 예시
- 컬럼 사용 기준 정하기 - 서류 합격의 기준(서류 합격 시간 컬럼의 유무 or 상태값), timestamp 기준을 UTC로 고정
- 쿼리 사용 현황 확인 - 사용 빈도가 높은 함수 확인
- 예시
2-2. 관리방식 정하기
기존 쿼리 베이스 마트 구조의 문제점
- 쿼리 비용: 뷰테이블 구조상 쿼리를 실행할 때마다 뷰테이블이 실행되어 비용이 발생됨
- 실행 소요시간: 하나의 테이블을 만들 때 원천 테이블의 join이 많아지면 조회해야 할 테이블이 많아져 소요시간이 증가됨
해결 방법
기존의 쿼리 기반 마트 구조에서 발생한 문제를 해결하기 위해 Airflow DAG를 활용하여 스케줄러로 실행시키는 방식으로 변경했다. 또한, python 코드를 활용하여 쿼리를 불러와서 컬럼을 가공하고 타입을 변경하는 등의 작업을 환경을 구축했다. 이를 통해 마트 작업 환경이 더욱 유연해지고 필요에 따라 쉽게 쿼리를 수정하고 관리할 수 있게 되었다.
2-3. 컬럼명 규칙 정하기
여러 원천 테이블에서 참조하는 경우가 많아 컬럼명만 보고도 직관적이고 타입과 출처를 알 수 있도록 네이밍 규칙을 정했다.
- 컬럼명은 snake_case를 기준으로 함
- 모든 테이블의 PK: 테이블명_id
- 테이블 간 join은 PK, FK 이용
- timestamp 날짜 컬럼: UTC 기준으로 통일
- true/false 값을 가지는 컬럼명: is_ 접두사 사용
- analytics_mart에서 user, company, position, apply, order, event와 같이 서비스의 핵심 기능이 되는 테이블에 해당하는 컬럼은 축약어를 사용하지 않고 그대로 컬럼명 prefix로 적용
- ex. apply 테이블 내 유저 정보 컬럼 : user_xxx
- 3rd-party 툴이나 다른 테이블의 정보를 불러오는 컬럼일 경우, 접두사로 출처 확인
- ex. 크레딧잡 출처 : kj_xxx, 앰플리튜드 출처 : amp_xxx
- 집계함수를 사용한 컬럼은 접두사로 표기
- count() : c_ , sum() : s_
앞으로의 마트 계획
초기에는 품질 검증 및 테이블 구조 변경과 같은 자잘한 수정 요청을 받았다. 그러나 현재는 마트를 만들 때 일정한 절차를 따라 검증하고 규칙을 준수하여 유지보수 하고 있다. 배포된 마트 테이블은 구성원들에 의해 대시보드 및 데이터 추출을 위한 쿼리 등에 활용되고 있다.
테이블의 구조가 방대해지면서 페이징을 통한 업데이트 시간 단축, 마트 테이블 구조의 쉬운 파악, 마트 테이블 수정과 테스트를 편하게 하는 방법 등의 보완이 필요하다. 데이터 팀은 계속해서 구성원들과 함께 이러한 유지보수 작업을 지속적으로 진행하고 있다.
후기
데이터 팀이 사용자 중심의 접근과 유연성을 중요하게 생각하며 지속적으로 성장하고 개선하려고 하는 점이 인상 깊었다. 나 역시 데이터 마트를 관리할 때 중요하다고 생각하는 부분이 확장성, 독립성, 품질인데 실제로 회사에서 이를 고려하며 각각 어떻게 해결하려고 했는지 알 수 있어서 좋았다.