dbt init을 하게 되면 다음과 같은 구조의 디렉토리가 생성되게 됩니다.

 

다음과 같은 구조로 프로젝트가 생성됩니다.

 

dbt run 을 실행하게 되면 디렉토리중 models 안에 있는 쿼리문을 실행하게 됩니다. 

실행하게 될 때 관리하는 파일은 dbt_project.yml 파일입니다.

 

dbt_project.yml은 어떤 SQL을 모델로 인식할지 정의하는 파일입니다. 

한 번 그 안에 구조를 자세히 들여다보면 다음과 같습니다.

name: 'learn_dbt'
version: '1.0.0'

# This setting configures which "profile" dbt uses for this project.
profile: 'learn_dbt'


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

clean-targets:         # directories to be removed by `dbt clean`
  - "target"
  - "dbt_packages"

models:
  learn_dbt:
    +materialized: view
    staging:
      +materialized: ephemeral
    marts:
      +materialized: table

 

name: 'lean_dbt' 

프로젝트 이름이며 로우케이스로 만들 수 있으며 언더스코어만 연결을 할 수 있습니다.

 

version: '1.0.0'

버전을 나타내고 있습니다. 패키징을 하거나 릴리즈 할 때 사용할 수 있고 Git을 사용해서 컨트롤 할 수 있습니다.

 

profile: 'learn_dbt' 

여러가지 프로파일이 있을 수 있는데 profiles.yml에 적힌 learn_dbt에 나온 타겟 스키마를 적을 수 있습니다.

 

model-paths: ["models"]

models에 나와있는 디렉토리를 dbt-run에 실행시키면 실행되는 파일들이 존재하고 있습니다.

models 밑에 특정폴더, 파일만을 실행 시킬 수 있고 특정 모델만 실행이 가능합니다.


analysis-paths: ["analyses"]

Ad-hoc SQL 관련된 폴더 입니다. dbt가 실행하지는 않지만, 프로젝트 안에서 관리하고 싶은 SQL을 두는 공간입니다.

DW에 남기지 않는 SQL로 탐색, 기준 검증용, 모델로 만들기 애매한 쿼리일때 관리를 하고 있습니다

dbt compile로 컴파일만 가능하며

target/comiled/... 에서 SQL 생성하고 있습니다.

 

models 와  analyses 분리하는 이유는

공식 결과물과 실험용 SQL을 섞지 않기 위해서 입니다. 

models = 회사 공식 데이터

anlyses = 개인/팀 분석

 

test-paths: ["tests"]

데이터 품질을 자동으로 검증하는 곳입니다. analyses 가 수동으로 확인하는 SQL이라면 tests/ 는 파이프라인이 돌 때 자동으로 실패 성공을 판단하는 규칙입니다.


seed-paths: ["seeds"] 

csv 파일 로드할 때 사용하는 디렉토리입니다.


macro-paths: ["macros"]

reusable 함수들을 저희가 매크로 디렉토리 안에다가 넣어서 사용할 수 있습니다.


snapshot-paths: ["snapshots"]

스냅샷은 디멘젼 로직이 바뀌는것을 넣어놓는 곳이라고 생각하면 됩니다.

 

clean-targets:         # directories to be removed by `dbt clean`
  - "target"
  - "dbt_packages"

dbt run을 사용하게 되면 컴파일 디렉토리가 있는데 그 디렉토리를 지우는 경로를 뜻합니다.

 

models:
  learn_dbt:
    +materialized: view

learn_dbt에 있는 모든 SQL은 view로 만든다고 보면 됩니다.

 

 

 

 

DataLake

DataLake는 가공되지 않은 데이터를 한곳의 스토리지 시스템에 저장하는 것

  • 구조적인 데이터, 조금 구조를 변경한 데이터, 아예 변경하지 않은 데이터를 지원하고
  • 데이터를 읽을 때 스키마 체크를 합니다.
  • 저렴하고 확장가능한 스토리지
  • 주로 데이터 엔지니어, 데이터 사이언티스트, ML 엔지니어들이 주로 사용합니다.

 

주로 Data Lake에는 다음과 같은 데이터들을 저장하고 있습니다.

  • JSON 포맷으로 된 Log나 csv 파일
  • parquet 파일들
  • 이미지, 비디오
  • 클릭 스트림 이벤트

이러한 데이터들은 머신러닝이나, EDA, 로그분석, 데이터 파이프라인 초입부에 사용합니다.

 

왜 바로 데이터를 가공하지 않고 저장하는걸까요?

우리는 데이터를 바로 어디에 쓸지 알수도 있지만 데이터를 언제 어떻게 사용할지 모를 경우가 존재합니다.

머신러닝 학습을 위한 데이터로 쓸 수 있고, 분석 데이터 활용시에도 사용할 수 있습니다.

그렇기 때문에 데이터레이크는 "지금 무엇을 쓸지 모르는 데이터를 미래의 질문을 위해 그대로 보존하기 위해"필요하게 됩니다.

 

  1. 원천 데이터를 그대로 저장하고 있습니다.
    • 지금은 의미가 없는 데이터들일 수 있습니다. 예를 들면 로그 이벤트, 스키마가 불분명한 데이터, 외부 공공데이터 등 하지만 이런것들이 추후 정의에 따라 의미있는 데이터로 바뀔 가능성이 있습니다.
  2. 기준이 바뀌는 현실에 대응을 할 수 있습니다.
    • 테이블이 바뀌거나 기준일자를(yyyy-mm-dd에서 yyyy-mm) 변경하거나 과거, 현재 데이터를 모두 저장하고 있어 대응을 빠르게 할 수 있습니다.
  3. 팀이 달라도 같은 원천을 쓰게 할 수 있습니다.
    • 같은 데이터를 사용하게 하고 AI는 feature 데이터로, BI팀은 지표로, 서비스팀은 통계로 사용하게 하여 원천은 하나로 해석은 각자하도록 할 수 있습니다.
  4. 비용과 확장성
    • 데이터 레이크는 값이 저렴합니다. 또한 무한 확장이 가능하고 컴퓨트와 분리가 가능합니다. 그렇기 때문에 쓸지 말지 고민하지말고 일단 쌓고 생각하자가 가능해지게 됩니다.
  5. AI/ML 시대의 전재조건
    • 가공된 데이터를 사용하게 되면 되돌리기 어렵고 의미가 변질될 수 있기 때문에 원천데이터 확보가 중요합니다. 또한 feature정의는 실험대상이기 때문에 언제든 되돌릴 수 있는 원본이 중요하니다.

 

dbt에 Data Lake가 중요한 이유

 

  • dbt는 "원천을 건드리지 않는다" 는 전제가 있습니다.
    • dbt는 데이터를 수집, 저장하는 도구가 아닙니다. 어딘가에 안전하게 저장되어있고 SQL로 의미를 만드는 도구입니다.
  • ELT의 출발점이 데이터 레이크입니다.
    • dbt = ELT의 T(Transform) 담당하고 있습니다. 그렇기 때문에 EL 단계에서 정의없이 쌓아둘 곳이 필요한 것이고 그것이 데이터레이크입니다. 레이크가 없으면 기준을 미리 정해야하고, 기준이 바뀌면 다시 수집을 해야하고, dbt의 장점(재가공, 기준 변경)이 반감됩니다. 레이크가 존재하면 데이터를 다시 되돌릴 수 있습니다.
  • 여러 부서들이 동시에 dbt 결과를 쓰는 이유입니다.
    • dbt는 레이크에 있는 같은 원천을 팀마다 다른 해석이 아니라 공식 기준을 고정해 주는 역할을 하고 있습니다.
Kafka / API
   ↓
Data Lake (raw)
   ↓
DW
   ↓
dbt (공식 모델)
   ↓
BI / AI / 리포트

 

 

데이터 레이크는 dbt의 '전제 조건' 이고 dbt는 데이터 레이크를 '쓸 수 있게 만드는 도구' 입니다.

 

 


 

Data Warehouse

데이터웨어하우스는 분석 및 보고에 최적화된 처리, 정제 및 구조화된 데이터입니다.

  • 변환 및 선별된 데이터를 잘 맞게 저장하게 됩니다.
  • 스키메아 딱 맞게 들어가야 하기 때문에 schema-on-write 입니다. 데이터를 쓸때 스케마가 필요한 것입니다.
  • 데이터를 읽어올 때 빠른 SQL에 최적화 되어있습니다.
  • 분석, BI툴, 비즈니스 유저에 사용합니다.

데이터웨어하우스에는 팩트 테이블(Fact Table) 즉 양적 데이터들이 존재합니다.

  • BI 데이터
  • 대쉬보드 리포팅 데이터
  • KPI 트래킹
  • Ad-hoc SQL 분석데이터

fact 데이터이기 때문에 유저에 대한 정보와 여러가지 데이터를 숫자로 나열되어 있습니다. 그렇기 때문에 데이터 양이 방대합니다.

 

Fact Table

팩트테이블은 양적이고 측정 데이터 즉 보고용 데이터가 나열되어 있습니다.

자와 메트릭을 포함하고 있고, 매우 크고, 비즈니스 이벤트를 표현하고 있고 demension 테이블과 조인하여 분석하게 됩니다.

 

 

 

 

 

