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

Tom Greenaway
Hongchan Choi

2017년 9월, 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에 확장하는 경우에만 iframe이 사용자 상호작용 없이 자동재생 권한을 얻을 수 있습니다.

커뮤니티를 지원하기 위해 변경사항 지연

Web Audio 개발자 커뮤니티, 특히 이 커뮤니티의 웹 게임 개발자 및 WebRTC 개발자 부분에서는 이 변경사항이 Chrome 안정화 버전 채널에 표시되었을 때 주목했습니다.

커뮤니티의 의견에 따르면 많은 웹 게임과 웹 오디오 환경이 이번 변경사항의 부정적인 영향을 받을 것으로 보입니다. 특히 업데이트되지 않은 많은 사이트에서 더 이상 사용자에게 오디오를 재생하지 못하게 됩니다. 이에 따라 웹 오디오 개발자가 웹사이트를 업데이트할 시간을 더 확보할 수 있도록 이 변경사항을 연기하기로 결정했습니다.

또한 이번 기회에 다음과 같은 작업도 진행했습니다.

  • 이 정책 변경이 최선의 조치였는지 진지하게 고려합니다.
  • 영향을 받는 오디오가 포함된 웹사이트의 수를 줄이는 데 도움이 되는 방법을 살펴보세요.

전자의 경우, YouTube는 대다수 사용자의 사용자 환경을 개선하기 위해 정책 변경이 실제로 필요하다고 판단했습니다. 정책 변경으로 해결되는 문제에 관한 자세한 내용은 이 도움말의 다음 섹션을 참고하세요.

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

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

이번 동작 변경의 목표는 무엇인가요?

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

하지만 사용자가 콘텐츠를 자동재생하기를 원하는 경우도 있으며, Chrome에서 차단된 자동재생이 상당수 사용자에 의해 재생됩니다.

따라서 Google은 사용자로부터 학습하고 웹사이트별로 사용자 의도를 예측하여 최고의 사용자 환경을 만들 수 있다고 생각합니다. 사용자가 웹사이트에서 콘텐츠를 재생하는 경향이 있는 경우 향후 해당 사이트의 콘텐츠가 자동재생됩니다. 반대로 사용자가 특정 웹사이트의 콘텐츠 자동재생을 중지하는 경향이 있는 경우 기본적으로 해당 콘텐츠의 자동재생이 차단됩니다.

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

웹 게임 개발자를 위한 새로운 조정사항

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

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

    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 객체의 생성을 가로채고 사용자가 다양한 사용자 상호작용을 실행할 때 이러한 객체의 resume 함수를 자동 트리거하는 짧은 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는 어떻게 구성되나요?

앞서 언급한 바와 같이 YouTube는 자동재생 콘텐츠가 있는 특정 웹사이트와 관련하여 사용자가 원하는 의도를 예측하기 위해 사용자의 행동을 기반으로 시간이 지남에 따라 MEI를 자동으로 빌드합니다. 각 웹사이트는 이 색인에서 0~1 사이의 점수를 부여받습니다. 점수가 높을수록 사용자가 해당 웹사이트에서 콘텐츠가 재생되기를 기대한다는 의미입니다.

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

사전 시드된 사이트 목록은 수동으로 선별되는 것이 아니라 알고리즘에 의해 생성되며 모든 웹사이트를 포함할 수 있습니다. 사이트를 방문하는 충분한 수의 사용자가 해당 사이트에서 자동재생을 허용하는 경우 사이트가 목록에 추가됩니다. 이 기준점은 큰 사이트에 유리하지 않도록 비율을 기준으로 합니다.

균형 찾기

이 정책의 결정 과정 및 설계 근거에 대해 자세히 설명하는 새로운 문서를 게시했습니다. 사전 시드된 사이트 목록의 작동 방식에 관한 새로운 문서도 제공됩니다.

Google은 항상 사용자를 최우선으로 생각하지만 웹 개발 커뮤니티를 실망시키고 싶지 않습니다. 브라우저의 경우 이러한 두 가지 목표를 신중하게 조정해야 하는 경우가 있습니다. 정책 구현을 조정하고 웹 오디오 개발자가 코드를 업데이트할 수 있도록 시간을 더 제공함으로써 Chrome 71에서 이 균형을 맞출 수 있을 것으로 기대합니다.

의견