[spotify-api] VINYLIFY : ์คํฌํฐํ์ด apiํ์ฉํ ๊ฒ์ + ์ฌ์ ํ๋ก์ ํธ(n)๊ฒ์ ๊ฒฐ๊ณผ react-infinite-scroll๊ณผ useI
๐ ๋๋์ด 2๋ฌ(?) ์ ๋ ๊ธด ๊ธฐ๊ฐ ๋์ ์งํํ๋ ํ๋ก์ ํธ๊ฐ ์ง์ง ๋์ ๋ฐ๋ผ๋ณด๊ณ ์๋ ๋๋! ๐ฅณ ์ ๋ฆฌํด์ ํ๋ฒ์ ์ฌ๋ฆฌ๋ ค๋ค๊ฐ ์ถํ ๊ธฐ๋ (?)์ผ๋ก ์ค๋ ๋ฐ๋ํ๊ฒ ๋๋ธ react-infinite-scroll+ useInfiniteQuery๋ฌด
pyotato-dev.tistory.com
๐ฅณ ๋๋์ด vercel๋ก ๋ฐฐํฌ! ํด์ ๋์๊ฐ๋ ๊ฑฐ ํ๋ฒ ๋ณด์! ํ๋๋ฐ..
์ผ์ ๋ฌด์จ ์ผ์ด์ผ! ๊ฐ์ฌ๋ฅผ ๋ถ๋ฌ์ค๋ api๊ฐ ๊ณ์ html document๋ฅผ ํธ์ถํ๊ณ ์์ด์ ๊ฐ์ฌ๋ฅผ ์์ ๊ฐ์ ธ์ค์ง ๋ชปํ๊ณ ์๋ค๋..
๋ฐฐํฌ ํ๊ฒฝ์์๋ง ๊ทธ๋ ๊ณ , dev ํ๊ฒฝ์์๋ ์ ๋์๊ฐ์ ๋ ํฉ๋นํ๋ค.
๐ต๏ธ ๋ฌธ์ ํ์
1. dev์์ ์ ๋์๊ฐ๊ณ , vercel๋ก ๋ฐฐํฌํ ํ๊ฒฝ์์๋ง ๋ฌธ์ ๊ฐ ์๋ค.
2. genius api ์ด์ธ์ ๋ค๋ฅธ api๋ค์ ๋ฌธ์ ๊ฐ ์๋ค.
๊ทธ๋ ๊ฒ ์์๋ ํ๋ฆฐ ๊ทธ๋ฆผ ์ฐพ๊ธฐ..
์๋ 1 : vite๋ก spa๋ฅผ ๋ง๋ค์ด์ฃผ๋ ค๋ฉด vercel.json์ ์ค์ ์ ํด์ค์ผํ๋๋ฐ, ์ฌ๊ธฐ์ ๋ฌธ์ ๊ฐ ์๊ฒผ๋?
vite spa๋ฅผ ์ํด์๋ ๊ฒฝ๋ก์ ๋ํ ์ค์ ์ vercel.json ํ์ผ์ ํด์ค์ผํ๋ค.
{
"rewrites": [
{
// ์ค์ ์ ์ํ๋ฉด '/'์ ์ธ ๋ชจ๋ ํ์ด์ง 404
"source": "/(.*)",
"destination": "/index.html"
}
],
}
ํน์ ์์ ์ค์ ๋๋ฌธ์ ๋ชจ๋ GET ์์ฒญ์ด html์ ๋ฐํํ๋๋ก ์ค์ ์ด ๋์๋?
NOPE! ๊ฐ๋ฐ์ ๋๊ตฌ๋ฅผ ์ด์ด ๋คํธ์ํฌ ๊ฒฐ๊ณผ๋ฅผ ์ดํด๋ณด๋ ๋ค๋ฅธ GET ์์ฒญ๋ค์ ํ์ด์ง๋ฅผ ๋ฐํํ๊ณ ์์ง ์๋ค.
์๋ 2 : vite.config.ts ์ค์ ์ด ์ ๋จน๋? vercel.json์๋ rewrite ๋๊ฐ์ด ํด๋ณด์
dev ํ๊ฒฝ์์ vite.config.ts๋ ๋ค์๊ณผ ๊ฐ์ด ์ค์ ์ ํด๋๊ณ , ํ๋ก์๋ฅผ ํตํด ํด๋ผ์ด์ธํธ์์ /genius/api๋ก ์์ฒญ์ ๋ณด๋ด๋ฉด
์๋ฒ์ธ https://api.genius.com์ผ๋ก ๋ณด๋ด ์ฃผ๋ฉด cors ๋ฌธ์ ์์ด api์ ๋ฐ์ดํฐ๋ฅผ ๊ฐ์ ธ์ฌ ์ ์์๋ค.
server: {
proxy: {
'/genius/api': {
target: 'https://api.genius.com',
changeOrigin: true,
rewrite: path => path.replace(/^\/genius\/api/, ''),
},
},
},
vercel.json์ ๋ค์๊ณผ ๊ฐ์ด ์ถ๊ฐํด ์คฌ๋ค.
{
"rewrites": [
{
"source": "/genius/api/:match*",
"destination": "https://api.genius.com/:match*"
},
{
"source": "/(.*)",
"destination": "/index.html"
}
]
}
์ด๋ ๊ฒ ํด๊ฒฐ๋์๋ค๋ฉด ๊น๋ํ๊ฒ ์ง๋ง, ์ ํ ๋ฌ๋ผ์ง์ง ์์๋ค.
์คํ๋ ค CORS ์๋ฌ ใ ใ ๋ฐ์.. header ์ค์ ๋ ํด์คฌ์ง๋ง ํด๊ฒฐ๋์ง ์์๋ค.
์๋ 3 : ๋๋ ๊ฑธ ๋ฐ๋ผ ํ์.
๋ค๋ฅธ api๋ค์ ๋ฐ๋ก vercel์ด๋ vite.config.ts์์ ์ค์ ์ ํด์ฃผ์ง ์์๋ค.
๊ทผ๋ฐ๋ ์ ๋์๊ฐ๋ ๊ฑฐ ๋ณด๋ฉด ๊ฑฐ๊ธฐ์ ํด์คฌ๋ ๋๋ก ํด๋ณด๊ณ ์ ky ์ฝ๋๋ฅผ ์์ ํ๋ค.
// ์คํฌํฐํ์ด api
const api = ky.extend({
prefixUrl: API.SPOTIFY,
hooks: {
beforeRequest: [
req =>
req.headers.set(
'Authorization',
`Bearer ${localStorage.getItem(VINYLIFY_TOKEN)}`,
),
],
// ... ์๋ต
// ๊ฐ์ฌ api ์์
import ky from 'ky';
const api = ky.extend({
prefixUrl: API._GENIUS, //๋ณ๊ฒฝ
hooks: {
// ... ์๋ต
},
// @/constants/url.ts
export const API = {
LOGIN: 'https://vinylify-express.vercel.app/',
SPOTIFY: 'https://api.spotify.com/v1/',
_GENIUS: 'https://api.genius.com/',
GENIUS:
'/genius/api' /** proxy vite.config.ts ์ค์ (https://api.genius.com) */,
EXPRESS: 'https://vinylify-express.vercel.app/',
};
๊ทธ๋ฌ๋๋ ํด๊ฒฐ!
๐ References
https://vercel.com/docs/frameworks/vite#using-vite-to-make-spas
Vite on Vercel
Learn how to use Vercel's features with Vite.
vercel.com
https://vercel.com/guides/how-to-enable-cors
How to Enable CORS on Vercel
Learn how to enable CORS in a single Node.js Serverless Function, in a Next.js app, and using vercel.json.
vercel.com