dbt에서의 DW(Data Warehouse) 중요한 이유

 

앞서 dbt = ELT의 T를 담당한다고 설명하였습니다.

다시 T에 대해 정의하면 dbt는 DW 안에서 SQL을 실행해 Transform만 하는 것입니다.

그렇기 때문에 DW가 강하면 raw를 많이 넣어도, 복잡한 집계도 안정적이고, 기준 변경 시 재가공이 빠릅니다.

 

dbt의 성능 = DW의 성능

 

dbt는 DW의 연산력을 전제로 합니다.

ETL이 아니라 ELT를 쓰는 이유는

Transform을 DW 밖에서 하지 않고, DW안에서 SQL로 끝내기 위함입니다.

 

dbt 모델 계층은 DW 설계 언어입니다.

raw -> stg -> fct/dim -> mart

 

  • raw: 원천에 가까운 적재(읽기 중심)
  • stg: 타입/컬럼 정리
  • fct/dim: OLAP 모델의 핵심
  • mart: BI/AI가 바로 쓰는 공식 결과

DW가 있어야 이런 계층을 물리 테이블/뷰로 안정적으로 운영하고 동시 접근에도 성능을 유지할 수 있습니다.

 

DW는 dbt의 안전장치입니다.

  • Time Travel / 재현: 과거 상태로 조회
  • 증분 처리: 대용량도 빠르게 업데이트
  • 동시성 격리: 여러 팀 쿼리에도 안정

그래서 dbt의 장점인:

  • 기준 변경
  • 재처리
  • 비교 분석
    운영 리스크 없이 가능해짐.

 

앞선 내용들을 크게 정리해보면

 

데이터레이크는 원천 보관까지 가능하고
DW가 있어야 분석/집계/공식화가 가능하며 
dbt는 DW가 있을때 진가를 발휘하게 됩니다.

 

DBT에 들어가기 앞서서 데이터파이프라인에 대한 정리를 짚어보려고 합니다.

 

데이터 파이프라인

데이터 파이프라인은 차례대로 전달해 나가는 데이터로 구성된 시스템 입니다.

여러가지 소스에서 데이터를 수집(추출)하고 작업을 위해 데이터를 변형하여 데이터 저장소에 모든 데이터를 저장하는 것을 데이터파이프라인의 과정이라고 생각하면 됩니다.

데이터 파이프라인은 어디에서 데이터를 수집하고 어디에 쓰일지(목적)에 따라서 그 구성이 바뀝니다.

나중에 얘기 할 ETL, ELT 다시 다뤄보려고 합니다.

 

먼저 여러가지 소스 데이터를 수집(추출)한다고 했습니다.

여러가지 소스 데이터는 원천 데이터라고도 불립니다.

 

원천데이터(Source Data)는 '정보의 출처가 되는 초기 데이터'로 어떠한 가공되지 않은 날 것의 데이터라고 보면 됩니다.

원천데이터로는 많은 것들이 있지만

1. 어플리케이션에서 사용되는 데이터베이스 이벤트들

2. 로그나 이벤트 로그

3. 마케팅에서 사용되는 고객 행동데이터

4. JSON, XML 

 

많은 원천 데이터들이 있지만 이 정도로 요약해보겠습니다. 

원천 데이터들을 그대로 쓸 수 없기 때문에 정제된 데이터들을 테이블에 저장을 하게 됩니다.

 

 

데이터파이프라인의 문제 발생

 

하지만 데이터 파이프라인은 종종 문제가 발생 할 경우가 있습니다.

회사에서는 매우 다양한 부서들이 존재합니다. 이러한 부서들이 데이터를 사용하는 기준들은 다 동일할까요?

 

예시 상황

과거에 AI 부서, 마케팅 부서는 최근 주문 기준을 7일자 기준으로 동일하게 보고 있었습니다.

그럼 동일하게 해당 쿼리를 사용하게 될 것 입니다.

select count(*) 
from orders
where status = 'COMPLETE'
  and order_date >= current_date - interval '7 day'

 

하지만 마케팅 부서에서 

마케팅 부서 : 저희는 주문 데이터를 최근 주문 기준을 14일자 기준으로 보겠습니다.

 

마케팅 부서가 사용하는 쿼리가 변경되었습니다.

select count(*) 
from orders
where status = 'COMPLETE'
  and order_date >= current_date - interval '14 day';

 

하지만 AI부서는 그 상황을 모르고 7일자 기준으로 데이터를 사용하고 있을 것입니다. 

 

대시보드 숫자(마케팅) != 모델 숫자(AI) 

 

데이터가 맞지 않는 현상이 발생합니다.

 

한가지 더 예시를 들어보겠습니다.

select *
from orders o
join users u on o.user_id = u.id;
select *
from orders o
left join users u on o.user_id = u.id;

 

사용자 탈퇴 정책 변경

한쪽은 inner, 한쪽은 left join 하는 경우가 발생한다면 데이터 차이가 발생 할 수 있습니다.

 

 

dbt를 사용하게 되는 경우

 

dbt에서는 이것의 해결책으로 사용됩니다.

공식적으로 사용하는 쿼리를 관리를 하고 파생 쿼리는 추가적으로 관리를 합니다.

 

하나의 공통적인 정의되는 쿼리를 관리합니다.

-- fct_orders.sql (공통 사실 테이블)
select
  order_id,
  order_date,
  amount,
  status,
  refunded
from raw_orders
where status in ('PAID','COMPLETE');

 

'매출은 이 테이블을 보세요' 로 공식 테이블을 명시합니다.

 

그럼 부서별로 차이나는 부분들을 어떻게 관리하는지에 대한 의문이 발생합니다.

그건 "파생 모델"로 분리합니다.

 

부서별 기준은 '파생 mart' 로 분리

 

-- 영업팀 기준

-- mart_sales_revenue.sql
select
  order_date,
  sum(amount) as revenue
from {{ ref('fct_orders') }}
where refunded = false
group by order_date;

 

-- 마케팅팀 기준

-- mart_marketing_revenue.sql
select
  order_date,
  sum(amount) as revenue
from {{ ref('fct_orders') }}
group by order_date;

 

같은 기반(fct_orders) 을 사용합니다. 

 

이게 왜 중요할까요?

 

1. "다름" 이 코드로 명시되어있습니다.

  • 영업팀은 환불 포함이구나가 보입니다.

2. 책임 소재가 명확해집니다.

  • 숫자가 다르면 기준이 다르다고 설명이 가능합니다.

3. 변경 영향 최소화

  • 공통 기준 변경 -> 모든 mart 반영
  • 부서 기준 변경 -> 해당 mart만 수정

 

dbt는 의견 차이를 안전하게 공존시키는 도구라고 생각하면 됩니다.

통합은:

  • 기반 데이터
  • 정의의 출발점

차이는:

  • 파생 모델
  • 의도적으로 관리

dbt는 docs로 정의 노출 "왜 바뀌었는지"를 남김니다.

1) 컬럼 설명을 하고 2) 기준 설명을 하고 3) 변경 이력을 관리합니다.

 

dbt는 기준이 반영된 결과만 전달하게 됩니다. 

 

dbt는 ETL이 아니라 ELT를 제대로 운영하게 만들어 주는 도구입니다.

ETL과 ELT는 무엇일까요?

 

 

ETL(Extract, Transform, Load)

ELT(Extract, Load, Transform)

순서가 다릅니다. 

 

ETL은 데이터를 추출하고(Extract), Spark를 이용해 데이터를 가공(Transform)해서 그 결과값을 DW(data warehouse)에 넣게됩니다. (Load)

Spark 안에서 SQL을 사용하기 때문에 스키마를 Transform 단계에서 사용하는 경우가 많습니다.

데이터를 사용하는 입장에서 Spark안에 고정되어있기 때문에 '유연성'이 떨어집니다.

그럼 다시 변형하기 어렵고 변형하면 다시 배포를 해야하고 비용이 너무 크게 듭니다.

 

ETL의 문제는 정리하자면

  • 바꾸는데 오래 걸립니다.
  • 엔지니어링 비용이 크게 듭니다.
  • 분석에 대한 유연성이 떨어집니다.

ELT는 데이터를 추출하고(Extract), 데이터를 바로 DW에 Load 합니다. 그 다음에 Transform 하는 방향으로 바뀌는것입니다.

 

분석하는 입장에서는 바로바로 쿼리를 통해 데이터를 받을 수 있습니다.  데이터웨어하우스 같은 엔진들이 성능이 매우 좋아졌기 때문에 바로바로 SQL을 돌려 확인이 가능합니다. 가격 또한 저렴해졌습니다.

  • 유연성이 높아집니다. 
  • 스토러지 비용이 싸졌습니다.
  • 빨리 바꿀 수 있습니다.

dbt는 DW 안에서  T할때 SQL 을 사용하면서 최적의 검증을 할 수 있도록 도와주는 도구입니다.

  • dbt는 T 레이어를 관리한다고 보면 됩니다.
  • 기준이 되는 변형을 관리하게 됩니다.
  • 테스트도 다큐멘테이션도 최적의 예측이 가능합니다.
  • 코드  재사용성이 높습니다. 

 

