OLTP와 OLAP의 차이¶
한 줄 요약: OLTP는 "한 줄을 정확하게, 자주 고치는 DB"다. OLAP은 "수백만 줄을 빠르게 훑어 집계하는 DB"다. 설계 목표가 달라서, 한쪽에 다른 쪽 일을 맡기면 꼭 필요한 기능이 빠진다.
📍 만난 상황¶
- 2026-11-10 11:03 — 시니어 보고 연습을 하다가 "FusionDB를 쓰라고 했는데 왜 PG를 썼나"라는 질문이 나왔다. 그래서 FusionDB가 PG를 대신할 수 있는지 검토하던 중이었다.
- 직전에 정정을 들었다. 검토하자던 건 "sqlway를 빼는 것"이 아니었다. sqlway 뒤에서 SQL을 실행하는 엔진(ClickHouse)을 FusionDB로 바꿀 수 있는지였다.
- 그 뒤 "PG는 OLTP이고 FusionDB는 OLAP이라 대체가 힘든 건가?"라고 물었다.
- 방향은 맞았다. 하지만 이름표만 알았고, OLAP 설계라서 잠금·원자성·제약이 왜 빠지는지는 몰랐다. → 그날 일지
🧩 쉽게 말하면¶
편의점 계산대와 본사 회계팀을 떠올리면 된다.
계산대(OLTP)는 손님 한 명씩 빠르고 정확하게 결제한다. 마지막 도시락 하나를 두 사람이 동시에 계산하려 해도, 파는 건 한 사람에게만이다.
회계팀(OLAP)은 한 달치 영수증 수백만 장을 모아 "지역별 매출"을 낸다. 영수증 한 장을 고치는 일은 거의 없다.
회계팀에게 계산대를 맡기면 어떻게 될까? 결제 한 건마다 장부를 통째로 다시 묶느라 줄이 길어진다. 도시락 하나가 두 번 팔리는 일도 생길 수 있다.
📖 제대로 알기¶
OLTP — 거래 처리¶
OLTP(Online Transaction Processing: 온라인 거래 처리)는 작은 읽기·쓰기를 동시에 많이 처리하는 데 맞춘 DB다.
- 전형적인 일: 즐겨찾기 한 줄 넣기, 제안 한 건 승인하기, 한 사람의 정보 읽기.
- 중요한 것: 정확성이다. 동시에 여러 명이 같은 행을 건드려도 결과가 꼬이면 안 된다.
- 예: PostgreSQL, MySQL, Oracle.
OLAP — 분석 처리¶
OLAP(Online Analytical Processing: 온라인 분석 처리)은 많은 행을 훑어서 합계·건수를 내는 데 맞춘 DB다.
- 전형적인 일: 침수흔적 수만 줄에서 구별
count(), 기간별 집계. - 데이터는 조금씩 넣기보다 크게 몰아서 적재(한꺼번에 싣기)한다.
- 중요한 것: 처리량이다. 같은 시간에 더 많은 행을 읽는 게 목표다.
- 예: ClickHouse, BigQuery, FusionDB(Delta Lake 기반).
OLTP가 지키는 네 가지 약속, ACID¶
트랜잭션(여러 작업을 "전부 되거나, 전부 안 되거나"로 묶은 단위)이 지키는 약속이다.
| 약속 | 뜻 |
|---|---|
| 원자성(Atomicity) | 묶은 작업이 전부 반영되거나 전부 취소된다 |
| 일관성(Consistency) | 제약을 어기는 데이터는 들어가지 않는다 |
| 격리성(Isolation) | 동시에 도는 작업끼리 중간 상태를 못 본다 |
| 지속성(Durability) | 커밋(확정)하면 서버가 꺼져도 남는다 |
함께 나오는 용어도 정리한다.
- 잠금(lock): "내가 고치는 동안 다른 사람은 기다려"라는 표시. PG의 SELECT … FOR UPDATE가 행 하나를 잠근다.
- 제약(constraint): DB가 직접 지키는 규칙. PK(기본 키: 행을 하나로 구별하는 열), UNIQUE(중복 금지), FK(외래 키: 다른 표의 행을 가리키는 열) 등이 있다.
저장 방식이 다르다: 행 저장 vs 열 저장¶
행 3개짜리 표로 보자.
id | 구 | 건수
1 | 강남 | 3
2 | 서초 | 5
3 | 강남 | 2
- 행 저장(OLTP): 디스크에
[1,강남,3] [2,서초,5] [3,강남,2]처럼 줄 단위로 둔다. 한 줄을 읽고 고치기 쉽다. - 열 저장(OLAP):
[1,2,3],[강남,서초,강남],[3,5,2]처럼 열 단위로 둔다. "구별 건수 합계"는 두 열만 읽으면 된다. 같은 값이 이어져 압축도 잘 된다. - 대신 열 저장에서 한 줄을 고치려면 열마다 흩어진 조각을 모두 손대야 한다.
⚙️ 어떻게 동작하나¶
OLTP(PG)에서 승인 한 건 처리하기¶
- 트랜잭션을 시작한다.
- 고칠 행(제안 17번)을 잠근다.
- 제안 표의 상태를 바꾸고, 변경 이력 표에 한 줄 넣는다.
- 커밋한다. 두 표가 한꺼번에 바뀐다. 중간에 실패하면 둘 다 원래대로 돌아간다(롤백).
파일 기반 OLAP(Delta Lake)에서 한 줄 고치기¶
- 그 행이 든 파일(보통 수만 행 묶음)을 읽는다.
- 고친 내용을 담은 새 파일을 S3에 쓴다. 기존 파일은 고치지 않는다(불변).
- 커밋 기록(트랜잭션 로그)에 "이제 이 파일이 최신"이라고 한 줄 추가한다.
- 그사이 다른 사람이 같은 표에 커밋했으면 충돌로 보고 다시 시도한다. 이를 낙관적 동시성(일단 하고, 끝날 때 충돌을 검사하는 방식)이라 한다.
이 설계는 대량 분석에는 아주 좋다. 하지만 여기서 OLTP의 기능이 빠진다. - 행 잠금이 없다. 고칠 "행"이 따로 있지 않고 파일 단위로 다시 쓰기 때문이다. - 여러 표를 묶는 원자성이 없다. 커밋은 표 하나 단위다. 같은 파일을 ClickHouse·Spark도 읽으므로, 한 엔진만의 트랜잭션은 그들에게 보이지 않는다. - PK·UNIQUE 강제가 어렵다. 쓸 때마다 기존 데이터 전체와 대조해야 한다. - 작은 쓰기가 비싸다. 한 줄을 넣어도 파일 하나와 커밋 하나가 생긴다.
sequenceDiagram
participant A as 관리자 A
participant B as 관리자 B
participant P as PostgreSQL
A->>P: 제안 17 잠금 (FOR UPDATE)
B->>P: 제안 17 잠금 요청
Note over B,P: A가 끝날 때까지 기다림
A->>P: 승인 + 이력 1줄 + 커밋
P-->>B: 잠금 넘겨줌
B->>P: 상태 확인 결과 이미 승인됨
잠금 덕분에 B는 A가 끝난 뒤의 상태를 본다. 그래서 승인이 두 번 반영되지 않는다. 행 잠금이 없으면 둘 다 "대기 중"을 읽고 둘 다 승인할 수 있다.
🧪 예시¶
-
예시 1 · 일상에 빗대어: 도시락 재고가 1개다. 손님 2명이 같은 순간 계산대 2곳에서 결제한다. OLTP는 첫 결제가 재고를 잠그고 0으로 만든다. 두 번째 결제는 "품절"을 받는다. 잠금이 없으면 둘 다 재고 1을 읽고 둘 다 결제되어, 재고가 -1이 된다.
-
예시 2 · 실제로는: 승인 흐름을 PG로 쓰면 이렇다(표 이름은 예시용).
BEGIN;
SELECT status FROM app.edit_proposal
WHERE id = 17 FOR UPDATE; -- ①
UPDATE app.edit_proposal
SET status = 'approved' WHERE id = 17; -- ②
INSERT INTO app.change_log (proposal_id)
VALUES (17); -- ③
COMMIT; -- ④
같은 시스템에서 OLAP이 맡는 일은 이런 질의다.
SELECT sgg_code, count() AS n
FROM disaster.norm_flood_trace
WHERE t_start >= '2022-08-01'
GROUP BY sgg_code;
sgg_code, t_start 두 열만 읽는다. 열 저장이 빛나는 경우다.
⚖️ 비교 · 흔한 오해¶
| 항목 | OLTP | OLAP |
|---|---|---|
| 한 번에 다루는 행 | 몇 줄 | 수만~수억 줄 |
| 쓰기 | 작고 잦음, 동시에 여럿 | 크게 몰아서 적재 |
| 저장 | 행 단위 | 열 단위 |
| 중요한 것 | 정확성(잠금·제약·원자성) | 처리량(압축·병렬 스캔) |
| 이 대시보드에서 | PG: 즐겨찾기, 제안 승인, 문의 | ClickHouse: 건수, 집계, 내려받기 |
- 헷갈렸던 점: "OLAP이라서 안 된다"로 끝내기 — 시험이나 면접에서 분류표로 외우는 경우가 많아서, 이름표만으로 답이 된 것처럼 느껴진다. 하지만 이름표는 근거가 아니다. 근거는 "승인 흐름이 기대는 잠금·원자성·제약이 그 엔진 구조에서 빠진다"는 점이다. 이렇게 말해야 상대가 반박하거나 납득할 수 있다.
- 오해: "OLAP은 쓰기를 못 한다" — 쓸 수 있다. FusionDB도 MERGE로 upsert(있으면 고치고 없으면 넣기)를 흉내 낼 수 있다. 다만 비싸고, 동시성 방식이 다르다.
- 구조적 한계와 "아직 없는 기능"을 구분한다 —
ON CONFLICT,RETURNING, 자동 번호는 나중에 생길 수 있다. 행 잠금, 여러 표 원자성, PK 강제, 작은 쓰기 비용은 구조에서 오는 한계라 쉽게 바뀌지 않는다. - 오해: "PG는 분석을 못 한다" — 수천 줄 규모 집계는 PG로 충분하다. 수십만~수억 줄을 자주 훑을 때 OLAP이 필요해진다.
🛠️ 실무에서는¶
- 어느 쪽인지 고르는 질문
- 한 줄을 자주 고치나? 같은 행을 여러 명이 동시에 건드리나? → OLTP
- 여러 표를 한 번에 바꿔야 하나? 중복이 절대 안 되나? → OLTP
- 많은 행을 훑어 집계하나? 데이터는 몰아서 들어오나? → OLAP
- 흔한 구성: 원본은 OLTP에 둔다. 파이프라인으로 OLAP에 복사해서 분석한다. 바뀐 행만 흘려보내는 방식을 CDC(Change Data Capture: 변경 데이터 수집)라 한다.
- 문제가 생기면 먼저 볼 것
- OLTP가 집계 쿼리로 느려진다 → 분석용 복사본을 OLAP에 둘 때가 됐다는 신호다.
- OLAP 쓰기가 점점 느려진다 → 작은 쓰기가 잦아 파일이 너무 많아졌는지(작은 파일 문제) 본다. 모아서 쓰거나 파일을 합친다(compaction).
❓ 자주 묻는 질문¶
- Q. 둘 다 SQL을 쓰는데 왜 DB를 나누나? A. 문법은 비슷해도 저장 방식과 잠금 구조가 다르다. 같은 SQL이라도 한쪽에선 빠르고 다른 쪽에선 느리거나 위험하다.
- Q. 둘 다 잘하는 DB는 없나? A. HTAP(두 가지를 함께 처리하는 DB)이라는 분류가 있다. 하지만 작은 서비스는 보통 OLTP 하나와 OLAP 하나로 나누는 편이 단순하다.
- Q. 나중에 사용자 기록이 수백만 줄이 되면 OLAP으로 옮겨야 하나? A. 원본은 PG에 둔다. 통계가 필요하면 분석용 복사본만 OLAP으로 보낸다.
🔭 더 깊이 보기¶
- PG는 잠금이 있는데 왜 읽기가 막히지 않나? MVCC(행의 여러 버전을 두어 읽기와 쓰기가 서로 막지 않게 하는 방식)를 알면 OLTP 동시성이 보인다.
- 열 저장은 왜 압축이 잘 되나? 같은 열의 값이 비슷해서다. ClickHouse 정렬 키·파티션 이해로 이어진다.
- Delta Lake의 트랜잭션 로그는 어떻게 생겼나? 파일 기반 OLAP이 "커밋"을 흉내 내는 방법이다.
- 관련 주제: 애플리케이션 서버와 DB 역할 분담
- 관련 주제: PostgreSQL 데이터베이스와 스키마
- 관련 주제: 데이터 규모 증가와 확장성 — OLAP 표가 커질 때 생기는 문제
📚 참고 자료¶
- OLAP과 OLTP의 차이점은 무엇인가요? (AWS 한국어) — 두 처리 방식의 목적·특징 비교 · 링크
- PostgreSQL Documentation: Concurrency Control (영문) — 트랜잭션 격리, 행 잠금(
FOR UPDATE), MVCC · 링크 - Delta Lake Documentation (영문) — 파일 기반 표의 커밋과 낙관적 동시성 · 링크
🗓️ 이력¶
- 2026-11-10: PG를 FusionDB로 대체하기 어려운 게 OLTP·OLAP 차이 때문인지 물음 → 일지