기존에는 한 페이지에 속하는 동영상을 모두 한 번에 로딩했었다.
한 페이지에는 3개의 게시글이 있고 한 게시글에는 최대 15개의 동영상이 있으니 사용자는 최대 45개의 동영상을 한 번에 로딩할 수도 있는 상황
🚨 당연히 페이지 로딩 속도가 매우 느려졌고, 불필요한 셀룰러 데이터 소모가 일어났다.(접속만 해도 100MB 이상이 확 소모됐다.)
HLS 방식을 이용해서 사용자가 재생하는 부분만 스트리밍하는 방식이 가장 보편적인 것 같아서 변경해봤는데, .m3u8파일을 잘 읽어와서 재생은 됐다. 그런데 유의미한 데이터 절약이 되지 않았다.
아마 해당 페이지에 이미 S3 URL을 모두 불러왔기 때문에 한 번에 스트리밍하는 것이 원인인 것 같았고, 게다가 안드로이드 환경에서 별도의 플레이어가 필요하다고해서 ▶️ 패스
사용자가 시청을 시작하면 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": ""
}
기존은 findAll로 post의 모든 레코드를 조회했다. 그래서 위 처럼 media에 들어간 동영상 URL을 모두 가져왔다.
{
"gym_name": "",
"post_idx": ,
"user_idx": ,
"gym_idx": ,
"clearday": "",
"thumbnailUrl": []
"content": ""
}
기존 응답에서exclude: ["media"] 로 media 배열을 제외시켰다.
이것만 해도 재생할 동영상이 없으니 페이지 로딩속도가 확실하게 차이가 났다.
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를 쿼리로 받아서 응답해준다.