웹 서비스를 개발하다 보면 대부분의 데이터는 MySQL, PostgreSQL 같은 운영 데이터베이스에 저장된다.

예를 들어 쇼핑몰이라면 다음과 같은 데이터가 계속 쌓인다.

회원 가입
주문
결제
상품 조회
배송

그런데 어느 날 회사에서 이런 요구사항이 들어온다고 생각해보자.

최근 3년간 지역별·상품별 매출을 집계하고
마케팅 캠페인별 고객의 평균 구매 금액을 분석해주세요.

단순 조회처럼 보이지만 실제로는 여러 테이블을 JOIN하고, 수년 치 데이터를 읽고, GROUP BY, SUM, AVG 같은 집계 연산을 수행해야 한다.

이런 무거운 분석 작업을 실제 서비스가 사용하는 운영 DB에서 계속 수행하면 서비스 트래픽과 분석 작업이 같은 CPU, 메모리, 디스크 I/O 자원을 놓고 경쟁하게 된다.

그래서 일반적으로 서비스 운영을 위한 데이터 처리와 데이터 분석을 위한 처리를 분리한다.

그리고 그 사이에서 데이터를 이동하고 가공하는 역할을 하는 것이 ETL이다.


1. ETL이란?

ETL은 다음 세 단어의 약자다.

Extract
   ↓
Transform
   ↓
Load
  • Extract : 데이터를 가져온다.
  • Transform : 데이터를 분석하기 좋은 형태로 가공한다.
  • Load : 가공된 데이터를 목적지에 저장한다.

전체 구조를 단순하게 표현하면 다음과 같다.

┌──────────────────────────┐
│       Data Sources       │
│                          │
│ MySQL / PostgreSQL       │
│ MongoDB / API / CSV      │
└────────────┬─────────────┘
             │
          Extract
             ↓
┌──────────────────────────┐
│        Transform         │
│                          │
│ 정제 / 변환 / JOIN       │
│ 중복 제거 / 집계         │
└────────────┬─────────────┘
             │
            Load
             ↓
┌──────────────────────────┐
│      Data Warehouse      │
│                          │
│ BigQuery / Redshift      │
│ Snowflake 등             │
└──────────────────────────┘

즉,

여러 시스템에 흩어진 데이터를 가져와 정리하고, 분석을 위한 별도의 저장소에 넣는 데이터 파이프라인

이라고 이해하면 된다.


2. 왜 운영 DB에서 바로 분석하지 않을까?

ETL을 이해하려면 먼저 OLTP와 OLAP의 차이를 알아두는 것이 좋다.

OLTP

OLTP는 실제 서비스의 트랜잭션을 처리한다.

예를 들어 쇼핑몰에서는 다음과 같은 작업이다.

SELECT *
FROM orders
WHERE id = 100;

또는

INSERT INTO orders (...);

사용자가 주문하고, 결제하고, 상품을 조회하는 실제 서비스 요청이다.

따라서 중요한 것은 보통 다음과 같다.

빠른 단건 조회
빠른 INSERT
빠른 UPDATE
동시 사용자 처리
트랜잭션 안정성

OLAP

반면 OLAP은 데이터를 분석하는 것이 목적이다.

SELECT
    category_id,
    YEAR(order_date),
    SUM(amount)
FROM orders
JOIN products
    ON orders.product_id = products.id
GROUP BY
    category_id,
    YEAR(order_date);

이런 쿼리는 대량의 데이터를 읽고 집계한다.

JOIN
GROUP BY
ORDER BY
SUM
AVG
COUNT

같은 연산을 많이 수행한다.

운영 서비스의 OLTP와 분석용 OLAP은 처리 특성이 다르기 때문에 분석을 별도의 시스템으로 분리하는 것이 일반적이다. 자료에서도 ETL을 이 두 환경 사이를 연결하는 파이프라인으로 설명한다.


3. Extract — 데이터를 가져오는 단계

ETL의 첫 번째 과정은 Extract다.

다양한 데이터 소스에서 데이터를 수집한다.

예를 들면 다음과 같다.

PostgreSQL
MySQL
MongoDB
외부 REST API
CSV
로그 파일

하나의 시스템에서만 데이터를 가져오는 것은 아니다.

회원 데이터    → PostgreSQL
결제 데이터    → 외부 결제 API
로그 데이터    → 파일
상품 데이터    → MySQL

이런 여러 데이터를 하나의 분석 시스템으로 가져올 수도 있다.