그럼 ELT를 무조건 써야할까요?

그건 NO 입니다.

 

1. 부서 규모가 작은 경우

  • 데이터를 쓰는 사람이 적거나
  • "각 부서 기준" 같은 이슈가 거의 없거나
  • 커뮤니케이션 비용이 낮음

-> 기준을 통합할 필요가 적습니다.

 

2. 가공 로직이 거의 안 바뀐다.

  • 파싱 -> 정합성 -> 집계
  • 로직이 몇 달 ~ 몇 년 고정

-> Load 먼저의 장점이 없을 때 

 

3. 데이터 목적이 명확한 경우

-> "공식 지표가 여러 개" 가 필요 없는 경우

 

4. DW가 단순 저장소에 가까운 경우

  • OLAP 성능 기대 안하는 경우

 

ELT/dbt가 오히려 과하게 느껴지게 됩니다.

  • 모델 계층 나누느라 파일 수 늘어남
  • 컴파일/실행 루프 늘림
  • 협업 오버헤드 발생

작은 조직에서는 과설계일 수 있습니다.

ETL vs ELT는 조직과 변화 빈도의 문제의 관점으로 바라보면 좋을 거 같습니다. 

 

ELT는 언제 적용하면 좋을까요

위와 반대되는 상황으로 

1. 부서가 늘어나 데이터 변화 빈도가 늘어나거나 

2. 데이터 변경 이력이 중요해질때 

 

 

사용하는것을 추천합니다. 

 

 

 

'BigData' 카테고리의 다른 글

[dbt] Data Lake vs Data Warehouse  (0) 2026.01.26

 

문제 설명

ANIMAL_INS 테이블은 동물 보호소에 들어온 동물의 정보를 담은 테이블입니다. ANIMAL_INS 테이블 구조는 다음과 같으며, ANIMAL_ID, ANIMAL_TYPE, DATETIME, INTAKE_CONDITION, NAME, SEX_UPON_INTAKE는 각각 동물의 아이디, 생물 종, 보호 시작일, 보호 시작 시 상태, 이름, 성별 및 중성화 여부를 나타냅니다.

 

ANIMAL_ID VARCHAR(N) FALSE
ANIMAL_TYPE VARCHAR(N) FALSE
DATETIME DATETIME FALSE
INTAKE_CONDITION VARCHAR(N) FALSE
NAME VARCHAR(N) TRUE
SEX_UPON_INTAKE VARCHAR(N) FALSE

 

ANIMAL_OUTS 테이블은 동물 보호소에서 입양 보낸 동물의 정보를 담은 테이블입니다. ANIMAL_OUTS 테이블 구조는 다음과 같으며, ANIMAL_ID, ANIMAL_TYPE, DATETIME, NAME, SEX_UPON_OUTCOME는 각각 동물의 아이디, 생물 종, 입양일, 이름, 성별 및 중성화 여부를 나타냅니다. ANIMAL_OUTS 테이블의 ANIMAL_ID는 ANIMAL_INS의 ANIMAL_ID의 외래 키입니다.

 

ANIMAL_ID VARCHAR(N) FALSE
ANIMAL_TYPE VARCHAR(N) FALSE
DATETIME DATETIME FALSE
NAME VARCHAR(N) TRUE
SEX_UPON_OUTCOME VARCHAR(N) FALSE

천재지변으로 인해 일부 데이터가 유실되었습니다. 입양을 간 기록은 있는데, 보호소에 들어온 기록이 없는 동물의 ID와 이름을 ID 순으로 조회하는 SQL문을 작성해주세요.

예시

예를 들어, ANIMAL_INS 테이블과 ANIMAL_OUTS 테이블이 다음과 같다면

ANIMAL_INS

ANIMAL_ID ANIMAL_TYPE DATETIME INTAKE_CONDITION NAME SEX_UPON_INTAKE

A352713 Cat 2017-04-13 16:29:00 Normal Gia Spayed Female
A350375 Cat 2017-03-06 15:01:00 Normal Meo Neutered Male

ANIMAL_OUTS

ANIMAL_ID ANIMAL_TYPE DATETIME NAME SEX_UPON_OUTCOME

A349733 Dog 2017-09-27 19:09:00 Allie Spayed Female
A352713 Cat 2017-04-25 12:25:00 Gia Spayed Female
A349990 Cat 2018-02-02 14:18:00 Spice Spayed Female

ANIMAL_OUTS 테이블에서

  • Allie의 ID는 ANIMAL_INS에 없으므로, Allie의 데이터는 유실되었습니다.
  • Gia의 ID는 ANIMAL_INS에 있으므로, Gia의 데이터는 유실되지 않았습니다.
  • Spice의 ID는 ANIMAL_INS에 없으므로, Spice의 데이터는 유실되었습니다.

따라서 SQL문을 실행하면 다음과 같이 나와야 합니다.

 

 

 


접근 방법

 

POINT. 이 문제를 풀때 가장 먼저 떠올려야 할 포인트는 OUTER JOIN 입니다. 

 

1. ANIMAL_OUTS 테이블에는 데이터가 있고 ANIMAL_INS 테이블에는 데이터 없는 ROW를 찾아야 합니다. 

    - ANIMAL_OUTS 기준으로 OUTER JOIN을 하여 ANIMAL_INS에 없는 데이터를 찾아보려 합니다. 

SELECT outs.ANIMAL_ID, ins.ANIMAL_ID, outs.NAME, ins.NAME
FROM ANIMAL_OUTS outs
LEFT OUTER JOIN ANIMAL_INS ins
ON outs.ANIMAL_ID = ins.ANIMAL_ID

 

2. 그럼 ANIMAL_INS 없는 데이터가 어떤것이 있는지 파악이 가능합니다. 그럼 답에 맞게 쿼리문을 정리해주면 됩니다.

SELECT outs.ANIMAL_ID, outs.NAME
FROM ANIMAL_OUTS outs
LEFT OUTER JOIN ANIMAL_INS ins
ON outs.ANIMAL_ID = ins.ANIMAL_ID
WHERE ins.ANIMAL_ID IS NULL
ORDER BY outs.ANIMAL_ID

최종 쿼리

SELECT outs.ANIMAL_ID, outs.NAME
FROM ANIMAL_OUTS outs
LEFT OUTER JOIN ANIMAL_INS ins
ON outs.ANIMAL_ID = ins.ANIMAL_ID
WHERE ins.ANIMAL_ID IS NULL
ORDER BY outs.ANIMAL_ID

 

문제 설명

다음은 어느 의류 쇼핑몰에서 판매중인 상품들의 상품 정보를 담은 PRODUCT 테이블과 오프라인 상품 판매 정보를 담은 OFFLINE_SALE 테이블 입니다. PRODUCT 테이블은 아래와 같은 구조로 PRODUCT_ID, PRODUCT_CODE, PRICE는 각각 상품 ID, 상품코드, 판매가를 나타냅니다.


PRODUCT_ID INTEGER FALSE
PRODUCT_CODE VARCHAR(8) FALSE
PRICE INTEGER FALSE

상품 별로 중복되지 않는 8자리 상품코드 값을 가지며, 앞 2자리는 카테고리 코드를 의미합니다.

OFFLINE_SALE 테이블은 아래와 같은 구조로 되어있으며 OFFLINE_SALE_ID, PRODUCT_ID, SALES_AMOUNT, SALES_DATE는 각각 오프라인 상품 판매 ID, 상품 ID, 판매량, 판매일을 나타냅니다.


OFFLINE_SALE_ID INTEGER FALSE
PRODUCT_ID INTEGER FALSE
SALES_AMOUNT INTEGER FALSE
SALES_DATE DATE FALSE

동일한 날짜, 상품 ID 조합에 대해서는 하나의 판매 데이터만 존재합니다.

 

문제

PRODUCT 테이블과 OFFLINE_SALE 테이블에서 상품코드 별 매출액(판매가 * 판매량) 합계를 출력하는 SQL문을 작성해주세요. 결과는 매출액을 기준으로 내림차순 정렬해주시고 매출액이 같다면 상품코드를 기준으로 오름차순 정렬해주세요.

 

각 상품 별 총 판매량과 판매가는 다음과 같습니다.

  • PRODUCT_CODE 가 A1000011인 상품은 총 판매량이 6개, 판매가가 15,000원
  • PRODUCT_CODE 가 A1000045인 상품은 총 판매량이 2개, 판매가가 8,000원
  • PRODUCT_CODE 가 C3000002인 상품은 총 판매량이 3개, 판매가가 42,000원

그러므로 각 상품 별 매출액을 계산하고 정렬하면 결과가 다음과 같이 나와야 합니다.

   
PRODUCT_CODE SALES
C3000002 126000
A1000011 90000
A1000045 16000

 

 


접근 방법 

POINT. 상품 별 매출액을 계산하는 문제로 상품 별로 팔린 상품 갯수를 어떻게 다루는지가 중요합니다.

 

1. OFFLINE_SALE 테이블에서 PRODUCT_ID 별로 SALES_AMOUNT 합계를 구합니다.

   - OFFLINE_SALE_ID 기준으로 생성된 데이터로 PRODUCT_ID는 중복이 존재합니다.  

   - 따라서 합계를 구하기 위해 GROUP BY 합니다. 

