
ACID: 데이터베이스의 절대 약속
은행이 NoSQL 대신 RDBMS를 쓰는 이유. All or Nothing(원자성)부터 트랜잭션 격리 수준(Isolation Levels), 데드락(Deadlock), 그리고 시니어 개발자가 되는 관점까지 완벽 정리.

은행이 NoSQL 대신 RDBMS를 쓰는 이유. All or Nothing(원자성)부터 트랜잭션 격리 수준(Isolation Levels), 데드락(Deadlock), 그리고 시니어 개발자가 되는 관점까지 완벽 정리.
내 서버는 왜 걸핏하면 뻗을까? OS가 한정된 메모리를 쪼개 쓰는 처절한 사투. 단편화(Fragmentation)와의 전쟁.

로버트 C. 마틴(Uncle Bob)이 제안한 클린 아키텍처의 핵심은 무엇일까요? 양파 껍질 같은 계층 구조와 의존성 규칙(Dependency Rule)을 통해 프레임워크와 UI로부터 독립적인 소프트웨어를 만드는 방법을 정리합니다.

미로를 탈출하는 두 가지 방법. 넓게 퍼져나갈 것인가(BFS), 한 우물만 팔 것인가(DFS). 최단 경로는 누가 찾을까?

이름부터 빠릅니다. 피벗(Pivot)을 기준으로 나누고 또 나누는 분할 정복 알고리즘. 왜 최악엔 느린데도 가장 많이 쓰일까요?

개발을 처음 배울 때, 저는 데이터베이스를 단순히 "데이터를 저장하는 엑셀 같은 것"이라고 생각했습니다. INSERT 하면 들어가고 SELECT 하면 나오는 단순한 창고로만 여겼죠. 하지만 금융 시스템 사례를 공부하면서 그 생각이 얼마나 안일했는지 깨닫게 되었습니다.
상황은 이렇습니다. A가 B에게 100만 원을 이체하는 로직을 짰습니다.
UPDATE accounts SET balance = balance - 100 WHERE id = 'A').UPDATE accounts SET balance = balance + 100 WHERE id = 'B').서버가 재부팅된 후 로그를 확인해보면, A의 돈은 줄어들었는데 B의 돈은 늘어나지 않았습니다. 100만 원이 디지털 허공으로 사라진 것입니다.
이런 사례를 통해 뼛속 깊이 느끼게 됩니다. "데이터베이스의 진짜 가치는 '저장'이 아니라 '보장'에 있구나." 금융 시스템이 왜 그 느리고 비싸고 확장하기 힘든 RDBMS(관계형 데이터베이스)를 고집하는지, 그 이유가 바로 트랜잭션(Transaction)이라는 "절대 약속" 때문이라는 걸 알게 됩니다.
트랜잭션이 안전하게 수행된다는 것을 보장하기 위해, DB는 다음 4가지 성질을 목숨 걸고 지킵니다. 핵심 개념인 ACID입니다.
ROLLBACK 명령이 떨어지면, 이 로그를 보고 원래 상태로 되돌립니다.CHECK 제약 조건). 트랜잭션 도중에 잔액이 마이너스가 되는 연산이 발생하면, DB는 즉시 트랜잭션을 중단시키고 롤백합니다. 단순히 타입 체크뿐만 아니라 외래키 제약조건(Foreign Key) 등 "약속된 규칙"을 절대 어기지 않습니다.COMMIT을 했고 DB가 "OK" 응답을 보냈다면, 그 직후에 전원이 뽑혀도 데이터는 살아있어야 합니다.DB 성능 최적화의 핵심입니다. 격리를 세게 할수록 데이터는 안전하지만 느려지고, 느슨하게 할수록 빨라지지만 데이터 오류(Anomaly) 가능성이 커집니다. 주니어와 시니어를 가르는 질문이 여기서 나옵니다.
SELECT를 두 번 날렸는데, 그 사이에 남이 데이터를 바꿔서 결과가 달라질 수 있습니다. "어? 아까는 잔액이 100원이었는데 지금은 200원이네?"단일 DB에서는 트랜잭션으로 해결되지만, 서버가 여러 대라면? 예를 들어 선착순 쿠폰 이벤트를 한다면, DB 락만으로는 부족할 수 있습니다. 이때 Redis를 이용한 분산 락(Redlock)을 씁니다.
SET key value NX PX 10000 (존재하지 않을 때만 쓰고, 10초 뒤 만료) 명령을 보냅니다. 성공한 서버만 로직을 수행하고, 나머지는 대기합니다.분산 시스템에는 CAP 이론이 있습니다.
ACID는 C(일관성)를 극한으로 추구하는 모델입니다. 반면 NoSQL(MongoDB 등)은 A(가용성)와 P(분할 내성)를 선택하고 C를 희생(Eventual Consistency)하는 경향이 있습니다. "내가 만드는 서비스가 금융(C)인가, SNS(A)인가?"를 먼저 정의해야 DB를 고를 수 있습니다.
격리 수준을 높이다 보면 필연적으로 데드락을 만납니다.
User 1 -> User 2) 맞춥니다.Q. 언제 NoSQL을 쓰고 언제 RDBMS를 써야 하나요? A. 데이터의 구조가 자주 바뀌거나(Schema-less), 엄청난 읽기/쓰기 성능이 필요하고 약간의 데이터 불일치를 감수할 수 있다면(좋아요 수 등) NoSQL을 쓰세요. 하지만 돈, 결제, 재고 등 정합성이 생명이라면 무조건 RDBMS입니다.
Q. @Transactional(readOnly = true)는 왜 쓰나요? A. 성능 최적화를 위해서입니다. 읽기 전용 트랜잭션이라고 명시하면, JPA가 변경 감지(Dirty Checking)를 위한 스냅샷을 만들지 않아 메모리를 절약합니다. 또한, Slave DB(Replica)로 요청을 보내 부하를 분산할 수도 있습니다.
ACID를 공부하고 나서야 비로소 "왜 엔터프라이즈 시스템이 NoSQL의 유혹에도 불구하고 여전히 RDBMS를 메인 저장소로 쓰는지" 이해하게 되었습니다. 데이터의 정합성은 타협할 수 없는 가치이기 때문입니다.
주니어 개발자는 "기능이 돌아가는가"에 집중합니다. 하지만 시니어 개발자는 "많은 트래픽과 동시성 환경에서도 데이터가 깨지지 않는가"를 고민합니다. 여러분도 이제 @Transactional 뒤에 숨겨진 거대한 메커니즘을 이해했으니, 시니어의 시야를 가지게 된 것입니다.