자료에서도 Extraction을 여러 데이터 소스에서 원본 데이터를 식별하고 수집하여 복사하는 과정으로 설명한다.


4. 무작정 SELECT * 하면 문제가 생긴다

가장 쉬운 데이터 추출 방법은 DB를 직접 조회하는 것이다.

SELECT *
FROM orders;

데이터가 몇천 건이라면 별문제가 없다.

하지만 orders 테이블에 수천만 건의 데이터가 있다면 이야기가 달라진다.

예를 들어 한 시간마다 이런 작업을 수행한다고 생각해보자.

매시간 Batch 실행

       ↓

SELECT *
FROM orders;

       ↓

수천만 Row Scan

       ↓

Disk I/O 증가

       ↓

CPU / Memory 사용 증가

       ↓

서비스 트랜잭션과 자원 경쟁

자료에서도 운영 데이터베이스를 대상으로 반복적인 대규모 전체 조회를 수행하면 Disk IOPS와 DB 자원을 크게 사용할 수 있다고 설명한다.

그래서 대규모 시스템에서는 전체 데이터를 매번 읽는 대신 변경된 데이터만 가져오는 방법을 사용하기도 한다.

여기서 등장하는 것이 CDC다.


5. CDC — 변경된 데이터만 가져오기

CDC는 Change Data Capture의 약자다.

말 그대로 데이터베이스에서 발생한 변경 사항을 잡아내는 기술이다.

예를 들어 주문 테이블에서 다음 작업들이 일어난다고 해보자.

INSERT
UPDATE
INSERT
DELETE
INSERT

기존 방식이라면 전체 테이블을 다시 읽고 이전 데이터와 비교해야 할 수도 있다.

orders 전체 조회
       ↓
기존 데이터와 비교
       ↓
변경 데이터 확인

CDC를 사용하면 데이터의 변경 자체를 추적할 수 있다.

INSERT 발생
   ↓
INSERT 이벤트 전달

UPDATE 발생
   ↓
UPDATE 이벤트 전달

DELETE 발생
   ↓
DELETE 이벤트 전달

즉,

전체 데이터를 계속 가져오는 것이 아니라 바뀐 데이터만 전달한다.

CDC는 INSERT, UPDATE, DELETE 같은 row-level 변경 사항을 추적하여 downstream 시스템으로 전달하는 방식이다.


6. WAL과 CDC는 어떤 관계일까?

PostgreSQL을 사용한다면 WAL이라는 용어를 자주 보게 된다.

WAL은 Write-Ahead Log다.

PostgreSQL에서 발생한 데이터 변경 사항이 기록되는 로그다.

개념적으로 보면 다음과 같다.

Spring Application

       ↓

INSERT INTO orders ...

       ↓

PostgreSQL

       ↓

WAL

INSERT
UPDATE
DELETE
INSERT

       ↓

CDC

       ↓

Kafka / Staging / DWH

대표적인 CDC 도구인 Debezium은 이런 데이터베이스 변경 로그를 이용해 변경 사항을 감지할 수 있다.

자료에서도 PostgreSQL의 WAL, MongoDB의 Oplog 같은 내부 로그를 CDC가 읽어 변경 데이터를 전달하는 방식을 설명한다.

실무에서는 다음처럼 구성하기도 한다.

PostgreSQL
     │
    WAL
     ↓
 Debezium
     ↓
   Kafka
     ↓
 Consumer
     ↓
Data Warehouse

7. Staging Area — 데이터를 바로 최종 테이블에 넣지 않는다

데이터를 Extract했다고 바로 최종 분석 테이블에 넣는 것만이 방법은 아니다.

중간 저장 공간을 하나 둘 수 있다.

이것이 Staging Area다.

Production DB
      ↓
   Extract
      ↓
┌────────────────┐
│  Staging Area  │
│                │
│    Raw Data    │
└───────┬────────┘
        ↓
    Transform
        ↓
┌────────────────┐
│ Data Warehouse │
└────────────────┘

쉽게 말하면

가공하기 전 데이터를 받아두는 임시 또는 중간 저장 영역

이다.

예를 들어 다음과 같이 구성할 수 있다.

staging.orders
staging.users
staging.payments

그리고 가공이 끝난 데이터는 다음으로 이동한다.

analytics.daily_sales
analytics.customer_summary
analytics.product_statistics

Staging을 두면 원본 데이터와 최종 분석 모델을 분리할 수 있기 때문에 데이터 검증이나 재처리 구조를 만들기도 편해진다.


