ADR-005: Concurrency Auto-Selection (동시성 자동 선택)
Status: Accepted | Date: 2026-02-10
맥락
서로 다른 백엔드 연산은 서로 다른 동시성 제어 전략을 필요로 합니다. 단순 읽기 연산은 잠금이 필요 없고, 단일 Entity 업데이트는 낙관적 잠금(optimistic locking)이 적합하며, 다중 Entity 금융 트랜잭션은 경쟁 조건(race condition)을 방지하기 위해 비관적 잠금(pessimistic locking)이 필요합니다.
Fascia의 대상 사용자는 비개발자입니다. 낙관적 잠금과 비관적 잠금 사이의 트레이드오프를 이해하거나 설계하는 각 연산에 올바른 전략을 선택하는 것을 기대할 수 없습니다.
결정
Fascia는 Tool의 플로우 그래프에 대한 정적 분석을 기반으로 스펙 컴파일 시점에 동시성 전략을 자동 선택합니다. 선택 규칙은 다음과 같습니다:
| 플로우 패턴 | 전략 |
|---|---|
| 읽기 전용 (Write 노드 없음) | 잠금 없음 |
| 단일 Entity 쓰기 | 낙관적 잠금 (version 필드 검사) |
| 다중 Entity 쓰기 | 비관적 잠금 (SELECT FOR UPDATE) |
| 금융 연산 (Payment 노드 존재) | 비관적 잠금 |
| 높은 행 영향 (100행 초과 쓰기) | 비관적 잠금 |
선택된 전략은 Flow Studio에서 정보성 배지(badge)로 표시되므로, 기술적 사용자가 선택된 이유를 확인하고 이해할 수 있습니다. 전체 비전에서는 고급 사용자가 자동 선택된 전략을 오버라이드할 수 있습니다.
검토한 대안
| 옵션 | 장점 | 단점 |
|---|---|---|
| 자동 선택 (선택됨) | 사용자 노력 제로, 안전한 기본값, 플로우 분석 기반 | 항상 최적의 전략을 선택하지 못할 수 있음 |
| 항상 낙관적 | 구현이 단순 | 다중 Entity 쓰기 및 금융 연산에 위험; 경쟁 조건 |
| 항상 비관적 | 가장 안전한 기본값 | 읽기 집중 또는 단순 쓰기 연산에 대한 성능 오버헤드 |
| 사용자 선택 | 최대 유연성 | 비개발자가 올바르게 결정할 수 없음 |
결과
긍정적
- 인지 부하 제로 -- 비개발자가 잠금 개념을 이해하지 않아도 안전한 동시성 동작을 얻습니다.
- 투명성 -- 선택된 전략이 Flow Studio에서 보입니다. 기술적 사용자가 특정 전략이 선택된 이유를 검사하고 이해할 수 있습니다.
- 안전한 기본값 -- 자동 선택은 안전 쪽으로 치우칩니다. 금융 연산과 다중 Entity 쓰기는 항상 비관적 잠금을 사용합니다.
- 오버라이드 경로 -- 전체 비전에서 고급 사용자가 선택을 오버라이드할 수 있어 엣지 케이스에 대한 탈출구를 제공합니다.
부정적
- 보수적 선택 -- 자동 선택이 낙관적 잠금으로 충분한 경우에도 비관적 잠금을 선택하여 데이터베이스 경합이 약간 높아질 수 있습니다.
- 엣지 케이스 -- 정적 플로우 분석이 모든 런타임 패턴을 포착하지 못할 수 있습니다. 일부 플로우는 차선의 전략을 받을 수 있습니다.
리스크
- 낙관적 잠금 실패를 우아하게 처리해야 합니다. Executor는 버전 충돌 시 자동으로 재시도하며, 재시도가 소진되면 사용자 대면 에러를 반환합니다.
- 비관적 잠금은 여러 쓰기 대상이 있는 복잡한 플로우에서 데드락을 일으킬 수 있습니다. Executor는 무한 차단을 방지하기 위해 설정 가능한 타임아웃과 함께 데드락 감지를 구현합니다.