--- kind: CONCEPT slug: adapter-outbound-fileserver-c04 title: 배타성이 필요한 쪽에만 OS 락을 둔다 topic: state-machines-and-ownership project: clean-architecture-backend-template status: 게시 전 sourceRevision: 21234e38cdb9a926cbc92bb97a2aee2e4a7d2916 rootTreeNode: concept:adapter-outbound-fileserver-c04 evidenceCapturedOn: 2026-09-01 assets: - key: adapter-outbound-fileserver-c04 file: ../../../final/evidence/rendered/adapter-outbound-fileserver-c04.svg evidence: - ../../../final/evidence/raw/adapter-outbound-fileserver-c04.txt source: - 원본 분석 절은 analysis/08-adapter-outbound-fileserver.md#L192 이다. module: adapter-outbound-fileserver --- # 배타성이 필요한 쪽에만 OS 락을 둔다 한 클래스 안에 락이 두 종류다. 얼핏 비대칭으로 보이지만 각자의 커밋 방식이 다르다. ## 본문 한 클래스 안에 락이 두 종류다. 얼핏 비대칭으로 보이지만 각자의 커밋 방식이 다르다 — 배타성이 필요한 쪽(replace)에는 OS 락을 두고, 원시연산 자체가 배타적인 쪽(create-link)에는 JVM 스트라이프만 둔 것이다. ## SecureRandom 참조 위치 :::evidence key="adapter-outbound-fileserver-c04" alt="코드베이스에서 SecureRandom 를 검색한 출력 39줄. 이 기록이 세는 참조가 그 출력에 그대로 보인다." caption="SecureRandom 코드베이스 검색 — 39줄 · exit 0" zoom="true" ::: ## root 미포함이 배타 누락으로 이어지지 않는 이유 후자의 root 미포함은 **과잉 직렬화** 방향이라(다른 root의 같은 fileId가 같은 스트라이프를 공유) 배타 누락으로는 이어지지 않고, `fileId`는 `SecureRandom` 16바이트라 실질 충돌도 없다. 결함이 아니라 설계로 기록한다. ## 충돌 경로가 닫히는 방법 `createLink`가 충돌하면 임시 파일을 정확히 지우고, 기존 레코드를 읽어 identity와 내용 동등성을 확인한 뒤 같으면 repair, 다르면 `CONFLICT`다. `concurrentCrossInstanceImmutableCollisionIsNeverClassifiedAsStorage`가 그 분류를 고정한다.