8. Transform — 데이터를 분석 가능한 형태로 바꾼다

Extract한 데이터는 그대로 분석하기 어려운 경우가 많다.

예를 들어 서로 다른 시스템이 날짜를 이렇게 저장한다고 해보자.

2026-09-09
2026/09/09
09-09-2026
1788940800

분석하기 전에 형태를 통일해야 한다.

또 다음과 같은 작업이 필요할 수도 있다.

NULL 처리

중복 데이터 제거

잘못된 데이터 제거

String → Integer 변환

Unix Timestamp → DateTime 변환

여러 데이터 JOIN

개인정보 Masking

SUM / AVG / COUNT 집계

예를 들어 주문 데이터와 회원 데이터를 합칠 수 있다.

orders
                  ┐
                  │
                  ├─ JOIN
                  │
users             ┘

       ↓

customer_orders

또 결제 시스템의 데이터까지 연결할 수도 있다.

User

   +

Order

   +

Payment

   ↓

고객별 구매 분석 데이터

자료에서는 Transform을 RAW 데이터를 정제하고 구조화하여 목적 시스템에서 사용할 수 있도록 만드는 과정으로 설명하며, JOIN, 시간 형식 통일, 손상 데이터 제거, 개인정보 처리 등을 예로 든다.


9. 데이터가 많아지면 Apache Spark가 등장한다

데이터가 적다면 하나의 서버에서도 처리할 수 있다.

하지만 데이터가 수백 GB 또는 TB 단위로 증가하면 한 서버에서 다음 작업을 수행하기 부담스러울 수 있다.

JOIN
SORT
GROUP BY
집계
데이터 변환

그래서 대규모 데이터 처리에서는 Apache Spark 같은 분산 처리 엔진이 사용된다.

Spark의 핵심 개념은 간단하다.

큰 데이터를 작은 단위로 나눈 뒤 여러 서버가 동시에 처리한다.

예를 들어 1TB 데이터를 네 부분으로 나눈다고 해보자.

                 1TB

                  ↓

        ┌─────────┼─────────┐

      250GB     250GB     250GB     250GB

        ↓         ↓         ↓         ↓

     Worker1   Worker2   Worker3   Worker4

Spark 구조에서는 Executor가 여러 Task를 실행하며 데이터를 병렬 처리한다.

            Cluster Manager
                   │
        ┌──────────┴──────────┐
        │                     │
        ↓                     ↓
    Executor               Executor
 ┌─────────────┐       ┌─────────────┐
 │ Task        │       │ Task        │
 │ Task        │       │ Task        │
 │ Cache       │       │ Cache       │
 └─────────────┘       └─────────────┘

자료에서도 Spark가 대규모 데이터를 여러 파티션으로 나누고 클러스터의 여러 컴퓨터에서 병렬 처리하는 구조를 설명한다.


10. Load — 가공된 데이터를 목적지에 저장한다

Transform까지 끝났다면 이제 데이터를 분석 시스템에 넣는다.

이 과정이 Load다.

Raw Data
    ↓
Transform
    ↓
Clean Data
    ↓
Load
    ↓
Data Warehouse

대표적인 Data Warehouse 서비스로는 자료에서 다음과 같은 제품을 예로 들고 있다.

Amazon Redshift
Google BigQuery
Snowflake

전체 흐름은 다음과 같이 완성된다.

Production Database

        ↓

      ETL

        ↓

Data Warehouse

        ↓

BI / Dashboard / Analytics

11. Data Warehouse는 왜 Column 기반일까?

운영 데이터베이스와 분석 데이터베이스는 데이터를 사용하는 방식부터 다르다.

일반적인 애플리케이션에서는 한 Row를 통째로 조회하는 일이 많다.

id | product | amount | date
--------------------------------
1  | Shirt   | 14.55  | 2025-01-01
2  | Pants   | 35.44  | 2025-04-01
3  | Tie     | 12.22  | 2025-04-02

그런데 분석 시스템에서는 이런 쿼리를 많이 사용한다.

SELECT SUM(amount)
FROM sales;

이 쿼리에 필요한 것은 사실 amount 컬럼뿐이다.

그래서 분석 시스템에서는 같은 컬럼의 데이터를 모아 저장하는 Columnar Storage 구조가 유리하다.

개념적으로 보면 다음과 같다.

Order ID
────────
1
2
3


Product
────────
Shirt
Pants
Tie


Amount
────────
14.55
35.44
12.22

SUM(amount)를 계산한다면 필요한 Amount 데이터 중심으로 읽을 수 있다.