SELECT SUM(s.SALES_AMOUNT) 
FROM OFFLINE_SALE s 
GROUP BY s.PRODUCT_ID

 

2. 그럼 매출액을 구하기 위해 PRODUCT 테이블과 JOIN이 필요합니다. 

   - 이후 PRODUCT 테이블의 PRICE 칼럼과 총 갯수와 곱을 구하면 매출액을 구할 수 있습니다.

SELECT p.PRODUCT_CODE,
       SUM(s.SALES_AMOUNT) * p.PRICE AS SALES
FROM OFFLINE_SALE s JOIN PRODUCT p 
ON s.PRODUCT_ID = p.PRODUCT_ID
GROUP BY s.PRODUCT_ID

 

3. 문제에서는 '매출액을 기준으로 내림차순 정렬해주시고 매출액이 같다면 상품코드를 기준으로 오름차순 정렬해주세요.'

조건이 있기 때문에 ORDER BY가 필요합니다.

SELECT p.PRODUCT_CODE,
       SUM(s.SALES_AMOUNT) * p.PRICE AS SALES
FROM OFFLINE_SALE s JOIN PRODUCT p 
ON s.PRODUCT_ID = p.PRODUCT_ID
GROUP BY s.PRODUCT_ID
ORDER BY SALES DESC, PRODUCT_CODE ASC

 

 


최종

SELECT p.PRODUCT_CODE,
       SUM(s.SALES_AMOUNT) * p.PRICE AS SALES
FROM OFFLINE_SALE s JOIN PRODUCT p 
ON s.PRODUCT_ID = p.PRODUCT_ID
GROUP BY s.PRODUCT_ID
ORDER BY SALES DESC, PRODUCT_CODE ASC

'코딩테스트 > 프로그래머스' 카테고리의 다른 글

[SQL/JOIN] 59042. 없어진 기록 찾기  (0) 2026.01.03

MLOps는 ML Life cycle을 체계적으로 관리하여 더 빠르고 신뢰할 수 있는 결과를 달성하는데 초점을 두고 있습니다.

MLOps는 강력한 인프라에 의존하고 있으며

데이터처리, 모델 트레이닝, 배포 및 모니터링과 같은 핵심 작업을 지원하며 안정적으로 수행하는 것을 목표로 두고 있습니다.

 

MLOps의 주요 인프라요소는 크게 다음과 같이 나눌 수 있습니다.

  • Storage : 개발된 모델을 저장하거나 로깅들 ML과 관련된 모든것들을 저장한다고 생각하면 됩니다.
  • Computing Resources : 데이터와 관련된 계산에 필요한 컴퓨팅 파워를 제공합니다.
  • 환경관리툴 : 프로젝트별 독립적인 환경을 제공하는 패키지 및 환경관리 시스템이며 파이썬을 사용하는 분들이라면 Anacoda 생각하시면 됩니다.
  • Container : App과 그 의존성을 패키지화 화여 일관된 환경에서 실행 할 수 있도록 지원합니다
  • Orchestrator : 여러 컨테이너를 배포, 확장, 네트워킹을 관리 
  • CI/CD : 코드리뷰부터 배포를 자동화하는데 지원합니다.
  • Version Control : 모델의 버전 관리를 지원합니다.
  • HTTP & REST API : 모델 개발 후 사용할 수 있는 프로토콜과 인터페이스를 지원합니다.

MLOps 인프라는 생각보다 다양한 요소들이 있는데 

조금 더 세세하게 살펴보도록 하겠습니다.

 


Storage(스토리지)

데이터의 저장, 백업, 복구 기능을 제공합니다.

데이터의 안정성, 접근성 및 확장성을 보장하는 것이 핵심

 

중요성

  • 데이터 보존 : 머신러닝 프로젝트에서 데이터의 안전한 저장은 데이터 손실을 방지하고, 언제든 데이터에 대한 접근이 가능하도록 되어야 합니다.
  • 접근성 : 효율적인 데이터 접근은 머신러닝 모델의 트레이닝 테스트 시간을 단축, 빠른 데이터 접근은 프로젝트 전반적인 생산성을 향상시킵니다.
  • 확장성 : MLOps 프로젝트는 시간이 지남에 따라 데이터 양이 증가합니다. 스토리지는 확장가능하고 유연해야 합니다.

 

유형

클라우드 스토리지

Amazon S3, Google Cloud Storage, Azure Blob Storage

  • 확장성 : 거의 무한에 가까운 저장 공간을 제공하며 자유롭게 확장 가능한게 특징
  • 내구성과 가용성 : 데이터 복제 및 여러 지역에 걸친 분산 저장으로 높은 내구성 및 가용성을 보장
  • 안정성 : 고급 암호화 및 보안 프로토콜을 통해 데이터를 보호
  • 비용 효율성 : 사용한만큼만 비용을 지불, 다양한 저장 옵션을 제공

 

MLOps 예시

대규모 이미지 데이터셋을 S3버킷에 저장하여 머신러닝 모델 트레이닝에 활용

글로벌 머신러닝 파이프라인에서의 데이터 공유

 

분산 파일 시스템

Hadoop Distributed File System(HDFS), GlusterFS

  • 대규모 데이터 처리 : 여러 노드에 걸쳐 대규모 데이터를 분산 저장하고 처리
  • 고가용성 : 데이터를 여러 노드에 복제하여 하나의 노드에 문제가 발생해도 데이터 손실을 방지
  • 확장 가능한 아키텍쳐 : 데이터 양이 증가함에 따라 쉽게 노드를 추가하여 시스템 확장 가능
  • 비용 효율적 : 오픈 소스 솔루션을 사용하여 비용 절감 가능

 

MLOps 예시

대규모 빅 데이터 분석, 복잡한 데이터 처리 작업, 대용량 데이터의 실시간 처리 및 저장

 

데이터 웨어 하우스

Snowflake, Amazon Redshift, Google BigQuery

  • 고속 쿼리 실행 : 최적화된 쿼리 엔진을 통한 빠른 데이터 처리 및 분석
  • 대규모 데이터 분석 : 구조화된 대용량 데이터에 대한 효율적인 분석 및 저장
  • 사용 편의성 : SQL 기반 쿼리로 사용자 친화적
  • 보안과 규제 준수 : 데이터 보안 및 다양한 규제 준수 및 옵션 제공

 

MLOps 예시

비즈니스 인텔리전스, 대규모 데이터셋에 대한 복잡한 분석 및 리포팅

 

데이터 레이크

AWS Lake Formation, Azure Data Lake

  • 다양한 데이터 형식 지원 : 구조화되지 않은 데이터에서부터 구조회된 데이터까지 다양한 형식의 데이터 저장 및 관리
  • 유연한 데이터 처리 : 데이터 형식에 구애받지 않고 저장, 검색 및 분석 가능
  • 대규모 데이터 관리 : 데이터 레이크는 방대한 양의 데이터를 효과적으로 관리할 수 있는 능력을 가짐
  • 비용 효율성 : 사용한 만큼의 비용만 지불, 다양한 저장 옵션 제공
  • 데이터 통합 : 다양한 소스의 데이터를 하나의 위치에서 관리하고 분석

 

MLOps 예시

대규모 이미지 또는 비디오 데이터셋의 저장 및 분석, 글로벌 머신러닝 파이프라인에서의 데이터 공유

 

Storage와 MLOps

  • 데이터 준비 : Model Training를 위한 데이터 준비 및 전처리
  • Model Registery : 트레이닝된 Model 및 관련 파일 저장
  • Data Pipeline : 지속적인 데이터 업데이트와 Model Re-training 지원
  • 클라우드 기반 스토리지 활용 : 대기업에서는 AWS S3를 사용하여 전 세계적으로 분산된 데이터 센터에서 대량의 사용자 데이터를 저장 및 관리
  • 데이터 레이크를 통한 유연한 데이터 관리 : 데이터 레이크를 구축하여 다양한 형태의 거래 데이터를 효과적으로 관리하고 분석

 

Container

• 정의 : Container 는 애플리케이션과 그 필요한 모든 것(코드, 런타임, 시스템 도구, 시스템 라이브러리 등)을 포함하는 표준화된 단위 애플리케이션은 어떤 컴퓨팅 환경에서도 일관되게 실행될 수 있음
• 작동 원리 : Container는 운영 체제의 커널을 공유하며, 각 컨테이너는 서로 격리된 공간에서 실행. 이는 각 Container가 자체 파일 시스템을 가지고 있는 가벼운 ‘가상 환경’과 유사하다고 보면 된다.

 

• 독립된 실행 환경 : 애플리케이션과 그 종속성을 담은 격리된 환경
• 경량화 : 전체 Os를 가상화하지 않고 필요한 컴포넌트만 포함
• 이미지 기반 : 애플리케이션 실행에 필요한 모든 파일을 포함하는 이미지 기반

 

Container 필요성
환경 일관성 제공
• Container는 개발, 테스트, 생산 환경에서 동일한 소프트웨어 환경을 유지할 수 있게 해 줍니다. 이는 애플리케이션의 이식성을 증가시키고 환경에 따른 문제를 줄임

