20P by neo 23일전 | favorite | 댓글과 토론
  • Web Locks API는 하나의 탭이나 웹 워커에서 비동기적으로 락을 획득하고, 작업을 수행한 후 락을 해제할 수 있게 해줌
  • 락이 유지되는 동안 동일한 origin 내에서 다른 스크립트는 동일한 락을 획득할 수 없으므로 여러 탭이나 워커에서 리소스를 안전하게 조율할 수 있음
  • Secure Context(HTTPS) 에서만 사용 가능하며, Web Workers 에서 사용 가능

주요 개념 및 사용 방법

  • 락(Lock) 은 웹 애플리케이션에서 정의한 이름으로 식별되는 추상적인 리소스
  • 예를 들어, 여러 탭에서 IndexedDB와 네트워크 동기화를 할 때, “my_net_db_sync”라는 락을 사용하여 한 번에 하나의 탭만 동기화를 수행할 수 있음
  • 사용 흐름:
    1. 락 요청
    2. 비동기 작업 수행
    3. 작업 완료 후 자동으로 락 해제

예제 코드

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의 동기화 이슈를 해결하는 대안으로 활용될 수 있음