웹 오디오, 자동재생 정책, 게임

톰 그리너웨이
최홍찬

2017년 9월, Google은 Chrome의 자동재생 동작 정책을 통해 오디오를 처리하는 방식에 대한 예정된 변경사항을 발표했습니다. 이 정책 변경사항은 2018년 5월에 Chrome 66 안정화 버전에서 출시되었습니다.

웹 오디오 개발 커뮤니티의 의견에 따라 개발자에게 웹사이트를 업데이트할 시간을 충분히 드리기 위해 자동재생 정책의 웹 오디오 부분의 출시를 연기했습니다. 웹 오디오 정책 구현도 일부 변경되었습니다. 이를 통해 코드를 조정해야 하는 웹사이트, 특히 웹 게임의 수를 줄여 사용자에게 더 나은 환경을 제공할 수 있게 되었습니다.

이 정책 변경사항은 2018년 12월에 Chrome 71에 출시될 예정입니다.

변경된 정책의 내용은 정확히 무엇인가요?

자동재생은 웹페이지가 로드되는 즉시 재생되는 콘텐츠에 지정된 이름입니다. 콘텐츠를 자동재생할 수 있을 것으로 예상되는 웹사이트의 경우 이 변경으로 인해 기본적으로 재생이 차단됩니다. 대부분의 경우 재생이 재개되지만, 코드를 약간 조정해야 하는 경우도 있습니다. 특히, 개발자는 사용자가 웹페이지와 상호작용하면 콘텐츠를 재개하는 코드를 추가해야 합니다.

하지만 사용자가 자동재생 콘텐츠가 있는 페이지에 도착하고 동일한 출처의 페이지에서 해당 페이지로 이동한 경우 해당 콘텐츠는 차단되지 않습니다. 자동재생 정책에 관한 자세한 예는 이전 블로그 게시물을 참고하세요.

또한 오디오를 자동재생하는 웹사이트와 관련된 사용자의 이전 행동을 학습하는 휴리스틱도 추가했습니다. Google에서는 사용자가 대부분의 웹사이트 방문 시 정기적으로 오디오가 7초 이상 재생되는 것을 감지하고 해당 웹사이트에 자동재생을 사용합니다.

Google은 기기의 Chrome 프로필별로 로컬로 저장된 색인을 사용하여 이를 수행합니다. 색인은 기기 간에 동기화되지 않으며 익명처리된 사용자 통계의 일부로만 공유됩니다. 이 색인을 미디어 참여 지수 (MEI)라고 하며 chrome://media-engagement에서 볼 수 있습니다.

MEI는 7초가 넘는 오디오 재생이 포함된 사이트 방문 수를 추적합니다. Google은 사용자의 MEI를 기반으로 사용자가 특정 웹사이트의 오디오를 기대하는지 여부를 파악하고 향후 사용자의 의도를 예측할 수 있습니다.

사용자가 웹사이트 도메인이 오디오를 7초 이상 재생하도록 허용하는 경우가 많다면 향후 이 웹사이트에 오디오를 자동재생할 권한이 있을 것이라고 사용자가 예상할 수 있습니다. 따라서 Google은 해당 웹사이트에 사용자가 도메인의 탭과 상호작용할 필요 없이 오디오를 자동재생할 권한을 부여합니다.

하지만 이러한 권리가 항상 보장되는 것은 아닙니다. 사용자가 여러 번 방문하는 동안 오디오 재생을 중지하거나 기준점에 7초 이내에 탭을 닫는 등 사용자의 행동이 바뀌면 웹사이트의 자동재생 권한이 삭제됩니다.

미디어 HTML 요소 (동영상 및 오디오)와 웹 오디오 (JavaScript 인스턴스화된 AudioContext 객체)를 모두 사용하면 MEI에 기여합니다. 이 정책의 출시에 대비해 웹 오디오와 관련된 사용자 동작은 Chrome 70부터 MEI에 기여할 예정입니다. 이렇게 하면 자동재생 및 사용자가 자주 방문하는 웹사이트와 관련하여 사용자가 원하는 의도를 이미 예측할 수 있습니다.