자원 효율성 증가
• Container 는 VM(가상 머신)보다 적은 리소스를 사용하여 더 많은 애플리케이션을 호스트할 수 있게 해 줍니다. 이는 하드웨어 비용을 줄이고, 자원 사용률을 최적화

배포 및 확장 용이성
• Container 는 배포와 확장이 용이하며, 빠른 시작과 중단이 가능합니다. 이는 CI/CD 파이프라인과 잘 통합되어 빠른 개발 및 배포를 가능

 

MLOps에서 Container 인프라
• MLOps에서의 중요성: 컨테이너는 MLOps의 핵심 구성 요소로 자리 잡음. 데이터 과학자와 엔지니어가 동일한 환경에서 작업할 수 있게 해 주며, 모델의 개발, 테스트, 배포 과정을 효율적으로 만듦.
• 효율성과 확장성: 컨테이너는 머신러닝 파이프라인의 효율성을 증가시키며, 클라우드 환경에서의 확장성을 제공. 이는 MLOps의 유연성과 속도를 증가시키는 데 기여

 


Orchestrator

 

다수의 Container를 조정하고 관리하는 시스템

-> 여러개의 작업을 함께 연결하여 크기가 큰 워크플로우나 프로세스를 실행하는 방식을 취함

컨테이너의 배포

스케일링 및 네트워킹을 자동화

 

목적 : 높은 가용성, 확장성 및 신뢰성을 가진 시스템을 구축하기 위해, Container화된 애플리케이션의 복잡한 작업을 간소화

 

중요성

1. 복잡성 관리

Orchestrator는 복잡한 서비스이 생명 주기를 관리하고, 여러 Container 간의 의존성을 조정

2. 자동화

자동화를 통해 수동 intervention 없이도 시스템을 안정적으로 운영가능

3. 확장성

사용량 증가에 따라 자동으로 리소스를 조정하고, 필요에 따라 서비스를 확장하거나 축소할 수 있음

4. 고가용성

서비스의 지속적인 가용성을 보장하며, 장애 발생 시 자동으로 복구해줌

 

프로세스 오케스트레이션 VS 프로세스 자동화

자동화와 오케스트레이션은 고도로 상호보완적이지만, 의미는 서로 다르다.

자동화는 사람이 개입할 필요 없이 작업이 실행되도록 프로그래밍하는 것이고 오케스트레이션은 여러 개의 작업을 하나의 종단간 프로세스나 작업으로 구성하는 것을 말한다. 

오케스트레이션은 프로세스 전체에 걸쳐 이벤트나 활동에 반응해야 하고, 한 가지 자동화된 작업에서 얻은 출력을 바탕으로 의사 결정을 내려 다음 작업을 판단하고 조율할 줄 알아야한다.

 

애플리케이션 오케스트레이션

두 개 이상의 소프트웨어 애플리케이션을 통합한 것. 프로세스 자동화 또는 데이터 실시간 동기화를 지원하기 위해 애플리케이션 오케스트레이션을 수행할 수 있다. 

 

서비스 오케스트레이션

여러 클라우드 공급업체 및 도메인에 걸쳐 있는 시스템을 조율하고 관리하도록 지원하기 때문에 애플리케이션 오케스트레이션과 유사하다.

오늘날 시스템의 조율과 관리는 필수적입니다. 이 접근법은 마이크로서비스 오케스트레이션, 네트워크 오케스트레이션, 워크플로 오케스트레이션을 포함하고 있다.

개별 서비스는 기본적으로 서로 통합될 수 있는 능력이 없으며 자체적인 종속성과 요구 사항이 있고 시스템이 복잡할수록 다양한 구성 요소를 오케스트레이션하는 것이 더욱 중요하다. 이를 통해 인프라를 확장하고 시스템을 최적화하고, 서비스 제공 실패를 방지할 수 있어야 한다.

 

컨테이너 오케스트레이션

컨테이너 관리와 조율을 자동화하는 것

 

클라우드 오케스트레이션

클라우드 오케스트레이션은 프라이빗 및 퍼블릭 클라우드에서 연결을 관리하는 작업을 자동화하는 프로세스

클라우드 오케스트레이션은 자동화된 작업과 프로세스를 특정 비즈니스 기능을 수행하는 데 도움을 주는 워크플로로 통합

 

 

컨테이너 오케스트레이션 툴

Kubernetes & Docker Swarm가 주요 툴

TO BE 툴에 대해 좀 더 상세히 알아보고 싶음

 

오케스트레이션 주요 기능

자동 배포 및 관리
• Orchestrator는 사용자가 정의한 설정에 따라 Container를 자동으로 배포하고, 실행

스케일링 및 로드 밸런싱
• 트래픽의 증가나 감소에 따라 자동으로 컨테이너 수를 조절

자동 복구 및 장애 대응
• 오류가 발생한 컨테이너를 자동으로 감지하고, 필요한 경우 복구 조치를 취함

서비스 발견 및 네트워킹
• Orchestrator는 컨테이너 간의 통신 및 서비스 발견을 관리

업데이트 및 롤백 관리
• 애플리케이션 업데이트를 안전하게 관리하고, 필요한 경우 이전 버전으로 롤백

 

 

 

 

 

 

ML Life Cycle

  • 머신러닝 모델을 개발, 배포, 유지보수하는 모든 단계를 정리하는 Life Cycle
  • 크게 다음과 같은 단계로 구분을 지을 수 있음

머신러닝 라이프 사이클 구성요소

  1. 데이터를 수집 & 준비 : Data Collection and Preparation
  2. 피처 엔지니어링 : Feature Enginnering
  3. 모델 엔지니어링 : Model Selection and Model Learning
  4. 모델 평가&튜닝 : Model Evaluation and Model Tuning
  5. 모델 배포 & 모니터링 : Deployment and Monitoring
  6. 재평가 및 모델 업데이트 : ReEvaluation and Model Update

ML을 다룰때 간과하고 있는 단계가 있다 그 단계는 5,6단계 모델 배포 & 모니터링 / 재평가 및 모델 업데이트 단계이다.

ML을 개발할 때 4번까지만 고려를 하는데 MLOps 입장에서는 5,6단계를 통해 모델을 더 안정화시킬 수 있으며 새로운 데이터가 들어오면서 모델이 편향될 경우 업데이트 재평가 및 업데이트 과정을 거치면 좀 더 개선된 모델을 만들어 낼 수 있다.

따라서 MLOps 공부를 하며 5,6번을 이번에 좀 더 주의깊게 살펴 볼 필요가 있다.

 

직무별 ML Life Cycle

데이터 엔지니어 : 데이터를 수집하고 머신러닝 모델을 개발하기에 적합하게 전처리를 하는 역할

데이터 사이언티스트 : 머신러닝 모델을 구축하고 데이터로 모델을 개발하는 역할

ML 엔지니어, 개발자 : 그 모델을 웹/앱에 implement하고, 그 product를 배포, 유지, 보수하는 일을 하는 역할

 


1. 데이터를 수집 & 준비 : Data Collection and Preparation

문제 정의 및 요구사항 -> Data 수집 -> EDA
  • 문제 정의 및 요구사항
    • 우리가 해결해야 할 문제를 위해 필요한 데이터가 무엇인가?
    • 우리가 해결하려는 문제는 무엇인가?
  • Data 수집
    • 다양한 소스로부터 데이터를 수집
    • 해당 데이터를 분석에 사용 가능한 형태로 정제 및 변환
  • EDA
    • 데이터의 핵심적인 특성 분포, 상관관계, 이상치 등을 조사하고 요약

2. 피처 엔지니어링 : Feature Engineering

EDA -> Feature Engineering
  • Feature Engineering
    • ML모델 구축 및 평가에 사용할 데이터를 준비 Encoding/Transformation/Sampling/결측치 처리 등이 포함

3. 모델 엔지니어링 : Model Selection과 Model Training

  • Model Selection
    • 데이터와 문제에 가장 적합한 모델 유형과 아키텍쳐를 선택
  • Model Training
    • 모델의 parameter를 최적화하도록 학습(MSE, Cross Entropy 등과 같은 loss 함수 기반)

5. 모델 배포 & 모니터링 : Model Deployment와 Monitoring

  • 최종 선택된 모델을 실제 Application으로 상품화 배포 진행
Model Integration -> Monitoring and Feedback -> Scaling and Maintenance
  • 모델 통합 : Model Integration
    • ML Model을 Application코드와 Database에 통합하는 과정
  • 모니터링 및 피드백 : Monitoring and Feedback
    • 모델 성능을 지속적으로 모니터링하고 사용자 피드백을 수집하여, 시스템을 시간이 지남에 따라 개선
  • 유지보수 : Scaling and Maintenance
    • 어플리케이션 소비자 증가(사용 증가)에 대응하기 위한 시스템 확장 및 데이터나 비즈니스 요구사항 변경에 따른 AI 모델 유지보수

6. 모델 재평가 및 업데이트 : Re Evaluation과 Model Update

ML LifeCycle은 배포로 끝나는 것이 아닌 실제로 모델을 정기적으로 재평가하고 업데이트하여 정확성과 관련성을 유지하는 것이 중요

