[노마드 코더 - NextJS 시작하기] 강의를 수강하고 강의 내용을 바탕으로 작성한 글입니다.
Layout
- 모든 페이지에서 공통으로 사용하는 header, footer 등을 공통 레이아웃으로 설정하여 반복된 코드를 줄일 수 있다.
▼ myapp/components/layout.tsx
import NavBar from "./NavBar";
const Layout = ({ children }) => {
return (
<div>
<NavBar />
<div>{children}</div>
</div>
);
};
export default Layout;
- 공통으로 들어가는 NavBar를 레이아웃 안에 넣어줌
- props로 children을 받음 -> 하나의 컴포넌트를 다른 컴포넌트에 넣을 때
▼ myapp/src/pages/_app.tsx
import type { AppProps } from "next/app";
import Layout from "components/Layout";
const App = ({ Component, pageProps }: AppProps) => {
return (
<div>
<Layout>
<Component {...pageProps} />
</Layout>
</div>
);
};
export default App;
- 위의 경우에 children에는 <Component {...pageProps} /> 가 전달된다.
Haed
- title, og_img, meta 등을 태그에 넣어서 SEO를 관리할 수 있게 해주는 기능
- react 프로젝트에서는 별도로 helmet 등을 다운로드 해주어야 하지만, next js에서는 흔하게 쓰이는 기능들은 패키지로 작업이 가능하다
▼ myapp/components/setHead.tsx
import Head from "next/head";
const SetHead = ({ title }) => {
return (
<Head>
<title>{title} | Next Movies</title>
</Head>
);
};
export default SetHead;
▼ myapp/src/pages/index.tsx
import SetHead from "components/SetHead";
const Home = () => {
return (
<div className="Home">
<SetHead title={"Home"} />
<h1>Home</h1>
</div>
);
};
export default Home;
▼ myapp/src/pages/about.tsx
import SetHead from "components/SetHead";
const About = () => {
return (
<div className="About">
<SetHead title={"About"} />
<h1>About</h1>
</div>
);
};
export default About;
TMDB 데이터 fetch
- TMDB : https://www.themoviedb.org/
- TMDB 사이트 회원가입
- 프로필 - 설정 - API - API 키 복사
- API_KEY에 API 키 넣기
▼ myapp/src/pages/index.tsx
const API_KEY = "your api key";
- movie 인터페이스
interface movie {
id: number;
original_title: string;
poster_path: string;
}
- movie 배열을 state로
const [movies, setMovies] = useState<movie[]>([]);
- TMDB에서 데이터 가져오기
useEffect(() => {
(async () => {
const { results } = await (
await fetch(
`https://api.themoviedb.org/3/movie/popular?api_key=${API_KEY}`
)
).json();
setMovies(results);
})();
}, []);
- 가져온 데이터 화면에 표시하기
<div className="Home">
<SetHead title={"Home"} />
<div className="container">
{!movies && <h4>Loading... Please Wait ...</h4>}
{movies?.map((movie) => (
<div key={movie.id} className="movie">
<Image
src={`https://image.tmdb.org/t/p/w500/${movie.poster_path}`}
alt="Landscape picture"
/>
<h4>{movie.original_title}</h4>
</div>
))}
</div>
API 키 숨기기
- API가 공개되면 남용 등의 우려가 있기 때문에 API 키를 숨기는 것이 좋다.
redirect
- next.config.js 파일 nextConfig 변수 안 redirects 함수 생성
- 배열을 리턴하도록 함
- source 의 경로로 갔을 때, destinatrion으로 강제 이동하도록 한다.
- permanent는 영구적 정보 기억 여부를 결정한다.
- next.config.js 파일 변경 후에는 항상 서버 재시작해야 함
▼ myapp/next.config.js
const API_KEY = process.env.API_KEY;
/** @type {import('next').NextConfig} */
const nextConfig = {
experimental: {
appDir: true,
},
reactStrictMode: true,
async redirects() {
return [
{
source: "contact",
destination: "form",
permanent: false,
},
];
},
};
module.exports = nextConfig;
async redirects() {
return [
{
source: "/old/:path*",
destination: "/new/:path*",
permanent: false,
},
];
},
- redirect를 하게 되면 url 자체가 바뀌면서 유저가 해당 사실을 인식하게 된다.
rewrite
- redirect를 하되 url이 바뀌지 않아 유저가 인식할 수 없다.
▼ myapp/next.config.js
async rewrites() {
return [
{
source: "/api/movies",
destination: `https://api.themoviedb.org/3/movie/popular?api_key=${API_KEY}`,
},
];
},
▼ myapp/src/pages/index.tsx
/* ... */
useEffect(() => {
(async () => {
const { results } = await (await fetch("/api/movies")).json();
setMovies(results);
})();
}, []);
/* ... */
▼ myapp/next.config.js
const API_KEY = process.env.API_KEY;
- .env 파일 안에 API_KEY를 저장하고, process.env.API_KEY로 불러오면 config 파일 내에서도 API 키를 숨길 수 있다.