Chrome 55에 auxclick 출시 예정

제프 포스닉
제프 포스닉

클릭이 click가 아닌 경우 복잡한 사용자 인터페이스로 작업하는 웹 개발자에게는 추상적인 철학적 질문이 아닙니다. 맞춤 마우스 입력 동작을 구현하는 경우 사용자의 의도를 고려해야 합니다. 예를 들어 사용자가 마우스의 가운데 버튼이 있는 링크를 클릭한 경우 해당 링크의 콘텐츠가 포함된 새 탭을 열려고 하는 것이 적절하다고 가정하는 것이 좋습니다. 사용자가 임의의 UI 요소를 가운데 클릭하는 경우, 이 작업이 의도치 않았다고 가정하고 그 입력을 무시하는 것이 좋습니다. 하지만 기본 버튼 클릭은 UI에서 응답을 트리거할 것으로 예상됩니다.

약간 번거롭더라도 단일 click 이벤트 리스너를 통해 이러한 미묘한 상호작용을 모델링할 수 있습니다. MouseEventbutton 속성을 명시적으로 확인하여 기본 버튼이 아닌 기본 버튼을 나타내는 0으로 설정되었는지 확인해야 합니다. 1는 일반적으로 가운데 버튼을 나타내는 식입니다. 그러나 button 속성을 명시적으로 확인하는 개발자가 많지 않으므로, 어떤 버튼을 눌렀는지와 상관없이 모든 click를 동일하게 처리하는 코드가 생성됩니다.

Chrome 55부터 기본 버튼이 아닌 버튼으로 클릭하는 경우 이에 대한 응답으로 새로운 유형의 MouseEventauxclick가 실행됩니다. 이 새 이벤트와 함께 click 이벤트의 동작이 변경됩니다. 이 이벤트는 기본 마우스 버튼을 누를 때만 실행됩니다. 이번 변경으로 웹 개발자가 특별히 MouseEvent.button 속성을 확인하지 않고도 관심 있는 클릭 유형에만 응답하는 이벤트 핸들러를 쉽게 작성할 수 있기를 바랍니다.

거짓양성 감소

앞서 언급했듯이 auxclick를 만든 한 가지 이유는 'middle-click-opens-a-tab' 동작을 실수로 재정의하는 맞춤 click 핸들러의 배포를 피하는 것이었습니다. 예를 들어 History API를 사용하여 위치 표시줄을 재작성하고 맞춤 단일 페이지 탐색을 구현하는 click 이벤트 핸들러를 작성했다고 가정해 보겠습니다. 다음과 같이 표시될 수 있습니다.

document.querySelector('#my-link').addEventListener('click', event => {
    event.preventDefault();
    // ...call history.pushState(), use client-side rendering, etc....
});

맞춤 로직은 마우스의 기본 버튼으로 트리거될 때 의도한 대로 작동할 수 있지만 가운데 버튼을 클릭할 때 이 코드가 실행되면 사실상 거짓양성입니다. 새 동작이 발생하면 사용자의 기대에 반하는 새 탭을 여는 기본 작업이 차단됩니다. 핸들러 시작 시 event.button === 0를 명시적으로 확인하고 이 경우에만 코드를 실행할 수 있지만 이 작업을 잊어버리거나 잊어버리기 십상입니다.

필요한 코드만 실행

거짓양성이 적은 단점은 auxclick 콜백이 실제로 기본이 아닌 마우스 버튼이 클릭되었을 때만 실행된다는 점입니다. 예를 들어 새 탭을 열기 전에 적절한 도착 URL을 계산해야 하는 코드가 있는 경우 auxclick를 리슨하고 해당 로직을 콜백에 포함할 수 있습니다. 기본 마우스 버튼을 클릭할 때 실행되는 오버헤드가 발생하지 않습니다.

브라우저 지원 및 호환성

이 새로운 동작은 현재 Chrome 55에서만 구현됩니다. 초기 제안서에서 언급했듯이 웹 개발자 커뮤니티의 긍정적 및 부정적 의견은 모두 소중합니다. GitHub 문제를 제출하는 것이 표준화 프로세스 관련 의견을 공유하는 가장 좋은 방법입니다.

그동안 개발자는 마우스 이벤트 처리를 위한 몇 가지 권장사항을 따르기 위해 auxclick가 널리 사용 가능해질 때까지 기다릴 필요가 없습니다. click 이벤트 핸들러의 시작 부분에서 MouseEvent.button 속성 값을 확인하면 적절한 조치를 취할 수 있습니다. 다음 패턴은 auxclick에 대한 기본 지원 여부와 관계없이 기본 클릭과 보조 클릭을 서로 다르게 처리합니다.

function handlePrimaryClick(event) {
    // ...code to handle the primary button click...
}

function handleAuxClick(event) {
    // ...code to handle the auxiliary button click….
}

document.querySelector('#my-link').addEventListener('click', event => {
    if (event.button === 0) {
    return handlePrimaryClick(event);
    }


    // This provides fallback behavior in browsers without auxclick.
    return handleAuxClick(event);
});

// Explicitly listen for auxclick in browsers that support it.
document.querySelector('#my-link').addEventListener('auxclick', handleAuxClick);