---
term: 'ACID 트랜잭션'
seoTitle: 'ACID 트랜잭션이란? 네 가지 속성과 예시'
headline: 'ACID 트랜잭션이란?'
slug: acid-transactions
category: database
shortDefinition: 'ACID 트랜잭션은 원자성, 일관성, 격리성, 지속성을 갖추고 하나의 단위로 커밋되는 데이터베이스 작업의 묶음입니다.'
relatedTerms:
  - database-queries
  - database-index
  - nosql-vs-sql
  - crud-operations
contrastsWith:
  - nosql-vs-sql
faq:
  - question: 'ACID는 무엇의 약자입니까?'
    answer: '원자성(Atomicity), 일관성(Consistency), 격리성(Isolation), 지속성(Durability)입니다. 오류, 장애, 동시 사용자를 거치면서도 데이터가 올바르게 유지되도록 데이터베이스 트랜잭션이 제공해야 하는 네 가지 보장입니다. Jim Gray가 1981년에 핵심 속성을 정의했고, Theo Härder와 Andreas Reuter가 1983년 트랜잭션 지향 복구에 관한 논문에서 이 약어를 만들었습니다.'
  - question: 'ACID 트랜잭션이란 쉽게 말해 무엇입니까?'
    answer: '전부 아니면 전무의 단일 단위로 실행되는 읽기와 쓰기의 묶음입니다. 모든 작업이 커밋되어 영구화되거나, 모든 작업이 롤백되어 아무 일도 없었던 것처럼 됩니다. 고전적인 예는 송금입니다. 한 계좌에서 출금하고 다른 계좌에 입금하는데, 두 작업 사이에 장애가 나더라도 출금만 되고 입금은 안 된 상태가 남아서는 절대 안 됩니다.'
  - question: '격리 수준이란 무엇입니까?'
    answer: '트랜잭션이 동시에 실행될 때 성능과 보호를 맞바꾸는 조절 장치입니다. SQL 표준은 네 가지를 정의합니다. Read uncommitted, read committed, repeatable read, serializable이며, 단계가 올라갈수록 더 많은 이상 현상(더티 리드, 반복 불가능 읽기, 팬텀 리드)을 더 큰 비용으로 막습니다. 실무에서 대부분의 현대 엔진은 MVCC 기반의 스냅샷 방식 격리를 기본값으로 삼으며, 읽는 쪽은 일관된 스냅샷을 보고 쓰는 쪽을 결코 막지 않습니다.'
  - question: 'ACID와 BASE의 차이는 무엇입니까?'
    answer: '정확성의 비용에 대한 두 가지 답입니다. ACID는 조정 비용을 치르고 모든 트랜잭션이 유효한 상태를 보고 유효한 상태를 남기도록 보장합니다. BASE(Basically Available, Soft state, Eventually consistent)는 일시적인 데이터 지연을 감수하고 가용성을 유지하며 수평으로 확장합니다. 어느 쪽도 우월하지 않습니다. 일관성에 매기는 값이 다를 뿐이며, 실제 시스템은 워크로드별로 둘을 섞어 씁니다.'
  - question: 'ACID의 일관성은 CAP 정리의 일관성과 같은 것입니까?'
    answer: '아닙니다. 이 둘을 혼동하는 것이 이 주제에서 가장 흔한 오해입니다. ACID의 일관성은 모든 트랜잭션이 선언된 규칙을 보존한다는 뜻입니다. 제약 조건이 지켜지고 불변 조건이 살아남습니다. CAP의 일관성은 분산 시스템의 모든 노드가 같은 시점에 같은 데이터를 본다는 뜻입니다. 단일 노드 데이터베이스는 CAP와 무관하게 완전한 ACID를 충족할 수 있습니다.'
  - question: 'NoSQL 데이터베이스는 ACID를 준수합니까?'
    answer: '점점 더 그렇게 되고 있지만, 세부 조항이 있습니다. 문서 데이터베이스는 언제나 단일 문서 쓰기를 원자적으로 처리했고, 관련 데이터를 임베딩하는 방식과 결합하면 대부분의 앱 요구를 충족합니다. 다중 문서 ACID 트랜잭션은 MongoDB 4.0(2018년)에서 스냅샷 격리와 함께 도입되었으며, 실질적인 성능 비용이 따릅니다. "NoSQL은 트랜잭션이 없다"는 옛 주장은 이제 그저 낡은 말이지만, 단일 문서 원자성을 중심으로 모델링하는 설계 선호는 여전히 유효합니다.'
  - question: '데이터베이스는 실제로 ACID를 어떻게 구현합니까?'
    answer: '세 가지 메커니즘이 부담을 나눠 집니다. 언두 정보가 롤백을 가능하게 하고(원자성), 선행 기록 로그(WAL), 즉 변경을 적용하기 전에 지속성 있는 로그에 먼저 기록하는 방식이 장애를 견디게 하며(지속성), 락이나 MVCC가 동시 트랜잭션들이 서로 간섭하지 않게 합니다(격리성). 일관성은 그 결과입니다. 나머지 셋의 보호 안에서 제약 조건이 검사됩니다.'
  - question: '최종 일관성은 언제 충분합니까?'
    answer: '잠시 오래된 데이터가 보여도 아무 손해가 없을 때입니다. 좋아요 수, 조회수, 활동 피드, 분석, 캐시, 상품 추천이 그렇습니다. 충분하지 않은 경우는 돈, 초과 판매될 수 있는 재고, 좌석과 티켓 예약, 규제 대상인 모든 것입니다. 엔지니어링 역량은 한쪽 편을 고르는 것이 아니라, 각 쓰기를 실제로 필요한 보장 수준으로 라우팅하는 데 있습니다.'
