
.env 파일에 넣어서 관리해 주었다.
v= 으로 시작하는 부분이 있는데 이것이 해당 콘텐츠의 ID다.
videos 다음에 쿼리스트링으로 id와 먼저 발급받은 key 값을 변수로 넣어준다.
const getYoutubeData = async (id: any) => {
try {
const res =
await axios.get(`https://www.googleapis.com/youtube/v3/videos?id=${id}&key=${process.env.REACT_APP_YOUTUBE_API_KEY}
&part=snippet`);
return res.data.items[0]?.snippet;
} catch (err) {
console.error(err);
}
};

사용자가 해당 유튜브의 전체 url을 복사 붙여넣기 하면 우리는 id 부분만 필터링해서 받아와야 한다.
정규식을 이용하여 id 부분만 필터링해서 가져온다.
const filteredUrlId = (allUrl: string) => {
if (allUrl.indexOf("/watch") > -1) {
const arr = allUrl.replaceAll(/=|&/g, "?").split("?");
return arr[arr.indexOf("v") + 1];
} else if (allUrl.indexOf("/youtu.be") > -1) {
const arr = allUrl.replaceAll(/=|&|\//g, "?").split("?");
return arr[arr.indexOf("youtu.be") + 1];
} else {
return;
}
};
1개의 플레이리스트에 channelId, title, thumbnails, url 4개의 데이터가 필요하기 때문에 각각 객체에 담아서 추가해 주는 방식으로 구현했다.
먼저 플레이리스트의 4가지 데이터를 담을 빈 객체를 만들어주고, 필터링 한 id를 변수에 저장해 준다.
const musicInfo: PlaylistData = {};
let urlId = filteredUrlId(newUrl);
그리고 필터링 한 id에서 정보를 불러온다. 여기서 thumbnail에 if문을 사용한 이유는 고화질의 썸네일의 해상도 때문이다.
고해상도인 maxres의 경우 없는 콘텐츠도 있기 때문에 없는 경우 일반 해상도의 mediume으로 불러오도록 했다.
4개의 데이터를 객체에 저장했다면 1개의 컨텐츠가 담긴 객체를 플레이리스트 배열에 앞에서부터 추가해 준다.
const res = await getYoutubeData(urlId);
musicInfo.channelId = res.channelId;
if (res.thumbnails.maxres) {
musicInfo.thumbnail = res.thumbnails.maxres.url;
} else {
musicInfo.thumbnail = res.thumbnails.medium.url;
}
musicInfo.title = res.title;
musicInfo.url = newUrl;
setNewPlayList((value) => [...value, musicInfo]);
setNewUrl("");
썸네일 해상도 차이
maxres해상도가 없는 컨텐츠
maxres해상도가 있는 컨텐츠
const [newPlayList, setNewPlayList] = useState<PlaylistData[]>([]);
const [newUrl, setNewUrl] = useState<string>("");
// input에 등록한 Url 정보 불러오는 함수
const getYoutubeData = async (id: any) => {
try {
const res =
await axios.get(`https://www.googleapis.com/youtube/v3/videos?id=${id}&key=${process.env.REACT_APP_YOUTUBE_API_KEY}
&part=snippet`);
console.log(res);
return res.data.items[0]?.snippet;
} catch (err) {
console.error(err);
}
};
// 전체 url을 입력받은 후 id만 필터링하는 함수
const filteredUrlId = (allUrl: string) => {
if (allUrl.indexOf("/watch") > -1) {
const arr = allUrl.replaceAll(/=|&/g, "?").split("?");
return arr[arr.indexOf("v") + 1];
} else if (allUrl.indexOf("/youtu.be") > -1) {
const arr = allUrl.replaceAll(/=|&|\//g, "?").split("?");
return arr[arr.indexOf("youtu.be") + 1];
} else {
return;
}
};
// 불러온 데이터를 플레이리스트 배열에 추가하는 이벤트 핸들러
const addPlayList = async () => {
const musicInfo: PlaylistData = {};
let urlId = filteredUrlId(newUrl);
const res = await getYoutubeData(urlId);
musicInfo.channelId = res.channelId;
if (res.thumbnails.maxres) {
musicInfo.thumbnail = res.thumbnails.maxres.url;
} else {
musicInfo.thumbnail = res.thumbnails.medium.url;
}
musicInfo.title = res.title;
musicInfo.url = newUrl;
setNewPlayList((value) => [...value, musicInfo]);
setNewUrl("");
};
새로 추가할 리스트의 url과 newPlayList에 담겨있는 리스트들의 url 중 동일한 url이 있을 경우 urlId를 "sameUrl"로 바꾸고 플레이리스트 추가를 제한하는 방식으로 구현해 보았다.
newPlayList를 map으로 순회하면서 newPlayList에 있는 url과 현재 사용자가 추가한 url이 담겨있는 state newUrl의 url이 동일하다면 urlId를 "sameUrl"로 바꾼다.
그리고 urlId가 "sameUrl"일 경우 이미 추가한 플레이리스트라는 alert을 return 한다.
newPlayList.map((value) => {
if (value.url === newUrl) {
urlId = "sameUrl";
}
});
if (urlId === "sameUrl") {
return toast.error("이미 추가한 플레이리스트 입니다.");
}
check 변수의 값을 true로 바꿔주고 true인 경우에만 플레이리스트 배열에 추가해 준다.let check = false;
const res = await getYoutubeData(urlId);
if (res) {
check = true;
musicInfo.channelId = res.channelId;
if (res.thumbnails.maxres) {
musicInfo.thumbnail = res.thumbnails.maxres.url;
} else {
musicInfo.thumbnail = res.thumbnails.medium.url;
}
musicInfo.title = res.title;
musicInfo.url = newUrl;
} else {
return toast.error("url을 다시 확인해 주세요.");
}
if (check) {
setNewPlayList((value) => [...value, musicInfo]);
setNewUrl("");
}
const addPlayList = async () => {
// 플레이리스트 등록 개수 제한(리스트가 20개 이상일 경우 alert 발생)
if (newPlayList.length >= 20) {
return toast.error("플레이리스트는 최대 20개까지만 등록 가능합니다.");
}
const musicInfo: PlaylistData = {};
let urlId = filteredUrlId(newUrl);
newPlayList.map((value) => {
if (value.url === newUrl) {
urlId = "sameUrl";
}
});
if (urlId === "sameUrl") {
return toast.error("이미 추가한 플레이리스트 입니다.");
}
let check = false;
const res = await getYoutubeData(urlId);
if (res) {
check = true;
musicInfo.channelId = res.channelId;
if (res.thumbnails.maxres) {
musicInfo.thumbnail = res.thumbnails.maxres.url;
} else {
musicInfo.thumbnail = res.thumbnails.medium.url;
}
musicInfo.title = res.title;
musicInfo.url = newUrl;
} else {
return toast.error("url을 다시 확인해 주세요.");
}
if (check) {
setNewPlayList((value) => [...value, musicInfo]);
setNewUrl("");
}
};