components 폴더에 Layout.js
만들어 NavBer, Header 등 공통으로 사용하는 것을 넣는다.
공통으로 사용하는 것을 _app.js
에 작성해도 되지만,
대중적으로 _app.js
를 크게 하기보단 Layout.js
에 넣고 _app.js
는 간단하게 사용한다.
// Layout.js
import NavBer from './NavBar';
export default function Layout({ children }) {
return (
<>
<NavBar />
<div>{children}</div>
</>
);
}
// _app.js
import Layout from '@/components/Layout';
export default function App({ Component, pageProps }) {
return (
<Layout>
<Component {...pageProps} />
</Layout>
);
}
Next.js는 head 같이 자주 사용하는 기능의 패키지를 제공한다.
head 컴포넌트 안에 기존 html의 <head>
에 작성했던 것 처럼 <meta>
,<title>
같은 것을 작성한다.
import Head from 'next/head';
export default function Seo({ title }) {
return (
<Head>
<title>{title} | Next Movies</title>
</Head>
);
}
public 폴더에 public 파일들을 불러와 사용할 때
../public/어찌구.jpg
로 불러오지 않고 /어찌구/.jpg
로 바로 pulic 파일을 불러올 수 있다.
next.config.js
에 들어가 redirects 옵션을 작성한다.(적용 후 서버 재시작해야 함)
source url 로 접속 시 destination으로 보낸다.
source url에서 바뀌는 게 destination url로 바뀌는 것이 보이며, 유저도 url이 바뀌었다는 것을 알 수 있다.
const nextConfig = {
reactStrictMode: true,
/* 이 부분 ↓ */
async redirects() {
return [
{
source: '/about', // 들어간 곳
destination: '/', // 보낼 곳 (외부 사이트도 가능 )
permanent: false, // 영구적인지 아닌지에 따라 브라우저나 검색엔진이
// 이 정보를 기억할지 말지 여부 결정
},
{
source: '/old/:path', // :path : 나머지 경로
destination: '/new/:path', // :path : 입력된 나머지 경로
// :path* : 나머지 경로 전체(source, destination 둘 다 작성해야 함)
permanent: false,
},
];
}
}
next.config.js
에 들어가 rewrites 옵션을 작성한다.(적용 후 서버 재시작해야 함)
source url 로 접속 시 destination으로 보낸다.
source url이 바뀌지 않고 유지되지만 destination url으로 설정된 페이지가 보이며, 유저는 url이 바뀌었다는 것을 알 수 없다.
const nextConfig = {
reactStrictMode: true,
/* 이 부분 ↓ */
async rewrites() {
return [
{
source: '/about', // 들어간 곳
destination: '/', // 보여질 곳
permanent: false, // 영구적인지 아닌지에 따라 브라우저나 검색엔진이
// 이 정보를 기억할지 말지 여부 결정
},
{
source: '/api/movies', /* 이런 식으로 작성하여 API_KEY를 숨길 수 있다*/
destination: `https://api.themoviedb.org/3/movie/popular?api_key=${API_KEY}`,
},
{
source: '/api/movies/:id', // :id 동적 url
destination: `https://api.themoviedb.org/3/movie/:id?api_key=${API_KEY}`,
// source에서 :id라고 했으면 destination도 동일하게 작성해야 함 명칭 동일하게
},
];
}
}
getServerSideProps는 server쪽(백엔드)에서만 작동하는 function이다.
getServerSideProps
를 export 시켜 사용한다.getServerSideProps
는 object를 return 하며 return 값은 props로써 page에게 주게 된다.// async는 await 사용해서 썼을 뿐, 원래는 안 써도 됨
// getServerSideProps 내부 작성되는 코드는 다 server쪽(백엔드)에서만 작동
export async function getServerSideProps(){
const { results } = await (await fetch(`http://localhost:3000/api/movies`)).json();
return {
// props라는 키를 갖고 원하는 데이터를 넘겨줄 수 있음
props: { results },
};
}
// 이런 식으로 return을 props로 받아서 사용할 수 있음
export default function Home({ results }) {}
getServerSideProps
는백엔드의 데이터를 fetch하고 결과를 pre-render하여 html에 데이터 포함시킨다.
이러한 것이 SEO에는 유용하지만, 백엔드의 api작업이 끝날 때까지 아무 것도 안 보인다.
즉, 이러한 장단점이 있으니 니즈에 따라 유동적으로 사용하면 된다.
getServerSideProps
사용getServerSideProps
사용 XLink
<Link href={`/movies/${movie.id}`}>{movie.original_title}</Link>
onClick
const router = useRouter();
const onClick = (id) => {
router.push(`/movies/${id}`);
};
<div onClick={() => onClick(movie.id)}></div>
// form 작성 후 페이지 이동하는 경우 등에서 사용할 수 있음
page 폴더에 안에 product 폴더 생성 시, product 폴더 안에 있는 index.js는 product 경로의 기본 페이지가 된다.
product 하위 경로에 동적인 경로가 필요하다면, [변수명].js
으로 폴더 안에 생성한다.
[...변수명].js
[변수명].js
를 [...변수명].js
로 바꾸면 모든 path를 잡을 수 있다.
앞서 말한 product 폴더로 예를 들자면,
pages/product/[...productid].js
라는 파일은 '/product/a'
이라는 url path와 매칭되며,
/product/a/b
,/product/a/b/c
와 같이 뒤에 추가로 붙는 path도 잡을 수 있다는 것이다.
아래 소스에서 query의 값으로 state를 넘길 수 있다.
const onClick = (id) => {
router.push(
{
pathname: `/movies/${id}`,
query: { title: 'hello' }, // ?title=hello
},
`/movies/${id}` // query를 안보이게 함
);
};
이렇게 state를 넘겼을 때,
자식 컴포넌트에는 그 값이 없고 부모 컴포넌트에게 state를 받은것 이기 때문에
자식으로 바로 접근하거나 자식 페이지에서 새로고침 시 state를 사용할 수 없어 에러가 난다.
page 폴더에 404.js
만 생성해주면 된다.
개인 key는 github에 커밋 시 개인 정보 노출 위험이 있어 .env
or .env.local
파일을 만들어 .env
or .env.local
파일에 변수로 지정해두어야 한다.
(파일 추가 후 .gitignore
에 파일명도 추가해야 함)
.env
) : API_KEY = 개인 API Key이때, CRA 에서는 변수에 REACT_APP_
를 붙여줘야 사용할 수 있었는데
Next에서는 NEXT_PUBLIC_
을 변수 앞에 붙여줘야 사용할 수 있다.