[React] 유튜브 썸네일 추출 방법

우지끈·2024년 11월 19일
post-thumbnail

뉴스피드 프로젝트로 추천하고 싶은 노래의 유튜브 url, 제목, 설명을 적으면 피드에 업로드 해주는 사이트를 제작하고 있었다.

유저에게 유튜브 url를 받아 화면에 그대로 그려주면 자동으로 썸네일이 뜰 것(도대체 왜?)이라 생각했지만 역시 아무것도 뜨지 않았다 ^^...

const PostCard = ({ post, type }) => {
  return (
    <PostCardContainer>
      <PostCardHeader>
        <ProfileImage src={post.users.profile_url} alt={post.users.nickname} />
        <span>{post.users.nickname}</span>
      </PostCardHeader>
      <Title>
        <p>{post.title}</p>
      </Title>
      // post.song_url 자리에 유튜브 링크가 들어간다.
      <Thumbnail src={post.song_url} alt={post.title} />
      {type === 'mypost' && (
        <ButtonBox>
          <EditButton to="">수정</EditButton>
          <DeleteButton>삭제</DeleteButton>
        </ButtonBox>
      )}
    </PostCardContainer>
  );
};

supabase에서 해당 데이터를 받아와 그려줬을 때의 화면은 다음과 같다.

post.users.profile_url, nickname, title은 알맞게 렌더링 되었으나 썸네일 이미지가 렌더링 되지 않아 alt에 적어둔 post.title이 대신 렌더링 된 것을 확인할 수 있다.


내가 의도한대로 유튜브 링크의 썸네일을 표시하려면
1. 유튜브의 영상 ID를 추출한 뒤,
2. 유튜브 썸네일 URL을 따로 구성하여
3. 이미지를 렌더링 해줘야 했다.

유튜브 썸네일 URL은 다음과 같은 형식을 따른다.

https://img.youtube.com/vi/[VIDEO_ID]/hqdefault.jpg

[VIDEO_ID] 부분에 유튜브 영상의 고유 ID가 들어가면 된다.
예를 들어, 내가 사용하고자 하는 유튜브 URL이 https://www.youtube.com/watch?v=2jMdRxeZEkQ 라면,

해당 영상의 썸네일 URLhttps://img.youtube.com/vi/2jMdRxeZEkQ/hqdefault.jpg인 것이다.

그리고 고유ID 추출 전에 한 가지 더 알아둬야 하는 게 있는데, 유튜브 링크는 총 세 가지의 형식으로 제공될 수 있다는 것이다.

  1. 표준 링크: https://www.youtube.com/watch?v=2jMdRxeZEkQ

    • 유튜브 웹사이트에서 기본적으로 생성되는 링크 형식
    • v라는 쿼리 매개변수로 유튜브 영상의 고유 ID 전달
    • 추가적인 정보나 매개변수 함께 전달 가능
      - ex. https://www.youtube.com/watch?v=abcd1234&t=60s → 60초부터 재생
    • 주 사용 목적: 유튜브 플랫폼에서의 유저의 영상 시청
  2. 짧은 링크: https://www.youtu.be/2jMdRxeZEkQ

    • 간결한 URL 형식으로, 유튜브에서 공유 기능을 통해 생성
    • 주 사용 목적: 링크 공유
  3. 임베드 링크: https://www.youtube.com/embed/2jMdRxeZEkQ

    • 임베드(Embed) 용도로 설계된 링크
    • 유튜브 영상을 iframe으로 다른 웹사이트에 삽입할 때 사용
    • 주 사용 목적: 다른 웹사이트에서 영상 삽입

이제 유튜브 링크의 형식과 고유 ID의 위치를 알게 되었으니, 이를 기반으로 링크에서 고유 ID를 추출 후 썸네일 URL을 구성하여 사용하면 정상적으로 썸네일이 렌더링 될 것이다.


처음에는

export const getYoutubeThumbnailUrl = (youtubeUrl) => {
  const regex = /(?:https?:\/\/)?(?:www\.)?(?:youtube\.com\/(?:[^/]+\/.+\/|(?:v|e(?:mbed)?)\/|.*[?&]v=)|youtu\.be\/)([^"&?/\s]{11})/;

이런식으로 정규표현식을 사용해보려 했으나, 저렇게 복잡한 정규표현식을 사용하는게 익숙하지 않을 뿐더러, 현재 프로젝트는 팀 프로젝트이기에 가독성 측면을 좀 더 고려하여 코드를 작성하게 되었다.

export const getYoutubeThumbnailUrl = (youtubeUrl) => {
  let videoId = '';

  // 1. 표준 링크 처리
  if (youtubeUrl.includes('youtube.com/watch?v=')) {
    videoId = youtubeUrl.replace('https://www.youtube.com/watch?v=', '').split('&')[0]; 
    // split('&')[0]: 매개변수가 있는 경우 잘라내기 위함
  }
  // 2. 짧은 링크 처리
  else if (youtubeUrl.includes('youtu.be/')) {
    videoId = youtubeUrl.replace('https://youtu.be/', '').split('?')[0];
  }
  // 3. 임베드 링크 처리
  else if (youtubeUrl.includes('youtube.com/embed/')) {
    videoId = youtubeUrl.replace('https://www.youtube.com/embed/', '').split('?')[0];
  }

  // 4. 썸네일 URL 반환(videoId 없으면 빈 문자열 반환)
  return videoId ? `https://img.youtube.com/vi/${videoId}/hqdefault.jpg` : '';
};

이렇게 유튜브 썸네일 URL을 반환해주는 유틸 함수를 만들고,

import { getYoutubeThumbnailUrl } from '../../utils/youtubeThumbnail';

const PostCard = ({ post, type }) => {
  const thumbnailUrl = getYoutubeThumbnailUrl(post.song_url);
  return (
    <PostCardContainer>
      <PostCardHeader>
        <ProfileImage src={post.users.profile_url} alt={post.users.nickname} />
        <span>{post.users.nickname}</span>
      </PostCardHeader>
      <Title>
        <p>{post.title}</p>
      </Title>
      <Thumbnail src={thumbnailUrl} alt={post.title} />
      {type === 'mypost' && (
        <ButtonBox>
          <EditButton to="">수정</EditButton>
          <DeleteButton>삭제</DeleteButton>
        </ButtonBox>
      )}
    </PostCardContainer>
  );
};

export default PostCard;

PostCard를 그려주기 전, post.song_urlgetYoutubeThumbnailUrl을 통해 썸네일 url로 변환 후, src 자리에 넣어주면...!!!

썸네일이 아주 예쁘게 잘 나오는 걸 확인할 수 있다!

0개의 댓글