💻오늘 배운 내용
Redirect and Rewrite
next.config.js
Next.js에서 커스텀 설정을 하기 위해서는 프로젝트 디렉터리의 루트(package.json 옆)에 next.config.js 또는 next.config.mjs 파일을 만들 수 있다. -next.config.js는 JSON 파일이 아닌 일반 Node.js 모듈-
Next.js 서버 및 빌드 단계에서 사용되며 브라우저 빌드에는 포함되지 않는다.
Redirects (URL변경됨)
Redirect을 사용하면 들어오는 request 경로를 다른 destination 경로로 Redirect할 수 있다. Redirect을 사용하려면 next.config.js에서 redirects 키를 사용할 수 있다.
redirects은 source, destination 및 permanent 속성이 있는 객체를 포함하는 배열을 반환하는 비동기 함수이다.
source: 들어오는 request 경로 패턴 (request 경로)
destination: 라우팅하려는 경로 (redirect할 경로)
permanent: true인 경우 클라이언트와 search 엔진에 redirect를 영구적으로 cache하도록 지시하는 308 status code를 사용하고, false인 경우 일시적이고 cache되지 않은 307 status code를 사용한다.
const nextConfig = {
reactStrictMode: true,
async redirects() {
return [
{
source: '/old-blog/:path*',
destination: '/sexy-new-blog/:path*',
permanent: false,
},
];
Rewrites (URL변경되지 않음)
Rewrites를 사용하면 들어오는 request 경로를 다른 destination 경로에 매핑할 수 있다.
Rewrites은 URL 프록시 역할을 하고 destination 경로를 mask하여 사용자가 사이트에서 위치를 변경하지 않은 것처럼 보이게 한다. 반대로 redirects은 새 페이지로 reroute되고 URL 변경 사항을 표시.
const nextConfig = {
reactStrictMode: true,
async rewrites() {
return [
{
source: '/api/movies',
destination: `https://api.themoviedb.org/3/movie/popular?api_key=${API_KEY}`,
},
];
},
};
Movie Poster Path
`https://image.tmdb.org/t/p/w500/${movie.poster_path}`
주의! fetch할 때 /api/movies 또는 http://localhost:3000/api/movies 둘 다 가능하지만 http가 아닌 https로 fetch하게 되면 오류가 발생한다.
export async function getServerSideProps() {
const res = await fetch('http://localhost:3000/api/movies');
const { results } = await res.json();
return {
props: {
results,
},
};
}
Server Side Rendering
getServerSideProps
page에서 서버 측 랜더링 함수인 getServerSideProps함수를 export하는 경우 Next.js는 getServerSideProps에서 반환된 데이터를 사용하여 각 request에서 이 페이지를 pre-render한다. getServerSideProps는 서버 측에서만 실행되며 브라우저에서는 실행되지 않는다.
즉 HTML이 클라이언트 사이드에서 자바스크립트를 통해 생성이 되는 게 아니라 Next.js가 사전에 각 페이지를 만들어 놓는다. 이때 각 HTML은 해당 페이지에 최소한으로 필요한 자바스크립트 코드와 결합되어있다. 페이지가 브라우저에 의해 로드될 때는 hydration이라는 프로세스를 거치게 된다. hydration은 자바스크립트 코드가 실행되어 해당 페이지를 완전히 인터렉티브하게 만드는 것을 의미한다.
프리 렌더링을 할 경우, 프리 렌더링을 하지 않을 때보다 더 나은 성능과 SEO를 갖출 수 있다.
getServerSideProps vs getStaticProps
getServerSideProps 👉 매 요청 시에 실행된다.
getStaticProps 👉 빌드 시에 실행된다. (즉 딱 한 번 실행된다.)
Dynamic Routes
미리 정의된 URL 주소로만 라우팅하는 것이 아니라 사용자가 접근한 경로 혹은 상황에 따라 동적인 라우팅을 제공하고 싶을 때 사용할 수 있는 방식이다.
예를들어, /my-profile/ 뒤에 이름을 주어서 회원들의 프로필을 표현하고 싶다면? /my-profile/ray-kim 페이지에서는 ray-kim 의 프로필을 제공하고, /my-profile/jake-seo 페이지에서는 jake-seo 의 프로필을 제공하고 싶을 때 사용할 수 있다.
Next.js에서는 page에 대괄호([param])를 추가하여 Dynamic Route를 생성할 수 있다.
/movies/1, /movies/abc 등과 같은 모든 경로는 pages/movies/[id].js와 일치한다.
const router = useRouter()
const { id } = router.query
Catch all routes
대괄호 안에 세 개의 점(...)을 추가하여 모든 경로를 포착하도록 Dynamic Routes를 확장할 수 있다.
pages/movies/[...id].js는 /movies/1와 일치하지만 /movies/1/2, /movies/1/ab/cd 등과도 일치한다.
// 예시
import { useRouter } from 'next/router'
const Movies = () => {
const router = useRouter()
const { id } = router.query
return <p>Movies: {id}</p>
}
export default Post
위의 소스코드에서 pid 값을 router.query 오브젝트를 통해 가져오고 있는데, router.query 오브젝트 내부의 pid 프로퍼티 값은 경로에 의해 설정된다.
/movie/123 경로에 접근했을 때, router.query 내부의 프로퍼티 값은 123 이 된다.
일치하는 매개변수는 페이지에 쿼리 매개변수로 전송되며 항상 배열이므로 /movies/a 경로에는 다음 쿼리 객체가 있다.
{ "id": ["a"] }
post/123?foo=bar 경로에 접근한다면, router.query 내부의 값은 다음과 같을 것이다.
{"pid": "123", "foo": "bar"}
❓발생한 이슈/고민
TMDB API를 이용해서 간단한 영화 정보페이지 만들기
💡해결과정
오늘 배운 것을 이용하여 간단한 영화체이지 만들기를 따라해보았다.
처음에 자꾸 fetch 오류가 나서 당황스러웠는데 검색해보니 데이터를 가져올 때,
http가 아닌 https로 fetch하게 되면 오류가 발생한다고 한다.
또,
이미지 태그마다 <img> 태그보다 <Image> 태그를 쓸 것을 권고하고 있는데,
Next/Image 컴포넌트에서 제공하는 대표적인 기능은 다음의 3가지다.
- lazy loading : 이미지 로드하는 시점을 필요할 때까지 지연시키는 기술. 예를 들면 스크린 밖에 있는 이미지들은 로딩을 지연시키고 스크린 안에 있는 이미지만을 로드해서, 불필요한 대역폭 사용을 줄이고 필요한 이미지만 빠르게 로드할 수 있도록 하는 것
- 이미지 사이즈 최적화 : 디바이스 크기 별로 srcSet을 미리 지정해두고, 사용자의 디바이스에 맞는 이미지를 다운로드할 수 있게 지원하고, 이미지를 webp와 같은 용량이 작은 포맷으로 이미지를 변환해서 제공.
- placeholder 제공: 레이아웃이 흔들리는 현상을 방지하기 위해 placeholder를 제공. 이미지가 로드되기 전에도 이미지 높이만큼 영역을 표시해서 이미지가 로드된 후에 레이아웃이 흔들리지 않도록 하는 것
즉, Next/Image를 사용하면 얻을 수 있는 장점은
- 성능 향상: 디바이스마다 적절한 사이즈의 이미지를 서빙하고, webp와 같은 작은 용량의 포맷을 사용함
- 시각적인 안정성: 이미지 로드 전 placeholder를 제공하여 CLS(Cumulative Layout Shift) 방지
- 빠른 페이지 로딩: viewport에 들어왔을 때만 이미지를 로드하고, 작은 사이즈의 blur 이미지를 미리 로딩하여 사용자에게 더 빠른 페이지를 보여줄 수 있음
그렇지만 이번에는 강의 따라서 그냥 img 태그로 작성했다. css부터 내가 다 새로 짜야하기에...
완성한 페이지
🧐궁금점과 부족한 내용
fetching data 함수를 보면서 특이한 구조를 발견했다.
useEffect(() => {
(async () => {
const { results } = await (
await fetch('/api/movies')
).json();
setMovies(results);
})();
}, []);
await (데이터 가져오는 로직) ( ) << 이런 구조인데, 처음 봤을 때 왜 괄호를 두 번이나..? 라고 생각했다.
async 함수를 바로 선언하고 호출하기 위해 두 개의 괄호로 감싸주는 형태의 함수를
IIFE(Immediately Invoked Function Expression)라고 한다. (함수를 정의하자마자 즉시 실행)
: 익명 함수를 일회성으로 호출하며, 스코프를 막기 위해 함수 내부를 괄호로 감싸주는 것이다.
오...
📋레퍼런스
'내일배움캠프 > Today I Learned' 카테고리의 다른 글
[TIL 2023.08.08] 심화 프로젝트 둘러보미 / 회원가입 만들기 (0) | 2023.08.08 |
---|---|
[TIL 2023.08.07] 심화 프로젝트 둘러보미 (0) | 2023.08.07 |
[TIL 2023.08.03] 클린코드에 대하여 (0) | 2023.08.03 |
[TIL 2023.08.02] Next.js 기본 개념 (0) | 2023.08.02 |
[TIL 2023.08.01] 자바스크립트로 만든 투두리스트 타입스크립트로 바꾸기 (0) | 2023.08.01 |