Monitoring Feedback -> Re Evaluation -> Model Update
  • Monitoring Feedback 
    • 사용자로부터 모델 성능과 정확성에 대한 피드백을 수집
  • Re Evaluation
    • 새로운 데이터로 모델을 평가하여 모델 성능 저하를 감지
  • Model Update
    • 모델을 새로운 데이터 혹은 알고리즘 등으로 업데이트하여 정확성을 개선

ML LifeCycle에서 다양한 문제

 

ML LifeCycle은 배포로 끝나는 것이 아니다. 실제로 모델을 정기적으로 재평가하고 업데이트하여 정확성과 관련성을 유지하는 것이 중요

Re-Evaluation 과 Update을 고려해줘야한다.

 

데이터 보안 문제

데이터 보안 위협

  • 데이터 노출 : 머신러닝에서 사용되는 데이터는 민감한 정보를 포함할 수 있는데 노출이 될 경우 개인 정보 침해 등의 문제가 발생
  • 데이터 조작 : 공격자(해커)가 데이터를 조작가능
  • 데이터 유출 : 외부로 유출될 경우 악용될 우려가 있다

데이터 보안을 위한 대책

  • 데이터 암호화 : 데이터를 암호화하여 외부로부터 보호
  • 데이터 분할 : 머신러닝에 사용되는 데이터를 여러 분산 시스팀에 나눠서 저장
  • 접근 제어 : 머신러닝 데이터에 대한 접근을 제한하여 외부로부터 보호
  • 로그 관리 : 데이터에 대한 접근 기록을 감시하여 외부 침입 시 신속한 대응

윤리적 문제

Bias와 Fairness

  • 데이터나 모델에서의 bias는 모델 accuracy와 fairness(공정성)에 영향을 미침
    • 예) 인종이나 성별 등 특정 인구 그룹에 대한 편견이나 차별성이 모델에 내재될 수 있음
  • 이를 위해 모델 데이터를 검토하고, 균형있는 데이터를 수집, 모델을 학습시키기 전에 데이터를 균형있게 조정하는 것이 필요
  • 모델의 공정성을 평가하기 위해 다양한 fairness metric을 사용할 수 있음

데이터 개인정보 보호

  • ML 개발을 위해 수집된 데이터는 개인정보일 가능성이 높아 익명성 또는 적절한 보안 처리를 해야함
  • 데이터 수집 및 사용시 관련 법규와 윤리적 지침을 준수해야함

신뢰도 문제

모델 해석성

  • 일부 ML 모델은 해석이 어려워, 모델의 예측 결과를 설명하기 어려움
  • 이로인해 ML 모델의 신뢰성에 대한 의구심을 불러 일으키거나, 올바르지 않은 결정을 내릴 수 있게함
  • 이를 해결하기 위해 모델을 설명 가능한 방식으로 개발하거나, 모델 결정 과정을 시각화하는 것이 필요

데이터 소스의 신뢰성

  • ML 모델의 성능과 결과는 모델이 학습한 데이터 소스의 신뢰성에 크게 영향을 받음
  • 만약 데이터 소스가 품질이 낮거나 편향되어 있다면, 모델 성능이 하락하거나 잘못된 결론을 내릴 수 있음
  • 이를 해결하기 위해, 데이터 소스의 품질을 검증하고 데이터를 다양한 소스에서 수집하며 적절한 데이터 전처리를 수행하는 것이 중요

ML System

  • 데이터 분석, 모델 훈련, 예측 생성 등을 포함하는 시스템
  • 머신러닝 모델과 관련된 어플리케이션 및 도구의 집합
  • 특정 비즈니스 문제를 해결하기 위해 데이터를 분석하고 학습하여 예측 모델을 제공

단순히 좋은 머신러닝 모델만으로 시스템을 운영할 수 없다. 모델이 핵심이기는 하나 프로덕션ML 시스템의 운영을 고려한다면 모델을 운영하기 위한 기반 데이터와 인프라를 포함한 모든 시스템이 유기적으로 돌아가야 한다.

 

주요 구성 요소

  • 데이터 수집 및 처리
  • 모델 개발 및 훈련
  • 예측 및 추론 메커니즘
  • 사용자 인터페이스 및 API

 

ML System은 ML Life Cycle을 모두 고려하지 않는다.

  • 시스템은 특정 머신러닝 모델의 구현과 기능에 초점을 마주지만, 모델 전체 생명 주기를 관리 최적화에는 초점이 많이 잡혀있지 않음
  • 시스템은 모델이 실제로 수행하는 작업과 관련이 있으며 특정 시점에 구축된 모델을 기반으로 함

-> ML System은 ML Life Cycle에서의 모니터링, 지속적인 모델 업데이트/지속적 배포, 신뢰성 관리 등은 고려되지 않음

 


MLOps란 무엇인가 

 

상세설명

  • MLOps는 전체적인 ML Life Cycle과 관련된 프로세스를 통합 -> 상품화 ML에 집중
  • 데이터 수집, 모델 구축 및 학습, 모델 배포, 모델 모니터링, 유지보수 관리, 피드백 관리, 리소스 관리 등이 포함
  • MLOps는 이러한 작업들을 자동화하고 표준화화여, 모델 개발 주기와 배포 주기를 빠르게 하고, 이를 안정적으로 운영할 수 있도록 지원
  • MLOps는 Machine Learning 모델을 적용하고 운영하는 방법을 혁신적으로 변화시킴
    • 과거 : 모델이 학습되고 배포되는 것에 집중
    • 현재 : 모델이 운영되는 시스템을 안정적으로 운영하고 유지보수 하기 위한 작업이 중요시됨
  • ML System보다는 더 많은 것을 다루는 것이 MLOps
ML System 비교 사항 MLOps
데이터 분석, 모델 훈련, 예측 생성 등을 포함하는 시스템 정의 머신러닝 모델의 개발, 배포 및 운영을 최적화하는 방법론 및 관행
특정 머신러닝 모델의 구현과 기능 초점 모델의 전체 생명주기 관리 및 최적화
데이터 처리, 모델 훈련, 예측 및 추론, 사용자 인터페이스 주요 구성 요소 ML System의 구성요소 + 모델 버전 관리, 자동화된 테스트 및 배포, 성능 모니터링
비즈니스 요구사항을 충족하는 데이터기반 예측 제공 목적 머신러닝 모델의 신속한 개발 및 안정적 운영지원
머신러닝 모델과 관련된 작업을 포함 공통점 머신러닝을 비즈니스 프로세스를 통합하려는 목표 공유
구체적인 머신러닝 모델 작업에 초점
한 번의 구축에 초점을 맞춤
차이점 지속적인 통합, 배포 및 모니터링에 초점을 맞춤

 

MLOps의 필요성

  • ML 학습 모델을 개발하고 배포하고 관리하는 전체 프로세스를 자동화하고 최적화하기 위해 필요
  • 기계학습 모델의 신뢰성 확보 : MLOps을 통해 모델의 품질을 높일 수 있다. 기계학습은 데이터와 알고리즘에 의존하기 때문에 데이터의 품질 문제나 알고리즘 오류로 부정확한 결과를 받을 수 있지만 MLOps을 통해 예방하고 모델 신뢰성 확보가 가능함
  • 빠른 개발과 배포 : MLOps을 통해 개발자는 데이터 처리, 모델 훈련 및 모델 배포 등의 프로세스를 자동화, CI/CD 파이프라인 구축하여 머신러닝 모델을 더욱 빠르게 개발하고 배포가능
  • 재현성과 확장성 : MLOps는 데이터와 모델의 버전 관리, 코드의 수정 내역을 관리하여, 모델의 재현성을 보장할 수 있음
  • 비용 절감 : 모델을 빠르게 개발하고 배포하면서 비용을 절감할 수 있음. MLOps를 사용하면 인력, 시간, 자원 등의 비용을 줄일 수 있으며 모델 성능 개선을 더욱 많은 비즈니스 가치 창출이 가능

 

MLOps의 핵심기능

자동화된 빌드, 테스트 및 배포, 모델 최적화 -> 버전 관리와 협업 -> 데이터 관리 및 모니터링
-> 성능 모니터링 및 로깅 -> 보안 및 규정 준수

데이터 관리 및 처리

  • 기능 : 데이터 수집, 저장, 전처리 및 관리
  • 예시 : Data Engineer가 매일 웹사이트에서 사용자 행동 데이터를 수집하여 클라우드 기반 데이터 웨어하우스에 저장. 이 데이터는 Data Scientist에 의해 필요한 형식으로 전처리되며, 결측치 처리/정규화/feature engineering 등이 포함

모델 개발 및 훈련

  • 기능 : 머신러닝 모델의 선택, 개발, 훈련 및 검증, HyperParameter Tuning 최적화
  • 예시 : Data Scientist가 고객 이탈 예측 모델을 위해 여러 알고리즘을 실험하고, 교차 검증을 사용하여 최적 모델을 선택. 최적화 알고리즘을 통해서 모델성능 최적화 진행

모델 배포 및 서빙

  • 기능 : 훈련된 모델을 프로덕션 환경에 배포하고 사용자에게 서비스 제공
  • 예시 : MLOps 엔지니어가 훈련된 모델을 Docker 컨테이너에 패키징하고, Kubernetes 클러스터를 사용하여 스케일링 가능하고 높은 가용성을 가진
    환경에 배포합니다. 모델은 REST API를 통해 실시간 예측 서비스를 제공합니다.