자료에서도 Columnar Storage가 컬럼 단위로 데이터를 저장함으로써 분석 쿼리에서 불필요한 데이터 읽기를 줄이고 디스크 I/O를 감소시키는 구조라고 설명한다.

간단하게 비교하면 다음과 같다.

구분OLTPOLAP
목적서비스 운영데이터 분석
주요 작업INSERT, UPDATE, 단건 조회SUM, AVG, GROUP BY
데이터현재 트랜잭션 중심대량의 과거 데이터
저장 구조Row 기반이 일반적Column 기반이 많이 사용됨
예시MySQL, PostgreSQLBigQuery, Redshift, Snowflake

12. ETL과 ELT는 무엇이 다를까?

전통적인 방식은 ETL이다.

Extract
   ↓
Transform
   ↓
Load

즉 데이터를 먼저 변환하고 목적지에 넣는다.

Source DB

   ↓

Extract

   ↓

Spark 등에서 Transform

   ↓

Data Warehouse

그런데 클라우드 데이터 플랫폼이 발전하면서 ELT 방식도 널리 사용되고 있다.

ELT는 순서가 다르다.

Extract
   ↓
Load
   ↓
Transform

즉 원본 데이터를 먼저 목적지에 저장하고 나중에 그 안에서 변환한다.

자료에서도 ETL과 ELT의 핵심 차이를 Transform이 Load 전인지 후인지로 설명한다.


13. 왜 ELT가 등장했을까?

과거에는 저장 공간과 Data Warehouse의 컴퓨팅 자원이 비쌌다.

그래서 필요한 형태로 데이터를 미리 정리한 다음 넣는 방식이 효율적이었다.

Raw Data

   ↓

외부 Transform

   ↓

필요한 데이터만 저장

하지만 클라우드 환경에서는 저장 공간과 컴퓨팅 자원을 훨씬 유연하게 활용할 수 있다.

그래서 원본 데이터를 먼저 저장하고,

Raw Data
   ↓
Data Warehouse

그 후 Warehouse 내부에서 필요한 데이터를 만들어낼 수 있다.

Raw Data

   ↓

SQL Transform

   ↓

Analytics Model

자료에서는 이러한 변화와 함께 ELT 방식이 확대되었으며, SQL 기반 변환에 dbt 같은 도구를 사용할 수 있다고 설명한다.


14. dbt를 사용하는 ELT 예제

자료에 나온 구조를 보면 ELT를 이해하기 쉽다.

CoinMarketCap API

        ↓

      Python

        ↓

PostgreSQL Data Warehouse

        ↓

Staging Schema

        ↓

       dbt

        ↓

Prod Schema

        ↓

Power BI

하나씩 보면 다음과 같다.

① Extract

Python이 외부 API에서 데이터를 가져온다.

response = requests.get(api_url)
CoinMarketCap API
        ↓
      Python

② Load

가져온 원본 데이터를 먼저 Data Warehouse의 Staging 영역에 저장한다.

Python
   ↓
PostgreSQL
   ↓
staging

여기까지는

Extract → Load

이다.


③ Transform

그다음 dbt가 SQL을 이용하여 데이터를 가공한다.

SELECT
    symbol,
    AVG(price) AS avg_price,
    MAX(price) AS max_price
FROM staging.crypto_prices
GROUP BY symbol;

그리고 결과를 분석용 데이터 모델에 저장한다.

staging.crypto_prices

        ↓

       dbt

        ↓

prod.crypto_summary

dbt는 Data Warehouse에 저장된 데이터를 SQL을 기반으로 분석 가능한 데이터 모델로 변환하는 데 사용하는 프레임워크다.


④ Visualization

최종 데이터는 Power BI 같은 BI 도구에서 사용할 수 있다.

Prod Schema
      ↓
Power BI
      ↓
Dashboard

예를 들어 다음과 같은 데이터를 시각화할 수 있다.

일별 가격 변화
월별 평균 가격
상품별 매출
사용자별 구매 금액
지역별 매출

15. Spring 개발자라면 이렇게 이해하면 쉽다

Spring 개발자 입장에서는 ETL이 완전히 낯선 개념은 아니다.

예를 들어 다음과 같은 서비스가 있다고 해보자.

Spring Boot
     ↓
   MySQL

주문 요청이 발생하면:

POST /orders

     ↓

OrderService

     ↓

INSERT INTO orders

데이터가 운영 DB에 쌓인다.

그런데 데이터 분석팀이 다음 데이터를 원한다고 해보자.