참고로 iframe을 삽입하는 상위 웹페이지가 특정 iframe으로 권한을 확장하는 경우에만 사용자 상호작용 없이 자동재생할 수 있는 권리가 있습니다.

커뮤니티 지원을 위한 변경 연기

웹 오디오 개발자 커뮤니티, 특히 웹 게임 개발자와 이 커뮤니티의 WebRTC 개발자들은 이 변경사항이 Chrome 공개 버전 채널에 표시되었을 때 주목했습니다.

커뮤니티 피드백은 많은 웹 게임 및 웹 오디오 환경이 이러한 변경으로 인해 부정적인 영향을 받을 것이라는 것이었습니다. 특히 업데이트가 되지 않은 많은 사이트가 더 이상 사용자에게 오디오를 재생하지 않을 것이라는 의견이 있었습니다. 따라서 Google 팀은 웹 오디오 개발자에게 웹사이트를 업데이트할 시간을 주기 위해 이 변경사항을 미루는 것이 좋겠다고 결정했습니다.

그 밖에도 다음과 같은 노력을 기울였습니다.

  • 이 정책 변경이 최선의 조치인지 신중하게 생각해 보시기 바랍니다.
  • 영향을 받을 수 있는 오디오가 있는 웹사이트의 수를 줄이는 데 도움이 되는 방법을 알아보세요.

전자의 경우, 대다수 사용자의 사용자 환경을 개선하기 위해 정책 변경이 반드시 필요하다는 결론을 내렸습니다. 정책 변경으로 해결할 수 있는 문제에 대한 자세한 내용은 이 도움말의 다음 섹션에서 확인할 수 있습니다.

후자의 경우, 웹 오디오 구현을 조정하여 원래 영향을 받은 웹사이트의 수를 줄였습니다. 이번 변경으로 인해 손상된 사이트 중 상당수가 웹 게임 개발 커뮤니티에서 제공한 사이트 중 80% 이상이 자동으로 작동하게 되었습니다. 예시 사이트에 대한 분석 및 테스트는 여기에서 확인할 수 있습니다. 새로운 조정은 아래에 자세히 설명되어 있습니다.

또한 WebRTC 애플리케이션을 지원하도록 변경했습니다. 활성 캡처 세션이 있는 동안 자동재생이 허용됩니다.

이 동작 변경을 통해 해결하려는 문제는 무엇인가요?

지금까지 브라우저는 사용자가 사운드를 관리하는 데 도움이 되지 않았습니다. 사용자가 웹페이지를 열었을 때 기대하지 않았거나 원하지 않는 소리가 들리면 사용자 경험이 저하됩니다. 이러한 사용자 환경이 저하된 문제를 해결하고자 합니다. 원치 않는 소음은 사용자가 브라우저에서 콘텐츠를 자동재생하는 것을 원하지 않는 주된 이유입니다.

하지만 사용자가 콘텐츠가 자동재생되기를 원하는 경우 Chrome에서 차단된 자동재생을 사용자가 다시 재생하는 경우가 있습니다.

따라서 Google은 사용자로부터 배우고 웹사이트별로 사용자의 의도를 예측함으로써 최상의 사용자 환경을 만들 수 있다고 믿습니다. 사용자가 웹사이트 콘텐츠를 재생하도록 허용하는 경우 향후 해당 사이트의 콘텐츠가 자동재생됩니다. 반대로 사용자가 특정 웹사이트에서 콘텐츠 자동재생을 중지하려는 경향이 있으면 해당 콘텐츠는 기본적으로 자동재생되지 않습니다.

커뮤니티에서 제안한 제안 중 하나는 자동재생을 일시중지하는 대신 탭의 오디오를 음소거하는 것이었습니다. 하지만 웹사이트에서 자동재생이 차단되었음을 인지하고 웹사이트 개발자가 이에 대응할 수 있도록 자동재생 환경을 중지하는 것이 좋습니다. 예를 들어 단순히 오디오를 음소거하고자 하는 개발자도 있지만, 사용자가 콘텐츠에 적극적으로 참여할 때까지 오디오 콘텐츠가 일시중지되기를 원하는 개발자도 있을 수 있습니다. 그러지 않으면 사용자가 오디오 환경의 일부를 놓칠 수도 있습니다.