codeLanguages: [javascript, dart, swift, kotlin]
externalAuthorities:
  - name: 'ACID (Wikipedia)'
    url: 'https://en.wikipedia.org/wiki/ACID'
  - name: 'The Transaction Concept — Jim Gray (1981)'
    url: 'https://jimgray.azurewebsites.net/papers/thetransactionconcept.pdf'
  - name: 'Principles of Transaction-Oriented Database Recovery — Härder & Reuter (1983)'
    url: 'https://dl.acm.org/doi/10.1145/289.291'
  - name: 'MongoDB ACID transactions guide'
    url: 'https://www.mongodb.com/resources/basics/databases/acid-transactions'
cta:
  title: '번거로운 절차 없는 정확성'
  text: 'Back4app은 앱에 실제로 필요한 원자성을 제공합니다. 원자적 카운터와 배열 연산, 전부 아니면 전무의 배치 저장, 그리고 서버 측에서 검증되는 다단계 워크플로를 위한 Cloud Code까지, 직접 운영할 필요 없는 관리형 문서 데이터베이스 위에서 제공됩니다.'
  linkText: '무료로 시작하기'
  linkUrl: 'https://www.back4app.com/signup'
author: 'Back4app Engineering'
publishedDate: '2026-10-28'
translationKey: acid-transactions
---

**ACID 트랜잭션은 원자성, 일관성, 격리성, 지속성을 갖추고 하나의 단위로 커밋되는 데이터베이스 작업의 묶음입니다.** 개념은 약어보다 먼저 있었습니다. Jim Gray가 1981년에 이 보장들을 정의했고, Härder와 Reuter가 1983년에 ACID라는 이름을 붙였으며, 40년이 지난 지금도 소프트웨어로 돈을 옮기면서 가끔 돈을 만들어 내거나 없애 버리지 않게 해 주는 계약으로 남아 있습니다.

## 핵심 요약

| 질문 | 답변 |
| --- | --- |
| 네 글자 | 원자성(전부 아니면 전무) · 일관성(규칙 유지) · 격리성(간섭 없음) · 지속성(장애를 견딤) |
| 고전적인 예 | 은행 이체: 출금 + 입금이 함께 커밋되거나 전혀 커밋되지 않음 |
| 조절 장치 | 격리 수준 – 성능과 읽기 이상 현상의 맞교환 |
| 경쟁 모델 | BASE / 최종 일관성 – 가용성과 데이터 지연의 맞교환 |
| 오늘의 현실 | 문서 데이터베이스도 ACID를 지원함. 세부 조항은 *범위* |

