뉴스피드 프로젝트로 추천하고 싶은 노래의 유튜브 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 라면,
해당 영상의 썸네일 URL은
https://img.youtube.com/vi/2jMdRxeZEkQ/hqdefault.jpg인 것이다.
그리고 고유ID 추출 전에 한 가지 더 알아둬야 하는 게 있는데, 유튜브 링크는 총 세 가지의 형식으로 제공될 수 있다는 것이다.
표준 링크: https://www.youtube.com/watch?v=2jMdRxeZEkQ
v라는 쿼리 매개변수로 유튜브 영상의 고유 ID 전달https://www.youtube.com/watch?v=abcd1234&t=60s → 60초부터 재생짧은 링크: https://www.youtu.be/2jMdRxeZEkQ
임베드 링크: https://www.youtube.com/embed/2jMdRxeZEkQ
이제 유튜브 링크의 형식과 고유 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_url을 getYoutubeThumbnailUrl을 통해 썸네일 url로 변환 후, src 자리에 넣어주면...!!!

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