웹 게임 개발자를 지원하기 위한 새로운 조정

개발자가 Web Audio API를 사용하는 가장 일반적인 방법은 두 가지 유형의 객체를 만들어 오디오를 재생하는 것입니다.

웹 오디오 개발자는 오디오 재생을 위한 AudioContext를 만들게 됩니다. 자동재생 정책이 AudioContext를 자동으로 정지한 후에 오디오를 재개하려면 사용자가 탭과 상호작용한 후 이 객체에서 restart() 함수를 호출해야 합니다.

    const context = new AudioContext();

    // Setup an audio graph with AudioNodes and schedule playback.
    ...

    // Resume AudioContext playback when user clicks a button on the page.
    document.querySelector('button').addEventListener('click', function() {
      context.resume().then(() => {
        console.log('AudioContext playback resumed successfully');
      });
    });

AudioNode에서 상속되는 많은 인터페이스가 있으며, 그 중 하나가 AudioScheduledSourceNode 인터페이스입니다. AudioScheduledSourceNode 인터페이스를 구현하는 AudioNode를 일반적으로 소스 노드 (예: AudioBufferSourceNode, ConstantSourceNode, OscillatorNode)라고 부릅니다. 소스 노드는 start() 메서드를 구현합니다.

소스 노드는 일반적으로 게임에서 재생되는 개별 오디오 스니펫을 나타냅니다. 예를 들어 플레이어가 코인을 수집할 때 재생되는 사운드나 현재 단계에서 재생되는 배경 음악을 들 수 있습니다. 게임 개발자는 이러한 사운드가 게임에 필요할 때마다 소스 노드에서 start() 함수를 호출할 가능성이 매우 높습니다.

Google은 웹 게임에서 이러한 공통 패턴을 인식한 후 다음과 같이 구현을 조정하기로 했습니다.

다음 두 조건이 충족되면 AudioContext가 자동으로 재개됩니다.

  • 사용자가 페이지와 상호작용했습니다.
  • 소스 노드의 start() 메서드가 호출됩니다.

이러한 변경사항으로 인해 이제 대부분의 웹 게임에서 사용자가 게임을 시작하면 오디오가 다시 시작됩니다.

웹 발전

웹 플랫폼을 발전시키기 위해 때로는 호환성이 손상될 수 있는 변경을 수행해야 할 때가 있습니다. 안타깝게도 오디오 자동재생은 복잡하며 이러한 변화의 범주에 속합니다. 하지만 웹이 정체되거나 혁신적인 우위를 잃지 않도록 하려면 이러한 변화를 만드는 것이 중요합니다.

그럼에도 불구하고 다음과 같은 여러 가지 이유로 웹사이트에 대한 수정사항을 단기적으로 적용하기가 불가능할 수도 있습니다.

  • 웹 개발자가 새 프로젝트에 집중하고 있을 수 있으며 이전 웹사이트를 유지보수하는 것은 바로 불가능합니다.
  • 웹 게임 포털은 카탈로그에 있는 게임의 구현을 제어할 수 없을 수도 있으며, 수천 개 또는 수천 개의 게임을 업데이트하는 데에는 많은 시간과 비용이 들 수 있습니다.
  • 일부 웹사이트는 매우 오래되어 어떤 이유로든 더 이상 관리되지 않지만 역사적 목적을 위해 호스팅되고 있습니다.

다음은 새로운 AudioContext 객체 생성을 가로채고 사용자가 다양한 사용자 상호작용을 수행할 때 이러한 객체의 재개 기능을 자동으로 트리거하는 짧은 JavaScript 코드 스니펫입니다. 이 코드는 웹페이지에서 AudioContext 객체를 만들기 전에 실행해야 합니다. 예를 들어 다음 코드를 웹페이지의 태그에 추가할 수 있습니다.

