문제상황
요약 : next js에서 제공하는 커스텀 에러 페이지를 만들기 위해서는 rewirte의 sorce가 '/' 이면 안된다.
(사실 rewirte를 사용하며 커스텀 에러페이지를 사용 할 수 있는 방법이 있을 것 같지만... (rewrite의 sorce의 depth를 바꾼다던가 등...) 내가 해결한 방향성과는 다르다. 그래도 해결 했으니까... 🥲)
1. 이전에 naver api를 사용하여 이미지를 불러오면 CORS 에러가 떠서, next js 에서 제공하는 rewrite 옵션을 추가하여 해결하였다.
// next.config.json
// some setting ...
async rewrites() {
return [
{
destination: 'https://openapi.naver.com/:path*',
source: '/:path*',
},
];
},
// some setting ...
2. rewrites는 말그대로 요청 경로를 특정 경로 (내 경우는 naver 쇼핑 api)로 프록시 하는 기능을 제공하며 이를 이용해 CORS 에러를 피해갈 수 있다. next js는 자체적으로 서버를 가지고 있는데(pages/api) 이 기능을 이용해 rewrites가 작동한다. destination으로 하는 요청을 마치 sorce 에서 하는 요청으로 덮어쓰는 것이다. 나의 경우 메인 페이지('/') 에서 네이버 api로 요청을 보내야 하는 상황이라 위처럼 와일드카드 경로를 사용해 url 뒤에 붙는 모든 요청을 naver api로 보내는 식으로 설정해두었다.
3. 그러나, 잘못된 ulr을 입력했을 때, next js에서 제공하는 커스텀 404페이지 같은 기능이 작동하지 않으며 naver api 에서 넘어오는 error json 메세지가 화면에 뜨게 된다.
💡아이데이션
1. rewrite를 사용하지 않고 cors 에러를 피하는 방법
2. 네이버에서 넘어오는 json error message를 받아서 처리하는 방법
1번 방법이 2번 방법보다 요청을 주고받는 단계가 간단하기에 1번방법으로 우선 접근해보기로 결정했다.
rewrite를 사용하지 않고 cors 에러 피하기
일단 사용하던 rewrite 코드를 삭제하고, axios 요청을 하던 url에 앞의 도메인을 다 적어주었다.
// before
export const SHOP_URL = 'v1/search/shop.json';
//after
export const SHOP_URL = 'https://openapi.naver.com/v1/search/shop.json';
역시 바로 CORS 에러가 떴다.
여기서 CORS에 대해 다시한번 생각해보고자 했다.
CORS란, Cross-orign Resource Sharing 의 약어로써 브라우저에서 다른 출처를 공유를 허용하는 규약이다. CORS는 브라우저에서 관리하고 따라서 서버끼리의 데이터 교환에는 영향을 미치지 않는다.
따라서 next js 에서 제공하는 API Routes는 server side이기에, 이를 이용해 피해갈 수 있지 않을까 라는 생각을 하게 되었다.
🔨구현
1. pages/api 아래에 api data를 받아오기 위한 api를 만든다. 나의 경우 제품 정보를 받아오는 기능을 해야 했기에 /api/product 로 만들었다.
2. 기존 src/utils/api 에서 네이버 api를 받아오기 위해 설정했던 부분을 싹 다 서버 api쪽으로 넘긴다. 나의 경우 header, params를 get요청으로 보내고 받아왔었는데, 그 역할을 server api로 넘기고, 클라이언트 쪽에서 api/product 로get 요청을 해서 받아오는 식으로 만들었다.
// src/utils/api/getProductsApi.ts
// Before
import axios from 'axios';
import { SHOP_URL } from '@/constant/list';
import type { NaverProductResponse } from '@/types/naverShopApi';
const getProductsApi = async (params: object) => {
const { data }: { data: NaverProductResponse } = await axios.get(SHOP_URL, {
params,
headers: {
'X-Naver-Client-Id': process.env.NEXT_PUBLIC_CLIENT_ID,
'X-Naver-Client-Secret': process.env.NEXT_PUBLIC_CLIENT_SECRET,
},
});
return data;
};
export default getProductsApi;
// src/utils/api/getProductsApi.ts
// after
import axios from 'axios';
import type { APIParams, NaverProductResponse } from '@/types/naverShopApi';
const getProductsApi = async (params: APIParams) => {
const { data }: { data: NaverProductResponse } = await axios.get('/api/products', { params });
return data;
};
export default getProductsApi;
// pages/api/products.ts
import axios from 'axios';
import { NextApiRequest, NextApiResponse } from 'next';
import { SHOP_URL } from '@/constant/list';
import type { NaverProductResponse } from '@/types/naverShopApi';
export default async function handler(req: NextApiRequest, res: NextApiResponse) {
try {
const { data }: { data: NaverProductResponse } = await axios.get(SHOP_URL, {
params: req.query,
headers: {
'X-Naver-Client-Id': process.env.NEXT_PUBLIC_CLIENT_ID,
'X-Naver-Client-Secret': process.env.NEXT_PUBLIC_CLIENT_SECRET,
},
});
return res.json(data);
} catch (err) {
return res.end(err);
}
}
API를 만들때, req로 클라쪽에서 보낸 요청들이 들어온다. 나의 경우는 쿼리 스트링을 통해 요청을 주었기에, req.query를 통해 받아왔다.
이런식으로 구현해주니 커스텀 404도 잘 뜨고, 무한스크롤 기능도 문제없이 잘 됨을 확인할 수 있었다.
참고 링크
Routing: API Routes | Next.js
Using Pages Router Features available in /pages
nextjs.org
'Study > PJ log' 카테고리의 다른 글
[PJ Log] React 프로젝트에 Next js 적용 (0) | 2023.03.06 |
---|---|
[PJ Log] git rebase로 커밋 히스토리 정리하기 (0) | 2023.03.05 |
[log.] 원티드 프리온보딩 인턴십 : 프론트엔드 숏 에세이 (0) | 2023.02.13 |
[Side Project] 일정 관리 어플 개발 (1) : 시작 (0) | 2023.01.15 |