## SQL에서 ACID 트랜잭션의 작동 방식(은행 이체 예시)

```sql
BEGIN;
UPDATE accounts SET balance = balance - 100 WHERE id = 'alice';
UPDATE accounts SET balance = balance + 100 WHERE id = 'bob';

-- 두 UPDATE 사이에 장애나 오류가 나면? 엔진이 롤백합니다:
-- ROLLBACK;  →  두 변경이 모두 사라지고, 돈은 증발할 수 없습니다

COMMIT;       -- 아니면 둘 다 원자적으로, 지속적으로 영구화됩니다
```

애플리케이션 코드는 같은 보장을 더 작은 단위로 만납니다. 읽기-수정-쓰기 경쟁 상태(race condition)를 없애는 원자적 필드 연산과, 함께 커밋되는 배치가 그것입니다:

**JavaScript:**

```javascript
// JavaScript / Node.js — Back4app JS SDK
// Atomicity where apps actually need it
counter.increment('sold', 1);        // atomic single-field update — no
await counter.save();                // read-modify-write race possible

// All-or-nothing batch: both rows commit, or neither does
await Parse.Object.saveAll([debitEntry, creditEntry], { transaction: true });
```

**Flutter:**

```dart
// Flutter / Dart — Back4app Flutter SDK
// Atomicity where apps actually need it
counter.setIncrement('sold', 1);     // atomic single-field update — no
await counter.save();                // read-modify-write race possible

// Batches group writes; atomic counters remove the classic race
await ParseObject.saveAll([debitEntry, creditEntry]);
```

**Swift:**

```swift
// iOS / Swift — Back4app Swift SDK
// Atomicity where apps actually need it
var updated = counter
updated.sold = (updated.sold ?? 0) + 1
// Prefer the atomic operation over read-modify-write:
let op = counter.operation.increment("sold", by: 1)
op.save { result in
  if case .success = result { print("atomic increment committed") }
}
```

**Kotlin:**

```kotlin
// Android / Kotlin — Back4app Android SDK
// Atomicity where apps actually need it
counter.increment("sold")            // atomic single-field update — no
counter.saveInBackground()           // read-modify-write race possible

// Batches group writes; atomic counters remove the classic race
ParseObject.saveAllInBackground(listOf(debitEntry, creditEntry))
```

## 트랜잭션 생명주기: BEGIN, COMMIT, ROLLBACK

```mermaid
flowchart LR
  accTitle: 트랜잭션 생명주기
  accDescr: 트랜잭션은 시작한 뒤 작업 상태에 대해 연산을 수행하고, 커밋하여 모든 변경을 영구화하거나, 어떤 실패에서든 롤백하여 이전의 유효한 상태를 복원합니다.
  B["BEGIN"] --> O["연산<br/>읽기 + 쓰기, 격리됨"]
  O -->|"모두 성공"| C["COMMIT<br/>영구적, 지속성 보장"]
  O -->|"하나라도 실패"| R["ROLLBACK<br/>아무 일도 없었던 것처럼"]
```

네 가지 속성을 각각 그것이 없을 때 무엇이 깨지는지로 설명하면 이렇습니다. **원자성**이 없으면 부분 쓰기가 생깁니다(출금은 됐는데 입금은 영영 안 된 이체). **일관성**이 없으면 자신이 정한 규칙을 위반하는 상태가 커밋됩니다(음수 재고, 고아 참조). **격리성**이 없으면 동시 트랜잭션들이 서로의 절반쯤 끝난 작업을 읽습니다. **지속성**이 없으면 "커밋된" 데이터를 장애가 조용히 되돌립니다. 내부적으로는 세 가지 메커니즘이 이를 제공합니다. 롤백을 위한 언두 로그, 장애 생존을 위한 선행 기록 로그(WAL), 동시성을 위한 락 또는 MVCC입니다.

## 격리 수준 vs. 읽기 이상 현상

검색 결과가 좀처럼 한데 모아 주지 않는 매트릭스, 즉 어떤 수준이 어떤 이상 현상을 막는지입니다:

| 수준 | 더티 리드 | 반복 불가능 읽기 | 팬텀 리드 | 비용 |
| --- | --- | --- | --- | --- |
| Read uncommitted | 가능 | 가능 | 가능 | 최저 |
| Read committed | 방지 | 가능 | 가능 | 낮음 |
| Repeatable read | 방지 | 방지 | 가능 | 중간 |
| Serializable | 방지 | 방지 | 방지 | 최고 |

용어 풀이: *더티 리드*는 커밋되지 않은 작업을 보는 것이고, *반복 불가능 읽기*는 같은 질문을 두 번 했을 때 다른 답을 받는 것이며, *팬텀 리드*는 트랜잭션 도중에 행이 나타나는 것을 보는 것입니다. 대부분의 현대 엔진은 MVCC 기반의 스냅샷 동작을 기본값으로 삼습니다. 각 트랜잭션은 일관된 스냅샷을 읽고 쓰는 쪽은 계속 진행하므로, "읽기는 쓰기를 막지 않는다"가 예외가 아니라 표준이 되었습니다.

## ACID vs. BASE, 그리고 "일관성"이라는 동음이의어

| 차원 | ACID | BASE |
| --- | --- | --- |
| 최적화 대상 | 트랜잭션 단위의 정확성 | 규모에서의 가용성 |
| 일관성 | 즉시, 규칙 보존 | 최종적(eventual consistency) |
| 자연스러운 영역 | 돈, 재고, 예약 | 피드, 카운터, 캐시 |
| 확장 방식 | 조정 비용에 묶임 | 설계상 수평 확장 |
| 실패 양상 | 경합 시 느려짐 | 일시적으로 오래된 읽기 |

이 비교 전체를 떠받치는 구분이 하나 있습니다. **ACID의 C와 CAP의 C는 같은 글자를 쓴 다른 단어입니다.** ACID의 일관성은 각 트랜잭션이 선언된 규칙을 보존한다는 뜻이고, CAP의 일관성은 모든 노드가 지금 이 순간 합의한다는 뜻입니다. 단일 노드 데이터베이스는 CAP가 등장할 일 없이 완전한 ACID이며, 분산 시스템은 CAP 트레이드오프*와* 트랜잭션 보장을 각각 따로 선택합니다.

## 누가 무엇을 보장하는가

| 엔진 계열 | ACID 지원 현황 |
| --- | --- |
| PostgreSQL | 완전한 ACID, MVCC, serializable 사용 가능 |
| MySQL | **InnoDB에서** 완전한 ACID – 스토리지 엔진 선택이 중요 |
| SQLite | 완전한 ACID, 단일 라이터, WAL 모드 |
| MongoDB | 단일 문서 원자성은 항상 보장. 다중 문서 트랜잭션은 4.0(2018년)부터, 스냅샷 격리 |
| 분산 SQL 엔진 | 합의 기반 복제를 통한 ACID – 네트워크 비용을 치르는 serializable |
| 와이드 컬럼 / 최종 일관성 저장소 | 조정 가능하고 부분적 – 설계상 BASE |

분산 트랜잭션에는 솔직한 각주가 필요합니다. **2단계 커밋**은 지연 시간과 블로킹되는 코디네이터라는 값을 치르고 노드 간 원자성을 삽니다. 그래서 마이크로서비스 아키텍처는 점점 **사가**(saga)를 선호합니다. 보상 롤백을 갖춘 로컬 트랜잭션의 연속으로, 즉각적인 일관성을 가용성과 맞바꿉니다. 어떤 워크플로가 정말로 보상을 감당할 수 없다면, 그것은 그 워크플로가 여러 데이터베이스에 걸쳐 있을 것이 아니라 하나의 데이터베이스 안에 있어야 한다는 증거입니다.

## 일반적인 사용 사례