(function () {
  // An array of all contexts to resume on the page
  const audioContextList = [];

  // An array of various user interaction events we should listen for
  const userInputEventNames = [
    'click',
    'contextmenu',
    'auxclick',
    'dblclick',
    'mousedown',
    'mouseup',
    'pointerup',
    'touchend',
    'keydown',
    'keyup',
  ];

  // A proxy object to intercept AudioContexts and
  // add them to the array for tracking and resuming later
  self.AudioContext = new Proxy(self.AudioContext, {
    construct(target, args) {
      const result = new target(...args);
      audioContextList.push(result);
      return result;
    },
  });

  // To resume all AudioContexts being tracked
  function resumeAllContexts(event) {
    let count = 0;

    audioContextList.forEach(context => {
      if (context.state !== 'running') {
        context.resume();
      } else {
        count++;
      }
    });

    // If all the AudioContexts have now resumed then we
    // unbind all the event listeners from the page to prevent
    // unnecessary resume attempts
    if (count == audioContextList.length) {
      userInputEventNames.forEach(eventName => {
        document.removeEventListener(eventName, resumeAllContexts);
      });
    }
  }

  // We bind the resume function for each user interaction
  // event on the page
  userInputEventNames.forEach(eventName => {
    document.addEventListener(eventName, resumeAllContexts);
  });
})();

이 코드 스니펫은 iframe 자체의 콘텐츠 범위 내에 포함되지 않는 한 iframe 내에서 인스턴스화된 AudioContext의 재개를 지원하지 않습니다.

사용자에게 더 나은 서비스 제공

정책 변경에 따라 자동 학습이 예상대로 작동하지 않는 경우 또는 변경사항으로 인해 사용할 수 없게 된 웹사이트에 대해 사용자가 자동재생 정책을 사용 중지할 수 있는 메커니즘도 도입됩니다. 이 변경사항은 Chrome 71의 새 정책과 함께 출시될 예정이며 소리 설정에서 확인할 수 있습니다. 사용자가 자동재생을 허용하려는 사이트는 허용 목록에 추가할 수 있습니다.

신규 사용자를 위한 MEI는 어떻게 구성되어 있나요?

앞서 언급했듯이 Google은 자동 재생 콘텐츠가 포함된 특정 웹사이트와 관련된 사용자가 원하는 의도를 예상하기 위해 사용자의 행동을 기반으로 시간이 지남에 따라 MEI를 자동으로 빌드합니다. 이 색인에서는 각 웹사이트의 점수가 0점과 1점 사이입니다. 점수가 높을수록 사용자가 해당 웹사이트에서 콘텐츠가 재생될 것으로 예상한다는 의미입니다.

하지만 신규 사용자 프로필이나 사용자가 인터넷 사용 기록을 지우는 경우에는 자동재생을 어디서나 차단하는 대신 익명 처리된 사용자 집계 MEI 점수를 기반으로 하는 프리시드 목록을 사용하여 자동재생할 수 있는 웹사이트를 결정합니다. 이 데이터는 사용자 프로필 생성 시의 MEI 초기 상태만 확인합니다. 사용자가 웹을 탐색하고 자동 재생 콘텐츠가 있는 웹사이트와 상호작용할 때 개인 MEI가 기본 구성을 재정의합니다.

사전 시드 사이트 목록은 수동으로 선별되지 않고 알고리즘을 통해 생성되며 모든 웹사이트를 포함할 수 있습니다. 해당 사이트를 방문한 충분한 수의 사용자가 해당 사이트에서 자동재생을 허용하면 사이트가 목록에 추가됩니다. 이 기준은 백분율을 기준으로 하므로 대형 사이트를 선호하지 않습니다.

균형 찾기

Google의 의사 결정 절차와 이 정책의 설계 근거에 대한 보다 유용한 정보를 제공하기 위해 새로운 문서를 게시했습니다. 사전 시드 사이트 목록의 작동 방식에 관한 새로운 문서도 있습니다.

Google은 항상 사용자를 최우선으로 생각하지만 웹 개발 커뮤니티를 실망시키고 싶지도 않습니다. 때로는 브라우저를 사용한다는 것은 이 두 가지 목표의 균형을 잘 맞추어야 한다는 것을 뜻하기도 합니다. Google은 정책 구현을 조정하고 웹 오디오 개발자가 코드를 업데이트할 수 있도록 시간을 추가로 확보하여 Chrome 71에서도 이러한 균형을 달성할 수 있을 것으로 기대합니다.

의견