ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • 자동재생을 켰는데 비디오가 멈춰 있는 이유
    Programming 2026. 10. 4. 00:48
    728x90
    반응형

    play 요청 뒤 시작됨, NotAllowedError, NotSupportedError로 나뉘는 세 갈래 도식
    재생 요청의 결과에 따라 화면과 진단 경로를 나눕니다.

    비디오에 autoplay를 넣어도 첫 화면이 그대로 멈춰 있을 수 있습니다. 브라우저가 소리 있는 자동재생을 제한하거나, 미디어 파일 자체를 재생할 수 없는 상황입니다. autoplay 속성만 믿지 말고 play()의 성공·거부를 처리하며 사용자가 누를 재생 경로를 제공하세요.

    화면의 재생 버튼이 일시정지 버튼으로 바뀌었는데 영상은 안 움직이는 경우도 같은 지점에서 생깁니다. 코드가 재생을 요청한 순간에 화면 상태를 바꿨기 때문입니다. play()가 돌려주는 Promise의 결과를 기다리면 이 어긋남을 줄일 수 있습니다.

    이 글의 코드는 현대 브라우저에서 Promise를 반환하는 play()를 전제로 한 작성 예시입니다. 2026년 9월 28일 MDN 문서를 확인했으며 실제 미디어 파일이나 브라우저별 재생 결과는 포함하지 않았습니다.

    무음 미리보기와 음성 설명은 시작 방식부터 다릅니다

    페이지에 들어오자마자 소리가 나면 사용자는 어느 탭에서 나는지부터 찾아야 합니다. 브라우저의 자동재생 정책은 이런 원치 않는 재생을 제한합니다. 사용자와 사이트의 상호작용, 소리 유무, 브라우저 설정, iframe의 정책 등에 따라 허용 조건이 달라집니다. JavaScript에서 play()를 호출하는 것도 이 정책의 영향을 받습니다. 자동재생 안내

    제품 기능을 보여 주는 무음 미리보기라면 muted를 사용해 자동 시작을 시도할 수 있습니다. 설명 음성이 핵심인 비디오는 제목과 재생 버튼을 먼저 보여 주고 사용자가 시작하도록 하는 편이 내용을 전달하기 쉽습니다. 음성을 없앤 채 재생 성공만 확보하면 설명을 놓칠 수 있기 때문입니다.

    무음 자동재생도 시작 실패를 처리할 화면이 필요합니다. 예를 들어 미리보기가 멈춰 있어도 기능을 설명하는 포스터와 한 줄 설명이 남아 있으면 방문자는 빈 영역을 보고 기다리지 않습니다. 포스터는 아직 재생하지 않았다는 상태도 자연스럽게 보여 줍니다.

    재생이 시작됐을 때 화면을 바꿉니다

    다음은 무음 미리보기용 구성입니다. /media/demo.mp4와 /media/demo-poster.jpg는 사이트에서 준비해야 할 예시 경로입니다. playsinline은 인라인 재생을 요청하는 속성이며 자동재생 허가 자체를 뜻하지 않습니다.

    <video id="preview"
      muted playsinline controls
      preload="metadata"
      poster=
        "/media/demo-poster.jpg">
      <source src="/media/demo.mp4"
        type="video/mp4">
    </video>
    <button id="start"
      type="button">재생</button>
    <p id="status" role="status"></p>
    

    여기서는 autoplay 속성 대신 스크립트가 처음 한 번 재생을 요청합니다. 시작 결과에 맞춰 안내 문장을 바꾸기 위해서입니다. controls는 사용자가 일시정지나 탐색을 할 수 있도록 남겨 둡니다.

    const video =
      document.querySelector(
        "#preview"
      );
    const button =
      document.querySelector(
        "#start"
      );
    const status =
      document.querySelector(
        "#status"
      );
    
    async function startVideo() {
      button.disabled = true;
      status.textContent =
        "재생을 시작하는 중입니다.";
      try {
        await video.play();
        status.textContent = "";
        button.hidden = true;
      } catch (error) {
        button.hidden = false;
        if (
          error.name ===
          "NotAllowedError"
        ) {
          status.textContent =
            "재생 버튼을 눌러 " +
            "시작해 주세요.";
        } else if (
          error.name ===
          "NotSupportedError"
        ) {
          status.textContent =
            "이 미디어를 " +
            "재생할 수 없습니다.";
        } else {
          status.textContent =
            "재생을 시작하지 " +
            "못했습니다.";
        }
      } finally {
        button.disabled = false;
      }
    }
    
    button.addEventListener(
      "click", startVideo
    );
    startVideo();
    

    await video.play()가 완료된 다음에 별도 시작 버튼을 숨깁니다. 실패하면 버튼과 안내를 남기고 기본 미디어 조작도 유지합니다. 시작 허가를 기다리는 동안 Promise가 바로 끝나지 않을 수도 있어 요청 중 상태를 따로 표시했습니다. play()의 반환값

    이 예시에서 자동 시작이 거부되면 사용자는 버튼을 눌러 직접 요청할 수 있습니다. 클릭 이벤트 안에서 곧바로 play()를 호출하는 경로입니다. 다만 사용자 클릭이 파일 손상이나 상위 프레임의 정책까지 고치지는 않으므로 두 번째 실패도 같은 방식으로 처리합니다.

    버튼을 더 눌러도 고쳐지지 않는 오류가 있습니다

    NotAllowedError라면 자동재생 정책과 페이지의 실행 환경을 봅니다. 사용자가 시작하는 재생이 가능한지, 사이트 설정이 차단돼 있는지, 외부 페이지 안에 삽입됐는지가 진단 단서입니다.

    NotSupportedError는 지원되는 미디어 소스로 재생할 수 없을 때의 오류입니다. 이때는 개발자 도구의 네트워크 패널에서 실제 요청이 어떤 응답을 받았는지 확인합니다. MP4 주소에 로그인 HTML이 내려왔거나 파일 경로가 잘못됐다면 클릭을 반복할 이유가 없습니다. 파일 확장자만 보지 말고 전달된 파일과 형식을 확인해야 합니다. play() 예외

    play()가 성공한 뒤에도 재생 도중 네트워크나 디코딩 오류가 생길 수 있습니다. 그래서 위 함수의 성공을 비디오 전체 재생 성공으로 기록하면 안 됩니다. 실제 플레이어에서는 미디어의 error 이벤트와 video.error도 함께 처리해야 합니다.

    video.addEventListener(
      "error", () => {
      status.textContent =
        "파일을 불러오거나 " +
        "재생하는 중 오류가 났습니다.";
      button.hidden = false;
    });
    

    이 핸들러는 사용자에게 멈춘 이유를 알려 주는 최소 장치입니다. 재시도 횟수와 오류 로그의 상세 수준은 서비스에 맞춰 정합니다. 자동으로 play()를 무한 반복하면 문제 원인은 그대로 둔 채 같은 요청만 늘어납니다.

    iframe에서는 삽입한 쪽의 설정도 확인합니다

    자체 페이지에서는 재생되는데 다른 사이트에 넣었을 때만 멈춘다면 iframe을 살펴볼 차례입니다. 상위 문서의 Permissions Policy와 iframe의 allow가 자동재생 허용 범위에 관여합니다. 삽입된 플레이어 내부의 속성만 수정해서는 해결되지 않을 수 있습니다.

    예를 들어 삽입하는 쪽에서 allow="autoplay"로 기능을 위임하는 구성이 있습니다. 이것은 브라우저의 모든 자동재생 제한을 해제하는 버튼이 아닙니다. 상위 정책과 사용자 설정을 포함한 실제 문맥에서 허용 여부가 결정됩니다. 자동재생 Permissions Policy

    확인할 때는 같은 파일을 독립 페이지와 iframe 페이지에서 각각 열어 보세요. 독립 페이지도 실패하면 먼저 파일과 재생 오류를 조사합니다. 삽입됐을 때만 실패하면 상위 페이지의 정책과 프레임 속성을 비교합니다. 이렇게 조건을 하나씩 나눠야 muted, autoplay, allow를 한꺼번에 바꾸고 어느 설정이 영향을 줬는지 놓치는 일을 피할 수 있습니다.

    최종 화면에서는 자동재생이 막힌 상태도 직접 확인합니다. 포스터와 설명이 읽히는지, 키보드로 시작 버튼에 접근할 수 있는지, 실패 안내가 남는지 보면 됩니다. 자동으로 시작되지 않는 방문자도 같은 내용을 볼 수 있어야 합니다.

    728x90
    반응형
Designed by Tistory.