동영상 로딩 방식 변경(전체 요청 -> 개별 요청)

AFDB·2025년 1월 14일

동영상 로딩 방식 변경(전체 요청 -> 개별 요청)

기존에는 한 페이지에 속하는 동영상을 모두 한 번에 로딩했었다.
한 페이지에는 3개의 게시글이 있고 한 게시글에는 최대 15개의 동영상이 있으니 사용자는 최대 45개의 동영상을 한 번에 로딩할 수도 있는 상황
🚨 당연히 페이지 로딩 속도가 매우 느려졌고, 불필요한 셀룰러 데이터 소모가 일어났다.(접속만 해도 100MB 이상이 확 소모됐다.)

고려한 점들

🤔 스트리밍 방식?

HLS 방식을 이용해서 사용자가 재생하는 부분만 스트리밍하는 방식이 가장 보편적인 것 같아서 변경해봤는데, .m3u8파일을 잘 읽어와서 재생은 됐다. 그런데 유의미한 데이터 절약이 되지 않았다.
아마 해당 페이지에 이미 S3 URL을 모두 불러왔기 때문에 한 번에 스트리밍하는 것이 원인인 것 같았고, 게다가 안드로이드 환경에서 별도의 플레이어가 필요하다고해서 ▶️ 패스

🤔 HTTP Range 요청 방식?

사용자가 시청을 시작하면 Range 헤더를 포함한 요청을 보내서 처음부터 일정 구간만 다운로드 받고, 건너뛰거나 다른 구간으로 가면 그 구간만 다시 요청하고 응답하는 방식이다. 이렇게 하면 브라우저는 필요한 구간만 받아오고, 한 번에 전체 파일을 다운로드하지 않는다고 한다.
그런데 Expo-AV 라이브러리는 기본적으로 자동 버퍼링으로 초반에 영상 전체를 긁어오는 로직이기 때문에 결국 전체 용량을 다운로드한다고 한다. 그래서 테스트 로그를 찍어봤는데 구간 요청을 하는 시점에서 오히려 전체 용량을 요청하는 바람에 데이터 소모량이 더 커져버렸다. ▶️ 패스

💡 동영상 전체를 불러오는 게 문제면, 개별로 불러오자

위에서 말한 원인처럼 사용자가 최대 45개의 동영상 URL에 노출되는 환경이 주요 원인 중 하나였다.
그래서 동영상이 1개든, 10개든, 45개든 그냥 뷰포트에 보이는 동영상 1개만 재생하도록 변경하는 것이 가장 직관적이고 근본적인 해결법 같았다.

기존의 응답값

{
    "gym_name": "",
    "post_idx": ,
    "user_idx": ,
    "gym_idx": ,
    "clearday": "",
    "media": [
        "https://버킷이름.s3.ap-northeast-2.amazonaws.com/객체 주소URL.mp4",
        "https://버킷이름.s3.ap-northeast-2.amazonaws.com/객체 주소URL.mp4",
        "https://버킷이름.s3.ap-northeast-2.amazonaws.com/객체 주소URL.mp4",
        "https://버킷이름.s3.ap-northeast-2.amazonaws.com/객체 주소URL.mp4",
        "https://버킷이름.s3.ap-northeast-2.amazonaws.com/객체 주소URL.mp4",
        "https://버킷이름.s3.ap-northeast-2.amazonaws.com/객체 주소URL.mp4",
        "https://버킷이름.s3.ap-northeast-2.amazonaws.com/객체 주소URL.mp4",
        "https://버킷이름.s3.ap-northeast-2.amazonaws.com/객체 주소URL.mp4",
        "https://버킷이름.s3.ap-northeast-2.amazonaws.com/객체 주소URL.mp4",
    ],
    "thumbnailUrl": []
    "content": ""
}

기존은 findAllpost의 모든 레코드를 조회했다. 그래서 위 처럼 media에 들어간 동영상 URL을 모두 가져왔다.

변경된 응답값

{
    "gym_name": "",
    "post_idx": ,
    "user_idx": ,
    "gym_idx": ,
    "clearday": "",
    "thumbnailUrl": []
    "content": ""
}

기존 응답에서exclude: ["media"] 로 media 배열을 제외시켰다.
이것만 해도 재생할 동영상이 없으니 페이지 로딩속도가 확실하게 차이가 났다.

개별 동영상 URL을 요청하는 컨트롤러, 라우터 작성

router.get("/posts/:post_idx/video/:video_index", Cpost.getPostVideo);

exports.getPostVideo = async (req, res) => {
  try {
    const { post_idx, video_index } = req.params;

    const post = await db.Post.findOne({
      where: { post_idx },
      attributes: ["media"],
    });
    // ... 생략
    
    const videoUrl = post.media[video_index];
      res.status(200).json({ videoUrl });
    // ... 생략

사용자가 보는 동영상인 media 컬럼은 배열로 URL이 저장되어 있기 때문에 video_index를 쿼리로 받아서 응답해준다.

결론적으로 사용자의 뷰포트에서 보여지는 1개의 동영상만 가져오는 덕분에 기존에 매우 느렸던 페이지 로딩과 동영상 재생이 해결됐다.

0개의 댓글