nextJS가 제시하는 data fetching(데이터 가져오기) 방법
getServerSideProps()
는 서버에서 가져온 데이터를 페이지에 props로 전달해줘서 자유롭게 사용할 수 있다....
export async function getServerSideProps() {
console.log('server')
return {
props: { time: new Date().toISOString() }
}
}
export default function Home({ time }) {
return (
<h1 className="title">
{time}
</h1>
)
}
...
export default function CSR() {
const [time, setTime] = useState()
useEffect(()=>{
console.log('client')
setTime(new Date().toISOString())
},[])
return (
...
)
}
getStaticProps()
를 사용했을때, npm run dev
로 실행시킨 개발환경에서는 ssg가 제대로 동작하지 않아서 ssg가 ssr처럼 동작한다. npm run build
를 해야 build하는 타이밍에 보여지는 페이지가 미리 만들어진다. 즉, 빌드하는 타이밍에 데이터를 다 가져와서 static page를 생성해버리는 것이다.getStaticPaths()
는 미리 그려놔야할 경로에 대해서 사용하는 메서드이다.getStaticProps()
와 getStaticPaths()
는 함께 사용하는 것을 권장한다....
export async function getStaticProps() {
console.log('server')
return {
props: { time: new Date().toISOString() }
}
}
export default function SSG({ time }) {
return (
<h1 className="title">
{time}
</h1>
)
}
getStaticProps()
에 revalidate값을 설정하면 된다. 이런식으로 구현을 하면 새로고침이 된다. 즉, 캐싱을 미리 갖고있다가 1초마다 다시 패칭을 해서 다시 생성을 한다. 결론적으로 ssg, ssr의 장점을 적절하게 사용할 수 있다....
export async function getStaticProps() {
console.log('server')
return {
props: { time: new Date().toISOString() },
revalidate: 1,
}
}
export default function ISR({ time }) {
return (
<h1 className="title">
{time}
</h1>
)
}
pages폴더 안에 있는 파일들은 url과 매칭
pages/index.js
⇒ /
pages/ssg.js
⇒ /ssg
pages/products/[slug].js
⇒ /products/*
nextJS는 모든 페이지를 기본적으로 pre-render, 즉 미리 그려둔다. CSR만 제공한다면 클라이언트(=브라우저)처럼 동작하지 않는 검색엔진의 경우 아무런 데이터도 조회해갈 수 없다. 아래의 이미지에서 오른쪽의 경우 처럼 js가 동작하지 않는 엔진에서는 아무것도 읽을 수 없을 것이다. 그래서 pre-render를 해두면 클라이언트처럼 동작하지 않는 검색엔진에게 필요한 데이터를 제공 할 수 있다. 결국 SEO는 다양한 검색엔진들이 내가 만든 사이트를 잘 읽어서 상위에 노출시켜줄 수 있도록 하는 것인데, SEO를 위해서는 pre-render가 필요하다.
getStaticProps()
사용getStaticProps() && getStaticPaths()
사용하나의 공통된 layout을 사용하는 경우 여러 페이지들의 공통처리(모듈화)
하나의 공통된 Layout을 쓰는 경우, components/Layout.js
를 만든 다음에, 해당 컴포넌트를 pages/_app.js
에서 활용하면 된다. 여러개의 레이아웃을 중첩적으로 쓰는 방법 등이 있다.
// /pages/_app.js
// => next.js 자체에서 제공하는 모든 페이지를 품을 수 있는 파일이다.
import Layout from "../components/Layout";
export default function App({Component, pageProps}) {
// 하나의 레이아웃을 사용하는 경우
// return (
// <Layout>
// <Component {...pageProps} />
// </Layout>
// )
// 여러개의 레이아웃을 중첩적으로 사용하는 경우
const getLayout = Component.getLayout || ((page) => <Layout>{page}</Layout>)
return getLayout(<Component {...pageProps} />)
}
nextJS가 제공하는 최적화 Image Component
모든 사이트에서 보여지는 리소스 중에 가장 많은 부분을 차지하는게 이미지이기 때문에 이미지 최적화가 필요하다.
네트워크 용어. 특정 주소가 있고, 그 주소와 매핑되어있는 데이터들을 받아서 사용하는 일련의 과정
nextJS의 라우터는 파일 시스템 기반이다. 즉, pages/
혹은 src/pages/
경로에 파일을 만들면 그것이 라우터로 인지 되고, url 주소와 매핑이 된다. pages/
폴더가 더 우선순위를 가진다. 단, pages/product
혹은 pages/settings
와 같이 특정 경로에 바로 접근할 수 있으려면 해당 폴더에 first-item.js
, info.js
파일들 외에 index.js
파일을 생성해야만 한다.
pages/product/first-item.js
=> /product/first-item
pages/settings/my/info.js
=> /settings/my/info
만약 위의 경로에서 depth가 더 깊어진다면, 절대경로로써 src를 접근할 수 있도록 아래와 같이 설정을 해주자.
// jsconfig.json - 절대경로로써 src를 접근할 수 있게 된다.
{ "compilerOptions": { "baseUrl": "src" } }
다이나믹한 경로설정은 slug를 사용하자. 단, 경로에서 명시해놓은 곳을 우선으로 이동한다.
pages/category/[slug].js
=> /category/:slug
(ex. /category/food)pages/[username]/info.js
=> /:username/info
(ex. /jimmy/info)pages/cart/[...date].js
=> /cart/*
(ex. /cart/2022/06/24)getServerSideProps()
getStaticProps()
등을 다시 실행시키지 않고, 즉 현재 상태를 잃지 않고 url을 바꾸는 방법이다. 이것은 사용자가 어떤 동작을 했고, 그 기록을 query로 남기고 싶을때 사용한다. 왜냐면 query로 남기면 사용자가 새로고침을 해도 유지되기 때문이다.
아래의 경로에서 [slug] 값을 활용해서 화면에 보여주려면 어떻게 해야할까?
// pages/category/[slug].js
...
import { useRouter } from 'next/router';
export default function CategorySlug() {
const router = useRouter();
const {slug} = router.query
return (
<>
<h1 className="title">Category {slug}</h1>
</>
);
}
...
아래와 같이 query가 있다면? { “slug”: “food”, “from”: “event” }
와 같이 꺼내서 활용할 수 있다.
/category/food?from=event
아래와 같이 query에 slug가 있다면? nextJS는 폴더구조의 slug를 우선시 한다. 그래서 뒤에 slug쿼리가 붙었을 경우엔 그 값이 무시된다.
/category/food?slug=book
// pages/[username]/[info].js
...
import { useRouter } from 'next/router';
export default function CategorySlug() {
const router = useRouter();
const {username, info} = router.query
return (
<>
<h1 className="title">{username}'s {info}</h1>
</>
);
}
...
// pages/cart/[...slug].js => slug는 배열, /cart 로 접근하면 404가 뜬다.
// pages/cart/[[...slug]].js => 옵셔널 slug, slug가 존재하지 않아도 받는다
...
import { useRouter } from 'next/router';
export default function CategorySlug() {
const router = useRouter();
const { date } = router.query
return (
<>
<h1 className="title">{JSON.stringify(date)}</h1>
</>
);
}
...
// pages/cart/[[...slug]].js
...
import Link from 'next/link';
import { useRouter } from 'next/router';
export default function CategorySlug() {
const router = useRouter();
const { date } = router.query;
return (
<>
<h1 className="title">{JSON.stringify(date)}</h1>
<Link href="/cart/2023/04/21">
<a>오늘의 날짜로 이동한다</a>
</Link>
<button onClick={() => router.push('/cart/2023/04/21')}>오늘 날짜로 이동한다</button>
</>
);
}
...
API(Application Programming Interface)란 컴퓨터나 컴퓨터 프로그램 사이의 연결, 즉 응용프로그래밍 인터페이스이다. nextJS가 제공하는 api routes는 pages/api/*
의 방식으로 사용하면 된다.