Web Locks API
(developer.mozilla.org)- Web Locks API는 하나의 탭이나 웹 워커에서 비동기적으로 락을 획득하고, 작업을 수행한 후 락을 해제할 수 있게 해줌
- 락이 유지되는 동안 동일한 origin 내에서 다른 스크립트는 동일한 락을 획득할 수 없으므로 여러 탭이나 워커에서 리소스를 안전하게 조율할 수 있음
- Secure Context(HTTPS) 에서만 사용 가능하며, Web Workers 에서 사용 가능
주요 개념 및 사용 방법
- 락(Lock) 은 웹 애플리케이션에서 정의한 이름으로 식별되는 추상적인 리소스
- 예를 들어, 여러 탭에서 IndexedDB와 네트워크 동기화를 할 때, “my_net_db_sync”라는 락을 사용하여 한 번에 하나의 탭만 동기화를 수행할 수 있음
- 사용 흐름:
- 락 요청
- 비동기 작업 수행
- 작업 완료 후 자동으로 락 해제
예제 코드
navigator.locks.request("my_resource", async (lock) => {
await do_something();
await do_something_else();
});
- 락이 유지되는 동안 동일한 락에 대한 다른 요청은 대기열에 추가되며, 락이 해제되면 첫 번째 요청이 처리됨
옵션
- mode: 기본 모드는 “exclusive”(단독), “shared”(공유) 모드도 가능. “exclusive”는 하나의 요청만 허용, “shared”는 다수 허용 가능
- ifAvailable: 즉시 락을 획득할 수 없는 경우 요청 실패, 콜백은 null 반환
- steal: 동일한 이름의 기존 락을 해제하고 새로운 요청을 우선 처리
- signal: AbortSignal을 통해 요청을 중단할 수 있음 (예: 타임아웃 구현)
모니터링
- navigator.locks.query()를 사용하여 현재 origin의 락 상태를 조회할 수 있음
- 이는 디버깅 시 유용하며, 어떤 락이 유지되고 있는지, 요청된 락이 무엇인지 확인 가능
고급 사용법
- 비동기 작업의 완료 시점을 명시적으로 제어하려면 Promise를 반환 가능
let resolve;
const p = new Promise((res) => { resolve = res });
navigator.locks.request("my_resource", (lock) => p);
- resolve() 호출 시 락이 해제됨
데드락(Deadlock) 방지
- 데드락은 서로 다른 요청이 순서 문제로 충돌하여 진행이 불가능한 상황
- 예를 들어, 탭 1이 락 A를 가지고 있고, 탭 2가 락 B를 가진 상황에서, 탭 1이 락 B를 요청하고 탭 2가 락 A를 요청하면 서로 기다리게 됨
- 이를 방지하려면:
- 락 요청은 중첩되지 않도록 함
- 락 요청은 순서를 지켜서 진행
- 타임아웃을 설정하여 요청을 중단
인터페이스
- Lock: 요청된 락의 이름과 모드를 제공
- LockManager: 새로운 락을 요청하거나 기존 락을 조회할 수 있는 메서드 제공
- navigator.locks로 인스턴스 획득 가능
- WorkerNavigator.locks는 Web Workers에서 사용 가능
스펙 및 브라우저 지원
- 스펙: Web Locks API
- 브라우저 호환성: 일부 브라우저에서만 지원되며, 최신 브라우저에서의 지원 여부는 MDN에서 확인 가능
GN⁺의 의견
- Web Locks API는 비동기 환경에서 리소스 동기화 문제를 해결하는 데 유용함
- 데드락 발생 가능성이 있으므로 사용 시 주의가 필요하며, 타임아웃 설정과 같은 안전 장치를 고려해야 함
- Shared mode는 읽기 전용 작업에서 성능을 높일 수 있으나, 여전히 경쟁 조건에 대한 철저한 검토가 필요함
- 이 API는 기존의 localStorage나 IndexedDB의 동기화 이슈를 해결하는 대안으로 활용될 수 있음