- **자금 이동.** 이체, 지급, 원장. 고전적인 사례이자 여전히 가장 명확한 사례입니다.
- **재고와 예약.** 재고 차감과 주문 확정을 함께 처리하지 않으면, 두 고객이 마지막 좌석을 동시에 사는 장면을 보게 됩니다.
- **다중 행 불변 조건.** 주문 + 주문 항목, 계정 + 감사 기록. 함께 태어나야만 유효한 레코드들입니다.
- **제대로 된 카운터.** 원자적 증가는 ACID를 가장 작게 적용한 실용적인 형태로, 완전한 트랜잭션 없이 읽기-수정-쓰기 경쟁 상태를 없앱니다.
- **최종 일관성이라는 보완재.** 피드, 좋아요, 분석. 의도적으로 트랜잭션 비용에서 *멀리* 라우팅하는 영역입니다.

## 반드시 ACID여야 할까? 결정 매트릭스

| 완전한 트랜잭션을 요구해야 할 때… | 최종 일관성으로 충분할 때… |
| --- | --- |
| 돈이나 소유권이 이전됨 | 오래된 카운트로 인한 손해가 없음 |
| 부분 쓰기가 유효하지 않은 상태를 만듦 | 각 쓰기가 독립적으로 유효함 |
| 규제 기관이 불변 조건을 물어볼 것임 | 데이터가 파생된 것이고 재구축 가능함 |
| 두 행이 언제나 일치해야 함 | 나중에 수렴해도 사용자 경험상 수용 가능함 |
| 초과 판매는 소송감 | 초과 집계는 웃고 넘길 일 |

핵심 기술은 쓰기별 라우팅입니다. 결제는 트랜잭션을 쓰고, 조회수 카운터는 원자적 증가를 쓰고, 피드는 1초의 어긋남을 허용합니다. 하나의 애플리케이션 안에 일관성의 가격대가 셋 있는 셈입니다.

## 한계와 트레이드오프

- **조정이 비용의 중심입니다.** 락은 경합하고, WAL 동기화는 디스크를 두드리며, serializable 재시도는 중단됩니다. 정확성의 대가는 처리량 저하이며, BASE가 존재하는 이유가 바로 이것입니다.
- **격리 수준의 기본값에는 함정이 있습니다.** 대부분의 엔진은 serializable을 기본값으로 삼지 않습니다. 자신의 수준을 알아야 합니다. 그렇지 않으면 불가능하다고 믿었던 이상 현상이 실제로는 드물게 일어날 뿐입니다.
- **긴 트랜잭션은 경고 신호입니다.** 사용자가 생각하는 시간이나 네트워크 호출에 걸쳐 락을 쥐고 있으면 보장이 경합으로 바뀝니다. 트랜잭션은 짧고 단호하게 유지해야 합니다.
- **분산 ACID는 본질적으로 비쌉니다.** 커밋마다 합의 라운드가 돕니다. 불변 조건이 요구하는 곳에서만 치르고, 반사적으로 모든 곳에서 치르지 말아야 합니다.
- **ACID가 규칙을 대신 검증해 주지는 않습니다.** 일관성은 *선언된* 제약 조건을 보존합니다. 제약 조건으로 선언하지 않은 비즈니스 규칙은 당연히 강제되지 않습니다.

## Back4app에서의 트랜잭션

Back4app은 관리형 데이터베이스, 자동 생성되는 REST 및 GraphQL API, 인증, 파일 스토리지, Cloud Code 서버리스 함수를 결합한 오픈소스 Backend as a Service(BaaS) 플랫폼입니다. 트랜잭션 도구 모음은 앱이 실제로 ACID를 활용하는 방식에 맞춰져 있습니다. 모든 단일 객체 쓰기는 기반 문서 엔진에서 원자적이고, [원자적 증가와 배열 연산](https://www.mongodb.com/resources/basics/databases/acid-transactions)은 고전적인 카운터 경쟁 상태를 없애며(위의 코드 탭), 배치 저장은 쓰기를 묶고, 다단계 불변 조건은 Cloud Code에 둡니다. 서버 측에서 검증되고 실행되므로, beforeSave 트리거가 규칙을 깨뜨릴 쓰기를 거부할 수 있습니다. 결정 매트릭스가 내장되어 있는 셈입니다. 기본값은 저렴한 원자성, 요청하는 곳에는 완전한 조정입니다.
