18일 차 TIL
동시성 문제에 관해서 DB단계에서 3가지 해결법을 알아보자.
동시성 문제 예시 상황)
현재 잔액이 100원일 때, 동시에 두 트랜잭션이 출금 시도를 한다고 가정해 보자.
1. A트랜잭션 : 잔액 조회 => 100원, 50원 출금
2. B트랜잭션 : 잔액 조회 => 100원, 30원 출금
3. A트랜잭션 커밋 => 잔액 50원으로 변경
4. B트랜잭션 커밋 => 잔액 70원으로 변경
실제로는 20원이 되어야 하지만, 결과는 70원이 됨 → 동시성 문제 발생
이 문제를 어떻게 해결할 수 있을까?
1. DB락
트랜잭션이 데이터를 읽거나 수정할 때 락을 걸어 접근을 막는다.
- 낙관적 락(Optimistic Lock): 충돌이 드물 것이라고 가정하여 별도의 락을 걸지 않고, 수정 시점에 버전(Version) 번호 등을 체크하여 데이터의 변경 여부를 확인하는 방식입니다.
- 비관적 락(Pessimistic Lock): 데이터 수정 시 충돌이 반드시 발생할 것이라고 가정하여, 데이터를 읽는 시점에 데이터베이스 레벨에서 즉시 락을 걸어 다른 트랜잭션의 접근을 차단하는 방식입니다.
2. CQRS ( Command Query Responsibility Segregation )
읽기(Read)와 쓰기(Write)를 분리

쓰기 트랜잭션은 쓰기 전용 DB에 기록
읽기 트랜잭션은 조회 전용 DB에서 가져옴
CQRS는 쓰기가 아무리 밀려도 읽기 성능은 유지된다.
위 그림에서 Write DB에서 낙관락이나 비관락을 추가하면 동시성 문제를 해결할 수 있다.
3. Queue 활용 ( 실시간 처리 )
잔액 조회, 출금 이벤트를 큐에 넣고 실시간으로 처리

- 1:1 처리: 큐에서 한 번에 딱 하나씩만 꺼내 처리합니다.
- 충돌 방지: A의 출금이 끝날 때까지 B는 큐에서 대기하므로, 별도의 복잡한 락(Lock) 없이도 잔액 계산이 꼬이지 않습니다.
순서가 보장되므로 동시성 문제를 원천 차단할 수 있다.
4 Queue 활용2 ( 일괄 처리 )
여러 이벤트를 모아서 한 번에 쿼리로 처리
이 방식은 주로 Read DB를 업데이트하거나, 로그성 데이터를 쌓을 때 성능을 극대화하기 위해 사용합니다.

- 일괄 처리: 매건마다 DB에 접근하는 대신, 큐에 쌓인 이벤트를 100개 또는 1,000개씩 모아서 한 번에 처리합니다.
- DB 비용 감소: DB 커넥션 비용이 줄어들어 처리량이 엄청나게 늘어납니다.
- 주의점: 배치 처리 전까지는 조회에 반영되지 않는다.
'내배캠' 카테고리의 다른 글
| [내일배움캠프] 20일 차 TIL Github Rules, Code Convention (0) | 2026.03.01 |
|---|---|
| [내일배움캠프] 19일 차 TIL 도메인 중심 아키텍처 (0) | 2026.03.01 |
| [내일배움캠프 본캠프] 17일 차 TIL ERD 설계 시 트레이드-오프 고려 (0) | 2026.02.26 |
| [내일배움캠프 본캠프] 16일 차 TIL 도커 (0) | 2026.02.25 |
| 스파르타 12조 질문 정리 (0) | 2026.02.25 |