모니터링 및 로깅

  • 기능 : 배포된 모델의 성능 모니터링 및 로깅
  • 예시 : 모델의 예측 성능이 시간이 지남에 따라 변할 수 있으므로, Prometheus와 같은 도구를 사용하여 모델의 응답 시간, 에러율, 정확도 등을 지속적으로 모니터링. 문제가 발견되면 로그 데이터를 분석하여 원인을 파악.

자동화 및 CI/CD

  • 기능 : 코드 변경 시 자동으로 모델을 재훈련, 테스트 및 배포하는 프로세스.
  • 예시 : Data Scientist가 모델의 성능을 개선하기 위해 알고리즘을 수정하면, 이 변경은 Git에 커밋되고, Jenkins와 같은 CI/CD 도구가 변경 사항을 감지하여 자동으로 새로운 모델을 훈련, 테스트 및 프로덕션 환경에 배포

협업 및 버전 관리

  • 기능 : 팀원 간의 협업 및 프로젝트의 버전 관리
  • 예시 : 프로젝트의 모든 코드, 데이터, 모델 버전이 Git과 DVC(Data Version Control)를 통해 관리. 이를 통해 프로젝트 내의 모든 변경 사항을 추적하고, 필요시 이전 버전으로 롤백할 수 있음

보안 및 규정 준수

  • 기능 : 저장되거나 전송되는 데이터의 보안을 유지.
  • 예시 : 모든 중요 데이터는 저장 시 암호화되며, 전송 시 SSL/TLS와 같은 안전한 프로토콜을 사용하여 암호화됩니다. 이는 데이터가 무단 접근이나 해킹으로부터 보호되도록 보장합니다.


접근 제어 및 권한 관리

  • 기능 : 시스템 및 데이터에 대한 접근을 엄격하게 관여
  • 예시 : 사용자 및 서비스 계정에 대한 역할 기반 접근 제어(RBAC)를 구현하여, 필요한 최소한의 권한만 부여. 예를 들어, 데이터 과학자에게는 데이터 분석 권한은 있지만, 운영 데이터베이스를 수정할 권한은 없을 수 있음.

 

MLOps를 위한 도구

CI/CD 도구
• MLOps에서 핵심적 역할
• ML Pipeline을 자동화하여 빠르게 릴리즈하고 모델 및 서빙 품질을 향상시키는데 필수적
• CI/CD 도구로는 Jenkins, Travis CI, Circle CI, GitLab CI 등이 존재함

모델 관리 및 배포 도구
• 머신 러닝 모델의 개발, 관리, 배포, 모니터링을 담당
• 대표적으로 Kuberflow, MLflow, Seldon Core, KubeDirector 등이 존재함

데이터 관리 도구
• 데이터 수집, 저장, 전처리, 변환, 버전 관리를 지원
• 대표적으로 DVC, Pachyderm, Kuberflow data pipelines 등이 존재함

로깅 및 모니터링 도구
• 모델의 성능 및 안정성을 보장하기 위해 필요
• 모델 및 인프라에 대한 모니터링, 로그 수집, 성능 및 사용량 추적, 경고 및 예측 등을 지원
• 대표적으로 Prometheus, Grafana, ELK Stack, Datadog 등이 있음

보안 도구
• 머신 러닝 모델과 관련된 데이터 및 시스템 보안을 유지하기 위해 사용
• 대표적으로는 HashiCorp Valut, Kubernetes Secrets, SOPS 등이 있음

 

프로젝트 중간에 투입이 되면서 Git Pull 당겨 기본적인 셋팅을 하고 실행을 시키니 다음과 같은 오류를 만나게 되었다.

caused by: org.flywaydb.core.api.exception.flywayvalidateexception: validate failed: migrations have failed validation migration checksum mismatch for migration version 20240831 -> applied to database : -886486009 -> resolved locally : 2094648100

 

Flyway? 아주 생소한 용어로 오류를 찾아보던 중 Flyway를 어느정도 이해하게 되고 프로세스 과정을 파악하게 되었다.

알아두면 유용한 도구라고 생각되었고 오류를 해결한 과정을 기록해보려 한다.


JPA 환경에서 DB에 새로운 칼럼이 추가될때 

 

Entity와 DB는 서버를 구동할 때 맵핑을 한다.

운영중인 애플리케이션의 경우 jpa.hibernate.ddl-auto 옵션은 기본적으로 none으로 Entity에 원하는 칼럼 필드를 추가하고 서버를 재실행 하더라도 바로 DB에 반영이 되지 않는다.

jpa.hibernate.ddl-auto : update 바꾼다면 서버를 재실행할때 추가된 컬럼에 대해 ALTER문이 실행되어 DB에 칼럼이 추가된다.

하지만 update 옵션 설정을 깜짝하고 기존에 존재하던 칼럼이 삭제되는 경우 매우 중요한 칼럼이 삭제가 된다면 어떻게 될까? 그리고 배포까지 해버리면 어떻게 될까? 큰 문제를 가져올 수 있다.

 

그러면 새로운 칼럼을 추가하거나 칼럼에 대한 변동사항이 있다면 직접 DB에 칼럼을 변동사항을 적용해주어야 할까?

위의 그림처럼 서버가 개발, 운영 서버 등 여러개 있다면 일일히 스키마 수정을 위한 DDL을 실행해주어야 하는가?

 

기존 로컬이나 개발에서 JPA사용하며 데이터에 문제가 생기거나 테이블 구조가 마음에 안들면 모두 밀어버리고 다시 CREATE해서 사용해도 무방했다. 하지만 운영중인 서버에서 DROP을 자주 사용할 수 있을까? 매우 위험한 명령어이다.

또한 소스코드는 GIT, SVN 등을 통해 형상관리가 되고 있는데 테이블은 형상관리가 되고 있는가? Human error에 대한 문제는 어떻게 잡고있을까? 

 

위와 같은 문제를 해결 할 수 있는 도구가 바로 Flyway이다.

 

Flyway란 무엇인가?

Flyway는 오픈소스 데이터베이스 마이그레이션 도구이다.

마이그레이션이란 이동하는 것을 말한다.

코드로 작성한 클래스를 실제 데이터베이스에 테이블로 옮기는 과정을 말한다.

Models -> Migrations -> Database 

 

하지만 Flyway에서는 Migrations(마이그레이션)을 다음과 같이 정의하고 있다.

With Flyway all changes to the database are called migrations.

 

정리하자면,

Flyway는 데이터베이스 마이그레이션 툴로 모든 변경사항을 추적하고, 업데이트나 롤백을 보다 쉽게 할 수 있는 도구이며 DB 형상관리를 위한 도구이다.

 

 

그럼 Flyway에 대해서 더 자세히 알아보도록 하자.

 

Flyway의 7가지 명령어

Flyway는 총 7가지 특징을 나눠볼 수 있다.

 

  • Migrate : 데이터베이스의 변경
  • Baseline : 비어있지 않은 데이터베이스에서 flyway을 적용할 때 사용하는 키워드
  • Info : 데이터베이스 변경이력을 저장
  • Repair : 스키마 기록 테이블을 다시 복구 할 수 있다.
  • Validate : flyway에 적용할때 사용 가능한 마이그레이션에 대해 적용된 마이그레이션의 유효성을 검사
  • Undo : 최근에 적용됐던 Migration 파일을 적용하지 않은 상태로 되돌리는 키워드
  • Clean : 데이터베이스를 깨끗이 지운다는 의미

 

 

1. Migrate

앞선 말한것과 같이 데이터베이스 변경사항을 추적하여 적용합니다.

flyway을 적용하여 실행하게 되면 history테이블이 자동생성된다.

현재 데이터베이스 상태는 version1이고 V2_Changes.sql을 이용해 마이그레이션을 적용한 결과가 오른쪽 그림이다.

2개의 빨간색 테이블이 추가로 생성된 것을 볼 수 있다.

 

2. BaseLine

비어있지 않은 데이터베이스에서 flyway을 적용할 때 사용하는 키워드

baseline version 까지의 모든 데이터베이스 마이그레이션을 제외하고 그 이후부터의 데이터베이스 flyway의 기능을 적용하게 되는데

해당 명령어를 통해 baseline 전까지의 모든 마이그레이션을 무시하게 되어

오래되고 관련이 없을 수 있는 많은 스크립트를 처리하는 오버헤드를 줄일 수 있다.

 

3. Info

데이터베이스 변경이력을 저장하고 있어 모든 데이터베이스 마이그레이션에 대한 세부 정보 및 상태 정보를 보여준다.

사진에서는 3개의 sql 파일을 테이블로 보여주고 있으며 카테고리, 버전, 설명, 설치 날짜, 성공여부등의 상세한 정보를 확인 할 수 있다.

 

4. Repair

스키마 기록 테이블을 복구하며 스키마 기록 테이블의 문제를 해결하는 도구로 사용된다.

 

5. Validate

사용 가능한 데이터마이그레이션에 대해 적용된 마이그레이션의 유효성을 검사합니다.