최근 3년간 연령별·지역별·상품별 월평균 매출

운영 MySQL에 매번 다음과 같은 무거운 쿼리를 실행하는 것보다는

SELECT ...
FROM orders
JOIN users
JOIN products
GROUP BY ...

분석용 시스템을 별도로 두는 구조를 생각할 수 있다.

                 사용자
                   ↓
              Spring Boot
                   ↓
            Production DB
                   │
                   │
            CDC / Batch
                   ↓
                Kafka
                   ↓
             Raw / Staging
                   ↓
          Spark / dbt / SQL
                   ↓
           Data Warehouse
                   ↓
              Power BI

이렇게 보면 ETL은 단순히 데이터 엔지니어만의 용어가 아니다.

백엔드 시스템에서 발생한 데이터를 어떻게 안전하게 분석 시스템까지 전달할 것인가에 대한 아키텍처이기도 하다.


16. Spring Batch도 ETL인가?

Spring 개발자에게 가장 익숙한 예는 Spring Batch다.

예를 들어:

MySQL
   ↓
Spring Batch
   ↓
PostgreSQL

Spring Batch에서는 일반적으로 다음 구조를 사용한다.

ItemReader
     ↓
ItemProcessor
     ↓
ItemWriter

ETL과 비교하면 개념적으로 상당히 비슷하다.

ETL                    Spring Batch

Extract      ≈         ItemReader

Transform    ≈         ItemProcessor

Load         ≈         ItemWriter

예를 들어:

ItemReader<Order> reader

운영 DB에서 주문 데이터를 읽고,

ItemProcessor<Order, SalesSummary> processor

필요한 형태로 가공하고,

ItemWriter<SalesSummary> writer

다른 DB나 파일에 저장한다면 하나의 ETL 파이프라인이라고 볼 수 있다.


17. 전체 흐름 다시 정리하기

지금까지의 내용을 하나의 구조로 합치면 다음과 같다.

┌───────────────────────────────┐
│         Data Sources          │
│                               │
│ MySQL / PostgreSQL / MongoDB  │
│ API / CSV / Application       │
└───────────────┬───────────────┘
                │
             Extract
                ↓
        ┌───────────────┐
        │ CDC / Batch   │
        │               │
        │ WAL           │
        │ Debezium      │
        └───────┬───────┘
                │
                ↓
        ┌───────────────┐
        │ Raw / Staging │
        └───────┬───────┘
                │
             Transform
                │
        ┌───────┴────────┐
        │                │
      Spark             dbt
  분산 데이터 처리     SQL 변환
        │                │
        └───────┬────────┘
                ↓
      ┌─────────────────┐
      │ Data Warehouse  │
      │                 │
      │ BigQuery        │
      │ Redshift        │
      │ Snowflake       │
      └────────┬────────┘
               │
               ↓
      Columnar Storage
               │
               ↓
              OLAP
               │
               ↓
        BI / Analytics

마무리

ETL을 단순히

Extract → Transform → Load

세 단어만 외우면 실제 시스템 구조가 잘 보이지 않는다.

조금 더 넓게 보면 다음 흐름으로 이해하는 것이 좋다.

운영 시스템
    ↓
OLTP
    ↓
Extract
    ↓
CDC / Batch
    ↓
Raw / Staging
    ↓
Transform
    ↓
Spark / dbt
    ↓
Data Warehouse
    ↓
Columnar Storage
    ↓
OLAP
    ↓
BI / 데이터 분석

그리고 최근의 데이터 플랫폼에서는 Transform의 위치에 따라 두 가지 방식으로 나눌 수 있다.

ETL

Extract
   ↓
Transform
   ↓
Load
ELT

Extract
   ↓
Load
   ↓
Transform

결국 핵심은 하나다.

ETL과 ELT는 운영 시스템의 데이터를 분석에 적합한 시스템으로 안전하게 이동하고, 사용할 수 있는 형태로 만드는 데이터 파이프라인이다.

Spring 개발자라면 특히 Spring Batch, CDC, Kafka, Spark, Data Warehouse를 각각 따로 공부하기보다 데이터가 어디에서 생기고 → 어떻게 이동하고 → 어디에서 가공되고 → 어디에 저장되는지 하나의 흐름으로 연결해서 이해하는 것이 훨씬 좋다.

profile
레거시를 이해하면서도 새로운 기술을 현실적으로 적용할 수 있는 백엔드 개발자가 되는 것이 목표입니다.

0개의 댓글