유효성 검사는 스키마를 안정적으로 재생성하지 못하게 할 수 있는 우발적인 변경 사항을 감지하는데 매우 유용하다.

 

6. Undo

최근에 적용됐던 Migration 파일을 적용하지 않은 상태로 되돌리는 키워드로 

해당 키워드는 flyway Teams 버전에서만 사용이 가능합니다.

 

7. Clean

clean 명령어는 개발과 테스트에 큰 도움을 주는 키워드로 구성된 스키마를 완전히 삭제하여 효과적으로 새로운 시작을 할 수 있다. 

모든 개체(테이블, 뷰, 프로시저 등)가 삭제된다.

 

 

7가지 특징을 살펴보면 중간에 .sql 파일을 볼 수 있는데 이 파일은 Migrate 파일로 생성규칙이 존재한다.

 

 

Mirgrate 파일 이름 규칙

SQL 파일 이름을 설정하는 방법으로 대표적으로 5가지의 요소를 가지게 된다.

  • Prefix - V, U, R 중 하나를 입력하며 V = version, U = undo, R = repeatable
  • Version - 버전 정보로 정수, 소수, 날짜 등이 가능하다. 
    • 파일의 버전은 Unique 한 특성이 있어 같은 버전이 2개가 있다면 오류를 발생시킨다.
  • Seperator - __(언더바 2개)
  • Description - 파일 설명
  • Suffix - 파일 확장자를 나타낸다.

 

 

 

  • 마이그레이션 파일의 위치 
    • main/resources/db/migration로 이 경로에 스크립트 파일을 추가하게 된다.
    • 커스텀 위치 : application.yml에서 spring.flyway.locations 옵션의 값을 classpath:db/migration/{다른 경로} 로 변경
  • 파일의 버전(unique)
    • 새로 적용하려는 파일은 기존에 적용된 파일의 버전보다 높아야 한다.
      • 만약 최근에 적용된 마이그레이션 파일이 V1이라고 가정한다면 V0, V2 동시에 적용하려고 할 때 V0 무시되고 V2가 적용된다.

 


실습환경구성

  • MySQL 8.3.0
  • SpringBoot 3.1.5
  • JDK 17
  • Hibernate 6.2.13
  • Flyway 9.16.3

 

의존성 추가

dependencies {
    implementation 'org.springframework.boot:spring-boot-starter-web'
    implementation 'org.flywaydb:flyway-core'  // flyway-core 의존성 추가
    implementation 'org.flywaydb:flyway-mysql' // Mysql 8.X 버전, MariaDB라면 해당 종속성 추가 필요

    implementation 'org.springframework.boot:spring-boot-starter-data-jpa'
    implementation 'com.mysql:mysql-connector-j'
	...
}

 

 

DataSource 설정

application.yml 또는 application.properties에 DataSource 관련 설정을 추가한다.

SpringBoot는 DataSource 설정으로 Flyway를 자동으로 연결한다.

spring:
  datasource:
    driver-class-name: com.mysql.cj.jdbc.Driver
    url: jdbc:mysql://localhost:3306/tablename
    username: XXX
    password: XXX
  jpa:
    show-sql: true
    properties:
      hibernate:
        format_sql: true
    generate-ddl: true
    hibernate:
      ddl-auto: validate
  flyway:
    enabled: true
    baseline-on-migrate: true

 

 

JPA 설정

jpa:
    show-sql: true
    properties:
      hibernate:
        format_sql: true
    generate-ddl: true
    hibernate:
      ddl-auto: validate

ddl-auto 옵션을 validate 로 설정하면, 실제 데이터베이스 스키마와 JPA 엔티티의 구조가 서로 같은지 비교하고, 같지 않다면 어플리케이션을 실행하지 못하도록 한다.

이 옵션을 사용하여 Flyway를 사용했을때 올바르게 데이터베이스 마이그레이션이 진행되었는지 확인해볼것

 

Flyway 활성화

spring:
	# ...
	flyway:
	    enabled: true

 

JPA 엔티티 구조

@Entity
public class Member {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;
    private String name;
    private String email;
    private String password;
}

 

 

최초 마이그레이션 스크립트 작성

최초로 실행될 마이그레이션 스크립트이다. 

 

파일의 경로는 resources/db/migration 이며 파일명은 V1__init.sql로 지정

 

 

프로젝트 Run 버튼을 누르고 테이블이 생성되었는지 확인

  • flyway_schema_history : 형상관리를 위한 테이블로 script에 버전관련 파일명과 checksum이 들어가 있다.
  • member -> 스크립트에 작성된 테이블 생성

 

 

Entity에 칼럼 추가 - content 추가

@Entity
public class Member {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;
    private String name;
    private String email;
    private String password;
    private String content;
}

 

 

재실행

Error starting ApplicationContext. To display the condition evaluation report re-run your application with 'debug' enabled.
2024-10-22T13:41:47.719+09:00 ERROR 38429 --- [           main] o.s.boot.SpringApplication               : Application run failed

org.springframework.beans.factory.BeanCreationException: 
Error creating bean with name 'entityManagerFactory' defined in class path resource 
[org/springframework/boot/autoconfigure/orm/jpa/HibernateJpaConfiguration.class]: 
[PersistenceUnit: default] Unable to build Hibernate SessionFactory; 
nested exception is org.hibernate.tool.schema.spi.SchemaManagementException: 
Schema-validation: missing column [content] in table [member]

 

에러가 발생한다 이점에 주목해보자

Schema-validation: missing column [content] in table [member]

ddl-autovalidation으로 설정하면서 변경된 내역을 반영하지 못하고 있다.

스키마 불일치로 발생하는 에러로 새로운 버전의 마이그레이션 스크립트 파일이 필요하다.

 

새로운 버전의 마이그레이션 스크립트 작성

V2__add_contact.sql 생성

ALTER TABLE member ADD COLUMN content VARCHAR(255);

 

프로젝트 RUN 실행

해당 칼럼이 추가되었다. 그리고 history 내역도 확인해보자

v2버전에 대해 로우가 추가되었다.

 

 

Versioned Migrations

다시 한 번 강조해보면 Migrations 기능은 Flyway 의 핵심기능이다.

마이그레이션 스크립트의 최신 버전과 현재 데이터베이스의 스키마 버전을 비교하여, 차이점이 있다면 마이그레이션 스크립트를 순차적으로 실행하여 최신 스크미와 격차를 좁혀 나간다.

 

만약 마이그레이션 버전이 1~0까지 있고 현재 개발환경에서 스키마가 5버전일때, 최신 버전에 대해 마이그레이션을 실행하면 스크립트 6~9 버전이 순차적으로 실행된다. 개발 환경의 최신 스키마가 9버전이면, 아무 스크립트도 실행되지 않는다.

 

최신 마이그레이션 버전의 숫자보다 작은 숫자의 버전으로 마이그레이션 스크립트를 추가한다면, 그 마이그레이션 스크립트는 무시된다.

예를 들어 최신 버전이 10인데 9를 이후에 추가하는 경우 해당 스크립트는 무시한다.

 

 

해당 프로젝트는 flyway v2까지 실행했다. 프로젝트를 다시 실행해보자

Caused by: org.flywaydb.core.api.exception.FlywayValidateException: Validate failed: Migrations have failed validation
Migration checksum mismatch for migration version 2
-> Applied to database : -2088626076
-> Resolved locally    : -104825358
Either revert the changes to the migration, or run repair to update the schema history.
Need more flexibility with validation rules? Learn more: https://rd.gt/3AbJUZE

 

FlywayValidateException이 발생하며 다음과 같은 오류메시지가 출력되었다.

Migration checksum mismatch for migration version 2

Flyway는 각 마이그레이션 스크립트 별로 체크섬을 비교하여 유효성 검사를 한다. 따라서, 스키마에 대한 모든 변경은 반드시 새로운 버전의 마이그레이션 스크립트를 추가하는 방법으로 진행해야 한다.

 

그렇다면 이때 어떻게 해결해야 할까?

 

checksum 재설정

@Bean
public Flyway flywayBean() {
    Flyway flyway = Flyway.configure().baselineOnMigrate(true).load();
        flyway.repair();
        flyway.migrate();
    return flyway;
}

checksum 이용해 유효성을 검사하기 때문에 flyway.migrate() 하기전에 flyway.repair()을 사용하여 체크섬을 재설정해준다.

 

주의점

형상관리의 장점이 있지만 주의해야할 점은 DB스키마에 변경사항이 생겼을때 이를 Flyway에게 알려주는 스크립트를 잊지 말고 작성해야 한다.

 

 

이렇게 DB관리하는 방법을 새롭게 배우게 되었다.

파면 팔수록 개발이란 어렵따,, 

 

Reference


https://www.youtube.com/watch?v=_fgOxPRo8tU

https://www.youtube.com/watch?v=pxDlj5jA9z4

https://www.blog.ecsimsw.com/entry/Flyway%EB%A1%9C-DB-Migration

https://velog.io/@choidongkuen/Flyway%EB%9E%80-%EB%AC%B4%EC%97%87%EC%9D%BC%EA%B9%8C

https://hudi.blog/dallog-flyway/

https://tecoble.techcourse.co.kr/post/2021-10-23-flyway/

 

+ Recent posts