ํ์ด์ง๋ณ๋ก ์ ์ ์์ฑ๊ณผ ์๋ฒ ์ธก ๋ ๋๋ง์ ๋ชจ๋ ์ํํ๋ ๋ฐฉ๋ฒ์ ์ ๊ณตํ์ฌ Next.js๊ฐ ์์ ํ ํ์ด๋ธ๋ฆฌ๋๊ฐ ๋๋๋ก ํฉ๋๋ค.
getStaticProps
- next build
์๊ฐ์ SSG(์ ์ ์์ฑ)๋ฅผ ์ ํํฉ๋๋ค.getServerSideProps
- ์จ๋๋งจ๋๋ก ๋ ๋๋งํ๋ SSR(์๋ฒ ์ธก ๋ ๋๋ง)์ ์ ํํฉ๋๋ค.getStaticPaths
- ์ ์ ์์ฑ(SSG)์ ์ํํ๊ธฐ ์ํ ๋์ ๊ฒฝ๋ก์ ๋ํ ๋งค๊ฐ๋ณ์ ๋ชฉ๋ก ๋ฐํ์ด RFC๋ API ์ถ๊ฐ์ ๋ํด ๋ ์ ์ ์ผ๋ก ์ค๋ช ํฉ๋๋ค. ๋ชจ๋ ์๋ก์ด ๊ธฐ๋ฅ์ ์ด์ ๋ฒ์ ๊ณผ ์์ ํ ํธํ๋๋ฉฐ ์ ์ง์ ์ผ๋ก ์ฑํํ ์ ์์ต๋๋ค. ์ด RFC๋ ๋ ์ด์ ์ฌ์ฉ๋์ง ์์ต๋๋ค.
์น ์ฌ์ดํธ ๋๋ ์น ์ ํ๋ฆฌ์ผ์ด์ ์ ๊ตฌ์ถํ ๋ ์ผ๋ฐ์ ์ผ๋ก ์ ์ ์์ฑ(SSG) ๋๋ ์๋ฒ ์ธก ๋ ๋๋ง(SSR)์ ๋ ๊ฐ์ง ์ ๋ต ์ค์์ ์ ํํด์ผ ํฉ๋๋ค.
๋์ Next.js๋ฅผ ์ฌ์ฉํ๋ฉด ์ฌ์ฉ๋๋ ์ ๋ต์ ํ์ด์ง๋ณ๋ก ์ ํํ ์ ์๋ ํ์ด๋ธ๋ฆฌ๋ ์ ํ๋ฆฌ์ผ์ด์
์ ๊ตฌ์ถํ ์ ์์ต๋๋ค. Next.js 9๋ถํฐ getInitialProps
๊ฐ ์๋ ํ์ด์ง๋ ์ ์ ์ผ๋ก ์ต์ ํ ๋๊ณ next build
์ .html
ํ์ผ๋ก ์ถ๋ ฅ๋ฉ๋๋ค.
๊ทธ๋ฌ๋ ํน์ ์ฌ์ฉ ์ฌ๋ก์ ๋ํ ์ ์ ํ์ด์ง๋ฅผ ์์ฑํ๋ ๋์ ๋ฐ์ดํฐ ๊ฐ์ ธ์ค๊ธฐ๋ฅผ ์ํํ ์ ์์ต๋๋ค.
์๋ฅผ ๋ค์ด CMS ๋๋ ์ฌ์ดํธ์ ๋ธ๋ก๊ทธ ์น์ ์์ ์ ์ ์ผ๋ก ๋ง์ผํ ํ์ด์ง๋ฅผ ์์ฑํฉ๋๋ค.
์ด ๊ฒฝ์ฐ getInitialProps
๋ฅผ ์ฌ์ฉํ๋ฉด SSR์ ์ ํํ ์ ์์ต๋๋ค.
Next.js์๋ ํ์ฌ next export
๋ช
๋ น์ด ์์ด ์ ํ๋ฆฌ์ผ์ด์
์ ์์ ํ SSG๋ก ๋ง๋ค๊ณ Next.js์ ํ์ด๋ธ๋ฆฌ๋ ํน์ฑ์ ์๊ฒ ๋ฉ๋๋ค.
next export
๋ฅผ getInitialProps
์ ํจ๊ป ์ฌ์ฉํ๋ฉด ๋ ๋ค๋ฅธ ๋ฌธ์ ๊ฐ ๋ํ๋ฉ๋๋ค. getInitialProps
๋ ๋น๋ ์ ํธ์ถ๋์ง๋ง(ํ๋ฅญํฉ๋๋ค) next/link
๋ฅผ ์ฌ์ฉํ์ฌ ํ์ด์ง ์ฌ์ด๋ฅผ ์ด๋ํ ๋ getInitialProps
์ฌ์ฉํ๋ ๋์ ํด๋ผ์ด์ธํธ ์ธก์ด๋ผ๊ณ ํฉ๋๋ค next export
๊ฒฐ๊ณผ.
์ด๊ฒ์ ๋ํ ๋ฐ์ดํฐ ์์ค(CMS/API ๋์ )๊ฐ ํด๋ผ์ด์ธํธ ์ธก ์ ํ์์ ์ง์ ํธ์ถ๋๋ค๋ ๊ฒ์ ์๋ฏธํฉ๋๋ค. ๋ฐ์ดํฐ ์์ค๊ฐ ๋ค์ด๋ ๊ฒฝ์ฐ ํ์ด์ง ๊ฐ์ ์ด๋ํ๋ ๋์ ํด๋ผ์ด์ธํธ ์ธก ์ ํ์ด ์ค๋จ๋ฉ๋๋ค.
์ฐ๋ฆฌ๋ HashiCorp์ ๊ฐ์ Next.js์์ SSG ๋ฐ next export
๋ฅผ ๋ง์ด ์ฌ์ฉํ๋ ์ฌ์ฉ์์ ํ๋ ฅํ์ผ๋ฉฐ(@jescalan์๊ฒ ๊ฐ์ฌ๋๋ฆฝ๋๋ค) ๋ ๊ฐ์ง ์๋ก์ด ๋ฐ์ดํฐ ๊ฐ์ ธ์ค๊ธฐ ๋ฐฉ๋ฒ์ธ getStaticProps
๋ฐ getServerSideProps
๋์
์ ๋ํ ์ฌ๋ฐ๋ฅธ ์ ์ฝ ์กฐ๊ฑด์ ๊ด๋ฒ์ํ๊ฒ ์กฐ์ฌํ์ต๋๋ค getStaticPaths
(ํ์ด์ง๋น exportPathMap
๋์ฒด).
์ด๋ฌํ ์๋ก์ด ๋ฐฉ๋ฒ์ getInitialProps
๋ชจ๋ธ์ ๋นํด ๋ง์ ์ด์ ์ด ์์ต๋๋ค. SSG์ SSR์ด ๋ช
ํํ๊ฒ ๊ตฌ๋ถ๋๊ธฐ ๋๋ฌธ์
๋๋ค.
getStaticProps
๋ ํ์ด์ง๊ฐ ๋น๋ ์ ์ ์ ์ผ๋ก ์์ฑ๋๋๋ก ํ์ํฉ๋๋ค( next build
).getStaticPaths
๋ ๋์ ๊ฒฝ๋ก์ ๋ํด ๋น๋ ์ ์์ฑํ ๋งค๊ฐ๋ณ์ ๋ชฉ๋ก์ ๋ฐํํ ์ ์์ต๋๋ค.getServerSideProps
๋ ๋ชจ๋ ์์ฒญ์์ ํ์ด์ง๊ฐ ์๋ฒ ์ธก ๋ ๋๋ง๋๋๋ก ํ์ํ๋ฉฐ ์๋ฒ๋ฅผ ์ฌ์ฉํ ๋์ ํ์ฌ getInitialProps
๋์๊ณผ ๊ฐ์ฅ ์ ์ฌํฉ๋๋ค.์ด๋ฌํ ๋ฉ์๋๋ฅผ ๋ถ๋ฆฌํ๋ฉด TypeScript๋ฅผ ์ฌ์ฉํ์ฌ ์
๋ ฅํ ์ ์๋ ์ฌ๋ฐ๋ฅธ ์ปจํ
์คํธ ๊ฐ์ฒด๋ฅผ ์ ๊ณตํ ์๋ ์์ต๋๋ค. ํน์ ๋ ๋๋ง ์ ๋ต์ ์ ํํ๋ฉด ํ์ฌ getInitialProps
์ฌ๋ฐ๋ฅธ ๊ฐ์ ์ป์ ์ ์์ผ๋ฉฐ TypeScript๋ฅผ ์ฌ์ฉํ ๋ SSG ๋ SSR์์ ์ฌ์ฉํ ์ ์๋ ๊ฒ์ ์ถ์ธกํด์ผ ํฉ๋๋ค.
๋ํ ์ด๋ฌํ ๋ฐฉ๋ฒ์ ๋ช ์์ ์ผ๋ก ์ง์ ํ๋ฉด ์๋ก ๋ค๋ฅธ ์ ์ถฉ์์ ๋ณด๋ค ๋ช ํํ๊ฒ ๋ฌธ์ํํ ์ ์์ต๋๋ค.
์ด๋ฌํ ๋ชจ๋ ๋ฉ์๋๋ ํ์ด์ง ๊ตฌ์ฑ ์์ ํ์ผ์ ์ต์์ ์์ค์ด๋ฉฐ getInitialProps
์ ์ ์ฌํ๊ฒ ์ค์ฒฉ๋ ์ ์์ต๋๋ค.
getStaticProps
getStaticProps
์ฌ์ฉํ๋ฉด ํ์ด์ง๊ฐ ๋น๋ ์๊ฐ(SSG)์ ์ ์ ์ผ๋ก ๋ ๋๋ง๋ฉ๋๋ค.
์ด ์๋ก์ด ๋ฐฉ๋ฒ์ ์ฌ์ฉํ๋ฉด next build
์๊ฐ์ .html
ํ์ผ๋ก ์ ์ ์ผ๋ก ์์ฑ๋ ํ์ด์ง์ ๋ํ ๋ฐ์ดํฐ ๊ฐ์ ธ์ค๊ธฐ๋ฅผ ์ํํ ์ ์์ต๋๋ค.
Next.js๋ ๋ํ next build
์๊ฐ์ getStaticProps
์ ๊ฒฐ๊ณผ๋ฅผ ๋ณด์ ํ๋ JSON ํ์ผ์ ์๋์ผ๋ก ์์ฑํฉ๋๋ค. ์ด๊ฒ์ ํด๋ผ์ด์ธํธ ์ธก ๋ผ์ฐํ
์ ์ฌ์ฉ๋ฉ๋๋ค.
next/link
๋๋ next/router
ํตํ ํด๋ผ์ด์ธํธ ์ธก ๋ผ์ฐํ
์ Next.js๋ ์ด JSON ํ์ผ์ ๊ฐ์ ธ์ ํด๋ผ์ด์ธํธ ์ธก ํ์ด์ง๋ฅผ ๋ ๋๋งํ๋ ๋ฐ ํ์ํ ์ํ์ ๊ฐ์ ธ์ต๋๋ค.
์์ฑ์ props
ํค ์๋์ ๋ฐํ๋๋ฏ๋ก ๋์ค์ ๋ค๋ฅธ ์ต์
์ด ๋์
๋ ์ ์์ต๋๋ค.
// pages/index.js
// getStaticProps is only called server-side
// In theory you could do direct database queries
export async function getStaticProps(context) {
return {
// Unlike `getInitialProps` the props are returned under a props key
// The reasoning behind this is that there's potentially more options
// that will be introduced in the future.
// For example to allow you to further control behavior per-page.
props: {}
};
}
context
์๋ ๋ค์์ด ํฌํจ๋ฉ๋๋ค.
params
- ๋์ ๊ฒฝ๋ก์ ์์ ๋์ ๋งค๊ฐ๋ณ์์
๋๋ค.getStaticPaths
์ด๊ฒ์ ๋์ ๊ฒฝ๋ก์ ๋ํ getStaticProps
์ฌ์ฉ์ ๋ํ ํ์ฅ์
๋๋ค.
getStaticPaths
๋ exportPathMap
๊ฐ ์์ด์ผ ํ๋ ํ์์ฑ์ ๋์ฒดํ๊ณ ํ์ด์ง๋ณ๋ก ์๋ํฉ๋๋ค.
slug
์๋์ ์์ ๊ฐ์ด ๋์ ๋งค๊ฐ๋ณ์๊ฐ ์๋ URL ๋ชฉ๋ก์ ์ ์ ์ผ๋ก ์์ฑํ ์ ์๊ธฐ ๋๋ฌธ์
๋๋ค. Next.js๋ URL ๋ชฉ๋ก์ ๋ฐํํ ์ ์๋ getStaticPaths
๋ฉ์๋๋ฅผ ์ ๊ณตํฉ๋๋ค. async
๋ฐฉ๋ฒ์ด๋ฏ๋ก CMS์ ๊ฐ์ ๋ฐ์ดํฐ ์์ค์์ ํด๋น ๋ชฉ๋ก์ ๊ฐ์ ธ์ฌ ์๋ ์์ต๋๋ค.
// pages/blog/[slug].js
// `getStaticProps` gets a `params` object holding the dynamic parameters
// For `/blog/hello-world` it would look like `{ slug: 'hello-world }`
export async function getStaticProps({ params }) {
return {
props: {}
};
}
// `getStaticPaths` allows the user to return a list of parameters to
// render to HTML at build time.
export async function getStaticPaths() {
return {
paths: [
// This renders /blog/hello-world to HTML at build time
{ params: { slug: "hello-world" } }
]
};
}
๋๋ถ๋ถ์ ๊ฒฝ์ฐ ๋น๋ ์ ์ ํ๋ฆฌ์ผ์ด์
์์ ๊ฐ๋ฅํ ๋ชจ๋ ๊ฒฝ๋ก๋ฅผ ๋ฏธ๋ฆฌ ๋ ๋๋งํ๊ณ ์ถ์ง ์์ ์ ์์ต๋๋ค(์: ์๋ฐฑ๋ง ๊ฐ์ ์ ํ์ด ์๋ ๊ฒฝ์ฐ). ์ด๋ฌํ ์ด์ ๋ก Next.js๋ ํ์ด์ง๊ฐ ์์ง ์์ฑ๋์ง ์์์ ๋ ๋ฐ์ดํฐ ์์ด ํ์ด์ง๋ฅผ ๋ ๋๋งํ๋ fallback
ํ์ด์ง๋ฅผ ์๋์ผ๋ก ์์ฑํฉ๋๋ค(๋ก๋ ์ํ๊ฐ ํ์๋ ์ ์๋๋ก).
์ ํํ ์๋น ๋์์ ๋ค์๊ณผ ๊ฐ์ต๋๋ค.
๋น๋ ์ ์์ฑ๋์ง ์์ ๊ฒฝ๋ก๊ฐ fallback: false
์์ getStaticPaths
fallback: false
๋ฅผ ๋ฐํํ์ฌ ๊ฐ๋ฅํ 404๊ฐ ๋๋๋ก ํ๋ ค๋ ๊ฒฝ์ฐ
// `getStaticPaths` allows the user to return a list of parameters to
// render to HTML at build time.
export async function getStaticPaths() {
return {
// Opt-out of the described fallback behavior
fallback: false,
paths: [
// This renders /blog/hello-world to HTML at build time
{ params: { slug: "hello-world" } }
]
};
}
getServerSideProps
getServerSideProps
๋ฅผ ์ฌ์ฉํ ๋ ํ์ด์ง๋ ์ ์ ์ผ๋ก ์์ฑ(SSG)๋์ง ์๊ณ ๋์ ์๋ฒ์ ๋ํ ๋ชจ๋ ์์ฒญ(SSR)์ ๋ํด ์จ๋๋งจ๋๋ก ๋ ๋๋ง๋ฉ๋๋ค.
Next.js๋ getServerSideProps
ํธ์ถ ๊ฒฐ๊ณผ๋ฅผ ๋ฐํํ๋ API ๋์ ๋ ์๋์ผ๋ก ๋
ธ์ถํฉ๋๋ค. ์ด๊ฒ์ ํด๋ผ์ด์ธํธ ์ธก ๋ผ์ฐํ
์ ์ฌ์ฉ๋ฉ๋๋ค.
next/link
๋๋ next/router
ํตํ ํด๋ผ์ด์ธํธ ์ธก ๋ผ์ฐํ
์ Next.js๋ ์ด ๋
ธ์ถ๋ API ์๋ํฌ์ธํธ๋ฅผ ๊ฐ์ ธ์ ํ์ด์ง ํด๋ผ์ด์ธํธ ์ธก์ ๋ ๋๋งํ๋ ๋ฐ ํ์ํ ์ํ์ผ๋ก ๋ณํ๋๋ JSON ๋ฐ์ดํฐ๋ฅผ ๊ฐ์ ธ์ต๋๋ค.
์ด ๋ฐฉ๋ฒ์ ํ์ฌ getInitialProps
์ ๊ฐ์ฅ ์ ์ฌํ๋ฉฐ, ์ฃผ๋ ์ฐจ์ด์ ์ getServerSideProps
๊ฐ ํญ์ ๋ธ๋ผ์ฐ์ ๊ฐ ์๋ ์๋ฒ ์ธก์์ ์คํ๋๋ค๋ ๊ฒ์
๋๋ค. ์๋ฒ ์ธก ๋ ๋๋ง ๋๋ ํด๋ผ์ด์ธํธ ์ธก ๋ผ์ฐํ
์ API ๊ฐ์ ธ์ค๊ธฐ ์ค ํ๋์
๋๋ค.
getStaticProps
์ ์ ์ฌํ๊ฒ ์์ฑ์ props
ํค ์๋์ ๋ฐํ๋ฉ๋๋ค.
// pages/index.js
// getServerSideProps is only called server-side
// In theory you could do direct database queries
export async function getServerSideProps(context) {
return {
// Unlike `getInitialProps` the props are returned under a props key
// The reasoning behind this is that there's potentially more options
// that will be introduced in the future.
// For example to allow you to further control behavior per-page.
props: {}
};
}
context
์๋ ๋ค์์ด ํฌํจ๋ฉ๋๋ค.
params
- ๋์ ๊ฒฝ๋ก์ ๋งค๊ฐ๋ณ์req
- HTTP ์์ฒญ ๊ฐ์ฒดres
- HTTP ์๋ต ๊ฐ์ฒดquery
- ์ฟผ๋ฆฌ ๋ฌธ์์ด(์ด๊ฒ์ ํ์คํ์ง ์์ง๋ง ์๋ง๋ ํ์ํ ๊ฒ์
๋๋ค)@timneutkens , @Timer , @ijjk , @lfades๊ฐ ์์ฑํ์ต๋๋ค. @rauchg , @jescalan ๋ฐ ๋ค๋ฅธ ์ฌ๋๋ค๊ณผ ๊ณต๋ ์์ ๐
export async function getStaticProps(context) { return { // Unlike `getInitialProps` the props are returned under a props key // The reasoning behind this is that there's potentially more options // that will be introduced in the future. // For example to allow you to further control behavior per-page. props: {} }; }
props
๋ด์ ํฌํจ๋ ์ ์๋ ๊ฒ ์ด์ธ์ ์ถ๊ฐ ๋ฐ์ดํฐ๋ฅผ ๋ฐํํด์ผ ํ๋ ์ํฉ์ ํ์ธํ๋ ๋ฐ ๊ด์ฌ์ด ์์ต๋๋ค. "ํ์ด์ง๋น ๋์์ ์ถ๊ฐ๋ก ์ ์ดํ๊ธฐ ์ํ" ์ธ๋ผ์ธ ์ค๋ช
์ด ์ฝ๊ฐ ๋ชจํธํ๋ค๋ ๊ฒ์ ์์์ต๋๋ค.
๋งค์ฐ ํฅ๋ฏธ๋กญ๊ฒ ๋ณด์
๋๋ค! getInitialProps
๋์ ํ ๊ฒ์ธ๊ฐ ์๋๋ฉด ํจ๊ป ํ ๊ฒ์ธ๊ฐ? ์๋ฅผ ๋ค์ด ์ฐ๋ฆฌ์ ์ฌ์ฉ ์ฌ๋ก์์ ๋ฐ์ดํฐ ๊ฐ์ ธ์ค๊ธฐ API๋ ๊ณต๊ณต ์๋น์ค์
๋๋ค. ๋ฐ๋ผ์ ํด๋ผ์ด์ธํธ ์ธก ํ์์์๋ ํด๋ผ์ด์ธํธ๊ฐ API ๊ณ์ธต์ ์ง์ ํธ์ถํ๋ ๋ฐ๋ฉด SSR์์๋ ์๋ฒ๊ฐ ํธ์ถํ ๊ฒ์ผ๋ก ์์ํฉ๋๋ค. ์์ผ๋ก ์ด ์ฌ์ฉ ์ฌ๋ก๋ ์ด์ ๋ฐฉ๋ฒ์ผ๋ก ๊ณ์ ํด๊ฒฐ๋ฉ๋๊น?
props
๋ด์ ํฌํจ๋ ์ ์๋ ๊ฒ ์ด์ธ์ ์ถ๊ฐ ๋ฐ์ดํฐ๋ฅผ ๋ฐํํด์ผ ํ๋ ์ํฉ์ ํ์ธํ๋ ๋ฐ ๊ด์ฌ์ด ์์ต๋๋ค. "ํ์ด์ง๋น ๋์์ ์ถ๊ฐ๋ก ์ ์ดํ๊ธฐ ์ํ" ์ธ๋ผ์ธ ์ค๋ช ์ด ์ฝ๊ฐ ๋ชจํธํ๋ค๋ ๊ฒ์ ์์์ต๋๋ค.
๋์ค์ ํ์ํ ๊ฒฝ์ฐ ํ์ฅํ ์ ์๋๋ก ๋ฐฉ๋ฒ์ ๋ฏธ๋์ ์ฆ๋ช ํ๋ ๊ฒ์ด ๋ ์ค์ํฉ๋๋ค.
๋งค์ฐ ํฅ๋ฏธ๋กญ๊ฒ ๋ณด์ ๋๋ค!
getInitialProps
๋์ ํ ๊ฒ์ธ๊ฐ ์๋๋ฉด ํจ๊ป ํ ๊ฒ์ธ๊ฐ? ์๋ฅผ ๋ค์ด ์ฐ๋ฆฌ์ ์ฌ์ฉ ์ฌ๋ก์์ ๋ฐ์ดํฐ ๊ฐ์ ธ์ค๊ธฐ API๋ ๊ณต๊ณต ์๋น์ค์ ๋๋ค. ๋ฐ๋ผ์ ํด๋ผ์ด์ธํธ ์ธก ํ์์์๋ ํด๋ผ์ด์ธํธ๊ฐ API ๊ณ์ธต์ ์ง์ ํธ์ถํ๋ ๋ฐ๋ฉด SSR์์๋ ์๋ฒ๊ฐ ํธ์ถํ ๊ฒ์ผ๋ก ์์ํฉ๋๋ค. ์์ผ๋ก ์ด ์ฌ์ฉ ์ฌ๋ก๋ ์ด์ ๋ฐฉ๋ฒ์ผ๋ก ๊ณ์ ํด๊ฒฐ๋ฉ๋๊น?
์ผ๋ฐ์ ์ผ๋ก ์ด๋ฌํ ๋์์๋ ์ ์ธ๊ณ์ ํน์ ์ง์ญ์์ ๋๋ฆด ์ ์๋ ํญํฌ์ ๊ฐ์ ธ์ค๊ธฐ์ ๊ฐ์ ๋ช ๊ฐ์ง ๋จ์ ์ด ์์ต๋๋ค. getServerProps
์ ๊ทผ ๋ฐฉ์์ ์ฌ์ฉํ๋ฉด ์๋ต์ ๋ณด๋ค ํจ์จ์ ์ผ๋ก ์บ์ฑํ ์ ์์ต๋๋ค.
์ด๊ฒ์ ์ ๋ง ํฅ๋ฏธ๋กญ๊ฒ ๋ณด์ ๋๋ค! ๋ฉ์ง ์์ด๋์ด!
๋ฐฐํฌ์ ๋ํ ์ฐ๋ ค๊ฐ ์์ง๋ง...
๋ด๊ฐ Now๋ฅผ ํธ์คํ
ํ๋ค๊ณ ์์ํด ๋ด
์๋ค.
์ฒซ ๋ฒ์งธ ๋ฐฐํฌ์ ๊ฒฝ์ฐ ์ ์ฒด ์์ฉ ํ๋ก๊ทธ๋จ์ด ๋ฐฐํฌ๋ฅผ ๊ธฐ๋ฐ์ผ๋ก ๊ตฌ์ถ๋๋ค๋ ๊ฒ์ด ๋ถ๋ช
ํฉ๋๋ค.
๊ทธ๋ฐ ๋ค์ CMS์์ ์ผ๋ถ ์ฝํ ์ธ ๋ฅผ ๋ณ๊ฒฝํ๊ณ SSG ํ์ด์ง์ ์ฌ๊ตฌ์ถ๋ง ํธ๋ฆฌ๊ฑฐํ๋ ค๊ณ ํ์ง๋ง ์ ํ๋ฆฌ์ผ์ด์ ์ฝ๋๋ ๋ณ๊ฒฝ๋์ง ์์์ต๋๋ค.
์ฆ์ ์๋์ด ์ธ๋ฆฝ๋๋ค. ์ด ๊ฒฝ์ฐ ๋น๋๋ฅผ ํธ๋ฆฌ๊ฑฐํ๋ฉด ๋ ๊ฐ์ง ๊ฐ๋ฅํ ์๋ฃจ์ ์ด ์์ต๋๋ค.
1) ๋ชจ๋ ๊ฒ์ด ์บ์๋๋ฏ๋ก ์๋ฌด ๊ฒ๋ ๋ค์ ๋น๋๋์ง ์์ต๋๋ค. ์ฝ๋๊ฐ ๋ณ๊ฒฝ๋์ง ์์์ผ๋ฉฐ blabla.
2) --force
, ์ด์ "๋ชจ๋ ๊ฒ"์ด ๋ค์ ๋น๋๋์ง๋ง SSG ํ์ด์ง๋ง ๋ค์ ๋น๋ํด์ผ ํ์ต๋๋ค.
_์ด๊ฒ์ ๋น๋ ์์คํ ์์ฒด์ ๋ฐ๋ผ ๋ฌ๋ผ์ง๋ฏ๋ก ๊ฐ์ค์ผ ๋ฟ์ ๋๋ค.
์ด๊ฒ์ ๋ค๋ฅธ ํธ์คํ ์๋ฃจ์ ์ ์ํฅ์ ์ค ์ ์์ต๋๋ค.
๋ค์ ์์ฒด์๋ .next/cache
... ์ด ๋ฌธ์ ๋ฅผ ํด๊ฒฐํ๋ ค๋ฉด ์ด๋ป๊ฒ ํด์ผ ํฉ๋๊น?
@joltmode ๋ ๊ธฐ๋ณธ์ ์ผ๋ก ํ์ฌ ๋ชจ๋ ์ ์ ์ฌ์ดํธ ์์ฑ๊ธฐ์ ๊ฒฝ์ฐ์
๋๋ค. .next/cache
๋ Now์ ๋ฐฐํฌ์ ์ฌ์ฌ์ฉ ๊ฐ์ ๋ณด์กด๋ฉ๋๋ค. ํ์ฌ ์ด ๊ฒฝ์ฐ์ ์บ์ฑ(https://zeit.co/blog/serverless-pre-rendering)๊ณผ ํจ๊ป getInitialProps๋ฅผ ์ฌ์ฉ ์ค์ผ ์ ์๋ค๋ ์ ์ ๋ช
์ฌํ์ญ์์ค. ์ด ์บ์ฑ์ ์๋ฒ๋ฆฌ์ค ๊ธฐ๋ฅ์์ ๋์ ์ผ๋ก ๋ ๋๋งํ ๋ค์ CDN์ ์บ์ํฉ๋๋ค. ๋์์ ์ฌ์ ํ โโ๊ด์ฐฎ์ผ๋ฉฐ getServerProps
๋ฅผ ์ฌ์ฉํ๋ฉด ๊ณ์ ์๋ํฉ๋๋ค.
์ ๋ง ๊ต์ฅํฉ๋๋ค. ๊ณ ๊ฐ ํ๋ก์ ํธ์ Next๋ฅผ ์ฌ์ฉํ๋ ๋ฐฉ๋ฒ์ ์ ๋ง๊ณ ๋ณต์ฌํ๋ ์ผ๋ถ ์์ฉ๊ตฌ ์ฝ๋๋ฅผ ์ ๊ฑฐํฉ๋๋ค.
ํ ๊ฐ์ง ๊ณ ๋ คํด์ผ ํ ์ฌํญ์ getStaticProps ๋ฐ getServerProps์ ์ด๋ฆ ์ง์ ์ ๋๋ค. { props } ๋ฐ ํฅํ ์ ์ฌ์ ์ธ ๋ค๋ฅธ ์ต์ ์ ๋ฐํํ๋ ๊ฒฝ์ฐ *Props๊ฐ ํผ๋๋์ง ์์๊น์? getStaticConfiguration, getStaticSetup, getStaticOptions๊ฐ ๋ ์ผ๋ฐ์ ์ผ๊น์?
@kibs ๋ฐํ ๊ฐ์ ํญ์ ์ํ์ด ์ฒ๋ฆฌ๋๋ ๋ฐฉ์๊ณผ ๊ด๋ จ์ด ์์ต๋๋ค. ๊ทธ๋์ ๋ค์ด๋ฐ์ด ์ข๋ค.
์ด๊ฒ์ ๋จ์ํ ๊ต์ฅํฉ๋๋ค! ์ด๊ฒ์ ๋ด๊ฐ ์ต๊ทผ์ ๊ฐ์ง๊ณ ์๊ฑฐ๋ ๊ฐ์ธ ๋ฐ ์ ๋ฌธ ์น ์ฑ์ ๊ฐ๋ฐํ๋ ๋์ ์๊ฐํ ์ ์์๋ ๋ชจ๋ ์ฌ์ฉ ์ฌ๋ก์ ํ์๋ฅผ ํด๊ฒฐํฉ๋๋ค. ๋น์ ์ ๋ด๊ฐ ํ์ด๋ธ๋ฆฌ๋ ์ฌ์ดํธ ์์ฑ๊ธฐ๋ฅผ ์์ํ๋ ๊ฒ์ ๋ง์์ต๋๋ค. ๊ฐ์ฌํฉ๋๋ค!
๋๋ ๋ํ ์๋ก์ด ๋ฐฉ๋ฒ์ด ์ด์ getInitialProps()
๋ฐ exportPathMap()
๋ณด๋ค ๋ซ๋ค๋ ๊ฒ๊ณผ ๊ด๋ จ๋ ์ ์์ต๋๋ค. ์ด๊ฒ์ ์ฒ์์ Next.js๋ฅผ ์ฌ์ฉํ๊ธฐ ์์ํ๊ณ SSR/SSG๋ฅผ ํํค์ณค์ ๋ ์ฝ๊ฐ ํผ๋์ค๋ฝ๊ฒ ๋ค๋ ธ์ต๋๋ค. ํ์ด์ง๋น ์ ๊ทผ ๋ฐฉ์์ด ๋์๊ฒ๋ ๋ ์๋ฏธ๊ฐ ์์ต๋๋ค.
์ด๊ฒ์ ์๋ํ๊ธฐ ์ํด ๊ธฐ๋ค๋ฆด ์ ์์ต๋๋ค!
์ฐธ๊ณ ์ฌํญ: ๋ง์ง๋ง ์์์
getServerProps()
์context
๋งค๊ฐ๋ณ์๊ฐ ๋๋ฝ๋ ๊ฒ ๊ฐ์ต๋๋ค.
์ฐธ๊ณ ์ฌํญ: ๋ง์ง๋ง ์์ ์์ getServerProps()์ ์ปจํ ์คํธ ๋งค๊ฐ๋ณ์๊ฐ ๋๋ฝ๋์๋ค๊ณ ์๊ฐํฉ๋๋ค.
๊ฒฐ์ ๋!
์ด๊ฒ์ ์ข์ ์๋ฆฌ์
๋๋ค! TypeScript ์ฌ์ฉ์ ๊ด์ ์์ getStaticProps
, getStaticPaths
๋ฐ getServerProps
๋ฅผ ํ์ด์ง ๊ตฌ์ฑ ์์์ ์ ์ ๋ฉ์๋(์ getInitialProps
)๋ก ์ฌ์ฉํ๋ฉด ๋ ์ฝ๊ฒ ์
๋ ฅ/์ฌ์ฉํ ์ ์์ต๋๋ค.
const Page: NextPage<Props> = (props) => ...
// Explicit types needed here
export const getStaticPaths: NextGetStaticPaths<Params> = () => ...
export const getStaticProps: NextGetStaticProps<Props, Params> = (context) => ...
export const getServerProps: NextGetServerProps<Props> = (context) => ...
export default Page
// vs.
const Page: NextPage<Props, Params> = (props) => ...
// Static method types come from NextPage<Props, Params>
Page.getStaticPaths = () => ...
Page.getStaticProps = (context) => ...
Page.getServerProps = (context) => ..
export default Page
@herrstucki ๊ทธ ์ ๊ทผ ๋ฐฉ์์ ๋ฌธ์ ๋ ๋๋ฌด๋ฅผ ํ๋๋ ๊ฒ์ด ํจ์ฌ ๋ ์ด๋ ค์์ง๋ค๋ ๊ฒ์ ๋๋ค(์ฝ๊ธฐ: ๋ถ๊ฐ๋ฅ์ ๊ฐ๊น์ต๋๋ค). ์ด๋ ๋ถํ์ํ ์ฝ๋๊ฐ ๋ธ๋ผ์ฐ์ ์ ์ ๋ฌ๋ ๊ฒ์์ ์๋ฏธํฉ๋๋ค.
@timneutkens ์ข์ ์ง์ ... ํ์ง๋ง ๋ณ๋์ ํ์ผ์ด ๋ ์๋ฏธ๊ฐ ์์๊น์? ์๋๋ฉด ์ด์ ๊ฐ์ ๊ฒ์ด _์์ ์ ์ผ๋ก_ ๋๋ฌด๋ฅผ ํ๋ค ์ ์์ต๋๊น?
// This should all be removed in client-side code โฆ
import {fetchQuery, queryTag} from 'big-data-fetching-lib';
const query = queryTag`...`
export const getStaticProps = async () => ({ props: await fetchQuery(query) })
// Only this should be included client-side
export default (props) => ...
@herrstucki ์ฐ๋ฆฌ๋ ๊ทธ๊ฒ์ ์์ ์ ์ผ๋ก ํ๋ค ์ ์์ง๋ง, ์ฐ๋ฆฌ๋ ์ฌ์ ํ ๋ณ๋์ ํ์ผ์ ๊ฐ๋ ๊ฒ์ ๋ํด ๋ ผ์ํ๊ณ ์์ต๋๋ค. ๊ฐ์ธ์ ์ผ๋ก ๋จ์ผ ํ์ผ ์ ๊ทผ ๋ฐฉ์์ ์ ํธํฉ๋๋ค.
๋งค์ฐ ํฅ๋ฏธ๋กญ๊ฒ ๋ณด์ ๋๋ค!
getInitialProps
๋์ ํ ๊ฒ์ธ๊ฐ ์๋๋ฉด ํจ๊ป ํ ๊ฒ์ธ๊ฐ? ์๋ฅผ ๋ค์ด ์ฐ๋ฆฌ์ ์ฌ์ฉ ์ฌ๋ก์์ ๋ฐ์ดํฐ ๊ฐ์ ธ์ค๊ธฐ API๋ ๊ณต๊ณต ์๋น์ค์ ๋๋ค. ๋ฐ๋ผ์ ํด๋ผ์ด์ธํธ ์ธก ํ์์์๋ ํด๋ผ์ด์ธํธ๊ฐ API ๊ณ์ธต์ ์ง์ ํธ์ถํ๋ ๋ฐ๋ฉด SSR์์๋ ์๋ฒ๊ฐ ํธ์ถํ ๊ฒ์ผ๋ก ์์ํฉ๋๋ค. ์์ผ๋ก ์ด ์ฌ์ฉ ์ฌ๋ก๋ ์ด์ ๋ฐฉ๋ฒ์ผ๋ก ๊ณ์ ํด๊ฒฐ๋ฉ๋๊น?์ผ๋ฐ์ ์ผ๋ก ์ด๋ฌํ ๋์์๋ ์ ์ธ๊ณ์ ํน์ ์ง์ญ์์ ๋๋ฆด ์ ์๋ ํญํฌ์ ๊ฐ์ ธ์ค๊ธฐ์ ๊ฐ์ ๋ช ๊ฐ์ง ๋จ์ ์ด ์์ต๋๋ค.
getServerProps
์ ๊ทผ ๋ฐฉ์์ ์ฌ์ฉํ๋ฉด ์๋ต์ ๋ณด๋ค ํจ์จ์ ์ผ๋ก ์บ์ฑํ ์ ์์ต๋๋ค.
๋ฌผ๋ก , ํ์ง๋ง ๋ฐ์ ์๋ฒ์ ๋ํ RTT๋ฅผ ์ ํ ํผํ๋ ๊ฒ์ ๋ํด ์ด์ผ๊ธฐํ๊ณ ์์ต๋๋ค. ์๋ฒ์ SSR ์ถ๋ ฅ์ด CDN/์บ์ ์๋ฒ ํ๋ก์์ ์บ์ฑ๋๋ ๊ฒฝ์ฐ๋ฅผ ์๊ฐํด ๋ณด์. ๋ค๋ฅธ API ๋ ์ด์ด(์น/์ฑ/๋ชจ๋ ํด๋ผ์ด์ธํธ์ ๊ณตํต)๋ฅผ ์ง์ ํธ์ถํ๋ ํด๋ผ์ด์ธํธ ํ์์ ์ํ ๋ฐ์ดํฐ ๊ฐ์ ธ์ค๊ธฐ์ ํจ๊ป ์ฌ์ฉํ๋ฉด ํธ๋ํฝ์ด ๋ง์ ์๋๋ฆฌ์ค์์ Next.js ์๋ฒ ๋ ์ด์ด๋ฅผ ํ์ฅํ ํ์๊ฐ ์์ต๋๋ค.
ํญํฌ์ ๊ฐ์ ธ์ค๊ธฐ์ ์์ ์ ์ดํดํ์ง๋ง ์๋น์์๊ฒ ๋ค์ ์๋ฒ๋ฅผ ๋ฐ์ดํฐ ์์ค์ ๋น๊ตํ์ฌ SSR ๊ณ์ธต์ผ๋ก ์ทจ๊ธํ ์ ์๋ ๊ธฐ๋ฅ์ ์ ๊ณตํ๋ฉด ํจ์ฌ ๋ ๋์ ํ์ฅ ์ค์ ์ด ๊ฐ๋ฅํฉ๋๋ค.
๋งค์ฐ ํฅ๋ฏธ๋กญ๊ฒ ๋ณด์ ๋๋ค!
getInitialProps
๋์ ํ ๊ฒ์ธ๊ฐ ์๋๋ฉด ํจ๊ป ํ ๊ฒ์ธ๊ฐ? ์๋ฅผ ๋ค์ด ์ฐ๋ฆฌ์ ์ฌ์ฉ ์ฌ๋ก์์ ๋ฐ์ดํฐ ๊ฐ์ ธ์ค๊ธฐ API๋ ๊ณต๊ณต ์๋น์ค์ ๋๋ค. ๋ฐ๋ผ์ ํด๋ผ์ด์ธํธ ์ธก ํ์์์๋ ํด๋ผ์ด์ธํธ๊ฐ API ๊ณ์ธต์ ์ง์ ํธ์ถํ๋ ๋ฐ๋ฉด SSR์์๋ ์๋ฒ๊ฐ ํธ์ถํ ๊ฒ์ผ๋ก ์์ํฉ๋๋ค. ์์ผ๋ก ์ด ์ฌ์ฉ ์ฌ๋ก๋ ์ด์ ๋ฐฉ๋ฒ์ผ๋ก ๊ณ์ ํด๊ฒฐ๋ฉ๋๊น?์ผ๋ฐ์ ์ผ๋ก ์ด๋ฌํ ๋์์๋ ์ ์ธ๊ณ์ ํน์ ์ง์ญ์์ ๋๋ฆด ์ ์๋ ํญํฌ์ ๊ฐ์ ธ์ค๊ธฐ์ ๊ฐ์ ๋ช ๊ฐ์ง ๋จ์ ์ด ์์ต๋๋ค.
getServerProps
์ ๊ทผ ๋ฐฉ์์ ์ฌ์ฉํ๋ฉด ์๋ต์ ๋ณด๋ค ํจ์จ์ ์ผ๋ก ์บ์ฑํ ์ ์์ต๋๋ค.๋ฌผ๋ก , ํ์ง๋ง ๋ฐ์ ์๋ฒ์ ๋ํ RTT๋ฅผ ์ ํ ํผํ๋ ๊ฒ์ ๋ํด ์ด์ผ๊ธฐํ๊ณ ์์ต๋๋ค. ์๋ฒ์ SSR ์ถ๋ ฅ์ด CDN/์บ์ ์๋ฒ ํ๋ก์์ ์บ์ฑ๋๋ ๊ฒฝ์ฐ๋ฅผ ์๊ฐํด ๋ณด์. ๋ค๋ฅธ API ๋ ์ด์ด(์น/์ฑ/๋ชจ๋ ํด๋ผ์ด์ธํธ์ ๊ณตํต)๋ฅผ ์ง์ ํธ์ถํ๋ ํด๋ผ์ด์ธํธ ํ์์ ์ํ ๋ฐ์ดํฐ ๊ฐ์ ธ์ค๊ธฐ์ ํจ๊ป ์ฌ์ฉํ๋ฉด ํธ๋ํฝ์ด ๋ง์ ์๋๋ฆฌ์ค์์ Next.js ์๋ฒ ๋ ์ด์ด๋ฅผ ํ์ฅํ ํ์๊ฐ ์์ต๋๋ค.
ํญํฌ์ ๊ฐ์ ธ์ค๊ธฐ์ ์์ ์ ์ดํดํ์ง๋ง ์๋น์์๊ฒ ๋ค์ ์๋ฒ๋ฅผ ๋ฐ์ดํฐ ์์ค์ ๋น๊ตํ์ฌ SSR ๊ณ์ธต์ผ๋ก ์ทจ๊ธํ ์ ์๋ ๊ธฐ๋ฅ์ ์ ๊ณตํ๋ฉด ํจ์ฌ ๋ ๋์ ํ์ฅ ์ค์ ์ด ๊ฐ๋ฅํฉ๋๋ค.
์ด ์๋ก์ด ๋์์ CDN์ด ๋์ ์๋ต์ ์ง์ํ๋ ๊ฒฝ์ฐ ์ค์ ๋ก ์ ์ฒด ๊ฒฐ๊ณผ๋ฅผ CDN์ ์บ์ํ ์ ์์์ ์๋ฏธํ๋ค๊ณ ์คํดํ๊ณ ์๋ ๊ฒ ๊ฐ์ต๋๋ค. ์ด๊ฒ์ ์ด์ ์ getInitialProps๋ฅผ ์ฌ์ฉํ์ฌ ์์ ์ ์ผ๋ก ๊ฐ๋ฅํ์ง ์์์ต๋๋ค.
@timneutkens babel-plugin-preval
์ฝ๋๋ฅผ getStaticProps
๋ก ์ด์ํ๋ ค๊ณ ํ๋ ์นด๋๋ฆฌ์๋ฅผ ๊ฐ์ง๊ณ ๋์์ต๋๋ค. fs
๋ฌธ์ ๊ฐ ์๊ฒผ์ต๋๋ค.
๋ด ./pages/blog/
๋๋ ํ ๋ฆฌ์ .md ํ์ผ์ ์ฝ๊ณ ๋ฃจํ๋ฅผ ํตํด ๋ชจ๋ ๊ฒ์๋ฌผ์ด ํฌํจ๋ ๋ธ๋ก๊ทธ ์์ธ ํ์ด์ง๋ฅผ ๋ง๋ค๋ ค๊ณ ํฉ๋๋ค.
import React from 'react';
import Link from 'next/link';
import fs from 'fs-extra';
const Index = ({ posts }) => (
<div>
Hello World. <Thing msg="hello" />
<Link href="/thing">
<a>About</a>
</Link>
{posts.map(p => (
<div key={p.title}>{p.title}</div>
))}
</div>
);
Index.getStaticProps = async () => {
const items = await fs.readdir('./pages/blog');
items.forEach(path => /* .... do some stuff ... */ )
return { props: { posts: items } };
};
export default Index;
์ด ์ฝ๋๋ ๋ค์ ์ค๋ฅ๋ก ์ด์ด์ง๋๋ค.
Module not found: Can't resolve 'fs' in '/Users/jared/Downloads/nextjs-typescript-template/node_modules/fs-extra/lib'
Razzle์ IIRC์ ๋ฐ๋ฅด๋ฉด ์ด ์ค๋ฅ๋ webpack์ ํ์ผ ์์คํ ์คํ (๋๋ ๊ทธ ๋ถ์กฑ)๊ณผ ๊ด๋ จ์ด ์์ต๋๋ค. ๋๋ ์ด๊ฒ์ webpack ๊ตฌ์ฑ์ ์ถ๊ฐํ์ฌ Razzle๋ก ํ ๋ฒ ์ด๊ฒ์ ์์ ํ๋ค๊ณ ์๊ฐํฉ๋๋ค.
node: {
fs: "empty";
}
์ด next.config.js๋ฅผ ์๋ํ์ง๋ง ์ค๋ฅ๊ฐ ์ฌ๋ผ์ง๋๋ค. fs
/ fs-extra
๊ฐ ์ค์ ๋ก ์๋ํ์ง ์๊ฑฐ๋ ์๋ํ์ง๋ง ์๋ง๋ ๊ฒฝ๋ก๊ฐ ์๋ํ์ง ์๋ ๊ฒ์ผ๋ก ๋ณด์
๋๋ค(๋์๊ฒ ๋ช
ํํ์ง ์์). ๊ทธ๊ฒ์ ๋ํ ์๊ฐ์ด ์์ต๋๊น?
๋ ์ผ๋ฐ์ ์ผ๋ก ๋ด ๋ค๋ฅธ ์ง๋ฌธ์ getStaticProps
์์ import ๋ require๋ฅผ ์ฌ์ฉํ๋ ๋ชจ๋ฒ ์ฌ๋ก๊ฐ ๋ฌด์์ด๋ผ๊ณ ์๊ฐํ๋์ง์
๋๋ค. ๋ด๊ฐ ํ๋ฆฌ์ง ์์๋ค๋ฉด ์์ ์ค๋ํซ์ fs-extra
๋ฅผ React์์ ๋ํ์ ์ผ๋ก ๊ฐ์ ธ์ค๋ ค๊ณ ์๋ํฉ๋๋ค??. ๋ฐ๋ผ์ ์ด์ ๊ฐ์ด ์ธ๋ผ์ธ ์๊ตฌ ์ฌํญ์ผ๋ก ๊ฐ์ ธ์ค๊ธฐ๋ฅผ ๋ณ๊ฒฝํ๋ ๊ฒ์ด ๋ ๋ซ์ต๋๊น?
js
Index.getStaticProps = async () => {
const fs = require('fs-extra'); // only require when needed at SSG
const props = await fs.readdir('./pages/blog');
return { props: { posts } };
};
์ด ์๋ก์ด ๋์์ CDN์ด ๋์ ์๋ต์ ์ง์ํ๋ ๊ฒฝ์ฐ ์ค์ ๋ก ์ ์ฒด ๊ฒฐ๊ณผ๋ฅผ CDN์ ์บ์ํ ์ ์์์ ์๋ฏธํ๋ค๊ณ ์คํดํ๊ณ ์๋ ๊ฒ ๊ฐ์ต๋๋ค. ์ด๊ฒ์ ์ด์ ์ getInitialProps๋ฅผ ์ฌ์ฉํ์ฌ ์์ ์ ์ผ๋ก ๊ฐ๋ฅํ์ง ์์์ต๋๋ค.
์, ๋ฌด์จ ๋ง์ธ์ง ์ ๊ฒ ๊ฐ์์. ๊ทธ๊ฒ์ ์ฒซ ๋ฒ์งธ SSR ์์ฑ์ getServerProps
๊ฐ ๊ณ ์ ํ ๋์ ์ ์์ฑํ๋ค๋ ๊ฒ์ ์๋ฏธํฉ๋๊น? ์ฝํ
์ธ ์ฃผ์ ์ง์ ๊ฐ๋ฅํ ํด์์์ ์๋ง๋ URL์ ์์ ์ ์์ผ๋ฉฐ ๊ทธ๋ฐ ๋ค์ CDN์ ์บ์ํ ์ ์์ต๋๊น? ์ด๊ฒ์ ์ ์ผํ ๋จ์ ์ ์บ์๊ฐ ๋น Next ์ฑ(android/ios)๊ณผ Next ์ฑ ๊ฐ์ ๊ณต์ ํ ์ ์๋ค๋ ๊ฒ์
๋๋ค. ๋ํ ์ธ๋ถ ๋ฐ์ดํฐ ์์ค์ ๊ฒฝ์ฐ ์บ์ ์ ์ด ์ง์๋ฌธ์ด ์
์คํธ๋ฆผ์ด์ง๋ง Next๊ฐ ๋ฐ์ดํฐ ์ ๊ณต์ ๋ด๋นํ๋ฏ๋ก ์์ฑ๋ ๋ฐ์ดํฐ ๋์ ์ ๋ํ API ๋๋ ์ํ์ ์ง์ ํ๊ธฐ ์ํด API ๋๋ ์ํ์ด ํ์ํฉ๋๋ค.
@jaredpalmer ๋๋ https://github.com/zeit/next.js/issues/9524#issuecomment -558628066 ( ์์ ์ ์ธ ํธ๋ฆฌ ํ๋ค๋ฆผ ๊ฐ๋ฅ์ฑ์ ๋ํ ๋ด ์ฐ๋ ค ํฌํจ)์ด ์์ ํ ๋ณ๋๋ก ์ปดํ์ผ๋๋ ๋ณ๋์ ํ์ผ์ ๊ฐ์ง์ผ๋ก์จ ํด๊ฒฐ๋ ๊ฒ์ด๋ผ๊ณ ๊ฐ์ ํฉ๋๋ค. ํด๋ผ์ด์ธํธ ๋ฒ๋ค ์ฝ๋? ์
pages/
foo.js
foo.data.js (<- exports getStaticProps etc.)
or:
pages/
foo.js
pages-data/
foo.js (<- exports getStaticProps etc.)
@jaredpalmer ํธ๋ฆฌ ์์ดํน์ ์นด๋๋ฆฌ์์์ ์์ง ๊ตฌํ๋์ง ์์์ต๋๋ค.
ํญ์ ๊ทธ๋ ๋ฏ์ด ๋ชจ๋ ์ผ์ ๊ฐ์ฌ๋๋ฆฝ๋๋ค. Next.js๋ ์์ ํ๋ ๋ฐ ์์ด ์ ๋์ ์ธ ๊ธฐ์จ์ ๋๋ ธ์ต๋๋ค. ์์ ๋ง์๋๋ฆฐ ๊ฒ์ฒ๋ผ ๊ฑฐ์ ๋ชจ๋ ๊ธฐ๋ฅ ๋ฆด๋ฆฌ์ค๋ฅผ ํตํด ์ ๊ฐ ๊ด๋ฆฌํ๋ ์ฝ๋๋ฒ ์ด์ค์ ํฌ๊ธฐ๋ฅผ _๊ฐ์_์ํฌ ์ ์์ต๋๋ค. ๋๋๋ค.
์ด RFC๋ ์์ฑ๋ ๋๋ก ๋ง์ ์์ฉ ํ๋ก๊ทธ๋จ์ ์ฆ์ ์ ์ฉํ๊ธฐ ๋๋ฌธ์ ์ด RFC๋ฅผ ๋นํํ๊ธฐ ์ด๋ ต์ต๋๋ค. ๊ทธ๋ฌ๋ ๋๋ ๋ด๊ฐ ๋์ํ๋์ง ํ์ ํ ์ ์๋ ํ ์ค์ ๋งํ๊ณ ์ถ์ต๋๋ค.
"
getStaticPaths
๋exportPathMap
๊ฐ ์์ด์ผ ํ๋ ํ์์ฑ์ ๋์ฒดํ๊ณ ํ์ด์ง๋ณ๋ก ์๋ํฉ๋๋ค."
์ผ๋ถ ์์ฉ ํ๋ก๊ทธ๋จ์์๋ ๋น๋ ์ ๊ฒฝ๋ก๋ฅผ ์๋ ๊ฒ์ด ๋นํ์ค์ ์ด๊ฑฐ๋ ๋ถ๊ฐ๋ฅํฉ๋๋ค. ๋ช ๊ฐ์ง ์๋ ๋ค์๊ณผ ๊ฐ์ต๋๋ค.
์ด์ ๊ฐ์ ํ์ด์ง์ ๊ฒฝ๋ก๋ /entity-name/entity-id
๊ฒ์ด๋ฉฐ Next์ ๋์ ๊ฒฝ๋ก๋ router.push('/customers/[customerId]', '/customers/baer')
์ ๊ฐ์ ์์
์ ์ํํ ์ ์๊ธฐ ๋๋ฌธ์ ์ ๋ง ์ ์๋ํฉ๋๋ค. ์์ง ํจ์ ์ด ์์ต๋๋ค. Serve, Netlify, NGINX ๋ฑ๊ณผ ๊ฐ์ ๊ฒ์ผ๋ก ์ด๋ฌํ ํ์ผ์ ์ ์ ์ผ๋ก ์ ๊ณตํ ๊ณํ์ด๋ผ๋ฉด ์ฌ์ฉ์๊ฐ ํ์ด์ง ์๋ก ๊ณ ์นจ์์ 404๋ฅผ ์ป์ง ์๋๋ก ๋ฆฌ๋๋ ์
์ธํธ๋ฅผ ์์ฑํด์ผ ํ๋ฉฐ ๊ทธ๋ ๊ฒ ํ๋ ค๋ฉด ์ฌ์ ํ exportPathMap
๊ฐ ํ์ํฉ๋๋ค.
๋ค์์ ๋ด๊ฐ ์ ๊ธฐ์ ์ผ๋ก ์์ ํ๋ ์ฝ๋๋ฒ ์ด์ค์์ ๊ฑฐ์ ๊ทธ๋๋ก ๋ณต์ฌ๋ฉ๋๋ค.
const buildServeConfig = redirects => {
const config = {
public: `dist`,
trailingSlash: true,
rewrites: redirects
};
const outputPath = `${__dirname}/serve.json`;
fs.writeFile(outputPath, JSON.stringify(config, null, 2), err => {
if (err) {
throw err;
}
// eslint-disable-next-line no-console
console.log(`Generated: ${outputPath}`);
});
};
...
exportPathMap: function(defaultPathMap, { dev, outDir }) {
const redirects = Object.entries(defaultPathMap)
// No need to create a redirect rule for `/dirname/` or `/dirname/index.html`
.filter(([url]) => url !== `/` && url !== `/index`)
.map(([url, { page }]) => ({
// Replaces /[customerId] with /:customerId
source: url.replace(/]/g, ``).replace(/\[/g, `:`),
destination: `${page}/index.html`
}));
// By default, the routes are sorted such that a route like `/order/:orderId`
// comes before `/order/new`. Since the `:orderId` portion of `/order/:orderId`
// is a wildcard, the route `/order/new` will be a match and consider `new`
// as a value for `:orderId`. To get past this, we sort the redirects by the
// number of parameters in ascending order.
const sortedRedirects = [...redirects].sort(
(currentRedirect, nextRedirect) =>
currentRedirect.source.split(`:`).length >
nextRedirect.source.split(`:`).length
);
buildServeConfig(sortedRedirects);
return defaultPathMap;
}
๋๋ ์ด RFC๊ฐ API๋ฅผ ๋ ์ด์ ์ฌ์ฉํ์ง ์๊ฑฐ๋ ์ ๊ฑฐํ์ง ์๋๋ค๋ ๊ฒ์ ์ดํดํ๊ณ ๋น๋ ๋๋ ํ ๋ฆฌ๋ฅผ ์ํํ์ฌ ์ด๋ฌํ ๋ฆฌ๋๋ ์
์ ๋น๋ํ ์ ์๋ค๋ ๊ฒ์ ์๊ณ ์์ผ๋ฏ๋ก ๋ ์ด์ ์ฌ์ฉ๋์ง ์๋ ๊ฒฝ์ฐ์๋ ๋ฉ์ง ํ์ถ ํด์น๋ฅผ ๊ฐ์ง๊ณ ์์ต๋๋ค. ๊ทธ๋ฌ๋ " getStaticPaths
๋ํ ํ์์ฑ์ ์ ๊ฑฐ"ํ์ง๋ ์์ต๋๋ค.
๋ค์ ํ ๋ฒ, ์ด ํ๋ก์ ํธ๋ฅผ ์ํํ๋ ๋ฐฉ์์ ๋ํด ์ฌ๋ ค ๊น๊ฒ ์๊ฐํด ์ฃผ์ ์ ๊ฐ์ฌํฉ๋๋ค.
getStaticProps
/getStaticPaths
๋ฐgetServerProps
์ํธ ๋ฐฐํ์ ์ ๋๊น? ์ฆ, ๋ฏธ๋ฆฌ ๋ ๋๋ง๋ ๋ถํ๊ณผ ๋์ ๋ถํ์ ๋์์ ๊ฐ์ง ์ ์์ต๋๊น?
์, ํ๋๋ ์ ์ ์์ฑ์ด๊ณ ํ๋๋ ์๋ฒ ์ธก ๋ ๋๋ง์ ๋๋ค.
์ด๊ฒ์ ์ฐ๋ฆฌ๊ฐ Next๋ก ๋ง์ด๊ทธ๋ ์ด์ ํ๊ธฐ ์ ์ Gatsby์์ ๋์น ํฐ ๊ฒ ์ค ํ๋๋ฅผ ์์ ํฉ๋๋ค.
๋ณ๊ฒฝ๋์ง ์๋ ํ์ด์ง๋ฅผ ๋ ๋๋งํ๊ธฐ ์ํด ๋ฐ์ดํฐ๋ฅผ ๊ฐ์ ธ์ค๋ ๋ชจ๋๋ฆฌ์(100kbs) JSON ํ์ผ์ด ์์ต๋๋ค. Gatsby์์ JSON ํ์ผ์ GraphQL ์คํค๋ง์ ๋ก๋ํ๊ณ ์ด์ ๋ํด ์ฟผ๋ฆฌํ์ฌ ์ฃผ์ด์ง ํ์ด์ง๋ฅผ ๋ ๋๋งํ๋ ๋ฐ ํ์ํ ๋ฐ์ดํฐ๋ง ๊ฐ์ ธ์์ต๋๋ค. Next๋ฅผ ์ฌ์ฉํ์ฌ ์ด๋ฅผ ์ํํ๋ ๊ฐ์ฅ ์ฝ๊ณ ๊นจ๋ํ ๋ฐฉ๋ฒ์ ์ฌ์ฉ์๊ฐ ์ ์ฒด JSON ํ์ผ์ ๋ค์ด๋ก๋ํด์ผ ํ๋ import monolith from './monolith.json'
์
๋๋ค.
์ด RFC 100%๋ ์ด ์ฌ์ฉ ์ฌ๋ก๋ฅผ ํด๊ฒฐํ๊ณ Gatsby๊ฐ ๋น๋๋ ์์ญ์์ Gatsby์ ๋๋ฑํ ์์ค์ ํ ๊ฑธ์ ๋ ๋ค๊ฐ๊ฐ๋๋ก ํฉ๋๋ค(๋ถ๋ช ํ Gatsby๋ ๋ฐํ์ SSR์ ์ํํ ์ ์์ผ๋ฏ๋ก ์ ์ ๋น๋ ํ์ ๋ ๋์ ๋ํด์๋ง ์ด์ผ๊ธฐํ๊ณ ์์ต๋๋ค).
@timneutkens , RFC์ ๊ฐ์ฌ๋๋ฆฝ๋๋ค!
์ต๊ทผ์ @rauchg์ ๋ ผ์ํ Next.js์ ์ฌ์ฉ ์ฌ๋ก๊ฐ ์์ต๋๋ค.
Next.js๋ ๋งค์ฐ ๋ถ๋๋ฌ์ด DX์ ๋ช ๊ฐ์ง ํฉ๋ฆฌ์ ์ธ ๊ธฐ๋ณธ๊ฐ์ ์ ๊ณตํฉ๋๋ค. ๊ทธ๋์ ์ ๋ ํด๋ผ์ด์ธํธ ์ธก ์ ์ฉ ๋ ๋๋ง ์ ํ๋ฆฌ์ผ์ด์ ์ธ Smart TV ์ฑ์ Next.js๋ฅผ ์ฌ์ฉํ๋ ๋ฐ ๊ด์ฌ์ด ์์ต๋๋ค.
์ค๋งํธ TV ์ฑ์ TV์ ๋ธ๋ผ์ฐ์ ์์ง์์ ์คํ๋๋ ๊ฑฐ์ ๊ณ ์ ์ ์ธ ์น ์ฑ์ ๋๋ค.
๋ฌธ์ ๋ ๋ฒ๋ค์ด TV ์ฅ์น ์์ฒด์ ์ํด ์ ์ ์ผ๋ก ํธ์คํ ๋๊ณ ์๋ฒ์์ ๋ก๋๋์ง ์๋๋ค๋ ๊ฒ์ ๋๋ค. ๋ฐ๋ผ์ SSR ์ต์ ์ ๋ถ๊ฐ๋ฅํฉ๋๋ค(Node.js๋ ์ด๋ฌํ ๋ชฉ์ ์ผ๋ก ๊ฐ๋ฐ์์๊ฒ ๋ ธ์ถ๋์ง ์์ต๋๋ค). ๊ทธ๋ฌ๋ ์ฑ ์์ฒด๋ ๋์ ์ ๋๋ค(์: Netflix).
๋ฐ๋ผ์ ์ ์ ์น ์๋ฒ์์ ํธ์คํ ํ๋ SPA๋ฅผ ์คํํด์ผ ํฉ๋๋ค.
getServerProps
(๋๋ getInitialProps
)๋ฅผ ์ ํ ํด์ ํ๋ฉด SSR์ ๋ฐฉ์งํ๋ ๋ฐ ์์ ํ ๋์์ด ๋ฉ๋๋ค. ๊ทธ๋ฌ๋ ํด๋ผ์ด์ธํธ์์ ๋์ ๋ ๋๋ง์ ์ด๋ป๊ฒ ๋ฉ๋๊น? ์ด ๊ฒฝ์ฐ ๋ผ์ฐํ
์ ์ด๋ป์ต๋๊น? ์ด RFC ์ ๋ฐ๋ฅด๋ฉด ๋ฌธ์ ๋ ์์ง ํด๊ฒฐ๋์ง ์์์ต๋๋ค. @timneutkens ,
์ถ์ : ์ด ์ฌ์ฉ ์ฌ๋ก์ ๋ํด ๋ณ๋๋ก ๋ ผ์ํ๋ ๊ฒ์ด ๋ ๋ซ๋ค๊ณ ์๊ฐํ๋ ๊ฒฝ์ฐ ์ด ์ฌ์ฉ ์ฌ๋ก์ ๋ํ ๋ฌธ์ ๋ฅผ ๋ง๋ค ์ ์์ต๋๋ค.
@grushetsky ๋ ๋ค๋ฅธ ๋ฌธ์ ๋ฅผ ๋ง๋ค ์ ์์ต๋๋ค. ์ด๊ฒ์ RFC์์ ๋ ผ์๋๋ ๊ฒ๊ณผ ์์ ํ ๋ค๋ฅธ ์ง๋ฌธ์ ๋๋ค ๐
@timneutkens ์ด RFC์ ์ฝ์์ ์ ๊ฐ Next! ๊ทธ๋๋ ๋ช
ํํ ํ์๋ฉด getInitialProps
๋ ์ฌ์ ํ ์กด์ฌํ๊ฒ ์ฃ ?
์ฌ๋ฐ๋ฅธ @outdooricon -- getInitialProps
๋ ๋น๋ถ๊ฐ ๊ณ์ ์ ์ง๋ฉ๋๋ค.
RFC์ ๋ฐ๋ผ:
์ด RFC๋ API ์ถ๊ฐ์ ๋ํด ๋ ์ ์ ์ผ๋ก ์ค๋ช ํฉ๋๋ค. ๋ชจ๋ ์๋ก์ด ๊ธฐ๋ฅ์ ์ด์ ๋ฒ์ ๊ณผ ์์ ํ ํธํ๋๋ฉฐ ์ ์ง์ ์ผ๋ก ์ฑํํ ์ ์์ต๋๋ค. ์ด RFC๋ ๋ ์ด์ ์ฌ์ฉ๋์ง ์์ต๋๋ค.
ํ๋ฅญํ RFC, ์ด์ ๋ํด ๋งค์ฐ ๊ธฐ๋๋ฉ๋๋ค!
ํน์ ์ฌ์ฉ ์ฌ๋ก์ ๊ด๋ จํ์ฌ getServerProps
์ ๋ํด ์๊ฐํ๊ณ ๊ฒฐ๊ณผ๋ฅผ ์บ์์ ์ ์ฅํ์ต๋๋ค. ์ด๊ฒ์ด API-endpoint๋ก ๋ฐ๋๊ณ ๊ทธ ๊ฒฐ๊ณผ๊ฐ props๋ก ์ปดํฌ๋ํธ์ ์ ๋ฌ๋๊ธฐ ๋๋ฌธ์ Redux, GraphQL-cache ๋ฑ๊ณผ ๊ฐ์ ์ธ๋ถ ์บ์์ ๊ฒฐ๊ณผ๋ฅผ ํด๋ผ์ด์ธํธ ์ธก์ผ๋ก ๋ฃ๋ ๊ท์ ๋ ๋ฐฉ๋ฒ์ด ์์ต๋๊น?
getInitialProps
์ฌ๋ฐ๋ฅด๊ฒ ์ดํดํ๋ฉด ์ ์ ๋ฐ ๋น๋๊ธฐ์์ด๋ฏ๋ก Next๋ ๊ตฌ์ฑ ์์๋ฅผ ์ฒ์์ผ๋ก ๋ ๋๋งํ๊ธฐ ์ ์ ์๋ฃ๋ ๋๊น์ง ๊ธฐ๋ค๋ฆด ์ ์์ต๋๋ค. ์ด๋ฅผ ํตํด ์ธ๋ถ ์บ์์ ๋ฌผ๊ฑด์ ๋ฃ์ ์ ์์ต๋๋ค. getServerProps
๋ ์๋ฒ์์ ์คํ๋๊ธฐ ๋๋ฌธ์ ํด๋น๋์ง ์์ผ๋ฉฐ ๊ตฌ์ฑ ์์ ์๋ช
์ฃผ๊ธฐ์ ์บ์์ ํญ๋ชฉ์ ๋ฃ๋ ๊ฒ์ ์์ง ์บ์์์ ๋ฐ์ดํฐ๋ฅผ ์ฌ์ฉํ ์ ์๋ ๋ ๋๋ง์ด ์์ด์ผ ํจ์ ์๋ฏธํ๋ ๊ฒ ๊ฐ์ต๋๋ค. , props์์ ์ฌ์ฉ ๊ฐ๋ฅํ๋๋ผ๋?
์ด๊ฒ์ ๋ฌผ๋ก ์๋์ ์ผ ์๋ ์๊ณ ์ ๊ทผ ๋ฐฉ์์ ๋์น๊ณ ์์ ์๋ ์์ง๋ง ๊ณ ๋ คํ ์ฌํญ์ธ์ง ๋ฌป๊ณ ์ถ๋ค๊ณ ์๊ฐํ์ต๋๋ค.
ํธ์ง: getStaticProps
์๋ ์ ์ฉ๋๋ ๊ฒ ๊ฐ์ต๋๋ค. ๐
์ด๋๊ฐ์์ ๋์ณค์ ์๋ ์์ง๋ง ์ฝํ ์ธ ๊ฐ ์บ์๋์์ง๋ง db์์ ์ ๋ฐ์ดํธ๋๊ฑฐ๋ ์ ๋ธ๋ก๊ทธ ๊ฒ์๋ฌผ์ด ์์ฑ๋๋ ์ํฉ์ ์ด๋ป๊ฒ ์ฒ๋ฆฌํฉ๋๊น? ์ ๋น๋๋ฅผ ์๋์ผ๋ก ์ํํ ํ์๊ฐ ์์ต๋๊น? ๊ทธ๋ฐ ๊ฒ ๊ฐ์์.
๊ฐ์ฅ ๋จผ์ ! ํ๋ฅญํ ์ ์์
๋๋ค. ๋๋ถ๋ถ์ ์ฌ๋๋ค์ ์ฌ์ฉ ์ฌ๋ก์์ exportPathMaps
๋ณด๋ค ํฌ๊ฒ ๊ฐ์ ๋์์ต๋๋ค. ์ ๋ง ๊ฐ์ฌํฉ๋๋ค. ๊ทธ๋ ๊ธด ํ๋ฐ, ๋๋ ์ฐ๋ฆฌ๊ฐ ์ด๋ป๊ฒ ๊ทธ๊ฒ์ ๊ฒฝ๋ก ๊ตญ์ ํ์ ํจ๊ป ์๋์ํฌ ์ ์์์ง ์ดํดํ๊ธฐ ์ํด ๊ณ ๊ตฐ๋ถํฌํ๊ณ ์์ต๋๋ค.
i18n ์ ๋์ฌ ๊ฒฝ๋ก๋ฅผ ์ฒ๋ฆฌํ๋ ๋ฐฉ๋ฒ์ ๋ํ ์ ์ ์ฌํญ์ด ์์ต๋๊น? ๋ด ํน์ ์ฌ์ฉ ์ฌ๋ก๋ ๋ค๋ฅธ ๊ตญ๊ฐ ์ธ์ด ์ ๋์ฌ ๋ฐ URL์ด ์๋ ํ์ด์ง์ ์์ฒ ๊ฐ๋ฅผ ๊ตฌ์ถํด์ผ ํฉ๋๋ค.
/nl/brillen
/gb/glasses
/es/gafas
...
getStaticPaths
๋ ๊ทํ์ ์( /blog/[id].js
)์ ๊ฐ์ด url์ ์ ๋์ฌ๊ฐ ์ ์๋ ค์ ธ ์์ ๋ ์ ๋ง ๋์์ด ๋ ๊ฒ ๊ฐ์ต๋๋ค. ๊ทธ๋ฌ๋ ๋์ ์ ๋์ฌ(country-lang)์ ๋์ ๊ฒฝ๋ก๋ฅผ ๋ชจ๋ ์ฌ์ฉํ์ฌ ๋ฃจํธ ์์ค์์ ๊ฒฝ๋ก๋ฅผ ์์ฑํด์ผ ํ๋ ๊ฒฝ์ฐ getStaticPaths
๊ตฌํ์ด ์ด๋ป๊ฒ ๋ณด์ผ ๊ฒ ๊ฐ์ต๋๊น?
@reaktivo pages/[lang]/blog/[id].js
-> getStaticPaths
์์ ์ ์ ์ผ๋ก ๋ ๋๋งํ ๋ชจ๋ URL์ ์ ๊ณตํฉ๋๋ค.
@timneutkens ์ด๊ฒ์ด ์ธ์ ์ฌ์ฉ ๊ฐ๋ฅํ๊ฑฐ๋ ํ ์คํธ ๊ฐ๋ฅํ์ง ์ ์ ์์ต๋๊น?
์ผ๋ฐ์ ์ผ๋ก ์ฐ๋ฆฌ๋ ์๋ฃจ์ ์ด ์ฌ๋ฐ๋ฅธ์ง ํ์ธํ๊ธฐ ์ํด ํ๋ก๋์ ์ฑ์ ๋ํด ๊ธฐ๋ฅ์ ๊ด๋ฒ์ํ๊ฒ ํ ์คํธํ๊ธฐ ๋๋ฌธ์ ETA๋ฅผ ์ ๊ณตํ์ง ์์ต๋๋ค.
์ด ๊ฐ์ ์ฌํญ์ผ๋ก ์ธํด "์ ์ง๋์ง ์๋" ํ์์ ํ๋ก์ ํธ(๋ ์ธ์๋ ์๋ฌด๋ ์ฌ์ฉํ์ง ์๋ react ssg)๊ฐ ๋ ์ด์ ์ฌ์ฉ๋์ง ์์ต๋๋ค. ์ด ๋๋ฝ๋ ๋ถ๋ถ์ ์ถ๊ฐํ๋ Next.js๋ฅผ ๋ณด๋ ์ ๋ง ๊ธฐ์ฉ๋๋ค!
๊ถ๊ธ์ฆ์ ํด์ํ๊ณ ์ ํฉ๋๋ค. WordPress์ ๊ฐ์ CMS ์ฌ์ฉ์ ๊ณ ๋ คํ์ญ์์ค. ๋ด๊ฐ ์ดํดํ๋ ๊ฒ์ฒ๋ผ getStaticPaths ๋ฉ์๋๋ฅผ ์ฌ์ฉํ์ฌ ๋ชจ๋ ๊ฒ์๋ฌผ์ ๊ฐ์ ธ์ค๊ณ ๋ค์๊ณผ ๊ฐ์ ๋ชฉ๋ก์ ์ ๋ฌํฉ๋๋ค.
export async function getStaticPaths () {
return [
ย ย // This renders / blog / hello-world to HTML at build time
{params: {slug: "hello-world"}}
];
}
๊ฐ ๊ฒ์๋ฌผ์ ์ฌ๋ฌ๊ทธ๋ ์ฝํ
์ธ ๋ฅผ ๊ฐ์ ธ์ค๊ธฐ ์ํด getStaticProps ๋ฉ์๋์์ ์ฌ์ฉ๋ฉ๋๋ค.
์ด๊ฒ์ npm ๋น๋์์ ๋ฐ์ํฉ๋๋ค.
๋ด ์ง๋ฌธ์ ๋น๋ ํ์ ์ถ๊ฐ๋ ์ ๊ฒ์๋ฌผ์ ๊ดํ ๊ฒ์
๋๋ค.
getStaticProps ๋ฉ์๋๋ฅผ ์ฌ์ฉํ์ฌ ์ด ์ ๊ฒ์๋ฌผ์ ์ฌ๋ฌ๊ทธ๋ก ๊ฐ์ ธ์ค๋์?
์ด ์ ๊ฒ์๋ฌผ์ ์ด์ ๋น๋์ ํ์ผ๊ณผ ๊ฐ์ .html ํ์ผ์ด ์์ต๋๊น?
๋๋ ๋ค์๊ณผ ํจ๊ป ์ผํ๋ ๊ฒ์ ์ข์ํ๊ณ ์ฌ๋ฌ ํ๋ก์ ํธ์์ ์ด๊ฒ์ด ๋งค์ฐ ์ข์ ๊ฒ์
๋๋ค.
์ง์ ์ ์ธ ๊ด๋ จ์ ์์ง๋ง ์ง์ํ์์ ๋ด ์ง๋ฌธ๊ณผ ์ผ์นํ๋ ๋ต๋ณ์ ์ ๊ณตํ ์ ์์ต๋๋ค.
์ฌ๊ธฐ์์ ์ ์ํ๋ ๊ฒ์ด ํด๊ฒฐ์ฑ ์ด ๋ ์ ์์ง๋ง ๊ทธ ๋์ webhook ๋ณ๊ฒฝ ์ฌํญ์ ๊ธฐ๋ฐ์ผ๋ก JAMSTACK์ ๋น๋ํ๋๋ก nextJS๋ฅผ ๋ง๋ค ์ ์์ต๋๋ค.
getInitialProps๊ฐ ์์ผ๋ฉด ์๋ฒ์์ ๋ ๋๋ง๋ฉ๋๋ค.
๊ทธ๋ ์ง ์์ผ๋ฉด ๋๋ ๋จ์ง CDNํ๋์ง๋ง ์ฌ์ ๋ ๋๋ง ์์ด๋ ๊ทธ๋ ์ง ์์ต๋๊น? ๊ทธ๋ฆฌ๊ณ XHR์ด ๋ฐํ๋์ง ์๋ ํ ํ์ด์ง๋ ์ฝํ
์ธ ๊ฐ ์์ ๊ฒ์
๋๋ค(์๋
ํ์ธ์ SEO)
nextJS๊ฐ ํฌํจ๋ Jamstack์ ํ์ฌ ์คํ ์ค์ธ ์์ ๊ฐ ์์ต๋๊น? netlify์์ ํ ์ ์์ต๋๋ค.
๊ฐ์ฌ ํด์,
์๋๋ ์์ค
Hey @ScreamZ - ์ด ๋ณํ๊ฐ next export
๋ฅผ ์ฌ์ฉํ์ฌ nextjs ์ฌ์ดํธ๋ฅผ ์ ์ ์ผ๋ก ์ปดํ์ผํ ์ ์์์ง๋ง ์ฌ์ ํ getInitialProps
์ฌ์ฉํ์ฌ ํด๋ผ์ด์ธํธ ์ธก ๊ฒฝ๋ก ์ ํ์ ๋ํ ๋ฐ์ดํฐ๋ฅผ ๊ฐ์ ธ์ต๋๋ค. getStaticProps
๋ฅผ ์ฌ์ฉํ๋ ๊ธฐ๋ฅ์ ์ฌ์ฉํ๋ฉด ์ถ๊ฐ ๋ฐ์ดํฐ๋ฅผ ๊ฐ์ ธ์ค์ง ์๊ณ ๋ ํด๋ผ์ด์ธํธ ์ธก ์ ํ์ ์คํํ ์ ์์ต๋๋ค. getStaticProps
์์ ๊ฐ์ ธ์จ ๋ชจ๋ ๋ฐ์ดํฐ๋ ๋น๋ ์ ํ ๋ฒ๋ง ๊ฐ์ ธ์ค๊ณ ๋ค์ ๊ตฌ์ถํ์ง ์๋ ํ ๋ผ์ด๋ธ ์ฌ์ดํธ. ์ด๊ฒ์ ๋ฐ์ดํฐ ๊ธฐ๋ฐ ์ ์ ์ฌ์ดํธ์ ๊ณ ์ ์ ์ธ ์ํคํ
์ฒ์ด๋ฉฐ ์นํ
์ ํตํด ๋ฐ์ดํฐ ์์ค๋ฅผ ํธ์คํธ์ ์ฐ๊ฒฐํ๊ณ ๋ฐ์ดํฐ ์์ค๊ฐ ๋ณ๊ฒฝ๋๋ฉด ํธ์คํธ์๊ฒ ์ฌ์ดํธ๋ฅผ ๋ค์ ๋น๋ํ๋๋ก ์ง์ํฉ๋๋ค.
์์ ํ ์ ์ ์ธ nextjs ์น์ฌ์ดํธ์ ๊ธฐ์กด ์์ ๊ฐ ๋ง์ด ์์ผ๋ฉฐ netlify์์ nextjs ์ฌ์ดํธ๋ฅผ ์คํํ๋ ๊ฒ์ ๊ฐ๋จํฉ๋๋ค. ์ฐ๋ฆฌ ํ์ฌ์ ์น์ฌ์ดํธ ๋ ํ์ฌ nextjs์์ ์คํ๋๊ณ ์์ผ๋ฉฐ netlify์์ ํธ์คํ ํ๊ณ ์์ต๋๋ค. ์ด๊ฒ์ด ์ข์ ์๊ฐ ๋๊ธฐ๋ฅผ ๋ฐ๋๋๋ค.
zeit์ ํธ์คํ ์๋น์ค๋ ๊ฐ๋ ฅํ๊ฒ ๊ณ ๋ คํด์ผ ํ ๊ฐ์น๊ฐ ์๋ค๋ ์ ์ ์ฃผ๋ชฉํ ๊ฐ์น๊ฐ ์์ต๋๋ค. ๊ฐ๊ฒฉ์ ๋งค์ฐ ๋น์ทํ๊ณ nextjs ์ฌ์ดํธ์์ ํตํฉ์ ํ์ ์ถ์ข ์ ๋ถํํฉ๋๋ค. ๋ง ๊ทธ๋๋ก ์๋ฌด ๊ฒ๋ ๊ตฌ์ฑํ ํ์๊ฐ ์์ต๋๋ค. github์ ์ฐ๊ฒฐํ๊ธฐ๋ง ํ๋ฉด zeit์ ํธ์คํ ์ด nextjs๋ฅผ ์คํ ์ค์์ ์ธ์ํ๊ณ ์๋์ผ๋ก ๊ตฌ์ฑ ๋ฐ ๋ฐฐํฌํฉ๋๋ค. ๋ชจ๋ ๊ฒ.
์ด๊ฒ์ ๊ฒฐ์ฝ ๊ด๊ณ ๊ฐ ์๋๋ฉฐ, ๋๋ zeit๋ฅผ ์ํด ์ผํ์ง ์์ผ๋ฉฐ, ๋จ์ง ์ง์ ํ ๋ณด์ฆ์ ๋๋ค. netlify๋ฅผ ์ฌ์ฉํ๋ฉด ์ ๋์ ์ผ๋ก ์๋ํ๊ฒ ๋ง๋ค ์ ์์ผ๋ฉฐ ๊ฐ์ธ์ ์ผ๋ก ์ฌ๋ฌ ์ฌ์ดํธ์ ๋ํ ์ฆ๊ฑฐ๋ฅผ ๊ฐ์ง๊ณ ์์ต๋๋ค. ๊ทธ๋ฌ๋ nextjs๊ฐ ์ด๋ป๊ฒ ์๋ํ๋์ง ์ฒ ์ ํ ์ดํดํด์ผ ํ๋ฉฐ netlify์์ ์ํํ๊ฒ ์คํ๋๋๋ก ๋ชจ๋ ๊ฒ์ด ์ฌ๋ฐ๋ฅด๊ฒ ๊ตฌ์ฑ๋์๋์ง ํ์ธํด์ผ ํฉ๋๋ค. nextjs ์ฌ์ดํธ๋ฅผ ์ํ ๊ฐ์ฅ ๊ฐ๋จํ๊ณ ํ์คํ ํธ์คํ ์ ์ฐพ๊ณ ์๋ค๋ฉด zeit's ํธ์คํ ์ ์๋ํด ๋ณผ ๊ฒ์ ๋๋ค.
@jescalan ์ข์ ๋๋ ๊ฐ์ฌํฉ๋๋ค ๐๐ป
Publish directory
๋ฅผ ์ฌ์ฉํ์ฌ out
ํด๋๋ฅผ ์ง์ ํ ์ ์๊ธฐ ๋๋ฌธ์ Netlify์ ํจ๊ป NextJS๋ฅผ ์ฌ์ฉํ๋ ๋ฐ ๋ฌธ์ ๊ฐ ์์ต๋๋ค. ๊ทธ๋ฌ๋ ์ง๊ธ์ SSR์ ์ฌ์ฉํ์ง ๋ง๊ณ next export
์ฌ์ฉํ์ฌ ์์ ํ ๊ณ ์ ํ์ญ์์ค.
@ScreamZ ์ด๊ฒ์ ์ผ์ข
์ ์ฌ์ค์ด์ง๋ง "์ ์ฒด ์ ์ " ์ฌ์ดํธ๋ฅผ ์ ํํ ์ ์ํ๋ ๋ฐฉ๋ฒ์ ๋ฐ๋ผ ๋ค๋ฆ
๋๋ค. zeit์ ํธ์คํ
์๋น์ค๊ฐ ์๋ ๋ชจ๋ ํ์ด์ง์ getStaticProps
๋ฅผ ์ฌ์ฉํ๋ฉด next export
์คํํ์ง ์๋๋ผ๋ ์ค์ ๋ก ์ป์ ์ ์๋ ๊ฒ์ ์ ์ ์ฌ์ดํธ์ ๋์ผํฉ๋๋ค getStaticProps
๋ ์ฌ์ดํธ๊ฐ ๋ฐฐํฌ๋ ๋๋ง ๊ตฌ์ถ๋๋ฉฐ ๊ทธ ์ดํ์๋ CDN์์ ์ง์ ์ ๊ณต๋ฉ๋๋ค.
๋ ์ฐจ์ด ํธ ์ต๊ทผ์ ์ด๋ ๊ฒ ํฌํจ ๋ ์ค์ ์ด๋ค ์ฌ์ดํธ๊ฐ ์์์ ๋ณ๊ฒฝ : ๊ฐ์ฅ ํฐ ์ฐจ์ด์ ์ ๋๋ ๋ ์ฐจ์ด ํธ์ ํธ์คํ
์ ์ ์ ์ผ๋ก ๋ชจ๋ ํ์ด์ง๋ฅผ ๊ฐ์ ํ ์์๋ ๋ฐฉ๋ฒ์ด ์๋๋ผ๋ ๊ฒ์ ์๊ณ ๋ฉ๋ฆฌ๋ก (ํธ์ง์ด๋ค exportPathMap
์คํ๋ฉ๋๋ค ์์ ํ ์ ์ ์ฌ์ดํธ์ด๋ฏ๋ก ๋ ์ด์ ์ฌ์ค์ด ์๋๋๋ค.) getStaticProps
๊ฐ ์๋ ํ์ด์ง๋ next export
์ํด ์์ฑ๋ ํ์ด์ง์ ์ ํํ ๋์ผํ๊ฒ ์๋ํฉ๋๋ค. ํ์ด์ง์ ๋จ์ผ ์ ์ ์ฌ๋ณธ์ ๋ชจ๋ ์กฐํ์ ๋ํด CDN์์ ์ง์ ์ ๊ณต๋ฉ๋๋ค. ๊ทธ๋ฌ๋ getServerProps
๋๋ getInitialProps
์ผ๋ถ ํ์ด์ง๋ฅผ ์คํํ ์๋ ์์ผ๋ฉฐ ์๋ฒ ๋ ๋๋ง ํ์ด์ง๋ก ์๋ํฉ๋๋ค. ๊ฐ์ธ์ ์ผ๋ก ์ ๋ ์ด๊ฒ์ ์ด์ ์ผ๋ก ๋ด
๋๋ค. SSR ๊ฒฝ๋ก๊ฐ ํ์ํ ๊ฒฝ์ฐ ๋จ์ํ ๋ค๋ฅธ ๋ฐ์ดํฐ ๊ฐ์ ธ์ค๊ธฐ ๋ฐฉ๋ฒ์ ์ฌ์ฉํ ์ ์์ผ๋ฉฐ ํด๋น ๋จ์ผ ๊ฒฝ๋ก๋ ์ด์ SSR์ด๊ณ ๋ค๋ฅธ ๋ชจ๋ ๊ฒฝ๋ก๋ ์ ์ ์ผ๋ก ์ ์ง๋ ์ ์์ต๋๋ค.
@jescalan ๊ฐ์ฌํฉ๋๋ค.
๋ฐ๋ผ์ ์ด๊ฒ์ด ๊ตฌํ๋๊ธฐ๋ฅผ ๊ธฐ๋ค๋ ค์ผ ํฉ๋๋ค. ๊ทธ ๋์ ์ ์ ์ netlify๋ฅผ ์ฌ์ฉํ ๊ฒ์ ๋๋ค.
SSG ๊ตฌ์ฑ์ ๋ํ ์ด์ผ๊ธฐ๊ฐ ์์ต๋๊น? ํนํ ์ฐ๋ฆฌ๋ ๊ณต์ ๋น๋ ์ํฐํฉํธ๋ฅผ ์ฌ์ฉํ๊ณ ์ถ์ง๋ง QA/์ ํ์ ๋ํด ๋ค๋ฅธ ๊ตฌ์ฑ์ผ๋ก next export
๋ฅผ ์คํํ๊ณ ์ถ์ต๋๋ค. ์ด๋ฌํ ๊ตฌ์ฑ ๊ฐ์ getStaticProps
์์๋ง ์ฝ์ ์ ์์ต๋๋ค. serverRuntimeConfig
๋๋ publicRuntimeConfig
๋๋ process.env
์ง์ ์ฌ์ฉํฉ๋๊น?
@ScreamZ @jescalan ์ ๋ ์ค๋ @Timer ์ ํจ๊ป Now์์ ์ ๋ก ๊ตฌ์ฑ next export
์ง์์ ๋ฐ์์ต๋๋ค (๊ทธ๋ ๋ชจ๋ ํฌ๋ ๋ง์ ๋ฐ์ ์๊ฒฉ์ด ์์ต๋๋ค). ๋ ํ ์์์ด:
"build": "next build && next export"
๊ทธ๋ฆฌ๊ณ ๊ทธ๊ฒ์ ์๋์ผ๋ก ์๋ํฉ๋๋ค.
์ด๋ป๊ฒ ๋๋์ง ์๋ ค์ฃผ์ธ์๐
๋ค, ์ ๋ ์ง์์ ์์ฒญํ ์ฌ๋์ด์๊ณ ๊ทธ๋ค์ ์ด๊ฒ์ด ์์ง ๊ตฌํ๋์๋ค๊ณ ๋งํ์ต๋๋ค ๐ ์ ๊ฐ ๋ณผ ์ ์๋ ํ, ๊ตฌ์ฑ์์ ๋ด๋ณด๋ด๊ธฐ ๋งต์ ์ ์ํด์ผ ํฉ๋๊น?
@ScreamZ ์๋์ ์์ ํ์๋ ๋๋ก next build && next export
๋ฅผ ์ถ๊ฐํ๋ฉด ๋ฉ๋๋ค.
@timneutkens getInitialProps
๋ฅผ getServerProps
๋ฐ๊พธ๋ฉด Server Pre Rendering
๋ฅผ ํ์ฑํํ๊ธฐ ์ํด ๊ตฌ์ฑ ํ์ผ์ target: 'serverless'
๋ฅผ ์ถ๊ฐํด์ผ ํฉ๋๊น? ๊ฐ์ฌ ํด์.
์ฐ๋ฆฌ๋ ์ด๊ฒ์ ์ด๋ป๊ฒ ์๋ํ ์ ์์ต๋๊น?
์ฐ๋ฆฌ๋ ์ด๊ฒ์ ์ด๋ป๊ฒ ์๋ํ ์ ์์ต๋๊น?
์ด ๋ชจ๋ ๋ฐฉ๋ฒ์ด ํ์ฌ ์ธ์๋๋ ค๋ฉด unstable_
์ ๋์ฌ๊ฐ ํ์ํฉ๋๋ค.
์: unstable_getStaticProps
@timneutkens
@ScreamZ @jescalan ์ ๋ ์ค๋ @Timer ์ ํจ๊ป Now์์ ์ ๋ก ๊ตฌ์ฑ
next export
์ง์์ ๋ฐ์์ต๋๋ค (๊ทธ๋ ๋ชจ๋ ํฌ๋ ๋ง์ ๋ฐ์ ์๊ฒฉ์ด ์์ต๋๋ค). ๋ ํ ์์์ด:"build": "next build && next export"
๊ทธ๋ฆฌ๊ณ ๊ทธ๊ฒ์ ์๋์ผ๋ก ์๋ํฉ๋๋ค.
์ด๋ป๊ฒ ๋๋์ง ์๋ ค์ฃผ์ธ์๐
๋ด ๋น๋ ์คํฌ๋ฆฝํธ๋ ๋ ๋ง์ ์์ ์ ์ํํ์ง๋ง ๋งค๋ ฅ์ฒ๋ผ ์๋ํ๋ ๊ฒ ๊ฐ์ต๋๋ค.
"build": "graphql codegen && next build && npm run export",
๊ฒ๋ค๊ฐ ๋๋จํด! ๋ด๊ฐ ์ฐพ๋ ๋ฐ๋ก ๊ทธ๊ฑฐ์ผ ๐ (Goodbye GatsbyJS, ๋ด๊ฐ ๊ฐ์ฅ ์ข์ํ๋ ํ๋ ์ ์ํฌ๋ ์ด์ ๋น์ ๋งํผ ๊ฐ๋ ฅํฉ๋๋ค!)
๊ทธ๋ฌํ ๋ฐ์์ ๋ํด ๋๋จํ ๊ฐ์ฌํฉ๋๋ค.
์ ๋ 9.1.6
์
๊ทธ๋ ์ด๋ํ๋๋ฐ ๋๋๊ฒ๋
๋๋ ๊ทธ ์ฐ๋ ๋๊ฐ RFC๋ผ๊ณ ์๊ฐํ๋๋ฐ, ๊ทธ๊ฒ์ ์ด๋ฏธ ์ฐ๋ฆฌ์๊ฒ ์ด๋ฆฐ ๊ฒ ๊ฐ๋ค ์์, ๊ทธ๋ ์ง?
๊ทธ๋ฌ๋ Typescript ์ ํ์ 9.1.6์์ ํ์ฑํ๋์ง ์์ต๋๋ค.
์ ์ฅ, ๋ ์ง๊ธ ๋๋ฌด ํฅ๋ถ๋ผ! ๐คฃ
๋ง์ง๋ง ์ง๋ฌธ:
getInitialProps
๋ ๋ฏธ๋์ ๋ ์ด์ ์ฌ์ฉ๋์ง ์์ ๊ฒ์
๋๊น? ์๋๋ฉด ์ด๋ค ๊ฒฝ์ฐ์๋ ์ฌ์ ํ ๊ด๋ จ์ฑ์ด ์์ต๋๊น? ์๋ฅผ ๋ค์ด?next export
๋ getStaticProps
๋ฐ next build
๋ง ์๋ ํ์ด์ง๋ฅผ ์ํด ๋ ์ด์ ์ฌ์ฉ๋์ง ์์ ์ ์์ต๋๊น?์ข์ ๋๊ตฌ ๊ฐ์ฌํฉ๋๋ค๐๐ป
๋ด๊ฐ ๊ทธ๊ฒ์ ์ป๋๋ค๋ฉด, getInitialProps๋ ๋ฏธ๋์ ๋ ์ด์ ์ฌ์ฉ๋์ง ์์ ๊ฒ์ ๋๊น? ์๋๋ฉด ์ด๋ค ๊ฒฝ์ฐ์๋ ์ฌ์ ํ ๊ด๋ จ์ฑ์ด ์์ต๋๊น? ์๋ฅผ ๋ค์ด?
์ด๊ธฐ RFC์์ ๋งํ๋ฏ์ด :
์ด RFC๋ API ์ถ๊ฐ์ ๋ํด ๋ ์ ์ ์ผ๋ก ์ค๋ช ํฉ๋๋ค. ๋ชจ๋ ์๋ก์ด ๊ธฐ๋ฅ์ ์ด์ ๋ฒ์ ๊ณผ ์์ ํ ํธํ๋๋ฉฐ ์ ์ง์ ์ผ๋ก ์ฑํํ ์ ์์ต๋๋ค. ์ด RFC๋ ๋ ์ด์ ์ฌ์ฉ๋์ง ์์ต๋๋ค.
๋๋ ๊ทธ ์ฐ๋ ๋๊ฐ RFC๋ผ๊ณ ์๊ฐํ๋๋ฐ, ๊ทธ๊ฒ์ ์ด๋ฏธ ์ฐ๋ฆฌ์๊ฒ ์ด๋ฆฐ ๊ฒ ๊ฐ๋ค ์์, ๊ทธ๋ ์ง?
๊ทธ๋ ์ง ์์ต๋๋ค. ์ฐ๋ฆฌ๋ ZEIT ์์ฉ ํ๋ก๊ทธ๋จ์์ ๊ทธ๊ฒ์ ์๋ํ๊ณ ์์ผ๋ฉฐ ๊ฐ์์ฑ ํ๋ฉดํ์ ์ผ๋ถ๋ ์ด๋ฏธ ์ฐฉ๋ฅํ์ต๋๋ค(์: ๋ณธ ํ์ด์ง ํธ๋ฆฌ).
๋ค์ ๋ด๋ณด๋ด๊ธฐ๋ getStaticProps ๋ฐ ๋ค์ ๋น๋๋ง ์๋ ํ์ด์ง๋ฅผ ์ํด ๋ ์ด์ ์ฌ์ฉ๋์ง ์์ ์ ์์ต๋๊น?
๋ง์ต๋๋ค. ์ผ๋ฐ์ ์ผ๋ก next export
์ฌ์ฉํ์ง ์๊ฒ ๋ฉ๋๋ค. ์ด์ ๋ฒ์ ๊ณผ์ ํธํ์ฑ์ ์ํด ์ ์ง๋์ง๋ง ์ผ๋ฐ์ ์ผ๋ก API ๊ฒฝ๋ก์ ๊ฐ์ ๋ค๋ฅธ ๊ธฐ๋ฅ์ ์ง์ํ๊ณ ์ผ๋ถ ํ์ด์ง์ ๋ํด ์๋ฒ ์ธก ๋ ๋๋ง์ ์ ํํ์ฌ ๋ด๋ณด๋ด๊ธฐ์ ๋ชจ๋ ์ด์ ์ ์ ๊ณตํ๋ฏ๋ก ํ์ด๋ธ๋ฆฌ๋ ์ฑ์ ๋ง๋ค๊ณ ์ถ์ ๊ฒ์
๋๋ค.
์ฐ๋ฆฌ๋ ์ด๊ฒ์ ์ด๋ป๊ฒ ์๋ํ ์ ์์ต๋๊น?
์ด ๋ชจ๋ ๋ฐฉ๋ฒ์ด ํ์ฌ ์ธ์๋๋ ค๋ฉด
unstable_
์ ๋์ฌ๊ฐ ํ์ํฉ๋๋ค.์:
unstable_getStaticProps
์์ง ์ฌ์ฉํ์ง ์๋ ๊ฒ์ด ์ข์ต๋๋ค. ์คํ์ ์ด๋ฉฐ ๋ฆด๋ฆฌ์ค ์ฌ์ด์ ์ค๋จ๋ ์ ์์ต๋๋ค.
๊ทธ๋์ ์ ๋ ์ด ๊ธฐ๋ฅ์ ๊ฐ์ง๊ณ ๋์๊ณ ํ์ด์ง ๋ฐ์ดํฐ๋ฅผ ํฌํจํ๋ JSON ํ์ผ์ ๋ค๋ฅธ ํ์ด์ง์์ SSG ํ์ด์ง์ ์ก์ธ์คํ ํ ํญ์ ๊ฐ์ ธ์ค๋ ๊ฒ์ ๊ด์ฐฐํ์ต๋๋ค.
JSON ํ์ผ์ ๋ํ ์ฌ์ ๋ก๋ ์ต์ ํ ๊ณํ์ด ์์ต๋๊น?
์๋ง๋ ์ฌ์ฉ์๊ฐ ํ์ด์ง๋ก ์ด๋ํ๋ ค๊ณ ํ ๋ ๋ฏธ๋ฆฌ ๋ก๋ํ๊ฑฐ๋(์ฆ, ์ฌ์ฉ์๊ฐ SSG ๋งํฌ๋ฅผ ๊ฐ๋ฆฌํค๊ณ ์์ ๋) ๋งํฌ ๊ตฌ์ฑ ์์์์ ์ฐธ์กฐ๋๋ ๋ค๋ฅธ js ํ์ด์ง๋ฅผ ๋ฏธ๋ฆฌ ๋ก๋ํ๋ ๊ฒ์ฒ๋ผ ๋ฏธ๋ฆฌ ๋ก๋ํ ์ ์์ต๋๋ค.
๊ทธ๊ฑด ๊ทธ๋ ๊ณ ๊ทธ ๊ธฐ๋ฅ์ ์ฌ๋ ํด์!
JSON ํ์ผ์ ๋ํ ์ฌ์ ๋ก๋ ์ต์ ํ ๊ณํ์ด ์์ต๋๊น?
์.
๊ทธ๋งํ ๊ฐ์น๊ฐ ์๊ธฐ ๋๋ฌธ์ ์ ๋ ๋ณ๋์ ํ์ผ๋ณด๋ค๋ ์ด๋ฌํ ํจ์์ ํธ๋ฆฌ ํ๋ค๋ฆผ ๋ด๋ณด๋ด๊ธฐ๋ฅผ ์ ํธํฉ๋๋ค.
์ด ๊ธฐ๋ฅ์ ์ํ๋ ๋ฌด์์ ๋๊น? ๊ทธ๊ฒ์ ์ฐจ๋จ์ ๋ ๋ฌด์์ ๋๊น?
@mikestopcontinues ์ด RFC๋ ํ์ฌ ์ฐ๋ฆฌ ํ๊ณผ ์ผ๋ถ ์ ๋ณ๋ ํํธ๋์ ์ํด ๋ด๋ถ์ ์ผ๋ก ๊ณผ์คํ๊ฒ ํ
์คํธ๋๊ณ ์์ต๋๋ค. ์์์ ์ธ๊ธํ ๊ฒ์ฒ๋ผ unstable_
์ ๋์ฌ ๋ฅผ ์ฌ์ฉํ์ฌ ๊ณ ๋๋ก ์คํ์ ์ธ ๋์ ์ ์ ํํ ์ ์์ต๋๋ค! ๐
API๋ฅผ ๊ณ์ํด์ ์ ๋ฐ์ดํธํ ์ ์์ผ๋ฏ๋ก ํ๋ก๋์ ์ํฌ๋ก๋๋ฅผ ์๋ก์ด ๋ฐฉ๋ฒ์ผ๋ก ๋ง์ด๊ทธ๋ ์ด์ ํ์ง ๋ง์ญ์์ค.
๊ฐ์ธ์ ์ผ๋ก 8~20K ํ์ด์ง์ ์ ์ ์ฌ์ดํธ ์์ฑ์ ์ฌ์ฉํฉ๋๋ค(์ผ๋ถ ํ์ด์ง์ ๋์ ์์ฒญ์ด ์์ ์ ์์). ๋งค์ฐ ์ ์๋ํฉ๋๋ค(Now์ 10K ํ์ผ ์ ํ ์ ์ธ). ๋ด๊ฐ ๋ถ๋๋ฝ๊ฒ ์๊ฐํ๋ ์ ์ผํ ๊ฒ์ getStaticPaths ๋ฉ์๋๊ฐ ์์ผ๋ฉด ๋ค์ ๋ก๋ํ ๋๋ง๋ค getStaticProps๊ฐ ํธ์ถ๋๋ค๋ ๊ฒ์ ๋๋ค. ์ข์ ๋์ ์ค ํ๋๋ ์ฒซ ๋ฒ์งธ ํธ์ถ์์ json ํ์ผ์ ๋ง๋ค๊ณ ๋ค์ ํธ์ถ์์ ์ด๋ฅผ ์ฌ์ฉํ๋ค๋ ๊ฒ์ ๋๋ค.
์ฆ๋ถ ๋น๋๊ฐ ๊ณํ๋์ด ์์ต๋๊น? ๊ทธ๋์ ์๋ก์ด/๋ณ๊ฒฝ๋ ์ฝํ ์ธ ๋ง ์ฌ๊ตฌ์ถ๋ฉ๋๊น?
์์์ ์ธ๊ธํ ๊ฒ์ฒ๋ผ
unstable_
์ ๋์ฌ ๋ฅผ ์ฌ์ฉํ์ฌ ๊ณ ๋๋ก ์คํ์ ์ธ ๋์ ์ ์ ํํ ์ ์์ต๋๋ค!
unstable_getServerProps
๋ฉ์๋๋ฅผ ํ
์คํธํ๊ณ ์ถ์ง๋ง ํ์ฌ๋ก์๋ ๋ฌด์๋๊ณ zeit/next.js
๋ฆฌํฌ์งํ ๋ฆฌ์์ ์ฐพ์ ์ ์์ต๋๋ค. ์์ง ๊ตฌํ๋์ง ์์์ต๋๊น, ์๋๋ฉด ์ ๊ฐ ์๋ชปํ๊ณ ์์ต๋๊น?
์ฆ๋ถ ๋น๋๊ฐ ๊ณํ๋์ด ์์ต๋๊น? ๊ทธ๋์ ์๋ก์ด/๋ณ๊ฒฝ๋ ์ฝํ ์ธ ๋ง ์ฌ๊ตฌ์ถ๋ฉ๋๊น?
๊ตฌํ์ ์ฆ๋ถ ์ฌ๊ตฌ์ถ์ ์ผ๋์ ๋๊ณ ์ค๊ณ๋์์ง๋ง ์์ง ์ง์๋์ง ์์ต๋๋ค(์ด RFC์์๋ ๋ค๋ฃจ์ง ์์).
์์ฌํ์ญ์์ค. ์ํคํ
์ฒ๊ฐ ์ค๋น๋์์ผ๋ฉฐ ์ด๋ฌํ ๊ธฐ๋ฅ์ด ์์ ํ๋ ํ ์ด๋ฅผ ํ์ํ ๊ฒ์
๋๋ค.
์ด๊ฒ์ด getStaticProps
๊ฐ ์ ์ฒด ์ ํ๋ฆฌ์ผ์ด์
์ ๋ํด ํ ๋ฒ์ด ์๋๋ผ ํ์ด์ง๋น ์ ์๋๋ ์ด์ ์
๋๋ค!
๋ถ์์ ํ_getServerProps ๋ฉ์๋๋ฅผ ํ ์คํธํ๊ณ ์ถ์ง๋ง ํ์ฌ๋ก์๋ ๋ฌด์๋๋ ๊ฒ ๊ฐ์ต๋๋ค [...]
getServerProps
์(๋) ์์ง ๋ฏธ๋ฆฌ ๋ณด๊ธฐ์์ ์ฌ์ฉํ ์ ์์ต๋๋ค. ์ฃ์กํฉ๋๋ค.
getServerProps
์(๋) ์์ง ๋ฏธ๋ฆฌ ๋ณด๊ธฐ์์ ์ฌ์ฉํ ์ ์์ต๋๋ค. ์ฃ์กํฉ๋๋ค.
๊ฐ์ฌํฉ๋๋ค. ๋๋ ํ์คํ ์ด ์ค๋ ๋๋ฅผ ๋ณผ ๊ฒ์ ๋๋ค. ์๋ํ๋ฉด ๊ทธ ๋ ์ ๋์ฐฉํ๋ฉด ๋จ์ผ ํจ์์ ์ด๋ฆ์ ๋ฐ๊พธ๋ ๊ฒ์ผ๋ก ๋์ฒดํ ์ ์๋ _๋ค๋ฐ_ ์ฝ๋๊ฐ ์๊ธฐ ๋๋ฌธ์ ๋๋ค! ๐
getServerProps
/ getStaticProps
๋ฅผ ํ์ฌ ์ฌ์ฉํ ์ ์๋์ง ์ฌ๋ถ๋ 100% ํ์คํ์ง ์์ต๋๋ค.
์ด ์ค๋ ๋ ๊ธฐ๋ฐ: ์๋์
๊ทธ๋ฌ๋ ๊ทธ๋ ๋ค๋ฉด next build
๋ฅผ ์คํํ ๋ ๋ด ํฐ๋ฏธ๋์ด ์์ง ์ฌ์ฉํ ์ ์๋ ๊ฒฝ์ฐ ์ด๋ฅผ ์ธ๊ธํ ์ด์ ๊ฐ ๋ฌด์์
๋๊น? ๋ฉ์์ง๋ฅผ ๋ณด๊ณ ์ด๋ฌํ ๋ฐฉ๋ฒ์ด ํ๋ก๋์
๋จ๊ณ์ ์๋ค๋ ์ด๊ธฐ ์์
๊ฐ์ ์ด ๋จ์๊ณ ๊ทธ๋ ์ง ์๋ค๋ ๊ฒ์ ๋ฐ๊ฒฌํ๋ ๋ฐ ์๊ฐ์ด ๊ฑธ๋ ธ์ต๋๋ค. ์ด์ ๊ฐ ๊ถ๊ธํ๊ฑฐ๋ ์ ๊ฐ ์๋ชป ์ดํดํ๊ณ ์๋ ๋ถ๋ถ์ด ์๋์ง ๊ถ๊ธํฉ๋๋ค.
ฮป (Server) server-side renders at runtime (uses getInitialProps or getServerProps)
โ (Static) automatically rendered as static HTML (uses no initial props)
โ (SSG) automatically generated as static HTML + JSON (uses getStaticProps)
(๋ค์ ๋ฒ์ 9.1.6์์)
๊ฐ์ฌ ํด์
@stevenjchang pages/**/*.js
์์ ๋ค์ ๊ตฌ๋ฌธ์ ์ฌ์ฉํ์ฌ ์ฌ์ฉํ ์ ์์ต๋๋ค.
export function unstable_getStaticPaths() {} // return [{params: {...}}, ...]
export function unstable_getStaticProps({params: {...}) {} // return {props: {...}}
๊ทธ๋ฆฌ๊ณ ์ถ๊ฐํด์ผ ํ ๊ฒ์ ํ๋ฅญํ์ง๋ง dev ์๋ฒ๋ฅผ ์ฌ์ฉํ ๋ ์ฌ์ ํ ๊ฐ์ฅ์๋ฆฌ๊ฐ ์ฝ๊ฐ ๊ฑฐ์น ๊ธฐ ๋๋ฌธ์ ๋๋ค.
dev ์๋ฒ๋ฅผ ์ฌ์ฉํ ๋ ์ฌ์ ํ ๊ฐ์ฅ์๋ฆฌ๊ฐ ์ฝ๊ฐ ๊ฑฐ์น ์ง๋ง.
@mikestopcontinues
์ด์ ๋ํด ์์ธํ ์ค๋ช ํด ์ฃผ์๊ฒ ์ต๋๊น? ๋ค๋ฅธ ๋๊ตฌ๋ dev ์๋ฒ ๊ฒฝํ์ ๋ํด ๋ถ์ ์ ์ธ ํผ๋๋ฐฑ์ ์ ๊ณตํ์ง ์์์ผ๋ฉฐ ์ฐ๋ฆฌ๋ ์ด ๋ฌธ์ ๋ฅผ ํด๊ฒฐํ๊ณ ์ถ์ต๋๋ค!
@Timer ์๋ก์ด API๊ฐ ์ ๋ง ๋ง์์
"๋ชจ๋ ๋ก๋ ์"๋ ํ์ด์ง ๋ก๋๋ฅผ ์๋ฏธํฉ๋๊น? ์๋๋ฉด ์ฌ๊ฑด? ๋๋...?
@mmmeff ๊ฐ์ ๊ฒฝ๋ก๋ก ์ด๋ํ ๋๋ง๋ค json์ ๋ค์ ์์ฒญํฉ๋๋ค. ๋ฐ๋ผ์ ๋ ํ์ด์ง ์ฌ์ด๋ฅผ ์๋ค๋ก ํด๋ฆญํ๋ฉด ๋ฐ์ดํฐ๋ฅผ ๊ธฐ๋ค๋ฆฌ๋ ๋ฐ ๋ง์ ์๊ฐ์ ํ ์ ํ๊ฒ ๋ฉ๋๋ค.
@mikestopcontinues ์ด๊ฒ์ ๊ฐ์ฅ ์ต์ ๋ฐ์ดํฐ๊ฐ ๊ฐ๋ฐ ๋จ๊ณ์์ ์ ํธ๋๋ ๊ฒฝ์ฐ๊ฐ ๋ง๊ธฐ ๋๋ฌธ์ ์๋๋ ๋์์ ๋๋ค. ์๋ก์ด ๋ฌธ์ ์์ ๋ ๋์ ๋ฐ๊ฒฌ์ ๋ฐฉ๋ฒ์ ๋ํด ๋ ผ์ํ ์ ์์ต๋๋ค!
@timneutkens ์ด RFC๋ ๋งค์ฐ ์ ๋งํด ๋ณด์ ๋๋ค. ๋ณด์๊ณผ ์ ํํ ์ด๋ป๊ฒ ์๋ํ๋์ง์ ๋ํ ๋ช ๊ฐ์ง ์ง๋ฌธ/์ฐ๋ ค ์ฌํญ์ด ์์ต๋๋ค.
SSR๊ณผ SSG ๋ชจ๋์ ์์กดํ๋ ์ผ๋ฐ์ ์ธ ๋น์ฆ๋์ค ์ฌ๋ก๋ฅผ ์ดํด๋ณด๊ฒ ์ต๋๋ค.
์ฐ๋ฆฌ๋ ์น์ฌ์ดํธ(์ผ๋ช
"์ฑ")์ ์ผ๋ถ ์ ๋ณด๋ฅผ ํ์ํ๊ณ ์ ํฉ๋๋ค.
์ด๋ฌํ ์ ๋ณด๋ GraphQL API๋ฅผ ํตํด ์ก์ธ์คํ ์ ์๋ BDD์ ์ ์ฅ๋ฉ๋๋ค.
์ด๋ฌํ ์ ๋ณด ์ค ์ผ๋ถ๋ ๊ณต๊ฐ๋๊ณ ์ผ๋ถ๋ ๋น๊ณต๊ฐ์
๋๋ค(์: ์ฌ์ฉ์ ์ด๋ฉ์ผ/๋น๋ฐ๋ฒํธ).
์ฑ์ ๋ ๋จ๊ณ๋ฅผ ์ฌ์ฉํฉ๋๋ค.
์ด ์๋๋ฆฌ์ค์์๋ SSR๊ณผ SSG๋ฅผ ๋ชจ๋ ์ฌ์ฉํฉ๋๋ค.
์ด ์๋๋ฆฌ์ค๋ ์ถฉ๋ถํ ์ผ๋ฐ์ ์ด์ด์ผ ํ๋ฉฐ (IMHO) SSG ์ฌ์ฉ์ ์ฃผ์ ์ฌ์ฉ ์ฌ๋ก ์ค ํ๋์ฌ์ผ ํฉ๋๋ค.
ํ๋ก๋์ ์ฑ์ ์คํ ์ด์ง ์ฑ์ ์ค๋ ์ท์ ๋ถ๊ณผํฉ๋๋ค.
์ด๊ฑฐ ์ธ์ ์ถ์ํ ์์ ์ธ๊ฐ์? ์ฃผ์ ์ ๋ฐ์ดํธ(v10)๊ฐ ๋ ๊ฒ์ ๋๊น, ์๋๋ฉด ์ด์ ๋ฒ์ ๊ณผ ํธํ๋๋ ์ ๋ฐ์ดํธ๊ฐ ๋ ๊ฒ์ ๋๊น?
์ด๋ด,
์ฌ์ฉ์ ์ ์ ์๋ฒ๋ก ์ด ์๋ฃจ์ ์ ์๋ํ๊ณ ์๋์ํค๋ ์ฌ๋์ด ์์ต๋๊น?
์์:
// server.js
const express = require('express');
const next = require('next');
const port = parseInt(process.env.PORT, 10) || 3000;
const dev = process.env.NODE_ENV !== 'production';
const app = next({ dev });
const handle = app.getRequestHandler();
app.prepare().then(() => {
const server = express();
server.get('/blog/:id', (req, res) => {
console.log('My params needed be passed to page:', req.params);
return app.render(req, res, '/blogDetail', { id: req.params.id });
});
server.listen(port, err => {
if (err) throw err;
console.log(`> Ready on http://localhost:${port}`);
});
});
// blogDetail.js
export async function unstable_getStaticProps(props) {
console.log('What is passed', props);
return {};
}
const BlogPostPage = ({ post }) => {
return <div>Hey</div>;
}
export default BlogPostPage;
# Terminal output
My params needed be passed to page: { id: 'test' }
What is passed { params: undefined }
getStaticProps
์ ์ฟผ๋ฆฌ ๋ฌธ์์ด์ ํฌํจํ ์ ์๋ ์ด์ ๋ ๋ฌด์์
๋๊น? ํ์ฌ ๋ค์ ๋ ๋๋งํ์ง ์๊ณ ์ฟผ๋ฆฌ ๋งค๊ฐ๋ณ์๋ฅผ ์ป๊ธฐ ์ํด SSR์ ์ํํด์ผ ํ๋ ํ์ด์ง๊ฐ ์์ต๋๋ค. useRouter
ํํฌ๋ฅผ ์ฌ์ฉํ๋ฉด ์ฟผ๋ฆฌ๊ฐ ์ฒ์์ ๋น ๊ฐ์ฒด์ด๊ธฐ ๋๋ฌธ์ ์ฌ๋ฌ ๋ฒ ๋ค์ ๋ ๋๋ง๋ฉ๋๋ค. ์ด๊ฒ์ ์ ํ ์ถ์ ์ ์ฌ์ฉ๋๋ ํ์ด์ง์ด๋ฏ๋ก ๋น์ฐํ ์์ ๋จ๊ณ๊ฐ ์๋๋๋ค.
@pjaws RFC๋ getStaticProps
๊ฐ ์ ์ ์์ฑ์ ์ํ ๊ฒ์ด๋ผ๊ณ ๊ตฌ์ฒด์ ์ผ๋ก ์ธ๊ธํฉ๋๋ค. ์ ์ HTML์ ์ฟผ๋ฆฌ ๋ฌธ์์ด์ ๋ฐ์ ์ ์์ต๋๋ค.
๊ทธ๋ ๋ค๋ฉด ๋์ URL ๋งค๊ฐ๋ณ์๋ฅผ ์์ ํ ์ ์๋ ์ด์ ๋ ๋ฌด์์ ๋๊น? ๊ทธ๊ฒ ์ด๋ป๊ฒ ๋ค๋ฅธ๊ฐ์?
2020๋
1์ 14์ผ ํ์์ผ ์ค์ 1์ 30๋ถ Tim Neutkens [email protected]
์ผ๋ค:
@pjaws https://github.com/pjaws ํน๋ณํ ์ธ๊ธํ๋ RFC
getStaticProps๋ ์ ์ ์์ฑ์ ์ํ ๊ฒ์ ๋๋ค. ์ ์ HTML์ ์์ ํ ์ ์์ต๋๋ค.
์ฟผ๋ฆฌ ๋ฌธ์์ด.โ
๋น์ ์ด ์ธ๊ธ๋์๊ธฐ ๋๋ฌธ์ ์ด๊ฒ์ ๋ฐ๋ ๊ฒ์ ๋๋ค.
์ด ์ด๋ฉ์ผ์ ์ง์ ๋ต์ฅํ๊ณ GitHub์์ ํ์ธ
https://github.com/zeit/next.js/issues/9524?email_source=notifications&email_token=AMVRRIQCKDJNF4MPWSLYNV3Q5WA2NA5CNFSM4JRPBEL2YY3PNVWWK3TUL52HS4DFVREXG43VMXHJ63LDNMV
๋๋ ๊ตฌ๋ ์ทจ์
https://github.com/notifications/unsubscribe-auth/AMVRRIRJXLYC4MC4U7DH7NDQ5WA2NANCNFSM4JRPBELQ
.
getStaticPaths
์์๋ ๋น๋ ์ ๋ ๋๋ง๋ ํ์ด์ง๋ฅผ ๋ฐํํด์ผ ํ๊ธฐ ๋๋ฌธ์
๋๋ค.
์ด๋ฌํ ๋ณํ๋ ์ธ์ ๋์ฒ๋ผ ๋งค์ฐ ์ ๋งํ๊ณ ํ๋ฅญํ ์์ ์ผ๋ก ๋ณด์ ๋๋ค! ๐
ํ์ด์ง ๊ฐ์ ๊ณต์ ๋๋ ๋ฐ์ดํฐ ์๊ตฌ ์ฌํญ์ ์ถฉ์กฑํ๊ธฐ ์ํด getInitialProps
in _app.js
๋ฅผ ์ฌ์ฉํ๋ ๊ฒฝ์ฐ(์: ์ปจํ
์คํธ ์ ๊ณต์ ์ค์ )์ ๋ํด ๊ถ๊ธํฉ๋๋ค. ๊ฐ์ ๋ฐฉ์์ผ๋ก getStaticProps
๋ฅผ ์ฌ์ฉํ ์ ์๋ค๋ ๊ฒ์ ์ฌ๋ฐ๋ฅด๊ฒ ์ดํดํ๊ณ ์์ต๋๊น? ๊ฐ๋ณ ํ์ด์ง์์๋ง ์ ์ํ ์ ์์ต๋๊น?
ํ์ด์ง ๊ฐ์ ๊ณต์ ๋๋ ๋ฐ์ดํฐ ์๊ตฌ ์ฌํญ(์: ์ปจํ ์คํธ ๊ณต๊ธ์ ์ค์ )์ ์ถฉ์กฑํ๊ธฐ ์ํด _app.js์ getInitialProps๊ฐ ์๋ ์ฌ์ฉ ์ฌ๋ก๊ฐ ๊ถ๊ธํฉ๋๋ค. getStaticProps๋ฅผ ๊ฐ์ ๋ฐฉ์์ผ๋ก ์ฌ์ฉํ๋ ๊ฒ์ด ๋ถ๊ฐ๋ฅํ๋ค๋ ๊ฒ์ ์ฌ๋ฐ๋ฅด๊ฒ ์ดํดํ๊ณ ์์ต๋๊น? ๊ฐ๋ณ ํ์ด์ง์์๋ง ์ ์ํ ์ ์์ต๋๊น?
๋ง์ต๋๋ค. ์ฒ์์๋ ๊ฐ๋ณ ํ์ด์ง์๋ง ์ ์ฉ๋ฉ๋๋ค. ๋์ค์ ๋ค์ ์๊ฐํด ๋ณผ ์๋ ์์ต๋๋ค. _app์ getInitialProps๋ ์ ์ HTML๋ก ๋ด๋ณด๋ผ ๋ ๊ณ์ ํธ์ถ๋๋ฏ๋ก getStaticProps๋ก ์ ์ง์ ์ผ๋ก ์ด๋ํ ์ ์์ต๋๋ค.
์๋ ํ์ธ์ ์ฌ๋ฌ๋ถ, ๊ด๋ จ ์ง๋ฌธ ํ๋ - ์์ฐ์ ์ด๋ป๊ฒ ์ฒ๋ฆฌ๋ฉ๋๊น? ํค๋๋ฆฌ์ค CMS(์ฌ์ง์ด wordpress ๋๋ graphcms ๋ฑ)๋ฅผ ์ฌ์ฉํ๋ ๊ฒฝ์ฐ ์์ฐ URL์ด ์ ์ html์์ ์ฌ์ฉ๋๋ค๋ ๊ฒ์ ์ง๊ธ ๋ณด๊ณ ์๊ธฐ ๋๋ฌธ์ ๋๋ค.
์ฌ๊ธฐ์๋ ์์ฐ ๋งํฌ๊ฐ ๊ทธ๋๋ก ์ฌ์ฉ๋๋ ๋ ๊ฐ์ง ๊ธฐ๋ณธ ์ค์ ์ด ์์ต๋๋ค.
๊ทธ๋ฌ๋ ๋ ๊ฐ๋ฅ์ฑ์ด ๋์ต๋๋ค. ์์ฐ์ ๋ค์ด๋ก๋ํ๊ณ html์ ๋น๋(๋ก์ปฌ๋ก ๋งํฌ)ํ ๋ค์ ์์ CDN์ ๊ณ์ธตํํฉ๋๋ค. ์ด๊ฒ์ ํจ์ฌ ๋ ์์ฉ ๊ฐ๋ฅํ ๊ดํ์
๋๋ค.
์ด๊ฒ์ ๋ํ Netlify์ ๊ฐ์ ๋ฐฐํฌ ์์คํ ์ ์ฌ์ฉํ๋ ๊ฒ๊ณผ๋ ๋งค์ฐ ์ ์ฐ๊ฒฐ๋ฉ๋๋ค. Netlify๋ DatoCMS ๋๋ Graphcms์ ๊ฐ์ ๊ฒ๋ณด๋ค ํจ์ฌ ๋ ์ ํฉํ ์ ์ธ๊ณ์ ์ผ๋ก ์ฌ์ฉ ๊ฐ๋ฅํ ์ธํ๋ผ๋ฅผ ๊ฐ์ถ๊ณ ์์ต๋๋ค. ๋ฐ๋ผ์ Netlify๋ฅผ ๋ฐฐํฌ๋ก ์ฌ์ฉํ๋ ๊ฒฝ์ฐ Netlify ๋๋ฉ์ธ์์ ๋ชจ๋ ๊ฒ์ด ์ ๊ณต๋๊ณ ๋ง๋ฒ์ด ์๋ํ๋๋ก ํ๊ณ ์ถ์ต๋๋ค.
@sandys https://github.com/zeit/next.js/issues/9054#issuecomment -570427085์์ ์ฌ๋ฐ๋ฅด๊ฒ ์ดํดํ๋ค๋ฉด ์์ฐ์ ๋ค์ด๋ก๋ํ๊ณ .next/static
์๋์ ์ ์ฅํ๊ณ ๋งํฌ๋ฅผ ๊ตฌ์ถํด์ผ ํฉ๋๋ค. getStaticProps
์์ต๋๋ค.
์ ์ API ๊ฒฝ๋ก๊ฐ ์๋ค๋ ์์ด๋์ด๋ ์์ง๋ง ์ด๋ฅผ ์ฌ์ฉํ์ฌ ๋ธ๋ผ์ฐ์ ์บ์ฑ ๋์์ ์ ์ดํ๋ โโ๋ฐฉ๋ฒ์ ์ ํํ ๋ชจ๋ฅด๊ฒ ์ต๋๋ค.
@Janpot ๋งํฌ
์ด ๊ธฐ๋ณธ ์ ๊ณต์ ๋ด ์์ฒญ์ ์ถ๊ฐํ์ญ์์ค. ์๋ง๋ #9054๊ฐ ๋ ์ผ๋ฐ์ ์ด์ง๋ง SSG์ ๊ด์ ์์ ์๊ฐํ๊ณ ์์ผ๋ฉฐ ์ด๊ฒ์ ๋งค์ฐ ์ค์ํฉ๋๋ค.
์ธ๊ธํ๋ ๊ฒ์ ์์์ง๋ง ์์ฐ ํด์ฑ๋ SSG์ ํ์์ ์ ๋๋ค.
@homoky , ๊ทธ ๋์ ์ ๋๋ก ์๋ํ์ง ์์์ต๋๊น?
@homoky , ๊ทธ ๋์ ์ ๋๋ก ์๋ํ์ง ์์์ต๋๊น?
๋ถ๊ฐ๋ฅํ๊ณ ๊ณํ๋ ์์ต๋๋ค: #10071
๐ข
@sandys ์ค์ ๋ก ์๋ฃจ์
์ https://github.com/zeit/next.js/issues/9081 ์ ์ฌ์ฉํ์ฌ ์๋ฅผ ๋ค์ด /images
์์ CMS๋ก ์ฌ์์ฑ์ ์ถ๊ฐํ ๋ ํจ์ฌ ๊ฐ๋จํฉ๋๋ค. ์: ZEIT์์ ์ด์ ์ฌ๋ฐ๋ฅธ ํค๋๊ฐ ์ถ๊ฐ๋๋ฉด ๊ฒฐ๊ณผ๋ฅผ ์ด๋ฏธ ์บ์ํ๋ฏ๋ก ์ถ๊ฐ ๋ค์ด๋ก๋๊ฐ ํ์ํ์ง ์์ต๋๋ค(๋น๋ ์ ๋ง๋ํ ์ค๋ฒํค๋).
@timneutkens ๋ต๋ณ
๋น์ ์ด ์๋ฏธํ๋ ๋ฐ๋ฅผ ์์ ํ ํ์ ํ์ง ๋ชปํฉ๋๋ค. ๊ทธ๋์ ์ฐ๋ฆฌ๋ netlify๋ฅผ ์ฌ์ฉํฉ๋๋ค. CMS URL์ ๊ทธ๋๋ก ์ ์งํ๊ณ ๊ทธ ์์ CDN ๋ ์ด์ด๋ฅผ ์์ ๋๋ผ๋ ์ ์์
๋๊น?
netlify(์ฐ๋ฆฌ๊ฐ ์ฌ์ฉํ ํด๋ผ์ฐ๋ํ๋ก ํธ)๊ฐ ์ด๋ฌํ ๋ชจ๋ ์๋น์ค์ ์ํํ๊ฒ ์๋ํ ์ ์๋์ง ํ์ ํ ์ ์์ต๋๋ค.
์ด๋ฏธ์ง๊ฐ ๋ค์ด๋ก๋๋์ด ๋ฐฐํฌ์ ์ผ๋ถ๊ฐ ๋๋ฉด ์ด ์ ์ฒด ๋ฌธ์ ๊ฐ ํฌ๊ฒ ๋จ์ํ๋ฉ๋๋ค. ๊ธฐ๋ณธ URL(๋ด ๊ฒฝ์ฐ์๋ s3์์ ์ ๊ณต๋จ)์์ ์บ์ํ๋๋ก CDN์ ์ค์ ํ๊ธฐ ๋๋ฌธ์ ๋๋ค.
Zeit NOW๋ฅผ ์ฌ์ฉํ์ฌ ๊ทํ์ ์๋ฃจ์ ์ด ์ ์๊ฒ ๊ทผ๊ฑฐํ ๊ฒ์ธ์ง ์์ ํ ํ์ ํ ์ ์์ต๋๋ค.
์ด๋ฏธ์ง๊ฐ ๋ค์ด๋ก๋๋์ด ๋ฐฐํฌ์ ์ผ๋ถ๊ฐ ๋๋ฉด ์ด ์ ์ฒด ๋ฌธ์ ๊ฐ ํฌ๊ฒ ๋จ์ํ๋ฉ๋๋ค. ๊ธฐ๋ณธ URL(๋ด ๊ฒฝ์ฐ์๋ s3์์ ์ ๊ณต๋จ)์์ ์บ์ํ๋๋ก CDN์ ์ค์ ํ๊ธฐ ๋๋ฌธ์ ๋๋ค.
์ด๊ฒ์ ์ค์ ๋ก ๋น๋ ํ๋ก์ธ์ค๋ฅผ ํจ์ฌ ๋ ๋ณต์กํ๊ณ 10๋ฐฐ ๋ ๋๋ฆฌ๊ฒ ๋ง๋ญ๋๋ค. ํ์คํ ๋จ์ํ์ง๋ ์์ต๋๋ค.
Zeit NOW๋ฅผ ์ฌ์ฉํ์ฌ ๊ทํ์ ์๋ฃจ์ ์ด ์ ์๊ฒ ๊ทผ๊ฑฐํ ๊ฒ์ธ์ง ์์ ํ ํ์ ํ ์ ์์ต๋๋ค.
์ ์ธ๊ณ์ ๋ชจ๋ ํ๋ก์์ ํจ๊ป ์๋ํฉ๋๋ค. ํด๋ผ์ฐ๋ ํ๋ก ํธ ํฌํจ.
@timneutkens ์ฐ๋ฆฌ๋ ์ค์ ๋ก ๋น๋ ํ๋ก์ธ์ค ์๊ฐ์ ๋ถ๊ฐ์ง๋ก ์ ์ ๋๋ค. ๋ ์ค๋ ๊ฑธ๋ฆฌ๋๋ผ๋ ์๊ด ์์ต๋๋ค. ๊ทธ๋ฌ๋ ์ฌ๋ฌ ๊ฐ์ง ์ด์ ๋ก(์๋ ค์ง ๊ธฐ๋ณธ URL์์ ์ ๊ณต๋๋ ๋ชจ๋ ์์ฐ์ ํฌํจํ์ฌ) ์ด๋ฅผ ๋น๋์์ ๊ตฝ๋ ๊ฒ์ด ๋งค์ฐ ๋ฐ๋์งํฉ๋๋ค.
๋ชจ๋ ์ฌ๋์ ์ํด ์ด ๊ธฐ๋ฅ์ ์ผ์ผ ํ๋ค๊ณ ์ฃผ์ฅํ๋ ๊ฒ์ ์๋๋๋ค. ๋ง์ ์ฌ๋๋ค์ด CMS๋ก์ ๋ฅ๋งํน์ ๋ง์กฑํ ๊ฒ์ ๋๋ค. ๊ทธ๋ฌ๋ ์ฐ๋ฆฌ๋ ํธ๋ํฝ์ด ๋ง์ ์ฌ์ดํธ๋ฅผ ์ด์ํ๊ณ ์์ผ๋ฉฐ ์ด๊ฒ์ ํ์คํ ์ฐ๋ฆฌ์ ๊ฐ์ ์ฌ์ดํธ์ ํ์ํ ๊ฒ์ ๋๋ค.
๋ํ ๋๋ฅผ ์ฉ์ํ์ง๋ง ๋๋ ๋น์ ์ ํด๊ฒฐ์ฑ ์ ์ดํดํ์ง ๋ชปํ์ต๋๋ค. ์ด๊ฒ์ ์ด๋ป๊ฒ ๊ตฌ์ฑํด์ผ ํฉ๋๊น? CMS๊ฐ ์ฌ์ฉํ๋ URL์ ์ ์ดํ ์ ์์ต๋๋ค. ์๋ฅผ ๋ค์ด, Datocms๋์์ ์ ๊ณต ์์ www.datocms-assets.com/ . #9081์ ์๋ฃจ์ ์ ์ด๋ป๊ฒ ์ฌ์ฉํฉ๋๊น?
์ฐ๋ฆฌ๋ ์ค์ ๋ก ๋น๋ ํ๋ก์ธ์ค ์๊ฐ์ ๋ถ๊ฐ์ง๋ก ์ ์ ๋๋ค. ๋ ์ค๋ ๊ฑธ๋ฆฌ๋๋ผ๋ ์๊ด์์ด
์ด๊ฒ์ ๊ทํ์ ์์ฉ ํ๋ก๊ทธ๋จ์ ํด๋น๋ ์ ์์ง๋ง ๋๋ถ๋ถ์ ์์ฉ ํ๋ก๊ทธ๋จ์๋ ํด๋น๋์ง ์์ต๋๋ค.
๊ทธ๋ฌ๋ ์ฌ๋ฌ ๊ฐ์ง ์ด์ ๋ก(์๋ ค์ง ๊ธฐ๋ณธ URL์์ ์ ๊ณต๋๋ ๋ชจ๋ ์์ฐ์ ํฌํจํ์ฌ) ์ด๋ฅผ ๋น๋์์ ๊ตฝ๋ ๊ฒ์ด ๋งค์ฐ ๋ฐ๋์งํฉ๋๋ค.
์ค์ ๋ก ๋งํ ๋๋ก์ผ ํ์๋ ์์ต๋๋ค. /images/*
๋ฅผ cms URL๋ก ํ๋ก์ํ๋ ์ฌ์์ฑ์ ์ฌ์ฉํ ์ ์์ต๋๋ค(์ www.datocms-asset.com/*
๋๋ ์ด์ ์ ์ฌํ ๊ฒ). ๊ทธ๋ฐ ๋ค์ /images
์ฌ์ฉํ์ฌ ๋ชจ๋ ์ด๋ฏธ์ง๋ฅผ ์ฐ๊ฒฐํฉ๋๋ค.
์ด๊ฒ์ ์ฃผ์ ์์ ๋ฒ์ด๋๊ธฐ ์์ํ์ต๋๋ค.
@sandys ์ค์ ๋ก ์๋ฃจ์ ์ #9081์ ์ฌ์ฉํ์ฌ ์๋ฅผ ๋ค์ด /images์์ CMS๋ก ๋ค์ ์ฐ๊ธฐ๋ฅผ ์ถ๊ฐํ ๋ ํจ์ฌ ๊ฐ๋จํฉ๋๋ค. ์: ZEIT์์ ์ด์ ์ฌ๋ฐ๋ฅธ ํค๋๊ฐ ์ถ๊ฐ๋๋ฉด ๊ฒฐ๊ณผ๋ฅผ ์ด๋ฏธ ์บ์ํ๋ฏ๋ก ์ถ๊ฐ ๋ค์ด๋ก๋๊ฐ ํ์ํ์ง ์์ต๋๋ค(๋น๋ ์ ๋ง๋ํ ์ค๋ฒํค๋).
@timneutkens ๋๋ฅผ ์ํด ๋ช ํํ๊ฒํ๊ธฐ ์ํด. ์ด์์ ์ธ ์ํฉ์์๋ ์ด๋ฏธ์ง๋ฅผ ํด์ํ๊ณ ๋ธ๋ผ์ฐ์ ์์ ๊ณ ์ ํ URL๋ก ์๊ตฌ์ ์ผ๋ก ์บ์ํ๊ณ ์ฝํ ์ธ ์์ฑ์๋ CMS์์ ๋์ผํ ์ด๋ฆ์ผ๋ก ์ํ ๋๋ง๋ค ํ์ผ์ ์ ๋ฐ์ดํธํ ์ ์์ต๋๋ค. ์ฆ, ์ ์ํ ์ค์ ์์ CMS๊ฐ ๋ค์์ ๋ด๋นํด์ผ ํจ์ ์๋ฏธํฉ๋๋ค.
getStaticProps
์์ ๋ค์ด๋ก๋ํ ์ ์๋ ํด์๋ ์ด๋ฏธ์ง URL๋ก์ ๋งต์ ์ ๊ณตํ์ฌ ์ด๋ฏธ์ง URL์ CMS์ ๋ณ๊ฒฝํ ์ ์๋ ๋์๋ฌผ์ ๋ค์ ๋งคํํฉ๋๋ค.๋ถ๊ฐ๋ฅํ์ง๋ ์์ ๊ฒ ๊ฐ์์. ์ด๊ฒ์ด ์ ์๋ ์ค์ ์ธ์ง ํ์ธํ๊ณ ์ถ์ ๋ฟ์ ๋๋ค.
@Janpot CMS ์ ๊ณต์ ์ฒด๋ ์ด๋ฏธ ์ด๋ฏธ์ง ๋ฑ์ ๊ณ ์ ํ URL์ ์ ๊ณตํ์ฌ ์ด๋ฅผ ์ฒ๋ฆฌํ๊ณ ์์ต๋๋ค.
์ด๊ฒ์ ๊ทํ์ ์์ฉ ํ๋ก๊ทธ๋จ์ ํด๋น๋ ์ ์์ง๋ง ๋๋ถ๋ถ์ ์์ฉ ํ๋ก๊ทธ๋จ์๋ ํด๋น๋์ง ์์ต๋๋ค.
๋ค์ ๋งํ์ง๋ง, ๋๋ ์ฌ๊ธฐ ํผ์๊ฐ ์๋๋๋ค. ๋น์ทํ ์์ฒญ์ด ๋ง์ด ์์ต๋๋ค. ๋๋ ๋น์ ์ด ์ด๊ฒ์ ๊ณ ๋ คํ๊ธฐ๋ฅผ ์์ฒญํฉ๋๋ค.
๊ฐ์ธ ๋น ์ธก์์๋ - https://github.com/gatsbyjs/gatsby/issues/14076
https://github.com/njosefbeck/gatsby-source-stripe/#๋ค์ด๋ก๋ ํ์ผ
@sandys ์ด๊ฒ์ SSG RFC์ ๊ด๋ จ์ด ์์ผ๋ฏ๋ก ๋ฆด๋ฆฌ์ค๋๋ฉด ์๋ก์ด ๋ฌธ์ ๋ฅผ ์์ ๋กญ๊ฒ ์์ฑํ์ญ์์ค.
๊ทธ๋ฌ๋ ์ฐ๋ฆฌ์ ๋ชจ๋ ์๊ฐ์์ ์ด๊ฒ์ SSG์ ๋ฐ์ ํ๊ฒ ๊ด๋ จ๋์ด ์์์ ์ธ๊ธํ๊ณ ์ถ์์ต๋๋ค. ์ด์์ ์ธ ๊ฒฝ์ฐ๋ SSG ๋ด๋ณด๋ด๊ธฐ ๋ช
๋ น์ด ์ด๋ฅผ ์ํํ๋ ๊ฒ์ด๊ธฐ ๋๋ฌธ์
๋๋ค. ๋ค๋ฅธ ๊ฒฝ์ฐ์๋ ์ผ๋ฐ์ ์ผ๋ก ํ์ํ์ง ์์ต๋๋ค.
๊ฐ์ฅ ์ข์ ๊ฒฝ์ฐ๋ ์ด๊ฒ์ด ๋ค์ ๋ด๋ณด๋ด๊ธฐ ๋์ ์ ํ์ ๊ธฐ๋ฅ์ธ ๊ฒ์
๋๋ค.
๊ทธ๋ฌ๋ ์ํ๋๋๋ก ๊ฒฐ์ ์ ์กด์คํ์ญ์์ค.
ํ์ง๋ง ์ง๊ธ์ next export
ํ์ง ์๋ ์ผ์
๋๋ค. ๋ฐ๋ผ์ ์ด๊ฒ์ด ์์ ํ ์๋ก์ด ๊ฒ์ด๊ณ ์ด RFC์ ๊ด๋ จ์ด ์๋ ์ด์ ์
๋๋ค.
๋ํ getServerProps
๋ฐ ์ฃผ๋ฌธํ ๋ ๋๋ง์์๋ ๊ทธ๋ ์ง ์์ต๋๋ค.
@Janpot CMS ์ ๊ณต์ ์ฒด๋ ์ด๋ฏธ ์ด๋ฏธ์ง ๋ฑ์ ๊ณ ์ ํ URL์ ์ ๊ณตํ์ฌ ์ด๋ฅผ ์ฒ๋ฆฌํ๊ณ ์์ต๋๋ค.
๐ ๋ค, ๋ง์ต๋๋ค. ๊ทธ๋ฌ๋ ์ด๋ ๋ํ ํ๋ก์ ํธ์์ ์ด๋ฏธ์ง๋ฅผ ์ฌ์ฉํ๊ณ ์ต์ ํ ๋ฐ ์บ์ํ๋ ค๋ ๊ฒฝ์ฐ 2๊ฐ์ง ์ ํ์ด ์์์ ์๋ฏธํฉ๋๋ค.
ํธ์งํ๋ค:
๊ทธ๋ฆฌ๊ณ ๋ด๊ฐ ์ฌ๋ฐ๋ฅด๊ฒ ์ดํดํ๋ค๋ฉด file-loader
๋ ์ด๋ฏธ CSS์ ํฌํจ๋์ด ์์ต๋๋ค. JS์์๋ ๊ฐ๋ฅํ๊ฒ ํ๋๊ฒ ๋ฌธ์ ์๋๊ฐ์?
@Janpot Sandeep์ด ์ธ๊ธํ ํน์ ์์ ์ URL์ด ํ๋ก์ ํธ ์์ฒด๊ฐ ์๋ ์ธ๋ถ ์์ค์์ ์ ๊ณต๋๋ค๋ ๊ฒ์ ๋๋ค. ๊ธฐ๋ณธ์ ์ผ๋ก ํ์ผ ๋ก๋๋ฅผ ํฌํจํ๋ ๊ฒ์ ๋ค๋ฅธ ๊ธฐ๋ฅ ์์ฒญ์ ๋๋ค.
ZEIT Now์ ๋ฐฐํฌ๋ ์ฌ์ดํธ์ ๊ฒฝ์ฐ ์๋ก์ด ์ ์ API๋ฅผ ์ฌ์ฉํ๋ ๋์ URL์ด ์๋ ํ์ด์ง๊ฐ ์์ ๋ unstable_getStaticPaths
์ฌ์ฉํ์ฌ ์ ์ ์ผ๋ก ์์ฑ๋์ง ์์ ํ์ด์ง์ ๊ฒฝ์ฐ unstable_getStaticProps
๋ 404๋ฅผ ๋ฐํํ์ง ์๊ณ ๋ฐํ์์ ์๋ฒ์์ ์คํ๋ฉ๋๋ค.
์๋ฅผ ๋ค์ด getStaticPaths
๊ฐ ๋ฐฐ์ด์ ๋ฐํํ๋ /blog/[slug].js
ํ์ด์ง๊ฐ ์์ต๋๋ค.
[{ params: { slug: 'hello' } }]
๋ด getStaticProps
์๋ ์ฌ๋ฌ๊ทธ๋ฅผ ๊ธฐ๋ฐ์ผ๋ก ํ์ผ์ ์ฝ๋ ๋
ผ๋ฆฌ๊ฐ ์์ต๋๋ค. /blog/hello
๋ฐฉ๋ฌธํ๋ฉด ํ์ด์ง๊ฐ ์์๋๋ก ๋ฏธ๋ฆฌ ๋ ๋๋ง๋์ง๋ง /blog/doesnt-exist
์ ๊ฐ์ ์๋ชป๋ ํ์ด์ง๋ฅผ ๋ฐฉ๋ฌธํ๋ฉด ๋ฐํ์์ getStaticProps
๊ฐ ์คํ๋๊ณ ์ค๋ฅ 500์ด ๋ฐ์ํฉ๋๋ค. a 404. ๋๋ ์ค๋ฅ ์ฒ๋ฆฌ๋ฅผ ์ถ๊ฐํ๋ฉด getStaticPaths
์ ์ถ๋ ฅ์ ๋์ด๋์ง ์์์๋ ๋ถ๊ตฌํ๊ณ ํ์ด์ง๊ฐ 404๊ฐ ์๋ ๋ ๋๋ง๋ฉ๋๋ค.
์ด ๋ ผ๋ฆฌ๊ฐ ์๋๋ ๊ฒ์ ๋๊น?
์ด๊ฒ์ ํ๋ฅญํ ๊ฐ์ ์ฌํญ์
๋๋ค. ์ฐ๋ฆฌ๋ ์ด ์์
์ ์ํํ๊ธฐ ์ํด ๋ช ๊ฐ์ง ์ฌ์ ๋น๋ ์คํฌ๋ฆฝํธ๋ฅผ ์์ฑํ๋ ค๊ณ ํ์ต๋๋ค.
Next 9.2์์ ์ฌ์ดํธ ์ค ํ๋๋ฅผ unstable_getStaticPaths
๋ฐ unstable_getStaticProps
์ด๋ํ๋ ๊ฒ์ ํ
์คํธํ๋๋ฐ ์ ์๋ํ์ต๋๋ค.
exportPathMap
๋นํด ํ๊ท๊ฐ ํ๋ ์์ต๋๋ค. exportPathMap
์ฌ์ฉํ์ฌ ๊ฒฝ๋ก๋ฅผ ์์ฑํ ๋ ๋ค์๊ณผ ๊ฐ์ด ์ง์ ํ ์ ์์ต๋๋ค.
{
"/path/to/page": {page: "/index", query: { pageId: 123 } }
}
์ ์ ๋น๋๊ฐ ๋น๋๋ฉ๋๋ค.
/path
/to
/page
index.html
[slug].jsx
ํ
ํ๋ฆฟ์ unstable_getStaticPaths
์์ ์ด์ ์์ํ๋ ๊ฐ์ ๋ฐํํ๋ฉด
[{ slug: '/path/to/page' }]
๋ค์ 9.2๋ ์ค์ฒฉ๋ ๋๋ ํฐ๋ฆฌ ๋์ '%2Fpath%2Fto%2Fpage'๋ฅผ ์์ฑํฉ๋๋ค.
/%2Fpath%2Fto%2F
index.html
๋๋ ํ ๋ฆฌ ๊ตฌ์ถ(๊ธฐ์กด exportPathMap ๋์๊ณผ ์ผ์น)์ ํ์ด์ง ๊ตฌ์ถ ๋ฐฉ์์ ์ค์ํฉ๋๋ค. ๋จ์ผ ํ ํ๋ฆฟ ํ์ผ์ ์ฌ์ฉํ์ง๋ง ๊ฒ์๋ ๊ฒฝ๋ก๋ ์์๋ก ์ค์ฒฉ๋ ์ ์์ต๋๋ค.
@dpfavand ์ด ๊ฒฝ์ฐ ํฌ๊ด ๊ฒฝ๋ก๋ฅผ ์ฌ์ฉํ๊ณ ์ถ์ ๊ฒ์ ๋๋ค. https://nextjs.org/blog/next-9-2#catch -all-dynamic-routes
์ฌ๋์๋ฅผ ํฌํจํ๋ ๊ฒฝ๋ก๋ฅผ ๋ฐํํ๋ ค๊ณ ํ ๋ ์ ์ฌ์ ์ผ๋ก ๊ฒฝ๊ณ ํ ์ ์์ง๋ง [slug].js
์ฌ์ฉํ ๋ ๋์์ ์ ํํฉ๋๋ค. ๊ทํ์ ๊ฒฝ์ฐ์๋ [...slug].js
๋ฅผ ์ํฉ๋๋ค.
์ธ์ ์ฐฉ๋ฅํ ๊ฒ์ผ๋ก ์์๋ฉ๋๊น? 9.2 ํจ์น์ ํฌํจ๋ฉ๋๊น ์๋๋ฉด ์์ฒด ๋ง์ด๋ ๋ฒ์ ์ ํฌํจ๋ฉ๋๊น?
์ด ๊ธฐ๋ฅ์ ๋ํ ๋ชจ๋ ๊ธฐ๋์ ๊ฐ์ฌ๋๋ฆฝ๋๋ค. ๋ค๋ฅธ ๊ณณ์์ ์ธ๊ธํ๋ฏ์ด ์ฐ๋ฆฌ๋ ์ผ๋ฐ์ ์ผ๋ก ๊ธฐ๋ฅ์ด ์ฌ๋ฐ๋ฅธ ๊ฐ๋ฐ์ ๊ฒฝํ, ์ ์ฝ ์กฐ๊ฑด ๋ฐ ๋ฏธ๋ ๋ณด์ฅ์ฑ์ ๊ฐ๋๋ก ํ๊ธฐ ์ํด ๊ธฐ๋ฅ์ ๋ํ ์ผ์ ์ ๊ณต์ ํ์ง ์์ต๋๋ค.
์๋ก์ด ๊ธฐ๋ฅ์ด๊ธฐ ๋๋ฌธ์ ๋ง์ด๋๊ฐ ๋ ๊ฒ์ ๋๋ค.
์, ์ผ๋ฐ์ ์ผ๋ก ์ดํดํ์ง๋ง 9.1.7 ๋ธ๋ก๊ทธ๋
๊ทธ๊ฒ์ ์ด๋ฏธ ์ผ์์ ์์๋ค.
2020๋
1์ 17์ผ ๊ธ์์ผ ์คํ 5:05 Tim Neutkens [email protected]
์ผ๋ค:
์ด ๊ธฐ๋ฅ์ ๋ํ ๋ชจ๋ ๊ธฐ๋์ ๊ฐ์ฌ๋๋ฆฝ๋๋ค. ๋งํ ๋ฐ์ ๊ฐ์ด
๋ค๋ฅธ ๊ณณ์์๋ ์ผ๋ฐ์ ์ผ๋ก ๊ธฐ๋ฅ์ ๋ํ ํ์๋ผ์ธ์ ๊ณต์ ํ์ง ์์ต๋๋ค.
์ฌ๋ฐ๋ฅธ ๊ฐ๋ฐ์ ๊ฒฝํ, ์ ์ฝ ์กฐ๊ฑด ๋ฐ ๋ฏธ๋๊ฐ ์๋์ง ํ์ธ
์ฆ๊ฑฐ์ฑ.โ
๋น์ ์ด ๋๊ธ์ ๋ฌ์๊ธฐ ๋๋ฌธ์ ์ด๊ฒ์ ๋ฐ๋ ๊ฒ์ ๋๋ค.
์ด ์ด๋ฉ์ผ์ ์ง์ ๋ต์ฅํ๊ณ GitHub์์ ํ์ธ
https://github.com/zeit/next.js/issues/9524?email_source=notifications&email_token=ADKINGF724256WCEFHBFIH3Q6ITRXA5CNFSM4JRPBEL2YY3PNVWWK3TUL52HS4DFVEXG43VMVBW63LN
๋๋ ๊ตฌ๋ ์ทจ์
https://github.com/notifications/unsubscribe-auth/ADKINGBVCG6MFMOG5U2FGMDQ6ITRXANCNFSM4JRPBELQ
.>
๋ผ์ํฐ ๊ทธ๋ ๊ทธ
[email protected] [email protected]
์
(832) 495-9903
getStaticProps
๊ฒ์ด ์์ง๋ง ํ์ด์ง๋น์ด ์๋๋ผ ์ ์ฒด ์ฑ์ ๋ํด ํ ๋ฒ๋ง ์คํ๋๋์?
๋ด ์ฌ์ฉ ์ฌ๋ก๋ ์ฌ๋ฌ ํ์ด์ง์์ ์ฌ์ฉ๋๋ React Context( PricingPlansContext
)๊ฐ ์๊ณ ๋น๋ ์( next export
์ธ๋ถ ์๋ฒ์์ ๋ฐ์ดํฐ(๊ฐ๊ฒฉ ์ฑ
์ ๊ณํ)๋ฅผ ํ ๋ฒ๋ง ๊ฒ์ํ๊ธฐ๋ฅผ ์ํ๋ค๋ ๊ฒ์
๋๋ค. getStaticProps
์ ์ถ๊ฐํ์ง ์์๋ ๋ฉ๋๋ค.
ํธ์ง: https://github.com/zeit/next.js/issues/9524#issuecomment -574179540์์ ๊ด๋ จ ๋๊ธ์ ์ฐพ์์ต๋๋ค. ๊ทธ๊ฒ์ด ๊ณ ๋ ค๋๊ธฐ๋ฅผ ๋ฐ๋๋๋ค.
๋๋ ๊ทธ๊ฒ์ ์ํด babel
plugin-preval`์ ์ฌ์ฉํฉ๋๋ค.
next.config.js๋ฅผ ์ฌ์ฉํ์ฌ exportPathMa() ๋ด์ json ํ์ผ์ ๊ฐ์ ธ์ต๋๋ค.
๊ทธ๋ค์ ์ฝ๋ ๋ด์์.
์ง๊ธ์ npm ์คํฌ๋ฆฝํธ๋ฅผ ์ฌ์ฉํ์ฌ json ํ์ผ์ ์์ฑํ์ง๋ง exportPathMap์ ์ ์ํด ์ฃผ์ ์ ๊ฐ์ฌํฉ๋๋ค.
@dpfavand ์ด ๊ฒฝ์ฐ ํฌ๊ด ๊ฒฝ๋ก๋ฅผ ์ฌ์ฉํ๊ณ ์ถ์ ๊ฒ์ ๋๋ค. https://nextjs.org/blog/next-9-2#catch -all-dynamic-routes
์ฌ๋์๋ฅผ ํฌํจํ๋ ๊ฒฝ๋ก๋ฅผ ๋ฐํํ๋ ค๊ณ ํ ๋ ์ ์ฌ์ ์ผ๋ก ๊ฒฝ๊ณ ํ ์ ์์ง๋ง
[slug].js
์ฌ์ฉํ ๋ ๋์์ ์ ํํฉ๋๋ค. ๊ทํ์ ๊ฒฝ์ฐ์๋[...slug].js
๋ฅผ ์ํฉ๋๋ค.
@timneutkens ํ์ getStaticPaths
, ๊ทธ๊ฒ์์ ํตํด ์ ๋ฌ๋์ง ์์ต๋๋ค getStaticProps
์ ํ. ์ฌ๋ฌ๊ทธ ๊ฐ์ ๋ฐฐ์ด๋ก ๋ฐํํ ๋ ๊ฐ์ด ๋ฌธ์์ด์ด์ด์ผ ํ๋ฏ๋ก ๋น๋๊ฐ ์คํจํฉ๋๋ค.
์ฌ๋ก 1, pages/[...slug].jsx
ํ์ผ์ ๋ฌธ์์ด๋ก ๊ฐ์ :
export async function unstable_getStaticPaths() {
return [{ params: { slug: 'en/about' } }];
}
export async function unstable_getStaticProps({ params }) {
console.log('params', params);
return { slug: params.slug };
}
์์ ๊ฒฝ์ฐ params
์ getStaticProps
๋ slug
ํค๊ฐ ์๋ ๋น ๊ฐ์ฒด์
๋๋ค.
์ฌ๋ก 2, pages/[...slug].jsx
, ์ฌ๋ฌ๊ทธ๋ฅผ ๋ฐฐ์ด๋ก,
export async function unstable_getStaticPaths() {
const allPaths = Object.keys(pathMap).map(slug => ({ params: { slug } }));
return [{ params: { slug: ['en', 'about'] } }];
}
export async function unstable_getStaticProps({ params }) {
console.log('params', params);
return { slug: params.slug };
}
๊ฒฝ์ฐ 2์ ๊ฒฝ์ฐ ๋น๋๊ฐ ์คํจํฉ๋๋ค.
> Build error occurred
{ Error: A required parameter (slug) was not provided as a string.
at _validParamKeys.forEach.validParamKey (/project/node_modules/next/dist/build/utils.js:21:569)
at Array.forEach (<anonymous>)
at toPrerender.forEach.entry (/project/node_modules/next/dist/build/utils.js:21:495)
at Array.forEach (<anonymous>)
at Object.isPageStatic (/project/node_modules/next/dist/build/utils.js:17:122)
at process._tickCallback (internal/process/next_tick.js:68:7) type: 'Error' }
์์ getStaticPaths
์์ ์๋ ๊ฒฝ๋ก ๋งค๊ฐ๋ณ์๋ง ํ์๋ฉ๋๋ค. ์ฟผ๋ฆฌ ๋งค๊ฐ๋ณ์๋ฅผ ํฌํจํ๋ SSG ๊ฒฝ๋ก์ ๊ฐ๋ฅํฉ๋๊น? ์๋ฅผ ๋ค์ด:
/store/widgets/circles-n-squares?sort=price&minWeight=2&color=black
์ ๋ ํนํ URL์ pathname
์์ ์ ํ ๊ฒ์์ ๋ชจ๋ ์ธก๋ฉด์ ๋ค๋ฃจ๊ธฐ ์ด๋ ค์ด ์ ์ ์๊ฑฐ๋ ์ฌ์ดํธ์ ๊ด์ ์์ ์๊ฐํ๊ณ ์์ต๋๋ค.
์ต๊ทผ์ ์ฌ๊ธฐ์ ๋ฉ์์ง๋ฅผ ๊ฒ์ํ์ง๋ง ๋ต์ฅ์ ๋ฐ์ง ๋ชปํ์ต๋๋ค. ๋ณธ์ง์ ์ผ๋ก getStaticProps
๋ ์ฌ์ดํธ๊ฐ ZEIT Now์ ๋ฐฐํฌ๋ ๋ getServerProps
์ฒ๋ผ ์๋ํฉ๋๋ค(์: getStaticPaths
๋ฌด์ํ๊ณ ์์ฒญ ์ฒ๋ฆฌ ๋์ ์ผ๋ก) - ์ด๊ฒ์ด ๋ฒ๊ทธ๋ผ๊ณ ์๊ฐํฉ๋๊น?
@dpfavand ์ ๋ ์ ํํ ๊ฒฝํ์ ํ๊ณ ์์ต๋๋ค! CMS์ ํ์ด์ง๋ฅผ ๊ธฐ๋ฐ์ผ๋ก ํ๋ ๋์ ํ์ด์ง ๋ผ์ฐํ ์ ์ฌ์ฉํ์ฌ agilitycms ๋ฐ nextjs ๋ฅผ
@timneutkens ํ์
getStaticPaths
, ๊ทธ๊ฒ์์ ํตํด ์ ๋ฌ๋์ง ์์ต๋๋คgetStaticProps
์ ํ.์ฌ๋ก 1,
pages/[...slug].jsx
ํ์ผ์ ๋ฌธ์์ด๋ก ๊ฐ์ :export async function unstable_getStaticPaths() { return [{ params: { slug: 'en/about' } }]; } export async function unstable_getStaticProps({ params }) { console.log('params', params); return { slug: params.slug }; }
์์ ๊ฒฝ์ฐ
params
์getStaticProps
๋slug
ํค๊ฐ ์๋ ๋น ๊ฐ์ฒด์ ๋๋ค.
BTW, ์์ ์ธ๊ณ! fastr_conf์์ ์ด์ผ๊ธฐํด์ฃผ์ ์ ๋ค์ ํ ๋ฒ ๊ฐ์ฌ๋๋ฆฝ๋๋ค.
์๋ ํ์ธ์ @timneutkens ์ ๋๋ค .
next.js๊ฐ ์ ์ ์ฌ์ดํธ ์์ฑ๊ธฐ์ฒ๋ผ ์๋ํ๋๋ก ํ๋ ์์ด๋์ด์ ๋ํด ๋งค์ฐ ํฅ๋ถ๋ฉ๋๋ค.
๋ง์ ์์ ๋ฐ์ดํฐ๋ฅผ ํ ๋ฒ ์์ฒญํ ๋ค์ ๋ค๋ฅธ ํ์ด์ง๋ฅผ ์์ฑํ๋ ๋ฐ ์ฌ์ฉ๋๋ ๊ฒฝ์ฐ getStaticProps
๋ฐ getStaticPaths
๋ฉ์๋๋ฅผ ์ด๋ป๊ฒ ์ฌ์ฉํ ์ ์๋์ง ๋ฌป๊ณ ์ถ์ต๋๋ค.
์๋ฅผ ๋ค์ด ์ฌ์ฉ ๊ฐ๋ฅํ ๋ชจ๋ ๊ฐ์ฒด๋ฅผ ๊ฐ์ ธ์ค๋ ๋ฉ์๋๊ฐ ์๋ API ๊ธฐ๋ฐ CMS์ JavaScript SDK ํด๋ผ์ด์ธํธ๋ฅผ ์ฌ์ฉํ๊ณ ์์ต๋๋ค. ์ด๋ฌํ ๊ฐ์ฒด ์ค ์ผ๋ถ๋ ์ฌ์ดํธ ํ์ด์ง๋ฅผ ๋ํ๋ ๋๋ค.
const entries = await cmsSdkCient.getEntries();
์ง๊ธ๊น์ง exportPathMap
๋ฉ์๋๋ฅผ ์ฌ์ฉํ์ฌ CMS์์ ๋ชจ๋ ํญ๋ชฉ์ ํ ๋ฒ์ ๊ฐ์ ธ์ ์ด ํ์ด์ง์ ๊ฒฝ๋ก์ ํด๋น ๋ฐ์ดํฐ ์ฌ์ด์ ๋งต์ ์์ฑํ์ต๋๋ค. exportPathMap
ํจ์๋ ๋ ๊ฐ์ง ์์
์ ์ํํฉ๋๋ค.
getInitialProps
์ ์ํด ์๋น๋๋ ๋ฐ์ดํฐ ๋ฐ ssr: true
๊ฐ ์๋ ํ์ด์ง ๋งต์ ์ ๊ณตํฉ๋๋ค.init-props.json
ํ์ผ์ ์ด๋ฒ์๋ ssr: false
๋์ผํ ๋ฐ์ดํฐ๋ฅผ ์๋๋ค. ๊ทธ๋ฌ๋ฉด ํด๋ผ์ด์ธํธ์์ getInitialProps
๊ฐ ํธ์ถ๋๋ฉด ์ผ์นํ๋ ํ์ด์ง์ init-props.json
์์ ํ์ํ ๋ฐ์ดํฐ๊ฐ ๋ก๋๋ฉ๋๋ค.exportPathMap
์ฌ์ฉํ๋ next.config.js
module.exports = {
exportTrailingSlash: true,
exportPathMap: (defaultPathMap, { outDir }) => {
// load data from CMS
const objects = await cmsSdkCient.getEntries();
// create map between page paths and page data
return objects.reduce((accum, object) => {
// if the object does not have a slug, it is not a page
if (!object.slug) return accum;
const pagePath = '/' + object.slug;
const ssrQueryData = Object.assign({ ssr: true }, object);
const clientQueryData = Object.assign({ ssr: false }, object);
// generate the map for export phase with {ssr: true}
accum[pagePath] = {
// using additional fields from the page object,
// the pageFromPagePath() computes which page file should
// be used to render the page object
page: pageFromPagePath(object),
query: ssrQueryData
};
// write json files that will be loaded by client
if (outDir) {
const jsonFilePath = path.join(outDir, _.trim(pagePath, '/'), 'init-props.json');
fse.outputFileSync(jsonFilePath, JSON.stringify(clientQueryData));
}
return accum;
}, {});
}
}
getInitialProps
์ฌ์ฉํ๋ ํ์ด์ง/my_page.js
Index.getInitialProps = async (context) => {
const ssr = _.get(context, 'query.ssr', false);
if (ssr) {
// we are on server, return the data
return _.get(context, 'query', {});
} else {
// we are on client side, request the data through /init-props.json endpoint
const url = context.asPath + '/init-props.json';
return fetch(url).then(response => {
return response.json();
});
}
};
getStaticProps
๋ฐ getStaticPaths
๋ฉ์๋๋ฅผ ์ฌ์ฉํ๋ฉด JSON ํ์ผ์ ์ ์ฅํ๊ณ ํด๋ผ์ด์ธํธ์์ ๋ก๋ํ๋ ๊ฒ๊ณผ ๊ด๋ จ๋ ์ฝ๋๋ฅผ ๋ง์ด ์ค์ผ ์ ์๋ค๋ ํฐ ์ด์ ์ ๋ณผ ์ ์์ต๋๋ค.
// pages/my_page.js
export async function getStaticProps(context) {
const objects = await cmsSdkCient.getEntries();
const props = _.find(object, { type: 'my_page' })
return { props };
}
// pages/blog/[slug].js
export async function getStaticProps(context) {
const objects = await cmsSdkCient.getEntries();
const props = _.find(object, { type: 'post', slug: context.params.slug })
return { props };
}
export async function getStaticPaths() {
const objects = await cmsSdkCient.getEntries();
return objects
.filter(object => object.type === 'post')
.map(object => ({ params: { slug: object.slug } }))
}
๋ฌธ์ ๋ getStaticProps
๋๋ getStaticPaths
๊ฐ ํธ์ถ๋ ๋๋ง๋ค ํญ๋ชฉ์ ๊ฐ์ ธ์ค๋ ๋์ ๋ชจ๋ ํญ๋ชฉ์ ํ ๋ฒ์ ๊ฐ์ ธ์ค๋๋ก ์ํฌํ๋ก๋ฅผ ์ต์ ํํ๋ ๋ฐฉ๋ฒ์ ๋ํ ์ง๋ฌธ์
๋๋ค.
๋ ๋ค๋ฅธ ์ง๋ฌธ์ ์ด ๋ฌธ์ ์ ๋ฐ๋์ ๊ด๋ จ์ด ์๋ ๊ฒ์ ์๋์ง๋ง ์ฐ๋ฆฌ๋ SSG ๋ฐ ์๊ฒฉ ๋ฐ์ดํฐ ์์ค์ ์ธ๊ณ์ ์๊ธฐ ๋๋ฌธ์ ์ง๋ฌธํ ๊ฐ์น๊ฐ ์์ต๋๋ค. next.js๊ฐ dev ๋ชจ๋์์ ์คํ๋๋ค๊ณ ๊ฐ์ ํ๋ฉด ์๊ฒฉ ๋ฐ์ดํฐ๋ฅผ ๋ค์ ๊ฐ์ ธ์ค๊ณ ์ฌ์ดํธ๋ฅผ ๋ค์ ๋น๋ํ๊ธฐ ์ํด ์ด๋ป๊ฒ next.js์ ์ด๋ฌํ ๋ฉ์๋๋ฅผ ๋ค์ ์คํํ๋๋ก ์๋ฆด ์ ์์ต๋๊น?
@smnh "๊ทธ๋ฅ JavaScript"์ด๊ธฐ ๋๋ฌธ์ ํญ๋ชฉ์ ํ ๋ฒ ๊ฐ์ ธ์ค๊ณ ๋ฐ์ดํฐ ๊ฐ์ ธ์ค๊ธฐ ๋ฐฉ๋ฒ์ ๊ฒฐ๊ณผ๋ฅผ ์บ์ํ ์ ์์ต๋๋ค. ๋ค๋ฅธ ํ์ด์ง์ getStatic* ๋ฉ์๋์์ ๋ค์ ํธ์ถ๋ ๋ ๋คํธ์ํฌ๋ ๋ค์ ์ ์ค๋์ง ์์ต๋๋ค.
๋ ๋ฒ์งธ ์ง๋ฌธ์ ์๋์ผ๋ก ์ํ๋ฉ๋๋ค. next dev
์คํํ๋ฉด ๋ฐ๋ก ์คํ๋ฉ๋๋ค.
์์
getStaticPaths
์์ ์๋ ๊ฒฝ๋ก ๋งค๊ฐ๋ณ์๋ง ํ์๋ฉ๋๋ค. ์ฟผ๋ฆฌ ๋งค๊ฐ๋ณ์๋ฅผ ํฌํจํ๋ SSG ๊ฒฝ๋ก์ ๊ฐ๋ฅํฉ๋๊น? ์๋ฅผ ๋ค์ด:/store/widgets/circles-n-squares?sort=price&minWeight=2&color=black
์ ๋ ํนํ URL์
pathname
์์ ์ ํ ๊ฒ์์ ๋ชจ๋ ์ธก๋ฉด์ ๋ค๋ฃจ๊ธฐ ์ด๋ ค์ด ์ ์ ์๊ฑฐ๋ ์ฌ์ดํธ์ ๊ด์ ์์ ์๊ฐํ๊ณ ์์ต๋๋ค.
๋๋ ์ด๊ฒ์ด ssg์ ๋งฅ๋ฝ์์ ์๋ฏธ๊ฐ ์๋ค๊ณ ์๊ฐํฉ๋๋ค. SSG๋ ๋ชจ๋ ํญ๋ชฉ์ ๋ํด ํ์ผ์ ์ถ๋ ฅํฉ๋๋ค. ์ฟผ๋ฆฌ ๋งค๊ฐ๋ณ์๋ ํ์ผ ์ด๋ฆ์ ์ผ๋ถ๊ฐ ์๋๋ฏ๋ก ์์ฒญ์ ์ค์ ํ์ผ์ ๋ค์ ์ฐ๋ ค๋ฉด ์๋ฒ ๊ณ์ธต์ด ํ์ํฉ๋๋ค. (์์ ์์์ ์ ์ ํ์ผ ์ด๋ฆ์ ๋ฌด์์ ๋๊น?) ๊ธฐ๋ณธ ๋ณด๊ธฐ(ํจ์ฏ์ด ์๋ ํ์ด์ง๋ฅผ ๋ฐฉ๋ฌธํ๋ฉด ์ป์ ์ ์๋ ๊ฒ)๋ฅผ ์ฌ์ ๋ ๋๋งํ๊ณ ์์ฒญ์ ์ฟผ๋ฆฌ ๋งค๊ฐ๋ณ์๊ฐ ์๋ ๊ฒฝ์ฐ ํด๋ผ์ด์ธํธ ์ธก์์ ์ ๋ฐ์ดํธํ๋ ๊ฒ์ ๊ณ ๋ คํ๋ ๊ฒ์ด ์ข์ต๋๋ค. ๊ทธ๋ฌ๋ ๊ทธ๊ฒ์ ์ด SSG RFC๋ฅผ ๋์ด์๋ ๋ฌธ์ ๊ฐ ๋ฉ๋๋ค.
@dpfavand ์ ๋ ์ ํํ ๊ฒฝํ์ ํ๊ณ ์์ต๋๋ค! CMS์ ํ์ด์ง๋ฅผ ๊ธฐ๋ฐ์ผ๋ก ํ๋ ๋์ ํ์ด์ง ๋ผ์ฐํ ์ ์ฌ์ฉํ์ฌ agilitycms ๋ฐ nextjs ๋ฅผ
@timneutkens ํ์
getStaticPaths
, ๊ทธ๊ฒ์์ ํตํด ์ ๋ฌ๋์ง ์์ต๋๋คgetStaticProps
์ ํ.
์ฌ๋ก 1,pages/[...slug].jsx
ํ์ผ์ ๋ฌธ์์ด๋ก ๊ฐ์ :export async function unstable_getStaticPaths() { return [{ params: { slug: 'en/about' } }]; } export async function unstable_getStaticProps({ params }) { console.log('params', params); return { slug: params.slug }; }
์์ ๊ฒฝ์ฐ
params
์getStaticProps
๋slug
ํค๊ฐ ์๋ ๋น ๊ฐ์ฒด์ ๋๋ค.BTW, ์์ ์ธ๊ณ! fastr_conf์์ ์ด์ผ๊ธฐํด์ฃผ์ ์ ๋ค์ ํ ๋ฒ ๊ฐ์ฌ๋๋ฆฝ๋๋ค.
์ด๋ด! Nextjs ํ์ ์ด ๋ฌธ์ ๋ฅผ ํด๊ฒฐํ๊ธฐ ์์ํ์ผ๋ฉฐ ํ์ฌ ์นด๋๋ฆฌ์ ๊ตฌํ๊ณผ ๊ด๋ จ๋ ๋ช ๊ฐ์ง ์ถ๊ฐ ๋ฌธ์ ๋ฅผ ํด๊ฒฐํ ์ ์๋ ํฐ์ผ์ด ์์ต๋๋ค. https://github.com/zeit/next.js/issues/10190
@smnh ๋ด๊ฐ ํ๋ ์ผ์ ๋น๋ + ๋ด๋ณด๋ด๊ธฐ๋ฅผ ์คํํ๊ธฐ ์ ์ ๊ณต์ ์ฝํ ์ธ ๋ฅผ ๋ฏธ๋ฆฌ ๊ฐ์ ธ์ค๊ณ JSON์ ์ ์ฅํ๋ ์คํฌ๋ฆฝํธ๋ฅผ ๊ฐ๋ ๊ฒ์ ๋๋ค. ๊ทธ๋ฐ ๋ค์ ํด๋น JSON์ ํ์ด์ง์์ ๋ชจ๋๋ก ์ง์ ๊ฐ์ ธ์ค๊ธฐ๋ง ํ๋ฉด ๋ฉ๋๋ค.
์ฌ๊ตฌ์ถ์ ์ํด ๊ด๋ จ ์ฝํ ์ธ ๊ฐ ๋ณ๊ฒฝ๋ ๋ Netlify ๋น๋ ํํฌ๋ฅผ ํธ๋ฆฌ๊ฑฐํ๋๋ก CMS์ ์นํํฌ๋ฅผ ์ค์ ํ์ต๋๋ค. ๊ทธ๋ฐ ๋ค์ GetStaticProps๋ ํ์ด์ง ํน์ ์ฝํ ์ธ ๋ฅผ ๊ฐ์ ธ์ฌ ์ ์์ต๋๋ค.
@zeusdeux ๊ฐ์ฌํฉ๋๋ค
๋ต์ฅ:
๋ ๋ฒ์งธ ์ง๋ฌธ์ ์๋์ผ๋ก ์ํ๋ฉ๋๋ค. ๋ค์ ๊ฐ๋ฐ์ ์คํํ๋ฉด ๋ฉ๋๋ค.
๋ชจ๋์ ์บ์ํ ๋ค์ CMS์์ ๋ฐ์ดํฐ๋ฅผ ๋ณ๊ฒฝํ๋ฉด ์บ์๊ฐ ๋ฌดํจํ๋๊ณ dev
์ํด ๋ค์ ์คํ๋์ง๋ง next.js๋ฅผ ์ค์งํ๊ณ ๋ค์ ์คํํ์ง ์์ต๋๋ค. :)
๋ชจ๋์ ์บ์ํ ๋ค์ CMS์์ ๋ฐ์ดํฐ๋ฅผ ๋ณ๊ฒฝํ๋ฉด ์บ์๊ฐ ๋ฌดํจํ๋๊ณ
dev
์ํด ๋ค์ ์คํ๋์ง๋ง next.js๋ฅผ ์ค์งํ๊ณ ๋ค์ ์คํํ์ง ์์ต๋๋ค. :)
getStaticPaths
๋ ํ๋ก๋์
๋น๋์์๋ง ํธ์ถ๋๋ฏ๋ก ํด๋น ํจ์์์ ํธ์ถ๋ ๋ ๋ชจ๋ ์ํ์์ ์บ์ํ๋๋ก ๊ฐ์ ธ์ค๋ ๋ฉ์๋๋ง ์๋ฆด ์ ์์ต๋๋ค.
์ด๋ด, ๋๋ ๋๊ตฐ๊ฐ๊ฐ ๋์ ๊ฐ์ ๋ฌธ์ ์ ์ง๋ฉดํ๋์ง ๋ณด์ง ๋ชปํ์ต๋๋ค.
unstable_getStaticProps
ํ์ฌ ์ฌ๋ฌ ๊ฒฝ๋ก์ ๋์ผํ ํ์ด์ง๊ฐ ์๋ค๊ณ ๊ฐ์ ํด ๋ณด๊ฒ ์ต๋๋ค.
1. /providers/[category]/[city]
2. /providers/[category]
์์ค ์ฝ๋๋ ๋ ํ์ด์ง ๋ชจ๋ ๋์ผํ๋ฏ๋ก ๋ณต์ ํ ํ์๊ฐ ์์ต๋๋ค. ๋ฐ๋ผ์ ์ฒซ ๋ฒ์งธ ํ์ผ์๋ ๋
ผ๋ฆฌ๊ฐ ์๋ ์์ค ์ฝ๋๊ฐ ํฌํจ๋์ด ์๊ณ ๋ ๋ฒ์งธ ํ์ผ์ export { default } from './[city]';
์ ๊ฐ์ ์ฒซ ๋ฒ์งธ ํ์ผ๋ง ๊ฐ์ ธ์ต๋๋ค.
๊ทธ๋ฌ๋ getStaticProps์ ๋ฐ์ดํฐ๊ฐ ์ ์๋์ง ์์๋ค๋ ์ค๋ฅ๊ฐ ๋ฐ์ํฉ๋๋ค. ๋์ผํ ์ฝ๋๋ฅผ ๋ ํ์ผ์ ๋ชจ๋ ๋ณต์ฌํ๋ฉด ์๋ํฉ๋๋ค.
@homoky ๋ฉ์๋๋ฅผ ๋ค์ ๋ด
export { default, unstable_getStaticProps } from './[city]';
๋๋ SSG๋ฅผ ์๋ํ์ง๋ง ์ด์ด ์์์ต๋๋ค.
v9.2.1์ด ํฌํจ๋ ์๋ ์ฝ๋๋ SSG๋ฅผ ์์ฑํด์ผ ํฉ๋๊น?
function Page({ stars }) {
return <div>Next stars: {stars}</div>
}
Page.unstable_getStaticProps = async ctx => {
return { props: { stars: 5 } }
}
export default Page
next build
๋ด ์ฝ์ ์ถ๋ ฅ์ ๋ค์์ ๋ณด์ฌ์ค๋๋ค.
Page Size First Load
โ โ / 354 B 72.1 kB
...
ฮป (Server) server-side renders at runtime (uses getInitialProps or getServerProps)
โ (Static) automatically rendered as static HTML (uses no initial props)
โ (SSG) automatically generated as static HTML + JSON (uses getStaticProps)
@joostmeijles unstable_getStaticProps
๋ ํ์ด์ง ๊ตฌ์ฑ ์์์ ์ฒจ๋ถ๋๋ ๋์ ๋ด ๋ณด๋ด์ผ ํฉ๋๋ค. ์:
export const unstable_getStaticProps = async () => {
return {
props: { stars: 5 }
}
}
@joostmeijles
unstable_getStaticProps
๋ ํ์ด์ง ๊ตฌ์ฑ ์์์ ์ฒจ๋ถ๋๋ ๋์ ๋ด ๋ณด๋ด์ผ ํฉ๋๋ค. ์:export const unstable_getStaticProps = async () => { return { props: { stars: 5 } } }
๋๋ถ์ ํด๊ฒฐ๋์์ต๋๋ค.
์ด์ ๋ํ ์ข ๋จ ๊ฐ ์์ ์๋ฅผ ๋ณด๊ณ ์ถ์ ์ฌ๋์ด ์์ผ๋ฉด ํฌ๊ด ๊ฒฝ๋ก ๋ฐ SSG๋ฅผ ์ฌ์ฉํ์ฌ ๋์ ํ์ด์ง(CMS์์) ์์ฑ https://github.com/agility/agilitycms-next-starter-๋ฅผ ํ์ธ
๋๋ ๋ช ๋ฒ ๋นํฉํ๊ณ ์ด๊ฒ์ด ๋ค๋ฅธ ์ฌ๋๋ค์๊ฒ ๋์์ด ๋ ์ ์๋ค๊ณ ์๊ฐํ์ต๋๋ค.
zeit.co/now์ ๋ฐฐํฌํ ๋ getStaticProps
๋น๋ํ๋ ๋์ ๋ค์ API ๊ฒฝ๋ก์ ์ก์ธ์คํ๋ ค๋ฉด ์ด๋ป๊ฒ ํด์ผ ํฉ๋๊น? Isomorphic-fetch์๋ ์ ๋ URL์ด ํ์ํฉ๋๋ค. ๋ก์ปฌ์์๋ http://localhost :3000์์ ์๋ํ์ง๋ง ์ง๊ธ ๋ฐฐํฌ์์๋ ์๋ํ์ง ์์ต๋๋ค(๋๋ ๋ด๊ฐ ์๋ชปํ์ต๋๋ค ๐คทโโ๏ธ). ์ด๋ค ์์ด๋์ด?
๋ด ๋ง์ด ๋ง๋ค๋ฉด API ๊ฒฝ๋ก๊ฐ ์๋ฒ๋ฆฌ์ค ๊ธฐ๋ฅ์ผ๋ก ๋ฐฐํฌ๋ ๊ฒ์ด๊ณ ๋น๋ ํ๋ก์ธ์ค ์ค์ ์ค๋น๋์ง ์์ ๊ฒ ๊ฐ์ต๋๊น?
http๋ฅผ ํตํด ์ด๋ํ๋ ๊ฒ๋ณด๋ค ํจ์ฌ ์ ์ ์ค๋ฒ ํค๋๋ก API ๊ฒฝ๋ก์ ๊ธฐ๋ฅ์ ์ง์ ํธ์ถํ๊ณ ์ถ์ ๊ฒ์ ๋๋ค.
http๋ฅผ ํตํด ์ด๋ํ๋ ๊ฒ๋ณด๋ค ํจ์ฌ ์ ์ ์ค๋ฒ ํค๋๋ก API ๊ฒฝ๋ก์ ๊ธฐ๋ฅ์ ์ง์ ํธ์ถํ๊ณ ์ถ์ ๊ฒ์ ๋๋ค.
ํด๋น ์ฃผ์ ์ ๋ํ ๋ฌธ์์์ ์ฝ์ ์ ์๋ ๋ฆฌ์์ค๊ฐ ์์ต๋๊น? ์ ๋ zeit.co/now๋ก ๋ง์ด๊ทธ๋ ์ด์ ํ๋ ์ค์ ๋๋ค :)
๋ง ๊ทธ๋๋ก ํจ์๋ฅผ ๊ฐ์ ธ์ค๊ณ ํธ์ถํฉ๋๋ค.
import MyFunction from '../lib/somewhere'
export async function /* unstable_ */getStaticProps() {
const result = await MyFunction()
}
๋ ๋ค๋ฅธ ์ง๋ฌธ: getStaticProps
/ getStaticPaths
๋ฐ getServerProps
๋๋ํ ์ฌ์ฉํ ์ ์์ต๋๊น? ์๋ฅผ ๋ค์ด SSG๋ก ์ผ๋ถ ํ์ด์ง๋ฅผ ๋ฏธ๋ฆฌ ๋ ๋๋งํ์ง๋ง CDN ์บ์์์ ์ฐพ์ ์ ์๋ ๊ฒฝ์ฐ ์์ฒญ ์ ํ์ด์ง๋ฅผ ์์ฑํ๊ธฐ ์ํด SSR๋ก ๋์ฒด๋ฉ๋๊น?
getStaticProps
๋ SSR๋ก ๋์ฒดํ๊ณ ๊ฒฐ๊ณผ๋ฅผ ์บ์์ ์ถ๊ฐํฉ๋๋ค.
getStaticProps
๋ SSR๋ก ๋์ฒดํ๊ณ ๊ฒฐ๊ณผ๋ฅผ ์บ์์ ์ถ๊ฐํฉ๋๋ค.
@lfades , ๋ด๊ฐ ๋น์ ์ ์ฌ๋ฐ๋ฅด๊ฒ ์ดํดํ๋ค๋ฉด ๋๋ ๊ทธ๊ฒ์ ๋ํด ๋งค์ฐ ๐ ์๋ํ๋ฉด ๋ฏธ๋ฆฌ ์์ฒ ํ์ด์ง๋ฅผ ์ฐพ์ ์์ฑํ๋ ๋์ ์ธ๊ธฐ์๋ ํ์ด์ง ๋ช ๊ฐ๋ฅผ ๋ฏธ๋ฆฌ ๋ ๋๋ง ํ ์ ์๊ธฐ ๋๋ฌธ์ ๋๋ค.
ํ์ง๋ง ์ดํด๋ฅผ ๋๊ธฐ ์ํด... /products/[productId].js
๋์ ๊ฒฝ๋ก ํ์ด์ง๊ฐ ์๋ค๊ณ ๊ฐ์ ํด ๋ณด๊ฒ ์ต๋๋ค. ๋ด๊ฐ ์ ๊ณตํ๋ ๊ฒฝ์ฐ getStaticProps
, ๊ทธ๋ฆฌ๊ณ ๊ฒฐ๊ณผ์ ์ ํ๋ ์์ getStaticPaths
๊ฒฝ์ฐ, ๋น์ ์ ๋ง์ํ๋์ง /products/123
CDN์ ์บ์์์ ๋ฐ๊ฒฌ๋์ง๋ ๋
ํ ๋๋ฌธ์ '( t in getStaticPaths
), SSR๋ก ๋์๊ฐ getStaticProps
์คํํ ๋ค์ ๊ฒฐ๊ณผ๋ฅผ ์ ์ ํ์ด์ง๋ก ์บ์ํฉ๋๊น?
ํ์ ์ง๋ฌธ: getStaticPaths
๋ฅผ ์ ํ ์ ๊ณตํ์ง ์์๋ ์๋ํฉ๋๊น?
@flintinatux ์, ๊ทธ๋ ์ต๋๋ค ๐
getStaticProps๋ SSR๋ก ํด๋ฐฑํ๊ณ ๊ฒฐ๊ณผ๋ฅผ ์บ์์ ์ถ๊ฐํฉ๋๋ค.
getStaticProps
๋ res
๊ฐ์ฒด๋ฅผ ๋ณ๊ฒฝํ๋ ๊ฒ์ ํ์ฉํ์ง ์๊ธฐ ๋๋ฌธ์ 404๋ฅผ ์ํํ ๋ฐฉ๋ฒ์ด ์๊ธฐ ๋๋ฌธ์ ์ด๊ฒ์ ๋ฌธ์ ์
๋๋ค. ํจ์ ํธ์ถ ์ค์ ์ค๋ฅ๊ฐ ์์ผ๋ฉด 200 ๋๋ 500์ด ๋ฉ๋๋ค.
๋ณ๊ฒฝ๋ ์์ ์ธ๊ฐ์?
@davidbailey00์ ์ ์ ์น์ฌ์ดํธ๋ฅผ ๋ง๋ค ๋ 404 ํ์ด์ง์ ์ด๋ฏธ 404 ์ํ ์ฝ๋๊ฐ ์์ต๋๋ค.
๋ฌผ๋ก ์ ์ฒด ์ ์ ๋ด๋ณด๋ด๊ธฐ๋ฅผ ์ํํ๋ฉด ๋ชจ๋ ๊ฒ์ด ํ์ผ์ผ ๋ฟ์ด๋ฏ๋ก ์ํ ์ฝ๋๋ฅผ ์ํํ ๋ฐฉ๋ฒ์ด ์์ต๋๋ค. ZEIT Now์ getStaticProps
๋ฅผ ์ฌ์ฉํ์ฌ ํ์ด๋ธ๋ฆฌ๋ ์ฌ์ดํธ๋ฅผ ๋ฐฐํฌํ๋ ๊ฒ์ ๋ํด ์ด์ผ๊ธฐํ๊ณ ์์ต๋๋ค. ์ด๊ฒ์ ๊ด๊ณ์์ด ๋์ ๊ฒฝ๋ก์ ์ผ์นํ๋ ๋ชจ๋ ํ์ด์ง๋ฅผ ๊ฐ์ ๋ก ๋ ๋๋งํ๊ธฐ ๋ณด๋ค๋ getStaticPaths
์กด์คํ๊ณ 404ํ์ด์ง๋ฅผ ์ ๊ณตํด์ผ ํ๋ ๊ฒ ๊ฐ์ต๋๋ค.
Now ์์๋ง ์๋ํ๋ ๊ฒ์ด ์๋๋ผ next start
ํฉ๋๋ค.
ํ์ง๋ง ์์ ๋งํ ๋๋ก ๋ฐ๋ณตํ๊ฒ ์ต๋๋ค. ์ด๊ฒ์ ์คํ์ ์ด๋ฉฐ ์ฌ์ ํ ๋์์ด ๋ณ๊ฒฝ๋ ์ ์์ต๋๋ค.
๊ทธ๋ฌ๋ getServerProps
๋๋ getInitialProps
404ํ์ด์ง๋ฅผ ์ ๊ณตํ ์ ์์ต๋๋ค. ์๋ต ์ฝ๋๋ฅผ ๊ณ ๋ คํ ๋ getStaticProps
๊ฐ getStaticPaths
๋ฌด์ํ๋ฉด ๊ด์ฌ์ ๊ฐ๋ ์ฌ์ดํธ์์๋ ์์ ํ ์คํ ๋ถ๊ฐ๋ฅํฉ๋๋ค. ์ข์ SEO.
์ํ ์ฝ๋๋ฅผ ์ฒ๋ฆฌํ๋ ๋ ๋ง์ ๋ฐฉ๋ฒ์ ์๊ฐํ ๊ฒ์ด์ง๋ง ๋๋ถ๋ถ์ ์ ์ ์ฌ์ดํธ(์: CRA)๋ /*
๋ฅผ index.html
๋ก ๋ผ์ฐํ
ํฉ๋๋ค. ์ฌ๊ธฐ์ 404๋ ์ฌ์ ํ 200์
๋๋ค.
์๋
ํ์ธ์ ์ฌ๋ฌ๋ถ, ์ง๋ฌธ์ด ์์ต๋๋ค. ์๋ก์ด [unstable_]getStaticProps
๋ฅผ ์ฌ์ฉํ์ฌ ์ผ๋ถ ํ์ด์ง๋ฅผ SSGํ๋ ๊ฐ๋จํ ์น์ฌ์ดํธ๋ฅผ ๋ง๋ค๊ณ ์์ต๋๋ค. amp ๋ฅผ ์ ์ธํ๊ณ ์ง๊ธ๊น์ง ๋ชจ๋ ๊ฒ์ด ์ ์๋ํฉ๋๋ค.
ํ์ด์ง์ [unstable_]getStaticProps
ํฌํจ๋์ด ์์ผ๋ฉด amp
๊ฐ ๋นํ์ฑํ๋ฉ๋๋ค. ๋ค์ v9.2.1์์ ๋ค์์ ํ์ธํ ์ ์๋ ๊ฐ๋จํ ์์
๋๋ค.
import React from "react";
import { useAmp } from "next/amp";
export const config = { amp: `hybrid` };
const AmpExample = ({ date }) => {
const isAmp = useAmp();
return (
<>
<p>
Welcome to the {isAmp ? `AMP` : `normal`} version of the Index page!!
</p>
<p>date: {date}</p>
</>
);
};
/**
* If I get the dynamic data from getStaticProps,
* page is SSG render but AMP is disabled when accessing
* with `/ampExample?amp=1`
*/
export async function unstable_getStaticProps() {
return {
props: {
date: new Date().toISOString(),
},
};
}
/**
* If I get the dynamic data from getInitialProps,
* page is SSR render but AMP is disabled when accessing
* with `/ampExample?amp=1`
*/
// AmpExample.getInitialProps = () => {
// return { date: new Date().toISOString() }
// }
export default AmpExample;
๋ฐ์ดํฐ๊ฐ ์๋ SSG
ํ์ด์ง์ amp
์๋ํ๋ ๋ฐฉ๋ฒ์ ์ดํดํ๋ ๋ฐ ๋์์ด ๋์
จ๋์?
์๋
ํ์ธ์, App
๊ตฌ์ฑ ์์( _app.tsx
), ์ฆ ๋น๋ ๋จ๊ณ์์ ๋ชจ๋ ํ์ด์ง ๊ตฌ์ฑ ์์์ ๋ํ ๊ณตํต ๋ฐ์ดํฐ๋ฅผ ๊ฐ์ ธ์ค๋ ๊ฒ๊ณผ ๊ฐ์ ๊ฒฝ์ฐ์ ๋ํด getStaticProps
๋ฅผ ์ง์ํ๋ ๋ฐฉ๋ฒ์ ๋ฌด์์
๋๊น?
์๋ ํ์ธ์,
App
๊ตฌ์ฑ ์์(_app.tsx
), ์ฆ ๋น๋ ๋จ๊ณ์์ ๋ชจ๋ ํ์ด์ง ๊ตฌ์ฑ ์์์ ๋ํ ๊ณตํต ๋ฐ์ดํฐ๋ฅผ ๊ฐ์ ธ์ค๋ ๊ฒ๊ณผ ๊ฐ์ ๊ฒฝ์ฐ์ ๋ํดgetStaticProps
๋ฅผ ์ง์ํ๋ ๋ฐฉ๋ฒ์ ๋ฌด์์ ๋๊น?
@pkral78 ์ค์ ๊ฐ๋ฐ ์ํฉ์์ ํด๊ฒฐ ๋ฐฉ๋ฒ์ ๋ง์๋๋ฆด ์ ์์ต๋๋ค.
"๊ณ ์ฐจ ๊ตฌ์ฑ ์์(HOC)๋ก์์ ๋ ์ด์์" ์ ๊ทผ ๋ฐฉ์์ผ๋ก ๋ ์ด์์์ ๋ง๋ค์์ต๋๋ค(๋ ์ด์ ํ์ต ๋ฌธ์ ๐คทโโ๏ธ์ ์์).
์ด์จ๋ ๋ค์๊ณผ ๊ฐ์ ๋ ์ด์์์ ๋ง๋ค์์ต๋๋ค(์์).
import React from "react";
import Head from "next/head";
const withSSGLayout = Page => {
const WithSSGLayout = props => {
return (
<>
<Head>
<title>My Web Page</title>
<link rel="icon" href="/favicon.ico" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<link
href="https://fonts.googleapis.com/css?family=Roboto:400,700&display=swap"
rel="stylesheet"
/>
</Head>
<Page {...props} />
</>
);
};
WithSSGLayout.unstable_getStaticProps = async () => {
const pageStaticProps = Page.unstable_getStaticProps
? await Page.unstable_getStaticProps()
: {};
// Here you can make parent level queries too
return {
props: {
...pageStaticProps.props,
parentProp: `dynamic prop-${new Date().toISOString()}`,
},
};
};
return WithSSGLayout;
};
export default withSSGLayout;
๊ทธ๋ฐ ๋ค์ ์ด ์ ๊ทผ ๋ฐฉ์์ ์ฌ์ฉํ๋ ค๋ ํ์ด์ง์์ HOC๋ฅผ ๊ฐ๋จํ ์ถ๊ฐํ ์ ์์ง๋ง( [unstable_]getStaticProps
๋ฐ amp๊ฐ ํจ๊ป ์๋ํ์ง ์๋ ๊ฒ์ ๋ช
์์ ์ผ๋ก ๋ด๋ณด๋ด์ผ ํจ) ๋์ ์์ค์ ์์ฒญ์ ๊ฐ๋ "์ข์ ๋ฐฉ๋ฒ"์ ์ฐพ์์ต๋๋ค. ํ์ด์ง๋น SSG ์ฟผ๋ฆฌ.
import React from "react";
import withSSGLayout from "../hocs/withSSGLayout";
export const config = { amp: `true` };
const Index = props => {
const { date, parentProp } = props;
return (
<div>
<h1>Example</h1>
<h3>Local Prop?: {date}</h3>
<h3>Parent Prop?: {parentProp}</h3>
</div>
);
};
// In theory you could do direct database queries
Index.unstable_getStaticProps = async () => {
// Here you can make page level queries
return {
props: {
date: new Date().toISOString(),
},
};
};
const IndexHOC = withSSGLayout(Index);
export const { unstable_getStaticProps } = IndexHOC;
export default IndexHOC;
์ข์ ์ ๊ทผ ๋ฐฉ์์ด๋ผ๋ฉด ์ธ๋ํธ๋ํ๊ณ ์ถ์ต๋๋ค. ์ ๊ฒฝ์ฐ์๋ ์ด ๊ธฐ์ ์ ์ฌ์ฉํ์ฌ ๋ถ๋ชจ์ ๋งํฌ์ ํ์ด์ง ์ฝํ ์ธ ์ ํ์ด์ง ์ฝํ ์ธ ๋ฅผ ์ฟผ๋ฆฌํฉ๋๋ค. ๋์์ด ๋๊ธฐ๋ฅผ ๋ฐ๋๋๋ค.
@robertovg ์ฝ๋๊ฐ ํธ๋ฆฌ ํ๋ค๋ ค์ ๋ชจ๋ ์์ค์์ ๋ด
@timneutkens ์ด ์์ ์์ ๋ํด ๋ ๋์ ์๋ฃจ์ ์ ์ ์ํ ์ ์์ต๋๊น? ์ด๋ค ์์ผ๋ก๋ "๋ ์ด์์ ์์ค SSG ์ฟผ๋ฆฌ"์ "ํ์ด์ง ์์ค SSG ์ฟผ๋ฆฌ"๋ฅผ ๋ชจ๋ ์ฌ์ฉํ๋ ค๊ณ ํ๊ณ ์ด HOC ๋ ์ด์์ ์ ๊ทผ ๋ฐฉ์์ ๋ํด ์๊ฐํ์ต๋๋ค.
๋๋ฅผ ์ํ ์ฃผ์ ์ ์ฝ์ SSG ํ์ด์ง๋ก ํ์ํ๊ธฐ ์ํด ๊ฐ ํ์ด์ง์ ์์ด์ผ ํ๋ ๋ช ์์ ์ผ๋ก "[unstable_]getStaticProps ๋ด๋ณด๋ด๊ธฐ"์์ต๋๋ค.
amp + SSG ๊ฐ ํธํ๋๋์ง ์ฌ๋ถ์ ๋ํ ์ถ๊ฐ ์ ๋ณด๋ ๊ฐ์ฌํ๊ฒ ์ต๋๋ค. ์ด์ ์ ์ง๋ฌธํ ์ ์ด ์์ต๋๋ค.
๊ฐ์ฌํฉ๋๋ค ๐
@robertovg ๋จผ์ ๋ฐ์ดํฐ์์ ๋ ์ด์์์ ๋ถ๋ฆฌํ๋ฏ๋ก ๊ณต์ ๋ ์ด์์์ ๊ฒฝ์ฐ ๋ค์๊ณผ ๊ฐ์ด ๊ฐ๋จํฉ๋๋ค.
import Layout from '../components/layout'
const Page = () => (
<Layout>
<h1>Hello World!</h1>
</Layout>
)
export default Page
๊ทธ๋ฆฌ๊ณ getStaticProps
๊ฒฝ์ฐ ๋ค๋ฅธ ๋ชจ๋์ ๋ฉ์๋๋ฅผ ์ฌ์ฉํ์ฌ ๊ณต์ ๋ฐ์ดํฐ๋ฅผ ๊ฐ์ ธ์ค๋ฏ๋ก ์ ์ฒด ์์ ๋ ๋ค์๊ณผ ๊ฐ์ ์ ์์ต๋๋ค.
import fetchSharedData from '../lib/fetch-shared-data'
import Layout from '../components/layout'
export const unstable_getStaticProps = async () => {
const sharedData = await fetchSharedData()
const pageProps = {...}
return { props: { ...sharedData, ...pageProps } }
}
const Page = () => (
<Layout>
<h1>Hello World!</h1>
</Layout>
)
export default Page
@robertovg ๋จผ์ ๋ฐ์ดํฐ์์ ๋ ์ด์์์ ๋ถ๋ฆฌํ๋ฏ๋ก ๊ณต์ ๋ ์ด์์์ ๊ฒฝ์ฐ ๋ค์๊ณผ ๊ฐ์ด ๊ฐ๋จํฉ๋๋ค.
import Layout from '../components/layout' const Page = () => ( <Layout> <h1>Hello World!</h1> </Layout> ) export default Page
๊ทธ๋ฆฌ๊ณ
getStaticProps
๊ฒฝ์ฐ ๋ค๋ฅธ ๋ชจ๋์ ๋ฉ์๋๋ฅผ ์ฌ์ฉํ์ฌ ๊ณต์ ๋ฐ์ดํฐ๋ฅผ ๊ฐ์ ธ์ค๋ฏ๋ก ์ ์ฒด ์์ ๋ ๋ค์๊ณผ ๊ฐ์ ์ ์์ต๋๋ค.import fetchSharedData from '../lib/fetch-shared-data' import Layout from '../components/layout' export const unstable_getStaticProps = async () => { const sharedData = await fetchSharedData() const pageProps = {...} return { props: { ...sharedData, ...pageProps } } } const Page = () => ( <Layout> <h1>Hello World!</h1> </Layout> ) export default Page
์ด ์๋ฃจ์
์ ๋ณด๊ณ ์ดํดํ์ง๋ง ์ ๊ฐ ์ ๊ธฐํ๋ ค๊ณ ํ๋ ๋ฌธ์ ๋ ๊ณต์ ๋ฐ์ดํฐ ์ฌ์ฉ๋์ ํ์ฅํ๋ ๋ฐฉ๋ฒ์ด์์ต๋๋ค.
์๋ฅผ ๋ค์ด, ๊ฒฝ์ฐ์ ๊ฐ์ง๊ณ <Header />
์ฉ๋ ๋ sharedData
๋งํฌ๋ฅผ ์ป๊ธฐ ์ํด ๊ทธ๊ฐ ํค๋๋ฆฌ์ค CMS์์์ค๊ณ ์๋ค. <Header />
๋ฅผ <Layout />
์ ์์์ผ๋ก ์ํ์ด๋ ๋ค๋ฅธ ์๋ฃจ์
์ผ๋ก ์ฃผ์
ํด์ผ ํฉ๋๋ค. ๊ทธ๋ฆฌ๊ณ ์ฌ์ฉํ๋ ค๋ ๋ชจ๋ ํ์ด์ง์ <Header />
์ฃผ์
์ ๋ฐ๋ณตํด์ผ ํฉ๋๋ค.
HOC ์ ๊ทผ ๋ฐฉ์ ์ ์ฌ์ฉํ๋ฉด <Header />
ํ ๋ฒ๋ง ์ถ๊ฐํ๋ฉด ๋ฉ๋๋ค.
๊ทธ๋์ ๊ฐ๋ฅํ ํ ์ฝ๋ ์ค๋ณต์ ํผํ๊ธฐ ์ํด @pkral78 ์์ ์ ๊ธฐํ ๊ฒ์ด ์ข์ ์ง์ ์ด๋ผ๊ณ ์๊ฐํ ์ด์ ์ ๋๋ค.
๊ทธ๋์ ๊ฐ๋ฅํ ํ ์ฝ๋ ์ค๋ณต์ ํผํ๊ธฐ ์ํด @pkral78 ์์ ์ ๊ธฐํ ๊ฒ์ด ์ข์ ์ง์ ์ด๋ผ๊ณ ์๊ฐํ ์ด์ ์ ๋๋ค.
๊ทธ๊ฒ์ ๋ด ๋ง์์ ์์๋ค. _app ํ์ด์ง์๋ ์ฒซ ๋ฒ์งธ ํ์ด์ง ๋ ๋๋ง ์ค์ ํ ๋ฒ ํธ์ถ๋ ๋ค์ ์ ์ฅ๋ props
๋ฅผ ๋ค์ ๋ ๋๋ง๋ ํ์ด์ง๋ก ์ ๋ฌํ๋ getStaticProps
์์ด์ผ ํฉ๋๋ค. ๊ทธ๋ฌ๋ ๋๋ ๊ทธ๊ฒ์ด ๊ณผ์ฐ ์ ์ ํ ๊ฐ๋
์ธ์ง์ ๋ํด ์ฌ์ ํ ์๊ฐํ๊ณ ์๋ค.
์ด๋ฐ ์ข ๋ฅ์ ๊ฒ์ด ์๋๋ ์ฌ์ฉ ์ฌ๋ก์ธ์ง ํ์คํ์ง ์์ง๋ง ์๋ํ์ง ์๋ ๊ฒ ๊ฐ์ต๋๋ค.
// /pages/[...slug].jsx
import ReactDOMServer from "react-dom/server";
export async function unstable_getStaticProps({ params: { slug } }) {
const filePath = "../content/" + slug.join("/") + ".mdx";
const { default: Component } = await import(filePath);
const content = ReactDOMServer.renderToStaticMarkup(<Component />);
return {
props: { title: slug.join(" "), content }
};
}
export default function Page({ title, content }) {
return (
<div>
<h1>{title}</h1>
<div dangerouslySetInnerHTML={{ __html: content }} />
</div>
);
}
์๋๋ ์ฌ์ฉ ์ฌ๋ก๊ฐ ์๋๋๋ผ๋ ์ฝ๊ฐ ์์ฌ์ค๋ฌ์ด ์ค๋ฅ๋ฅผ ๊ธฐ๋กํฉ๋๋ค.
[ warn ] ./pages/[...slug].jsx
Critical dependency: the request of a dependency is an expression
ํธ์งํ๋ค:
์ค, ๊ทธ๋, ๋ด๊ฐ ํ ๋ ํด๊ฒฐ๋๋ค
const { default: Component } = await import(`../content/${slug.join("/")}.mdx`);
์ด๊ฒ์ ๊ฐ์ ธ์ค๊ธฐ ํ์ผ ๊ฒฝ๋ก๊ฐ ๋์ ์ด๋ผ๋ ๋ถํ์ ๋๋ค.
2020๋ 1์ 30์ผ ๋ชฉ์์ผ 00:29์ Jan Potoms [email protected]์์ ๋ค์๊ณผ ๊ฐ์ด ์ผ์ต๋๋ค.
์ด๋ฐ ์ผ์ธ์ง ํ์คํ์ง ์๋ค.
https://codesandbox.io/s/nifty-cache-jspqr ์ ์๋๋ ์ฌ์ฉ ์ฌ๋ก์ด์ง๋ง
์๋ํ์ง ์๋ ๊ฒ ๊ฐ์ต๋๋ค.// /pages/[...slug].jsximport ReactDOMServer from "react-dom/server";
๋น๋๊ธฐ ํจ์ ๋ด๋ณด๋ด๊ธฐ ๋ถ์์ _getStaticProps({ params: { ์ฌ๋ฌ๊ทธ } }) {
// ์ด๊ฒ์ด ์ผ๋ง๋ ์์ ํ๊ฐ?
const ํ์ผ ๊ฒฝ๋ก = "../๋ด์ฉ/" + slug.join("/") + ".mdx";
const { ๊ธฐ๋ณธ๊ฐ: ๊ตฌ์ฑ ์์ } = import(filePath)๋ฅผ ๊ธฐ๋ค๋ฆฝ๋๋ค.
const ๋ด์ฉ = ReactDOMServer.renderToStaticMarkup(๊ตฌ์ฑ ์์);
๋ฐํ {
์ํ: { ์ ๋ชฉ: slug.join(" "), ์ฝํ ์ธ }
};
}
๊ธฐ๋ณธ ํจ์ ๋ด๋ณด๋ด๊ธฐ ํ์ด์ง({ ์ ๋ชฉ, ๋ด์ฉ }) {
๋ฐํ ({์ ๋ชฉ}
);
}์๋ํ ์ฌ์ฉ ์ฌ๋ก๊ฐ ์๋๋๋ผ๋ ๋ค์๊ณผ ๊ฐ์ ์ค๋ฅ๋ฅผ ๊ธฐ๋กํฉ๋๋ค.
์ฝ๊ฐ ์์ฌ์ค๋ฌ์ด:[๊ฒฝ๊ณ ] ./pages/[...slug].jsx
์ค์ ์ข ์์ฑ: ์ข ์์ฑ ์์ฒญ์ ํํ์์ ๋๋ค.โ
๋น์ ์ด ์ธ๊ธ๋์๊ธฐ ๋๋ฌธ์ ์ด๊ฒ์ ๋ฐ๋ ๊ฒ์ ๋๋ค.
์ด ์ด๋ฉ์ผ์ ์ง์ ๋ต์ฅํ๊ณ GitHub์์ ํ์ธ
https://github.com/zeit/next.js/issues/9524?email_source=notifications&email_token=AAADKRKOL34WKTG7J5QFRJ3RAIGPBA5CNFSM4JRPBEL2YY3PNVWWK3TUL52HS4DFVREXG43VMXHJKTNMV0
๋๋ ๊ตฌ๋ ์ทจ์
https://github.com/notifications/unsubscribe-auth/AAADKRIWNA2DSMWFRGD453DRAIGPBANCNFSM4JRPBELQ
.
๊ทธ๋์ ๊ฐ๋ฅํ ํ ์ฝ๋ ์ค๋ณต์ ํผํ๊ธฐ ์ํด @pkral78 ์์ ์ ๊ธฐํ ๊ฒ์ด ์ข์ ์ง์ ์ด๋ผ๊ณ ์๊ฐํ ์ด์ ์ ๋๋ค.
๊ทธ๊ฒ์ ๋ด ๋ง์์ ์์๋ค. _app ํ์ด์ง์๋ ์ฒซ ๋ฒ์งธ ํ์ด์ง ๋ ๋๋ง ์ค์ ํ ๋ฒ ํธ์ถ๋ ๋ค์ ์ ์ฅ๋
props
๋ฅผ ๋ค์ ๋ ๋๋ง๋ ํ์ด์ง๋ก ์ ๋ฌํ๋getStaticProps
์์ด์ผ ํฉ๋๋ค. ๊ทธ๋ฌ๋ ๋๋ ๊ทธ๊ฒ์ด ์ ์ ํ ๊ฐ๋ ์ธ์ง ์ฌ์ ํ ์๊ฐํ๊ณ ์์ต๋๋ค.
@pkral78 , ๋ด๊ฐ ์์ํ๋ ๋๋ถ๋ถ์ SSG ์ฌ์ดํธ์์ Next๋ก ๊ตฌํ
๋ด ์ ์ผํ ๊ด์ฌ์ฌ๋ _app.js
๋ฃ์ผ๋ฉด ํ์ด์ง์ ๋ฐ๋ผ ํ๋ ์ด์์ "๊ณตํต ๋ถ๋ถ"์ ๊ฐ์ง ์ ์๋ค๋ ๊ฒ์
๋๋ค. ๋ด๊ฐ ํ๋กํ ํ์
์ ๋ง๋ค๊ณ ์๋ค๋ ์์ด๋์ด๋ก ๋ ์ด์์์ ํฌํจํ ์ ์๊ธฐ๋ฅผ ์ํ์ต๋๋ค. ๋ ๋๋งํ๋ ค๋ ํ์ด์ง ์ ํ์ ๋ฐ๋ผ ์ฌ๋ฌ ๋ ์ด์์์ ๊ฐ์ง ์ ์๊ธฐ ๋๋ฌธ์
๋๋ค. "๊ทธ๋์ withSSGLayout
๋ฅผ ํธ์ถํ์ต๋๋ค. ๋ด HOC๋ SSG ํ์ด์ง๋ฟ๋ง ์๋๋ผ SSR๊ณผ ์์ ํ ํด๋ผ์ด์ธํธ ๊ธฐ๋ฐ ํ์ด์ง, ๋๋ ํ๋ ์ด์์ SSGLayout์ ๊ฐ์ง ๊ณํ์ด์๊ธฐ ๋๋ฌธ์ ๋ ์ด์์์ด ์์ getStaticProps
๋ฉ์๋๋ ๋ด๋นํ ์ ์๋ค๋ฉด ์ด ์์
์ ์ํํ ์ ์์ต๋๋ค.
์ด์จ๋ Next์ SSG๊ฐ ์์ผ๋ฉด ๋ชจ๋ ์ข ๋ฅ์ ์น ์ฌ์ดํธ๋ฅผ ์ํ ๋๊ตฌ๊ฐ ๋ฉ๋๋ค ๐
@Janpot ๊ด๋ จ https://github.com/zeit/next.js/issues/9524#issuecomment -580012327
import()
์์ ๋์ ๊ฒฝ๋ก๋ฅผ ์ฌ์ฉ ํ์ง ์๋ ๊ฒ์ด ์ข์ต๋๋ค. ๊ฒฝ๋ก ์๋์ ์๋ ๋ชจ๋ ๊ฐ๋ฅํ ํ์ผ์ JS ๋ฒ๋ค๋ก ๋ฌถ๊ณ ๊ทธ๋ ๊ฒ ํ๋ฉด ๋น๋ ์ฑ๋ฅ์ด ํฌ๊ฒ ์ ํ๋ฉ๋๋ค.
@timneutkens ๋ฌผ๋ก ์ด์ฃ . ์ดํด๊ฐ ๋ฉ๋๋ค. getStaticProps
๋ ํ์ผ ์์คํ
์ด ์๋ ์ธ๋ถ API๋ฅผ ์ฟผ๋ฆฌํ๊ธฐ ์ํ ๊ฒ์
๋๊น?
@Janpot ํ์ผ ์์คํ ์์ ์ฝ์ ์ ์์ง๋ง ์ข ์ข ์ธ๋ถ API๋ฅผ ์ฟผ๋ฆฌํ๊ฒ ๋ฉ๋๋ค.
@timneutkens ์ข์์, @next/mdx
์ ์์กดํ๋ ๋์ @mdx-js/runtime
๋ฅผ ์ฌ์ฉํ๋ ๊ฒ์ด ๋ ์ข์ต๋๋ค.
import ReactDOMServer from "react-dom/server";
import { promises as fs } from "fs";
import MDX from "@mdx-js/runtime";
export async function unstable_getStaticProps({ params: { slug } }) {
const mdxContent = await fs.readFile(`./content/${slug.join('/')}.mdx`, {
encoding: "utf-8"
});
const content = ReactDOMServer.renderToStaticMarkup(<MDX>{mdxContent}</MDX>);
return {
props: { title: slug.join(" "), content }
};
}
export default function Page({ title, content }) {
return (
<div>
<h1>{title}</h1>
<div dangerouslySetInnerHTML={{ __html: content }} />
</div>
);
}
@์ํ ๋ค! ์ผ๋ฐ ๋งํฌ๋ค์ด์ ์ฌ์ฉํ ์๋ ์์ต๋๋ค. ์ด๊ฒ์ด ์ฐ๋ฆฌ๊ฐ nextjs.org/docs์์ ํ๋ ์ผ์ ๋๋ค.
https://github.com/zeit/next.js/issues/9524#issuecomment -580207073์ ๊ดํด์๋ ํ์ฌ SSR๊ณผ ํจ๊ป Next๋ฅผ ์ฌ์ฉํ๋ ๊ฒ๊ณผ ๋์ผํฉ๋๋ค. ๋ ์ด์์ ์์ค์์ ์ํ๋๋ GraphQL ์์ฒญ์ด ์์ผ๋ฉฐ ํด๋น ์ฝํ ์ธ ๋ ์ฑ์ ๊ณตํต ๊ตฌ์ฑ ์์(Navbar, ๋ฐ๋ฅ๊ธ ๋ฐ ๋์ ์์)์ ๊ณต์ ๋ฉ๋๋ค. ๊ทธ๋ฐ ๋ค์ ๋์ ์์์ ์ผ๋ฐ์ ์ผ๋ก ํ์ด์ง๋ณ ์ฝํ ์ธ ์ ๋ํด ๋ ๋ค๋ฅธ GraphQL ์์ฒญ์ ํฉ๋๋ค.
๋ฐ๋ผ์ ์ด๊ฒ์ ์ฌ์ฌ์ฉํ๋ ๋ฐฉ๋ฒ์ด ์ค์ํด ๋ณด์ ๋๋ค. ์ ๋ ์ด๋ฌํ ๊ณตํต ๋ฐ์ดํฐ๋ฅผ ๊ฐ์ ธ์ค๊ธฐ ์ํด ๊ฐ ํ์ด์ง์ ์ฝ๋๋ฅผ ๋ณต์ ํ๊ณ ์ถ์ง ์์ ๊ฒ์ ๋๋ค.
์ด๋ด!
๋๋ ์ฌ๊ธฐ์์ ์์ฃผ ์๋กญ๋ค. ์ฑ์ NextJS๋ก ๋ง์ด๊ทธ๋ ์ด์
ํ๋ ์์
์ ๋ง ์์ํ์ต๋๋ค.
์ด ๊ธฐ๋ฅ์ ์ด์ ์ ์ป์ ์ ์๋ ๊ธฐ๋ณธ ์ฌ์ฉ ์ฌ๋ก๊ฐ ์์ต๋๋ค(๋ค๊ตญ์ด ๋ฒ์ ). ๋ด๊ฐ ์์ ํ๊ณ ์๋ ์น ์ฑ์๋ ํ๋ฃจ์ 100,000ํ ์ด์์ ํ์ด์ง ์กฐํ์๊ฐ ์๋ 16๊ฐ ์ธ์ด ๋ฒ์ ์ด ์์ผ๋ฉฐ ์๋ฅผ ๋ค์ด ๋ฐฉ๋ฌธ ํ์ด์ง๋ฅผ ์ ์ ์ผ๋ก ์์ฑํ ์ ์๋ค๋ ๊ฒ์ ํ์์ ์ด์ง๋ง ๋ฌธ์ ๋ ๋ผ์ฐํ ์ ๋๋ค.
์๋ฒ ์ธก ๋ ๋๋ง์ ์ฌ์ฉํ๋ฉด ์์ฒญ ํค๋ ๋๋ ์ฟ ํค๋ฅผ ์ฝ๊ณ ์ ์ ํ ์ธ์ด ๋ฒ์ ์ ๋ ๋๋งํ ์ ์์ง๋ง ๊ทธ๊ฒ ์์ด๋ /en, /de, /fr ๋ฐ "/"์ ๊ฐ์ ๋ชจ๋ ๋ฒ์ ์ ๋ํ ๊ฒฝ๋ก๋ฅผ ์์ฑํ๊ณ NextJS๊ฐ ๋ฆฌ๋๋ ์ ๋ง ํ๋๋ก ๋ง๋๋ ์ ์ผํ ์๋ฃจ์ ์ ๋๊น?
ReactDOMServer.renderToStaticMarkup
์ ๋ํด ๋ฐฐ์ด ํ ์ด๋ฅผ unstable_getStaticProps
ํจ์์ ์ถ๊ฐํ์ผ๋ฉฐ ๋ํํ ์๊ฐ ๋ฐ ์ต๋ ์ ์ฌ์ ์ธ ์ฒซ ์
๋ ฅ ์ง์ฐ ์๊ฐ์ ๋ํญ ๊ฐ์ ํ ๋๋ถ์ (๋ชจ๋ฐ์ผ) PageSpeed โโ์ ์๊ฐ 96์์ 100์ผ๋ก ํฅ์๋์์์ ์์์ต๋๋ค. .
JavaScript ์์ด ํ์ด์ง๋ฅผ ๋ฐฉ๋ฌธํ ์ ์๊ณ ์ ๋ก๋๋๋ฏ๋ก SSG๋ฅผ ์ฌ์ฉํจ์๋ ๋ถ๊ตฌํ๊ณ React๊ฐ ํ์ด์ง ๋ก๋ ์์ ์ ์ํํ๋ ๊ฒ์ผ๋ก ๋ณด์ ๋๋ค.
์ด๊ฒ์ React์ ๋ํ ์ดํด๊ฐ ๋ถ์กฑํ ๊ฒ์ผ ์๋ ์์ง๋ง JavaScript๋ฅผ ์ฌ์ฉํ๊ฑฐ๋ ์ฌ์ฉํ์ง ์๋ ์ฑ๋ฅ์ ๋์ผํ ๊ฒ์ผ๋ก ์์ํ๊ณ ๊ตฌ์ฑ ์์๋ฅผ ์ฌ์ ๋ ๋๋งํ๋ ๊ฒ์ด ๋์์ด ๋ ๊ฒ์ด๋ผ๊ณ ๊ธฐ๋ํ์ง ์์ต๋๋ค(SSG๊ฐ ํ๋ ์ผ์ด๋ผ๊ณ ์๊ฐํ์ต๋๋ค).
์์ํ ๊ฒ์ ๋๊น, ๋ฒ๊ทธ์ ๋๊น, ์๋๋ฉด ์ ๊ฐ ์๋ชปํ๊ณ ์๋ ๊ฒ์ ๋๊น?
์ฌ์ ์ปค๋ฐ: https://developers.google.com/speed/pagespeed/insights/?url=https%3A%2F%2F5e310826bcf5030008a91209--josephduffynextjs.netlify.com%2Fposts%2Fgathered-1-0-1&tab=mobile
์ปค๋ฐ: https://github.com/JosephDuffy/josephduffy.co.uk/pull/54/commits/d23898b874e5088ebcfabf577ee396b476ed97e4
์ปค๋ฐ ํ: https://developers.google.com/speed/pagespeed/insights/?url=https%3A%2F%2F5e3371beda1b8f0009368ef9--josephduffynextjs.netlify.com%2Fposts%2Fgathered-1-0-1&tab=mobile
@JosephDuffy
๋ฐ๋ผ์ React๋ SSG๋ฅผ ์ฌ์ฉํจ์๋ ๋ถ๊ตฌํ๊ณ ํ์ด์ง ๋ก๋ ์์ ์ ์ํํ๋ ๊ฒ์ผ๋ก ๋ณด์ ๋๋ค.
DOM์ ์๋ถ์ ๊ณต๊ธํ๊ณ ์์ต๋๋ค. ์๋:
๋ถ์์ฉ์ด๋ ์ด๋ฒคํธ ํธ๋ค๋ฌ๊ฐ ์๋ ๊ฒ์ฒ๋ผ ์ฝํ
์ธ ๊ฐ ์ง์ ์ผ๋ก ์ ์ ์ด๋ผ๋ฉด 2๋จ๊ณ์ 3๋จ๊ณ๋ ํ์ํ์ง ์์ต๋๋ค. ๊ทํ์ ๋ฐฉ๋ฒ์ ์ฌ์ฉํ๋ฉด ๊ธฐ๋ณธ์ ์ผ๋ก ๊ตฌ์ฑ ์์ ํธ๋ฆฌ๋ฅผ 1 ์์ฑ์ ๊ฐ์ง 1 ๊ตฌ์ฑ ์์๋ก ์ค์
๋๋ค. ์ด๋ React๊ฐ ๋ ๋๋งํ๊ณ ์ํํ๋ ๋ฐ ๋งค์ฐ ๋น ๋ฆ
๋๋ค. (+ dangerouslySetInnerHTM
๋ ์ํ ์ค ๋ฌด์)
<div dangerouslySetInnerHTML={{ __html: props.htmlContent }} />
์ด๋ฒคํธ ํธ๋ค๋ฌ์ ๋ถ์์ฉ์ ์ด ๋ฐฉ๋ฒ์ผ๋ก ์๋ํ์ง ์์ต๋๋ค.
ํธ์งํ๋ค:
ํ ๊ฐ์ง ์์ด๋์ด๋ getStaticProps
๊ฐ ์ ์ html์ ๋ฐํํ๋ ๊ฒฝ์ฐ ํ์ด์ง์์ ๊ธฐ๋ณธ ๋ด๋ณด๋ด๊ธฐ๋ฅผ ์๋ตํ ์ ์๋๋ก ํ๋ ๊ฒ์
๋๋ค. ์ฆ
export async function unstable_getStaticProps() {
// ...
return {
props: { dangerouslySetInnerHTML: { __html: '<div>static content</div>' } }
};
}
ํด๋ผ์ด์ธํธ ์ธก์์ ๋ ๋๋งํ ํ์๊ฐ ์๊ธฐ ๋๋ฌธ์ next.js๋ ํ์ด์ง์์ ๋ฐํ์์ ์ ์ธํ๊ณ getStaticProps
๋ฐํํ html์ ์ธ๋ผ์ธํ ์ ์์ต๋๋ค. ๊ทธ๋ฆฌ๊ณ next.js ๋ฃจํธ ๋
ธ๋์์ dangerouslySetInnerHTML
๊ฐ ์ฌ์ฉ๋ ๊ฒ๊ณผ ๊ฐ์ ๋ฐฉ์์ผ๋ก ์๋ํฉ๋๋ค.
๋๋ ๊ทธ๊ฒ์ด ๋ ๊ฐ๋ ฅํ์ง๋ง ๋ถ๋ถ์ ์ธ ์ํ๋ณด๋ค ๊ตฌํํ๊ธฐ๊ฐ ๋ ์ฌ์ธ ๊ฒ์ด๋ผ๊ณ ์๊ฐํฉ๋๋ค. ์ฌ๊ธฐ์์ React ์์ฒด์ ์ฉ์ด๋ฅผ ์ฌ์ฌ์ฉํ๋ฉด ์ด ๊ธฐ๋ฅ์ด ์๋ํ๋ ๋ฐฉ์์ ๋ํ ํผ๋์ ์ค์ผ ์ ์์ต๋๋ค.
์ ์ ์ฌ์ดํธ๋ฅผ Next.js๋ก ๋ง์ด๊ทธ๋ ์ด์
ํ๋ ค๊ณ ํ๋ฉฐ ๋ธ๋ก๊ทธ ๊ฒ์๋ฌผ์ ๋ชจ๋ .html ๋ณํ์ .html๋ก ๋๋์ง ์๋ ๋ฒ์ ์ผ๋ก ๋ฆฌ๋๋ ์
ํ๊ณ ์ถ์ต๋๋ค. getStaticProps
ํ์ฌ ์ปจํ
์คํธ๋ฅผ ์ป์ง ๋ชปํ๋ ๊ฒ ๊ฐ์์ ๋ค์ด์ค๋ ์ฌ๋ฌ๊ทธ ๋ฐ ๋ฆฌ๋๋ ์
์ ํ์ธํ ์ ์์ต๋๋ค. getStaticProps
์ ์ ์ฒด ์ปจํ
์คํธ๊ฐ ์์ผ๋ฏ๋ก ์กฐ๊ฑด๋ถ ์์
์ ์ํํ ์ ์์ผ๋ฉด ๋์์ด ๋ฉ๋๋ค.
@nodabladam ์ฌ์ฉ์ ์ง์ ๊ฒฝ๋ก RFC: #9081์ ์ฐพ๊ณ ์๋ ๊ฒ ๊ฐ์ต๋๋ค.
ํด๋น RFC๋ฅผ ์ฌ์ฉํ๋ฉด ๋ค์๊ณผ ๊ฐ์ด ์ ์ํ ์ ์์ต๋๋ค.
// next.config.js
module.exports = {
redirects() {
return [
// Redirect from the old HTML version of a blog post
{
source: "/blog/:post.html",
destination: "/blog/:post",
permanent: true
}
];
}
};
ํ์ฌ experimental
ํค์์ ์ด ๊ธฐ๋ฅ์ ์ฌ์ฉํด ๋ณผ ์ ์์ต๋๋ค.
// next.config.js
module.exports = {
experimental: {
redirects() {
// ...
}
}
};
๋ด ํ๋ก์ ํธ(์ฝ 8K ํ์ด์ง)์ getStaticProps ๋ฐ getStaticPathNames๋ฅผ ๊ตฌํํ์ต๋๋ค.
๊ทธ๋ฌ๋ ์ถ๋ ฅ ํ์ผ์ ๋ฐฐํฌ๋น ํ์ผ์ 10K ์ ํ์ ํฌํจ๋ฉ๋๋ค. 8K ํ์ด์ง์ ๊ฒฝ์ฐ ๊ฐ ํ์ด์ง์ json ํ์ผ๋ ์์ผ๋ฏ๋ก 16K์ ์ถ๋ ฅ ํ์ผ์ ์ป์ ์ ์์ต๋๋ค.
์ด ํ๋๋ฅผ ๋๋ฆด ๊ณํ์ด ์์ต๋๊น? ์๋๋ฉด ์ด ์ ํ์ ํด๊ฒฐํ ์ ์์ต๋๊น?
๋๋ ๊ฐ์ ๋ฌธ์ ๋ฅผ ์๊ณ ์์ด.
๊ทธ๋ค์ด ๊ทธ ํ๋๋ฅผ ๋์ด๋ ค๊ณ ํ๋ค๋ ๊ฒ์ ์ดํดํ์ง๋ง ์ธ์ ๋ฐฐํฌ๋ ์ง๋ ๋ชจ๋ฆ
๋๋ค.
๊ทธ๋์ ์ ๋ ๋ชจ๋ ํ์ด์ง์์ getStaticProps๋ฅผ ์ฌ์ฉํ๊ณ ๊ทธ ์ค ์ผ๋ถ์์๋ง getStaticPaths๋ฅผ ์ฌ์ฉํ๋ฉฐ ์๋ํฉ๋๋ค(์ ์ ํ ํ์ด์ง๋ ์ ์ฒด ํ์ด์ง์ 70%๋ฅผ ์์ฑํ๋ฏ๋ก getStaticPaths๋ฅผ ๋ฃ์ง ์์์ต๋๋ค). ํ๋์ ๋จธ๋ฌผ๊ณ ์์ง๋ง ์๋ฒฝํ์ง ์๊ณ ์ฒซ ๋ฒ์งธ๋ก๋๊ฐ ์๋นํ ๊ธธ๊ณ 404 ์ค๋ฅ๋ฅผ ์ฒ๋ฆฌํ๊ธฐ๊ฐ ์ด๋ ต์ต๋๋ค.
๋๋ ๊ฐ์ ๋ฌธ์ ๋ฅผ ์๊ณ ์์ด.
๊ทธ๋ค์ด ๊ทธ ํ๋๋ฅผ ๋์ด๋ ค๊ณ ํ๋ค๋ ๊ฒ์ ์ดํดํ์ง๋ง ์ธ์ ๋ฐฐํฌ๋ ์ง๋ ๋ชจ๋ฆ ๋๋ค.๊ทธ๋์ ์ ๋ ๋ชจ๋ ํ์ด์ง์์ getStaticProps๋ฅผ ์ฌ์ฉํ๊ณ ๊ทธ ์ค ์ผ๋ถ์์๋ง getStaticPaths๋ฅผ ์ฌ์ฉํ๋ฉฐ ์๋ํฉ๋๋ค(์ ์ ํ ํ์ด์ง๋ ์ ์ฒด ํ์ด์ง์ 70%๋ฅผ ์์ฑํ๋ฏ๋ก getStaticPaths๋ฅผ ๋ฃ์ง ์์์ต๋๋ค). ํ๋์ ๋จธ๋ฌผ๊ณ ์์ง๋ง ์๋ฒฝํ์ง ์๊ณ ์ฒซ ๋ฒ์งธ๋ก๋๊ฐ ์๋นํ ๊ธธ๊ณ 404 ์ค๋ฅ๋ฅผ ์ฒ๋ฆฌํ๊ธฐ๊ฐ ์ด๋ ต์ต๋๋ค.
๋๋ ๊ทธ๋ค์ด ๊ณง ํ๋๋ฅผ ์ฌ๋ฆฌ๊ธฐ๋ฅผ ํฌ๋งํ์ง๋ง ๊ทธ๊ฒ์ด 20K๊ฐ ์๋๊ธฐ๋ฅผ ๋ฐ๋๋๋ค. ์ฅ๊ธฐ์ ์ผ๋ก ๋์๊ฒ ์ถฉ๋ถํ์ง ์์ ๊ฒ์ ๋๋ค.
getStaticPaths๋ฅผ ์ฌ์ฉํ์ฌ ์ฒซ ๋ฒ์งธ ๋ก๋ ์๊ฐ์ ํผํ๊ณ ์ถ์ต๋๋ค. Zeit Now ์ธ์ ๋ค๋ฅธ ์๋ฃจ์ ์ ์ฐพ์์ผ ํ ์๋ ์์ต๋๋ค.
Next.js๋ getServerProps ํธ์ถ ๊ฒฐ๊ณผ๋ฅผ ๋ฐํํ๋ API ๋์ ๋ ์๋์ผ๋ก ๋ ธ์ถํฉ๋๋ค. [...] Next.js๋ ์ด ๋ ธ์ถ๋ API ๋์ ์ ๊ฐ์ ธ์ ํ์ด์ง ํด๋ผ์ด์ธํธ ์ธก์ ๋ ๋๋งํ๋ ๋ฐ ํ์ํ ์ํ์ผ๋ก ๋ณํ๋๋ JSON ๋ฐ์ดํฐ๋ฅผ ๊ฐ์ ธ์ต๋๋ค.
Next.js๋ ์ค์ ๊ฒฝ๋ก ๋ณ๊ฒฝ์ ์ํํ๊ณ ํ์ด์ง ๊ตฌ์ฑ ์์๋ฅผ ๋ ๋๋ง ํ๊ธฐ ์ ์ ์ด ๋์ ์์ ๋ฐ์ดํฐ๋ฅผ ๊ฐ์ ธ์ต๋๋ค(์ ์ด๋ ๊ธฐ๋ณธ์ ์ผ๋ก ๋ค๋ฅธ ๋ฐฉ๋ฒ์ผ๋ก๋ ์ํํ ์ ์์). ๋ฐ๋ผ์ ์ฌ์ฉ์๋ ํน์ ํ์ด์ง๊ฐ ์ ์ ์ผ๋ก ์์ฑ๋์ด ๋งค์ฐ ๋น ๋ฅธ ์ฌ์ดํธ๋ฅผ ๊ฒฝํํ ์ ์์ง๋ง SSR ํ์ด์ง์ ๋ํ ๋งํฌ๋ฅผ ํด๋ฆญํ๋ฉด ๊ฒฝ๋ก๊ฐ ๋ณ๊ฒฝ๋๊ธฐ ์ ์ ๊ฐ์๊ธฐ ์ฌ์ดํธ๊ฐ ์ ์ "๋ฉ์ถค"๋ฉ๋๋ค.
๋ก๋ ํ์๊ธฐ, ์ ๋๋ฉ์ด์ ์๋ฆฌ ํ์์ ๋ฑ์ผ๋ก ์ฑ์ธ ์ ์๋๋ก ๊ตฌ์ฑ ์์ _first_๋ฅผ ๋ก๋ํ๋ ๊ถ์ฅ ๋ฐฉ๋ฒ์ด ์์ต๋๊น? (ํ์ฌ ํ์ด์ง์ ์ถ๊ฐํ๋ ๋์ .) ๊ทธ๋ ์ง ์๋ค๋ฉด ์๋ก ์ ์๋ ๊ธฐ๋ฅ๊ณผ ๊ด๋ จ์ด ์์ ์ ์์ต๋๊น? render ๋ฉ์๋ ๋ด๋ถ์ getInitialProps์ hooks ์กฐํฉ์ ์ฌ์ฉํ์ฌ ๋ฌ์ฑํ์ง๋ง ์ง์ ๋ถํ ๋๋์ด ๋ญ๋๋ค.
๋ง์ ์ฌ๋๋ค์ด ์ด UX ํจํด(์ฆ์ ํ์ด์ง ์ ํ)์ ์ ํธํ๋ค๊ณ ์๊ฐํ์ง๋ง(๋๋ถ๋ถ?) Next.js๋ฅผ ์ฌ์ฉํ๋ ์์ ๋ ์์ง ๋ณธ ์ ์ด ์์ต๋๋ค. ํ๋ ์์ํฌ๋ฅผ ์ฌ์ฉํ์ง ๋ฉฐ์น ๋์ง ์์์ผ๋ ํ๋ฆฐ ๋ถ๋ถ์ด ์์ผ๋ฉด ์ง์ ๋ถํ๋๋ฆฝ๋๋ค.
์๋ก์ด ๊ธฐ๋ฅ์ด ์ ๋ง ๊ธฐ๋๋ฉ๋๋ค! ์์ ํด์ฃผ์ ์ ๊ฐ์ฌํฉ๋๋ค.
@nicoqh , ํ์ฌ getInitialProps
์์ ์ค๋จ์ด ๋ฐ์ํ๊ธฐ ๋๋ฌธ์ ํ์ด์ง ์ ํ์ ๋ํ ๊ทํ์ ์ฐ๋ ค๋ SSG์๋ง ๊ตญํ๋์ง ์์ต๋๋ค. ๋๋ nprogress
๋ฅผ ์ฌ์ฉํ์ฌ ๋ค์ ํ์ด์ง๊ฐ ๋ก๋๋๋ ๋์ ์ต์ํ ๋งจ ์์ ์งํ๋ฅ ํ์์ค์ ํ์ํ์ง๋ง ์ค๋ช
ํ๋ ๋ด์ฉ์ ๋ ๊ฐ๊น๊ฒ ๋ค๋ฆฌ๋ ํฉ๋ฒ์ ์ธ ํ์ด์ง ์ ํ์ด ์๋ ์ด ์๋ ๋ด
๋๋ค. ๋๋ ๊ทธ๊ฒ์ ์ง์ ์๋ํ์ง ์์์ง๋ง ๋น์ ์ด ํ์๋กํ๋ ๊ฒ์ ๋์์ด๋๊ธฐ๋ฅผ ๋ฐ๋๋๋ค.
https://github.com/zeit/next.js/tree/canary/examples/with-next-page-transitions
๋ฐํ๋ json ํ์ผ /_next/data/BUILD_ID/<file>.json
์ด assetPrefix๋ฅผ ์กด์คํ์ง ์๋ ๊ฒ ๊ฐ์ต๋๋ค. ์ด๋ก ์ธํด ๋ด ํ๋ก๋์
ํ๊ฒฝ์์ ํ์ผ์ด 404๊ฐ ๋ฉ๋๋ค. ์๋ํ๋ฉด ๋ชจ๋ _next๊ฐ CDN์ ํต๊ณผํ๋ ์์ฐ์ด ๋ ๊ฒ์ผ๋ก ์์ํ๋ ์ค์ ์ด ์๊ธฐ ๋๋ฌธ์
๋๋ค. ์ด๋ฌํ json ํ์ผ์ ๊ถ๊ทน์ ์ผ๋ก assetPrefix(CDN)๋ฅผ ํตํด ๋ผ์ฐํ
๋์ด์ผ ํฉ๋๋ค. ๋ง๋์?
๋๋ ๊ฐ์ ๋ฌธ์ ๋ฅผ ์๊ณ ์์ด.
๊ทธ๋ค์ด ๊ทธ ํ๋๋ฅผ ๋์ด๋ ค๊ณ ํ๋ค๋ ๊ฒ์ ์ดํดํ์ง๋ง ์ธ์ ๋ฐฐํฌ๋ ์ง๋ ๋ชจ๋ฆ ๋๋ค.
๊ทธ๋์ ์ ๋ ๋ชจ๋ ํ์ด์ง์์ getStaticProps๋ฅผ ์ฌ์ฉํ๊ณ ๊ทธ ์ค ์ผ๋ถ์์๋ง getStaticPaths๋ฅผ ์ฌ์ฉํ๋ฉฐ ์๋ํฉ๋๋ค(์ ์ ํ ํ์ด์ง๋ ์ ์ฒด ํ์ด์ง์ 70%๋ฅผ ์์ฑํ๋ฏ๋ก getStaticPaths๋ฅผ ๋ฃ์ง ์์์ต๋๋ค). ํ๋์ ๋จธ๋ฌผ๊ณ ์์ง๋ง ์๋ฒฝํ์ง ์๊ณ ์ฒซ ๋ฒ์งธ๋ก๋๊ฐ ์๋นํ ๊ธธ๊ณ 404 ์ค๋ฅ๋ฅผ ์ฒ๋ฆฌํ๊ธฐ๊ฐ ์ด๋ ต์ต๋๋ค.๋๋ ๊ทธ๋ค์ด ๊ณง ํ๋๋ฅผ ์ฌ๋ฆฌ๊ธฐ๋ฅผ ํฌ๋งํ์ง๋ง ๊ทธ๊ฒ์ด 20K๊ฐ ์๋๊ธฐ๋ฅผ ๋ฐ๋๋๋ค. ์ฅ๊ธฐ์ ์ผ๋ก ๋์๊ฒ ์ถฉ๋ถํ์ง ์์ ๊ฒ์ ๋๋ค.
getStaticPaths๋ฅผ ์ฌ์ฉํ์ฌ ์ฒซ ๋ฒ์งธ ๋ก๋ ์๊ฐ์ ํผํ๊ณ ์ถ์ต๋๋ค. Zeit Now ์ธ์ ๋ค๋ฅธ ์๋ฃจ์ ์ ์ฐพ์์ผ ํ ์๋ ์์ต๋๋ค.
@erhankaradeniz ๋ฐ @ziltosh ์ฐ๋ฆฌ๋ ์ผ๋ฐ์ ์ผ๋ก ๋งค์ฐ ๋น ๋ฅธ ์์ผ ๋ด์ ์ด๋ฅผ ์ถ์ ํด์ผ ํฉ๋๋ค. ์ต๋ํ ๋นจ๋ฆฌ ๋์์ ๋ฐ๊ณ ์ถ๋ค๋ฉด ์ ์๊ฒ ์ง์ ping์ ๋ณด๋ด ๊ฑฐ๋
๋๋ ๊ฐ์ ๋ฌธ์ ๋ฅผ ์๊ณ ์์ด.
๊ทธ๋ค์ด ๊ทธ ํ๋๋ฅผ ๋์ด๋ ค๊ณ ํ๋ค๋ ๊ฒ์ ์ดํดํ์ง๋ง ์ธ์ ๋ฐฐํฌ๋ ์ง๋ ๋ชจ๋ฆ ๋๋ค.
๊ทธ๋์ ์ ๋ ๋ชจ๋ ํ์ด์ง์์ getStaticProps๋ฅผ ์ฌ์ฉํ๊ณ ๊ทธ ์ค ์ผ๋ถ์์๋ง getStaticPaths๋ฅผ ์ฌ์ฉํ๋ฉฐ ์๋ํฉ๋๋ค(์ ์ ํ ํ์ด์ง๋ ์ ์ฒด ํ์ด์ง์ 70%๋ฅผ ์์ฑํ๋ฏ๋ก getStaticPaths๋ฅผ ๋ฃ์ง ์์์ต๋๋ค). ํ๋์ ๋จธ๋ฌผ๊ณ ์์ง๋ง ์๋ฒฝํ์ง ์๊ณ ์ฒซ ๋ฒ์งธ๋ก๋๊ฐ ์๋นํ ๊ธธ๊ณ 404 ์ค๋ฅ๋ฅผ ์ฒ๋ฆฌํ๊ธฐ๊ฐ ์ด๋ ต์ต๋๋ค.๋๋ ๊ทธ๋ค์ด ๊ณง ํ๋๋ฅผ ์ฌ๋ฆฌ๊ธฐ๋ฅผ ํฌ๋งํ์ง๋ง ๊ทธ๊ฒ์ด 20K๊ฐ ์๋๊ธฐ๋ฅผ ๋ฐ๋๋๋ค. ์ฅ๊ธฐ์ ์ผ๋ก ๋์๊ฒ ์ถฉ๋ถํ์ง ์์ ๊ฒ์ ๋๋ค.
getStaticPaths๋ฅผ ์ฌ์ฉํ์ฌ ์ฒซ ๋ฒ์งธ ๋ก๋ ์๊ฐ์ ํผํ๊ณ ์ถ์ต๋๋ค. Zeit Now ์ธ์ ๋ค๋ฅธ ์๋ฃจ์ ์ ์ฐพ์์ผ ํ ์๋ ์์ต๋๋ค.@erhankaradeniz ๋ฐ @Ziltosh ์ฐ๋ฆฌ๋ ์ผ๋ฐ์ ์ผ๋ก ๋งค์ฐ ๋น ๋ฅธ ์์ผ ๋ด์ ์ด๋ฅผ ์ถ์ ํด์ผ ํฉ๋๋ค. ์ต๋ํ ๋นจ๋ฆฌ ๋์์ ๋ฐ๊ณ ์ถ๋ค๋ฉด ์ ์๊ฒ ์ง์ ping์ ๋ณด๋ด ๊ฑฐ๋
@kvangundy ๊ฐ์ฌํฉ๋๋ค
์ด ๋ฌธ์ ์ ๊ด๋ จํ์ฌ Twitter์์ ์ฐ๋ฝ์ ๋๋ ธ์ต๋๋ค ;-)
@erhankaradeniz ๋์ [email protected]๋ก ์ด๋ฉ์ผ์
@flintinatux , ํ ์ฃผ์ ์ ๊ฐ์ฌํฉ๋๋ค. ์์ ๋ฅผ ๋ดค๋๋ฐ ๋ฐ์ดํฐ๋ฅผ ๋ก๋ํ๊ธฐ ์ ์ ํ์ด์ง ๊ตฌ์ฑ ์์๋ฅผ ๋ก๋ํ๋ ๋ฐ ๋์์ด ๋์ง ์์ผ๋ฏ๋ก ํ์ด์ง ๋ด ์๋ฆฌ ํ์์ ๋ฑ์ด ๋ถ๊ฐ๋ฅํฉ๋๋ค. ๊ทธ๋๋ ํฅ๋ฏธ๋ก์ด ์์ ๋๋ค. ๊ฐ์ฌํฉ๋๋ค!
์ด ๋ฌธ์ ์์๋ ๋ค๋ฃจ์ง ์์ ๊ฒ ๊ฐ์ต๋๋ค. ์ฆ, ์ฃผ์ ์์ ๋ฒ์ด๋ฌ์ผ๋ฏ๋ก ๋ ผ์ํ ๋ค๋ฅธ ๊ณณ์ ์ฐพ์๋ณด๊ฒ ์ต๋๋ค. :)
getInitialProps๋ฅผ getStaticProps
& getServerProps
๋ก ๋๋๋ ์ ๊ทผ ๋ฐฉ์์ด ํจ์ฌ ๊น๋ํ๋ค๊ณ ์๊ฐํฉ๋๋ค! ์ด๊ฒ์ด ์ฐ๋ฆฌ์ ์ฌ์ฉ ์ฌ๋ก์ ์ด๋ค ์ํฅ์ ๋ฏธ์น๋์ง ์ง๋ฌธ์ด ์์ต๋๋ค.
์ฐ๋ฆฌ๋ 2๊ฐ์ ๊ฐ๋ณ ๋น๋๋ฅผ ๋ง๋ค๊ณ ์ถ์ต๋๋ค. ํ๋๋ ํ๋ก๋์
์ฌ์ดํธ์ฉ ์ ์ ๋ฒ์ ์ด๊ณ ๋ค๋ฅธ ํ๋๋ ํธ์ง ํ๊ฒฝ์ฉ SSR์ ์ฌ์ฉํ๋ ๋ฒ์ ์
๋๋ค.
์กฐ๊ฑด๋ถ๋ก getStaticProps
vs getServerProps
๋ฅผ ๋น๋์ ๋ฐ๋ผ ์ ์ ๋ฉ์๋๋ก ์ฒจ๋ถํ ์ ์๋ค๊ณ ์๊ฐํ์ต๋๋ค(https://github.com/zeit/next.js/issues/9524#issuecomment-์ ์ ์ฌ). 558617056), ๊ทธ๋ฌ๋ ์ด๊ฒ์ด ์กฐ๊ฑด๋ถ๋ก ๊ทธ๋๋ก ๋ด๋ณด๋ผ ์ ์๋์ง ํ์คํ์ง ์์ต๋๋ค. ๋น๋์ ๋ฐ๋ผ ๋์ /์ ์ ์ ์ง์ํ ์ ์๋ค๋ฉด ์ด๋ค ์์ด๋์ด๊ฐ ์์ต๋๊น?
์ ๊ดํด์:
RFC๋ ๋์ค์ ๋ณ๊ฒฝ ์ฌํญ์ ๋ฐ์ํ๋๋ก ์ ๋ฐ์ดํธ๋๋ฉฐ ์ฑ์์ ์ค์ ์ฌ์ฉ์ ๊ณ์ ๋ฐ๋ณตํฉ๋๋ค.
๋น๋ ์ ์ ์ ์๋ ๊ฒฝ๋ก๋ฅผ ์ก๊ธฐ ์ํด ์ผ์ข ์ ์์ผ๋ ์นด๋ ๊ฒฝ๋ก๋ฅผ ์ฌ์ฉํ๋ ๋ฐฉ๋ฒ์ด ์๋์ง ๊ถ๊ธํฉ๋๋ค. ์๋ฅผ ๋ค์ด CMS ๋ฐ์ดํฐ์์ ์ ์ ํ์ด์ง๋ฅผ ๋ ๋๋งํ ์ ์๋ค๋ ๊ฒ์ ๋ฉ์ง ์ผ์ด์ง๋ง ๋๊ตฐ๊ฐ ์ ํญ๋ชฉ์ ์ถ๊ฐํ๋ฉด ์ด๋ป๊ฒ ๋ ๊น์? ๋๋ ๊ทธ๊ฒ์ ๋ํ ์ ์ ํ์ด์ง๊ฐ ์์ต๋๋ค. ์ด ๋ฌธ์ ๋ ์ค๋ซ๋์ ๋ด ๋จธ๋ฆฌ๋ฅผ ๊ธ์ ์ ๋๋ค.
์ ์ ํ์ด์ง _pages/[slug].js_๋ฅผ ๋ ๋๋งํ๊ธฐ ์ํด ๋์ ๊ฒฝ๋ก๋ฅผ ์ค์ ํ์ต๋๋ค. _getStaticPaths_๋ ์ ์ ์ผ๋ก ๋ ๋๋งํ๋ ค๋ ๋ชจ๋ ํ์ด์ง๋ฅผ ๊ฐ์ ธ์ต๋๋ค. _getStaticProps_๊ฐ ์์ด ๋ฐ์ดํฐ๋ฅผ ์ฟผ๋ฆฌํ๊ณ ์ด๋ฅผ ๋ ๋ ํจ์์ ์ ๋ฌํฉ๋๋ค. _getStaticPaths_์ ์ ๊ณต๋ ๋ชจ๋ ํ์ด์ง๋ ๋น๋ ์ _.next/server/static_ ๋ด๋ถ์์ HTML ํ์ผ๋ก ๋ ๋๋ง๋ฉ๋๋ค. ์์ฒญ๋!
์ด์ npm run start
๋ฐ ์ด ํ์ด์ง๋ฅผ ์คํํด์ผ ํฉ๋๋ค. ๊ทธ๋ฌ๋ ๋๋ฝ๋ URL(์: _/foo_)์ ์์ฒญํ๋ฉด _.next/server/static_ ๋ด๋ถ์ ์๋ก์ด ์ ์ HTML ๋ฐ JSON ํ์ผ์ด ์์ฑ๋ฉ๋๋ค. ์ด๊ฒ์ ์ข์ง ์๋ค. ๋ค๋ฅธ ๋ชจ๋ URL์ _pages/_error.js_๋ก ๋ฆฌ๋๋ ์
ํ๋๋ก ์๋ฒ๋ฅผ ๋ง๋ค๋ ค๋ฉด ์ด๋ป๊ฒ ํด์ผ ํฉ๋๊น?
https://github.com/zeit/next.js/issues/9524#issuecomment -582777067
์ฐ๋ฆฌ๋ ๊ทธ๊ฒ์ ๋ค๋ฃจ๊ณ ์์ต๋๋ค.
์ด์ npm run start ๋ฐ ์ด ํ์ด์ง๋ฅผ ์คํํด์ผ ํฉ๋๋ค. ๊ทธ๋ฌ๋ ๋๋ฝ๋ URL(์: /foo)์ ์์ฒญํ๋ฉด .next/server/static ๋ด๋ถ์ ์๋ก์ด ์ ์ HTML ๋ฐ JSON ํ์ผ์ด ์์ฑ๋ฉ๋๋ค. ์ด๊ฒ์ ์ข์ง ์๋ค. ๋ค๋ฅธ ๋ชจ๋ URL์ ํ์ด์ง/_error.js๋ก ๋ฆฌ๋๋ ์ ํ๋๋ก ์๋ฒ๋ฅผ ๋ง๋ค๋ ค๋ฉด ์ด๋ป๊ฒ ํด์ผ ํฉ๋๊น?
์ด๊ฒ์ ์ฌ์ ํ โโ์งํ ์ค์ด๋ฉฐ ํ์ฌ๋ก์๋ ์์์น ๋ชปํ ๋์์ด ์๋๋๋ค.
์คํ์ ์ธ ๊ธฐ๋ฅ์ ์ฌ์ฉ ์ค์ด๋ฉฐ ๋์์ ์ธ์ ๋ ์ง ๋ณ๊ฒฝ๋ ์ ์์์ ๋ค์ ํ ๋ฒ ์๋ ค๋๋ฆฝ๋๋ค. ์์ ์ ์ด์ง ์์ ๋ ์ด๊ฒ์ ์ฌ์ฉํ๋ ๋์ ๋ชจ๋ ๋ฒ์ ๊ฐ์ ์ํฉ์ด ๋ณ๊ฒฝ๋๊ณ ์ ์ฌ์ ์ผ๋ก ์ค๋จ๋ ์ ์์ต๋๋ค.
@timneutkens ๊ฐ์ฌํฉ๋๋ค! ๋ถ์์ ํจ์ ์ดํดํฉ๋๋ค. ์ด๊ฒ์ ๊ด๋ฆฌํ๋ ๋ฐฉ๋ฒ์ ์๊ณ ์์ต๋๊น? ์ฝ๋๋ฅผ ์ดํด๋ณด๊ณ _unstable_getStaticProps_ ๋ด๋ถ์ ์ค๋ฅ๋ฅผ ๋์ง๋ฉด ์ค๋ฅ ํ์ด์ง๊ฐ ๋ ๋๋ง๋๋ค๋ ๊ฒ์ ์์์ต๋๋ค. ์ด๊ฒ์ ์ข์ ๋ฐฉ๋ฒ์ด ๋ ์ ์์ต๋๋ค. _pages/_error.js_์ ์๋ ๊ทธ๋๋ก ์ค๋ฅ๋ฅผ ์ ๋ฌํ๋ ๋ฐฉ๋ฒ์ด ํ์ํฉ๋๋ค. 404๋ก ๋ณด๋ด๊ณ ์ถ์ต๋๋ค. ์ด์ 500์ผ๋ก ๊ฐ๋๋ค.
๋๋ ์ด๊ฒ์ ๋ค๋ฅธ ์ค๋ ๋์์ ์ฌ๋ฌ ๋ฒ ๊ฒ์ํ์ง๋ง "_error๋ก ๊ฐ๋ ๊ฒ"์ ์๊ธฐ์น ์์ ๋์์
๋๋ค. ํ์ฌ ๊ทํ์ ํ์ด์ง๋ 404 ์ํ๋ฅผ ๋ ๋๋งํด์ผ ํฉ๋๋ค. ๊ฐ๋จํ if(!data.something) { return <My404Component /> }
๋ผ๊ณ ๋งํ ๋ค์ My404Component
๋ noindex
๋ฉํ ํ๊ทธ๋ฅผ ์ค์ ํด์ผ ํฉ๋๋ค.
์ง์ง? ๋ฌธ์์๋ 404์ _pages/_error.js_๋ฅผ ์ฌ์ฉํ๋๋ก ๋ช ์๋์ด ์์ต๋๋ค.
์ฐธ์กฐ: https://nextjs.org/docs/advanced-features/custom-error-page
@jiv-e๋ ๋ค์์ผ๋ก ์ธํด 404์ด ๋์ ๋ฐ์ํฉ๋๋ค.
๋์ ๊ฒฝ๋ก๊ฐ ์๋ ๊ฒฝ์ฐ ๋ด๊ฐ ๋งํ ๊ฒ์ฒ๋ผ "404" ์ฌ๋ก๋ฅผ ์ฒ๋ฆฌํด์ผ ํฉ๋๋ค(์: https://nextjs.org/docs/advanced-features/custom-error-page#reusing -the-built-in-error-). ํ์ด์ง
์์์ด์! ๊ฐ์ฌ ํด์!
getStaticProps
๋ฅผ ์ฌ์ฉํ์ฌ ๋น๋ ์ ๋ฒ์ญ/์ธ์ด ํค๋ฅผ ๊ฐ์ ธ์ค๊ณ ์ถ์ต๋๋ค. ์๋ํ๋ฉด ๊ทธ๋ค์ ํ ๋ฌ์ 1-2๋ฒ ๋๋ ์ฌ์ง์ด ๋งค๋
๋ณ๊ฒฝ๋ ๊ฐ๋ฅ์ฑ์ด ๋๊ธฐ ๋๋ฌธ์
๋๋ค. ๋ํ DOM ๋ด์์ JSON/props๋ก ํ์ํ์ง ์์ต๋๋ค. ๋ฌธ์ ๋ ํค๋ฅผ ์ค์ ๋ก ์ฌ์ฉํ๋ ๊ตฌ์ฑ ์์๋ก ํธ๋ฆฌ ์๋๋ก ์ ๋ฌํ๊ณ ์ถ์ง ์๋ค๋ ๊ฒ์
๋๋ค. ์ฌ์ฉ ์ฌ๋ก์ ์ ํฉํ ์ ๊ทผ ๋ฐฉ์์ ๋ฌด์์
๋๊น?
์ปจํ ์คํธ๊ฐ ์๋ useTranslation() ํํฌ(๋๋ HOC)?
AppTree
๊ฐ NextGetStaticProps ์ปจํ
์คํธ( getStaticProps({ AppTree })
)์ ์ผ๋ถ๊ฐ ๋๋ฉด ์ข์ ๊ฒ์
๋๋ค. ๊ทธ๋ ์ง ์์ผ๋ฉด ssg์์ apollos getDataFromTree
์ ๊ฐ์ ๊ฒ์ ์คํํ ์ ์์ต๋๋ค.
์ด ์์ ์์ ์ฐ๋ฆฌ๋ getStaticProps์์ AppTree ํ์์ ํ์ฉํ์ง ์์ ๊ณํ์ ๋๋ค. ์ฑ๋ฅ์ ๋งค์ฐ ์ข์ง ์๊ธฐ ๋๋ฌธ์ ๋๋ค(ํ์ฌ์ ์ผ๊ด๋ ํผ๋๋ฐฑ). ํ์ด์ง์ getStaticProps๋ฅผ ์ถ๊ฐํ๋ฉด ์ฌ์ ํ _app์ getInitialProps๋ฅผ ํตํด ์ ์ง์ ์ฑํ์ ํ์ฉํ๋ฏ๋ก Apollo์ ์ฌ์ ํ ์๋ํฉ๋๋ค.
amp: 'hybrid'
์ SSG ๊ธฐ๋ฅ์ ๋์์ ๊ฐ์ง ์ ์๋ค๋ฉด ์ข์ ๊ฒ์
๋๋ค.
์ด๊ฒ์ ๋ค์๊ณผ ๊ฐ์ ํ์ด์ง์ ๋ํด ๋ ๊ฐ์ ํ์ผ์ ์์ฑํ์ฌ ๋ฌ์ฑํ ์ ์์ต๋๋ค.
์ด๋ ๊ฒ ํ๋ฉด ํ๋ก์๊ฐ ?amp=1
์ฟผ๋ฆฌ ๋งค๊ฐ๋ณ์๋ฅผ ๊ธฐ๋ฐ์ผ๋ก amp ๋ฌธ์๋ฅผ ํ์ธํ ์ ์์ต๋๋ค.
amp: 'hybrid'
์ SSG ๊ธฐ๋ฅ์ ๋์์ ๊ฐ์ง ์ ์๋ค๋ฉด ์ข์ ๊ฒ์ ๋๋ค.
์ด๊ฒ์ ๋ค์๊ณผ ๊ฐ์ ํ์ด์ง์ ๋ํด ๋ ๊ฐ์ ํ์ผ์ ์์ฑํ์ฌ ๋ฌ์ฑํ ์ ์์ต๋๋ค.
- (SSG) index.html
- (AMP) index.amp.html
์ด๋ ๊ฒ ํ๋ฉด ํ๋ก์๊ฐ
?amp=1
์ฟผ๋ฆฌ ๋งค๊ฐ๋ณ์๋ฅผ ๊ธฐ๋ฐ์ผ๋ก amp ๋ฌธ์๋ฅผ ํ์ธํ ์ ์์ต๋๋ค.
์ ํํ @Dacturne , ์ด๊ฒ์ ์ ๊ฐ ์ด ์ค๋ ๋ ์๊ฐ ์ ์ ์ธ๊ธํ๋ ๊ฒ์ฒ๋ผ ํ๋ก์ ํธ์์ ์ด๋ฏธ SSG๋ฅผ ์ฌ์ฉํ๊ธฐ ์์ํ๋ ์ ์ผํ ๋จ์ ์ ๋๋ค.
๐ค
@jansedlon ๊ทํ์ ์ง๋ฌธ์ ๋ํ ๋ธ๋ก๊ทธ ๊ฒ์๋ฌผ์ ์์ฑํ์ต๋๋ค.
๋น๋ ์ ์ ์ ์๋ ๊ฒฝ๋ก๋ฅผ ์ก๊ธฐ ์ํด ์ผ์ข ์ ์์ผ๋ ์นด๋ ๊ฒฝ๋ก๋ฅผ ์ฌ์ฉํ๋ ๋ฐฉ๋ฒ์ด ์๋์ง ๊ถ๊ธํฉ๋๋ค. ์๋ฅผ ๋ค์ด CMS ๋ฐ์ดํฐ์์ ์ ์ ํ์ด์ง๋ฅผ ๋ ๋๋งํ ์ ์๋ค๋ ๊ฒ์ ๋ฉ์ง ์ผ์ด์ง๋ง ๋๊ตฐ๊ฐ ์ ํญ๋ชฉ์ ์ถ๊ฐํ๋ฉด ์ด๋ป๊ฒ ๋ ๊น์? ๋๋ ๊ทธ๊ฒ์ ๋ํ ์ ์ ํ์ด์ง๊ฐ ์์ต๋๋ค. ์ด ๋ฌธ์ ๋ ์ค๋ซ๋์ ๋ด ๋จธ๋ฆฌ๋ฅผ ๊ธ์ ์ ๋๋ค.
https://paqmind.com/en/blog/ssr-is-not-the-future
(๋๋ฌด ์ปค์ ์ฌ๊ธฐ์ ์ฌ๋ฆฌ์ง ์์ต๋๋ค)
@ivan-kleshnin ๊ฐ๋จํ ์ดํด๋ณด์๋๋ฐ ์ ๋ง ํฅ๋ฏธ์ง์งํด ๋ณด์ ๋๋ค! ๋น์ ์ ๋์๊ฒ ์๋ฐฑ ์๊ฐ์ ์ ์ฝํ์ ์๋ ์์ต๋๋ค! ๊ฐ์ฌํฉ๋๋ค. ์ค๋์ ๋์ค์ ์์ธํ ์ดํด๋ณด๊ฒ ์ต๋๋ค.
https://github.com/zeit/next.js/issues/9524#issuecomment -582799948
@jansedlon ์์ ๋งํ๋ฏ์ด @ivan-kleshnin์ ๋ธ๋ก๊ทธ ํฌ์คํธ์์ ๋ค๋ฃจ์ง ์์ ์ด๊ฒ๊ณผ ๊ด๋ จํ์ฌ ์์ ํ๊ณ ์์ต๋๋ค. ์กฐ๋ง๊ฐ ์ด์ ๋ํด ๋ ๋ง์ ์ ๋ณด๋ฅผ ๊ณต์ ํ ์ ์๊ธฐ๋ฅผ ๋ฐ๋๋๋ค.
@timneutkens ์ง๊ธ๊น์ง์ ๋ณ๊ฒฝ ์ฌํญ์ด ๋ง์์ ๋ญ๋๋ค ๐ ์์ ํ ์ ์ + ๊ตญ์ ํ๋ฅผ ๊ฐ์ /์ง์ํ ๊ณํ์ด ์์ต๋๊น?
์ฐ๋ฆฌ๋ Gatsby์์ Next.js๋ก tinacms.org๋ฅผ ๋ง์ด๊ทธ๋ ์ด์
ํ ๋ ์๋ก์ด getStaticProps
/ getStaticPaths
API๋ฅผ ์ฌ์ฉํด ์์ผ๋ฉฐ ์ง๊ธ๊น์ง๋ ํ๋ฅญํ์ต๋๋ค!
์ฐ๋ฆฌ๊ฐ ๊ฐ์ง ํ ๊ฐ์ง ๊ฑธ๋ฆผ๋์ RSS ํผ๋๋ฅผ ์์ฑํ๋ ๊ฒ์ ๋๋ค. ์ฐธ์กฐํ๋ ์ฝํ ์ธ ๊ฐ ์ ์ ์ผ๋ก ์์ฑ๋๊ธฐ ๋๋ฌธ์ ์ด์์ ์ผ๋ก๋ ์ ์ ์ผ๋ก ์์ฑํ๊ณ ์ถ์ต๋๋ค. ํ์ฌ๋ก์๋ ์ด ์์ ์ ์ํํ ๋ฐฉ๋ฒ์ด ์์ต๋๋ค. ๋์ ์ฝํ ์ธ ๋ฅผ ์ฟผ๋ฆฌํ๊ณ ์๋ต์ XML์ ์์ฑํ์ฌ ์๋ฒ ์ธก์์ ์ฒ๋ฆฌํ๊ณ ์์ต๋๋ค.
HTML์ด ์๋ ์ฝํ ์ธ ์ ํ์ ๋ํ ์ ์ ์์ฑ ์ง์์ ๋ํ ๋ ผ์๊ฐ ์์์ต๋๊น?
์ฐธ๊ณ ๋ก ์ฐ๋ฆฌ๋ ์ง๊ธ zeit์์ getStaticProps
๋ฅผ ์ฌ์ฉํ๊ธฐ ์์ํ๊ณ --prod
ํ๋๊ทธ๋ฅผ ์ฌ์ฉํ๋ ๋ฆด๋ฆฌ์ค์ ์ ๋ฆด๋ฆฌ์ค์ json ํ์ผ์ ๋ํ ์บ์๊ฐ ์ง์์ง์ง ์์์ต๋๋ค. ๋ณ์นญ ๊ธฐ๋ฅ์ ์ฌ์ฉํ๋๋ก ํ๋ก๋์
๋ฆด๋ฆฌ์ค๋ฅผ ๋ค์ ์ ํํ๋ฉด ์บ์๊ฐ ์ง์์ง๋๋ค.
์ฐ๋ฆฌ๋ Gatsby์์ Next.js๋ก tinacms.org๋ฅผ ๋ง์ด๊ทธ๋ ์ด์ ํ ๋ ์๋ก์ด
getStaticProps
/getStaticPaths
API๋ฅผ ์ฌ์ฉํด ์์ผ๋ฉฐ ์ง๊ธ๊น์ง๋ ํ๋ฅญํ์ต๋๋ค!์ฐ๋ฆฌ๊ฐ ๊ฐ์ง ํ ๊ฐ์ง ๊ฑธ๋ฆผ๋์ RSS ํผ๋๋ฅผ ์์ฑํ๋ ๊ฒ์ ๋๋ค. ์ฐธ์กฐํ๋ ์ฝํ ์ธ ๊ฐ ์ ์ ์ผ๋ก ์์ฑ๋๊ธฐ ๋๋ฌธ์ ์ด์์ ์ผ๋ก๋ ์ ์ ์ผ๋ก ์์ฑํ๊ณ ์ถ์ต๋๋ค. ํ์ฌ๋ก์๋ ์ด ์์ ์ ์ํํ ๋ฐฉ๋ฒ์ด ์์ต๋๋ค. ๋์ ์ฝํ ์ธ ๋ฅผ ์ฟผ๋ฆฌํ๊ณ ์๋ต์ XML์ ์์ฑํ์ฌ ์๋ฒ ์ธก์์ ์ฒ๋ฆฌํ๊ณ ์์ต๋๋ค.
HTML์ด ์๋ ์ฝํ ์ธ ์ ํ์ ๋ํ ์ ์ ์์ฑ ์ง์์ ๋ํ ๋ ผ์๊ฐ ์์์ต๋๊น?
ํผ์ ์๊ฐํ๋ค๊ฐ ์ด๋ฒ์ ์๊ฒ ๋์์ด์. ๋ด ์คํฌ๋ฆฝํธ๋ ๋ค์๊ณผ ๊ฐ์ต๋๋ค.
"scripts": {
"dev": " next",
"build": "yarn sitemap && next build",
"start": "next start",
"sitemap": "ts-node --project ./cli/tsconfig.spec.json ./cli/generateSitemap.ts"
},
next build
์๋ ์ ์ ์ผ๋ก ์ฌ์ดํธ๋งต์ ์์ฑํ๋ yarn sitemap
๋ผ๊ณ ํฉ๋๋ค. ์๋ฅผ ๋ค์ด getStaticProps
ํ์ํ ๋ชจ๋ ๋ฐ์ดํฐ๋ฅผ json์ ์บ์ํ๊ธฐ ์ํด ๋์ผํ ๊ธฐ์ ์ ์ฌ์ฉํ ์ ์์ผ๋ฉฐ ์ฌ๋ฌ ํ์ด์ง์์ ์ฌ์ฌ์ฉํ ์ ์์ต๋๋ค.
์ RFC ์
๋ฐ์ดํธ, ๋ณ๊ฒฝ getStaticPaths
๋์์ ์กฐ๊ธ (๋น์ ์ด ๋ฐํํด์ผ paths
, ์ง๊ธ์ด ๊ฑฐ์ธ ํค๋ฅผ getStaticProps
๊ณณ์ props
๋ฐํํด์ผํฉ๋๋ค.์ด๋ฅผ ๋ณ๊ฒฝ ์ฌํญ์ ์์ง Next.js์ ์ ์ฉ๋์ง ์์์ต๋๋ค.
๋ํ fallback
๋์์ ๋ํ ์ค๋ช
์ ์ถ๊ฐํ์ต๋๋ค(๋น๋ ์ ๋ด๋ณด๋ด์ง ์์ ํ์ด์ง์ ์จ๋๋งจ๋ ๋ฐฑ๊ทธ๋ผ์ด๋ ์์ฑ).
RFC์ ๋ํ ๋ ๋ค๋ฅธ ์
๋ฐ์ดํธ๋ฅผ ์ํํ์ผ๋ฉฐ Loading
์ํ์ ๊ด๋ จ๋ ํด๋ผ์ด์ธํธ ํ์ ๋ณ๊ฒฝ ์ฌํญ์ ๋ํ ์ค๋ช
์ ์ถ๊ฐํ์ต๋๋ค.
๋ก๋ฉ ์ํ๊ฐ React ํํฌ๋ฅผ ํตํด ๋ ๋๋ง๋๊ณ ์๋์ง ์ฌ์ฉ์๊ฐ ์ ์ ์๋ ๋ฐฉ๋ฒ์ ์ถ๊ฐํ๊ณ ์ถ์ ์๋ ์์ต๋๋ค ๐ค
์ข์ ๋ฌผ๊ฑด! ์ ์ ์ผ๋ก ์์ฑ๋ ํ์ด์ง๊ฐ ๋จ์ผ JSON ํ์ผ์ ์ฌ์ฉํ์ฌ ์ฌ๋ฌ ๊ฒฝ๋ก ๊ฐ์ ๋ฐ์ดํฐ๋ฅผ ๊ณต์ ํ ์ ์๋ ๋ฐฉ๋ฒ์ด ์๋์ง ๊ถ๊ธํฉ๋๋ค(์ฝ๋ ๋ถํ ๊ณผ ๊ฐ์ง๋ง ๋ฐ์ดํฐ์ฉ)?
๋๋ ์ต์ canary
๋น๋์ ๋ถ๋ช์ณค๊ณ ์ฆ์ ์๋ก์ด Loading
์ํ์ ๋น ์ก์ต๋๋ค. ๊ณผ๊ฑฐ์๋ ๋ทฐ ๋ ์ด์ด๊ฐ ๋ ๋๋ง์ ์์ํ๊ธฐ ์ ์ ์ด๋ฏธ ์ฌ๋ฐ๋ฅธ ๋ฐ์ดํฐ๋ฅผ ์ป์๋ค๊ณ ์์ ํ๊ฒ ๊ฐ์ ํ๋ ๊ฒ์ด ์ข์์ต๋๋ค. ๊ฐ์ ๋น๋๊ธฐ ๋ก๋ฉ์ ๊ทธ๊ฒ๊ณผ ํฌ๊ฒ ๋ค๋ฆ
๋๋ค. ๋๋ ์๋ก์ด ์๋ ์์ฑ SSR ๋์ ์ด ๋์ฒดํ ๋ชจ๋ ์์ฉ๊ตฌ ๋์ ์ ์ ๊ฑฐํ๋ ๊ฒ์ ์ ๋ง ์ฆ๊ฒผ์ง๋ง ์๋ก์ด Loading
์ํ๋ฅผ ํฌํจํ๋๋ก ๋ชจ๋ ํ์ด์ง๋ฅผ ๋ค์ ๋์์ธํ ๊ณํ์ ์์์ต๋๋ค.
๋ ๋น ๋ฅธ TTFB์ ๋ํ ์ด๋ง๊ณผ ๋ฏธ๋์๋ ๋ด ์ฑ์ ์ข์ ๊ธฐ๋ฅ์ด ๋ ์ ์๋ค๋ ์ ์ ์ดํดํฉ๋๋ค. ํ์ง๋ง ํ ์์์ ๊ฒ์
๋๋ค Loading
์ํ ์ ์ฌํ ์ตํธ ์ธ ๋๋ ์ตํธ ์์ ๊ธฐ๋ฅ, fallback: false
์ ๋ํด getStaticPaths
? ํ์ด์ง์ export const enableLoadingState = false
๋๋ next.config.js
์ฌ์ดํธ ์ ์ฒด
https://github.com/zeit/next.js/issues/9524#issuecomment -583962425
์คํ ๊ธฐ๋ฅ์ ์ฌ์ฉ ์ค์ด๋ฉฐ ํ์ฌ ์ด ๋์์ ์คํํ๊ณ ์์์ ๋ค์ ํ ๋ฒ ์๋ ค๋๋ฆฝ๋๋ค.
๋ด (์คํ์ ) SSG ์น ์ฌ์ดํธ๋ฅผ Now(๊ธฐ๋ณธ ์ค์ ์ฌ์ฉ)์ ๋ฐฐํฌํ์ต๋๋ค. ์ ์๋ํ์ง๋ง ์ฌ์ดํธ๋ฅผ ํ์ํ ๋ ๋คํธ์ํฌ ํญ์ 404 ์ค๋ฅ๊ฐ ํ์๋ฉ๋๋ค. ๋ชจ๋ 404 ์ค๋ฅ๋ _next/static/pages/[slug].js
๊ฐ๋ฆฌํต๋๋ค.
์คํ ์ค์ ์์๋๋ ๋์์ ๋๊น? ์๋๋ฉด ์ผ๋ถ ์ค์ ์ ๋ณ๊ฒฝํด์ผ ํฉ๋๊น?
@joostmeijles ์ฌ๋ฐ๋ฅธ href
๋ฐ as
์ next/link
. ๋์ ํ์ด์ง์ ๊ฒฝ์ฐ href
๋ ํ์ด์ง href='/[slug]'
์ฌ์ผ ํ๊ณ as
๋ URL as='/slug-1'
์ด์ด์ผ ํฉ๋๋ค.
๋น๋ํ๋ ๋์ ์ฝ์์ 3๊ฐ์ ๋ก๊ทธ๊ฐ ํ์๋ฉ๋๋ค. ๋ฒ๊ทธ์ธ๊ฐ์?
// Page is showing three logs despite static path only having 2 entries and output generating only two files as intended
export default function Page(props){
console.log("Page - should only show twice", props);
return <><h1>Page</h1></>
}
export async function unstable_getStaticProps(props) {
console.log("unstable_getStaticProps - should only show twice", props);
return {
props
};
}
export async function unstable_getStaticPaths() {
console.log("show once")
return {
paths: [
{ params: { year: "1901" } },
{ params: { year: "1902" } },
]
}
}
์๋์, RFC์ fallback
์ ๋ฐ๋ผ ์์๋ฉ๋๋ค.
์๋์, RFC์
fallback
์ ๋ฐ๋ผ ์์๋ฉ๋๋ค.
export async function unstable_getStaticPaths() {
console.log("show once")
return {
fallback: false,
paths: [
// This renders /blog/hello-world to HTML at build time
{ params: { year: "1901" } },
{ params: { year: "1902" } },
]
}
}
์ ํ ํด์ ๋ฅผ ์๋ํ์ง๋ง ์ด ์ค๋ฅ๊ฐ ๋ฐ์ํฉ๋๋ค.
์ค๋ฅ: /[์ฐ๋]์ ๋ถ์์ ํ_getStaticPaths์์ ๋ฐํ๋ ์ถ๊ฐ ํค(๋์ฒด) ํ์ฌ ํ์ฉ๋๋ ์ ์ผํ ํ๋๋
paths
์คํ ๊ธฐ๋ฅ์ ์ฌ์ฉ ์ค์ด๋ฉฐ ํ์ฌ ๋์์ ์คํ ์ค์ด๋ฉฐ ๋ชจ๋ ๊ฒ์ด ๊ตฌํ๋๋ ๊ฒ์ ์๋์ ๋ค์ ํ ๋ฒ ์๋ ค๋๋ฆฝ๋๋ค.
getStaticProps
์ด ๊ธฐ๋ฅ์ ํ์ด์ง์์๋ง ์ฌ์ฉํ ์ ์์ต๋๊น?
์๋ฅผ ๋ค์ด ์์ฉ ํ๋ก๊ทธ๋จ์ ๋ํ ์ผ๋ถ ์ ์ญ ๊ตฌ์ฑ์ ๊ฐ์ ธ์ค๋ ๊ฒ๊ณผ ๊ฐ์ด ์ฑ/๋ฌธ์์๋ ํฅ๋ฏธ๋ก์ธ๊น์?
๋๋ ์ด๊ฒ์ '์ฑ๊ณต์ ์ผ๋ก' ๊ตฌํํ๊ณ ์ง๊ธ๊น์ง์ ๊ฒฐ๊ณผ์ ๋ง์กฑํฉ๋๋ค. ํ์ง๋ง ํ์ ๋น๋๋ฅผ '๋ ๋น ๋ฅด๊ฒ' ๋ง๋ค ์ ์๋ ๋ฐฉ๋ฒ์ด ์๋์ง ๊ถ๊ธํฉ๋๋ค. ์๋ฅผ ๋ค์ด SSG ์์ฑ ํ์ด์ง๊ฐ ๋ณ๊ฒฝ๋์ง ์์๋์ง ํ์ธํ๊ณ ๋ค์ ์์ฑํ์ง ์์ต๋๊น? (์๋ง๋ ๋์๊ฒ์ ํฌ๋ง์ ์ธ ์๊ฐ)
@timneutkens SSG ํ์ด์ง์ฉ sitemap.xml ์์ฑ๊ธฐ๋ฅผ ์ถ๊ฐํ ๊ณํ์ด ์์ต๋๊น? ์ง๊ธ์ ์ ์ ํ์ด์ง์ ๋ํด์๋ง ๊ตฌํํ๋ ๊ฒ์ด ๋ ์ฝ๋ค๊ณ ์๊ฐํ๊ธฐ ๋๋ฌธ์ ๋์ ๊ฒฝ๋ก์ ๋ํด ์ด์ผ๊ธฐํ์ง๋ ์์ต๋๋ค.
@timneutkens SSG ํ์ด์ง์ฉ sitemap.xml ์์ฑ๊ธฐ๋ฅผ ์ถ๊ฐํ ๊ณํ์ด ์์ต๋๊น? ์ง๊ธ์ ์ ์ ํ์ด์ง์ ๋ํด์๋ง ๊ตฌํํ๋ ๊ฒ์ด ๋ ์ฝ๋ค๊ณ ์๊ฐํ๊ธฐ ๋๋ฌธ์ ๋์ ๊ฒฝ๋ก์ ๋ํด ์ด์ผ๊ธฐํ์ง๋ ์์ต๋๋ค.
์, ์ด๊ฒ์ ํ๋ฅญํ ์ ํ์ด ๋ ๊ฒ์ ๋๋ค. ํ์ฌ SSR๋ก ์ง์ ์์ฑ ์ค์ ๋๋ค. (๊ทธ๋ฌ๋ sitemap.xml ํ์ผ์ ๋ก๋ํ๋ ๋ฐ ์๊ฐ์ด ์ค๋ ๊ฑธ๋ฆฝ๋๋ค)
https://github.com/zeit/next.js/issues/9524#issuecomment -585293270
getStaticProps๊ฐ ๋์ฐฉํ ํ ์ํฅ์ ์ฃผ๋ ๋ค๋ฅธ ์์ ์ด ์๊ธฐ ๋๋ฌธ์ ์ฒ์์๋ ํ์ด์ง์๋ง ํด๋น๋ฉ๋๋ค.
https://github.com/zeit/next.js/issues/9524#issuecomment -586957539
์, ํ์ง๋ง ์ด RFC์ ์ผ๋ถ๋ ์๋๋๋ค. ์ด ๋ ์ดํ์ ํ์ ์กฐ์น๊ฐ ์์ ๊ฒ์ ๋๋ค.
@timneutkens ๋ค์์ด ์ ์ ํ์ด์ง๋ฅผ ๋น๋ํ ๋๋ง๋ค URI๋ฅผ ๋ฐฐ์ด์ ํธ์ํ ์ ์๊ธฐ ๋๋ฌธ์ SSG ํ์ด์ง์ ๋ํ ๊ตฌํ์ด ์ฝ๋ค๊ณ ์๊ฐํฉ๋๋ค. ๊ทธ๋ฐ ๋ค์ ์ข
๋ฃ๋๋ฉด ๋ฐฐ์ด์ ๊ฐ XML ํ๊ทธ์ ๋งคํํ๊ณ ์ค๊ฐ์ ์กฐ์ธํ๊ณ ์ฝ์
ํ๊ธฐ๋ง ํ๋ฉด ๋ฉ๋๋ค. <sitemapindex>
ํ๊ทธ. getStaticProps
๋ excludeFromSitemap
๋ผ๋ ๋ฐํ ๊ฐ์ฒด์ ๋ค๋ฅธ ํค๋ฅผ ๊ฐ์ง ์ ์์ผ๋ฏ๋ก ๊ธฐ๋ณธ๊ฐ์ ๋ชจ๋ ํ์ด์ง๊ฐ sitemap.xml
๋์ง๋ง ์ตํธ์์ ์ต์
์ด ์๋ ๊ฒ์
๋๋ค.
์ด ๊ฒฝ์ฐ ๊ฐ๋ฐ์๋ ์ฌ์ดํธ๋งต์ ๋ค์ด๊ฐ ์ ์ ํ์ด์ง๋ฅผ ๋ฏธ์ธํ๊ฒ ์ ์ดํ ์ ์์ต๋๋ค(์: page [foo]
์ getStaticPaths
ํจ์๊ฐ foo
๋ก ๊ฒฝ๋ก๋ฅผ ๋ฐํํ ๊ฒฝ์ฐ) 'abc'
๋ฐ 'xyz'
๊ทธ๋ฌ๋ 'abc'
ํ์ผ excludeFromSitemap
๋ฅผ true
์ผ๋ก ์ค์ ํ ์ ์์ต๋๋ค getStaticProps
๋งค๊ฐ๋ณ์ ==='xyz'
getStaticProps
.
๋ํ SSR ๋ฐ ์ ์ ํ์ด์ง์ ๊ฒฝ์ฐ getServerProps
, getStaticPaths
๋ฐ getStaticProps
๊ณผ ๊ฐ์ด ํ์ด์ง ํ์ผ์์ ์์(์: export const excludeFromSitemap = true;
)๋ฅผ ๋ด๋ณด๋ผ ์ ์์ต๋๋ค. getStaticProps
๋ฅผ) ๋ด๋ณด๋
๋๋ค.
SSG ํ์ด์ง์์ ๋ด๋ณด๋ธ excludeFromSitemap
์์(ํ์ด์ง ๊ธฐ๋ณธ๊ฐ)๊ฐ ์๊ณ ํด๋น ํค๊ฐ getStaticProps
ํจ์(๊ฒฝ๋ก๋ณ)์์ ๋ฐํ๋ ๊ฐ์ฒด์๋ ์๋ ๊ฒฝ์ฐ ๋ด๋ณด๋ธ ๊ฐ์ด ๊ธฐ๋ณธ๊ฐ์ผ๋ก ์๋ํด์ผ ํฉ๋๋ค. ํด๋น ํ์ด์ง์ ๋ชจ๋ ๊ฒฝ๋ก์ ๋ํ ๊ฐ๊ณผ ๊ฒฝ๋ก๋ณ excludeFromSitemap
๊ฐ getStaticProps
๊ฐ์ฒด์ ์๋ ๊ฒฝ์ฐ ํ์ด์ง์ ๊ธฐ๋ณธ๊ฐ์ ์ฌ์ ์ํด์ผ ํฉ๋๋ค(ํ์ด์ง๊ฐ export cosnt excludeFromSitemap = true
์ํํ ์ ์๋๋ก ๊ทธ๋ฐ ๋ค์ getStaticProps
๊ฐ์ด false
๊ฐ์ฒด์ excludeFromSitemap
ํค๋ฅผ ์ถ๊ฐํ์ฌ ํน์ ๊ฒฝ๋ก๋ฅผ ์ ์ธํ ์ฌ์ดํธ๋งต์ ๋ชจ๋ ๊ฒฝ๋ก๋ฅผ ์ ์ธํฉ๋๋ค.
๋ฐฐ์ด์ ์ถ๊ฐํ๋ ์ฝ๋๋ ๋ค์๊ณผ ๊ฐ์ต๋๋ค(์ ๋ ์ง๋ฆฌํ๋ฅผ ๊ณ์ฐํ๊ณ Karnaugh ๋งต์ผ๋ก ์ต์ ๋ถ์ธ ํํ์์ ์ป์์ต๋๋ค).
//...somewhere else
const validExcludeFromSitemapTypes = ['boolean','undefined'];
//...for each path
const isSSG = !!getStaticPropsReturnedObj && typeof getStaticPropsReturnedObj === "object";
if(
validExcludeFromSitemapTypes.indexOf(typeof pageExports.excludeFromSitemap)<0 ||
(isSSG && validExcludeFromSitemapTypes.indexOf(typeof getStaticPropsReturnedObj.excludeFromSitemap)<0)
) {
throw new Error("'excludeFromSitemap' can either be ommited (undefined) or be a boolean");
}
const defaultExcludedValue = !!pageExports.excludeFromSitemap;
const hasSpecificExcluded = isSSG && typeof getStaticPropsReturnedObj.excludeFromSitemap !== "undefined";
const specificExcludedValue = isSSG ? !!getStaticPropsReturnedObj.excludeFromSitemap : false;
if(!specificExcludedValue && (!defaultExcludedValue || hasSpecificExcluded))
sitemapURIs.push(correctlyEncodedURI);
๋ฐฐ์ด์ ์ฌ์ดํธ๋งต์ผ๋ก ๋ฐ๊พธ๋ ๊ฒ์ ์ด๋ ๊ฒ ํ๋ ๊ฒ๋งํผ ์ฝ์ต๋๋ค(๋ฐฐ์ด์ URI๊ฐ ์ด๋ฏธ !excludeFromSitemap
์ธ์ฝ๋ฉ ๋ฐ ํํฐ๋ง๋์๋ค๊ณ ๊ฐ์ ).
function createSitemap(sitemapURIs: string[]): string {
return `<sitemapindex>${sitemapURIs.map(u=>`<sitemap><loc>u/loc></sitemap>`).join('')}</sitemapindex>`;
}
์ด ๊ธฐ๋ฅ์ ์ฌ์ฉ์์๊ฒ 100 SEO ์ ์๋ฅผ ์ ๊ณตํ๊ณ sitemap.xml
๊ฐ๋ ๊ฒ์ด ํฐ ๋์์ด ๋ ๊ฒ์ด๊ธฐ ๋๋ฌธ์ ์ด ๊ธฐ๋ฅ์ด Next.JS์ ์ ๋ค์ด๋ง์ ๊ฒ์ด๋ผ๊ณ ์๊ฐํฉ๋๋ค! ( robots.txt
๋ ์ฌ์ดํธ๋งต ๋ฐฐ์ด์ ๊ฒฝ๋ก๋ฅผ ์ถ๊ฐํ์ฌ ํ์ฉ๋์ง ์๋ ํ์ด์ง์ ๋ค๋ฅธ ๋ฐฐ์ด์ ํด๋น ๊ฒฝ๋ก๋ฅผ ์ถ๊ฐํ๋ ์กฐ๊ฑด์ else
๋ฅผ ์ถ๊ฐํ์ฌ ์ ์ฌ์ ์ผ๋ก ์์ฑ๋ ์๋ ์์ต๋๋ค.
ํ์ฌ ๋ฆด๋ฆฌ์ค ๋ฒ์ ์์ ์ฌ์ฉํ๋ ๊ฒฝ์ฐ unstable_getStaticPaths
ํจ๊ป unstable_getStaticProps
์ํ ๊ธฐ๋ฅ์ ๋ํ ๊ธฐ๋ฅ, ๋น์ ์ ํ ์ ์์ต๋๋ค API๋ฅผ ํธ์ถ /api/
.
์๋ฒ๊ฐ ์คํ๋๊ณ ์์ง ์๊ธฐ ๋๋ฌธ์ ์ด๋ฌํ ๋ฐฉ์์ผ๋ก ํด๋น ์์ฒญ์ ์ํํ๊ณ ์ ์ props๋ฅผ ์์ฑํ๋ ๊ฒ์ ๋ถ๊ฐ๋ฅํฉ๋๋ค.
๊ฒฝ๋ก ๊ธฐ๋ฅ์ ์ ๊ณตํ์ง ์๊ฑฐ๋(๊ธฐ๋ณธ์ ์ผ๋ก ์บ์๊ฐ ์๋ ์ด SSR์ ๋ง๋๋ ๊ฒ์ ์ฌ์ ํ โโ์ข์ต๋๋ค!) SSG ๋์ SSR์ ์์กดํด์ผ ํฉ๋๋ค.
์ด ๊ธฐ๋ฅ์ ์ข์ ์ถ๊ฐ ๊ธฐ๋ฅ์ด ์๋๊น์? ์ฌ๊ธฐ์ ๊ฐ์ฅ ์ข์ ๋ฐฉ๋ฒ์ด ๋ฌด์์ธ์ง ํ์คํ์ง ์์ต๋๋ค. SSR ๋ฐ /api
๊ฒฝ๋ก๋ฅผ ์ฌ์ฉํ์ฌ http ์์ฒญ์ ๋ฐ๋ก ๊ฐ๊ธฐ๋ก ์ ์ํ๋ ๋ค๋ฅธ ๊ณณ์์ ์ ์์ ์ฝ์์ต๋๋ค. ์ด๊ฒ์ ์ฌ๊ธฐ์์๋ ์ ์ฉํ ๊ฒ์
๋๋ค.
๊ทธ๋ฌ๋ ์ด ๋ชจ๋ ๊ฒ์ ๋ฌผ๋ก ๋น๋ ํ๊ฒฝ์์ ์ฝ๋๋ฅผ ์คํํ๋ ๊ฒ์ ์๋ฏธํ๋ฉฐ, ์ด๋ ๋ค๋ฅธ ์๋น์ค/db ํธ์ถ ๋๋ ์ด์ ์ ์ฌํ ๊ฒ์ ํธ์ถํฉ๋๋ค. ์ด๊ฒ์ ๊ตฌํ๋ ๋ ๋ช ํํด์ผ ํ์ง๋ง ์ด ๊ธฐ๋ฅ์ ๋ํ ๋ฉ์ง ์ถ๊ฐ ์ฌํญ์ด ๋ ๊ฒ์ ๋๋ค.
@reckter ์, ๋ฐฉ๊ธ ๋น์ทํ ์์ ์ ์ํํ์ต๋๋ค. ์ ์ ์ผ๋ก ์์ฑ๋๋ ๋์ ๊ฐ๋ณ ํ์ด์ง ์์ฒญ๋ง๋ค db์ ์ฐ๊ฒฐํด์ผ ํ์ต๋๋ค. ๊ธฐ๋ถ์ด ๋ง์ด ์ด์ํ๋ค...
๊ทธ๊ฒ์ด ์ต์ข ์ฌ์ฉ ์ฌ๋ก๊ฐ ์๋๊ธฐ๋ฅผ ๋ฐ๋๋๋ค.
next.config์์ ์ค์ ํ ์ ์๋ ์ผ์ข ์ ์ด๊ธฐํ ์คํฌ๋ฆฝํธ๊ฐ ์์ผ๋ฉด ์ข์ ๊ฒ์ ๋๋ค.
@reckter HTTP ์์ฒญ์ SSG/SSR์์ API ๊ฒฝ๋ก๋ก ๋ฐ๋ก ๊ฐ๊ธฐ ์ํ ๋ฐฉ๋ฒ์ ์ ๋ง ์ข์ ๊ฒ์ ๋๋ค! ์ด๋ฌํ ์๋๋ฆฌ์ค ์ค ํ๋์์ ๋ ์์ ์๊ฒ ๋คํธ์ํฌ ์์ฒญ์ ํ๋ ๊ฒ์ด ์ด์ํ๊ฒ ๋๊ปด์ง๋๋ค.
์ด์จ๋ , SSG ๋์ API ๊ฒฝ๋ก์ ์ก์ธ์คํ๊ธฐ ์ํ ๊ฐ๋ฅํ ์๋ฃจ์
์ ์ ์ ํ์ด์ง๋ฅผ ์ปดํ์ผํ๊ธฐ ์ ์ ๋ก์ปฌ ์๋ฒ์์ /api
๊ฒฝ๋ก๋ง ์คํํ๋๋ก ํ๋ ๊ฒ์
๋๋ค! ๋ฐ๋ผ์ ๋น๋ ๋จ๊ณ๋ ๋ค์๊ณผ ๊ฐ์ต๋๋ค.
/api
๊ฒฝ๋ก๋ง ์ ๊ณตํ๋ ์๋ฒ("api ์ปดํ์ผ ์๋ฒ" ๋๋ ์ด์ ์ ์ฌํ ๊ฒ)๋ฅผ ์์ํฉ๋๋ค.unstable_getStaticPaths
unstable_getStaticProps
@reckter ๊ธฐ๋ณธ์ ์ผ๋ก API ๋ผ์ฐํธ๋ฅผ ํธ์ถํ ํ์๊ฐ ์์ต๋๋ค. ๊ตฌํํ๋ ํจ์๋ฅผ ์ง์ ํธ์ถํ ์ ์์ต๋๋ค. ์ด๋ ๊ฒ ํ๋ฉด http ์์ธ์ ๋์ด์๋ ๋ง์ ์ค๋ฒํค๋๋ ํผํ ์ ์์ต๋๋ค.
๊ธฐ๋ณธ์ ์ผ๋ก ํ์ฌ ๋ค์๊ณผ ๊ฐ์ API ๊ฒฝ๋ก๊ฐ ์๋ ๊ฒฝ์ฐ:
import myDb from 'mydatabaseprovider'
const db = myDb()
export default async (req, res) => {
cont myData = await db.query('posts')
res.json(myData)
}
๋ค์๊ณผ ๊ฐ์ด ๋ณ๊ฒฝํ ์ ์์ต๋๋ค.
import myDb from 'mydatabaseprovider'
const db = myDb()
export async function getData() {
const myData = await db.query('posts')
return myData
}
export default (req, res) => {
const myData = await getData()
res.json(myData)
}
๊ทธ๋ฐ ๋ค์ ํ์ด์ง์์:
import {getData} from './api/myfunction'
export async function getStaticProps() {
const myData = await getData()
return {
props: {
myData
}
}
}
GraphQL API์ ๋ํด ๋์ผํ ์์ ์ ์ํํ๋ ๊ฒ์ ๊น๋ค๋ก์ธ ๊ฒ์ ๋๋ค. ๊ทธ๋ฆฌ๊ณ ๋๋ถ๋ถ์ REST์์๋ ๋ง์ฐฌ๊ฐ์ง์ ๋๋ค.
API ํธ์ถ != DB์์ ๊ฐ์ ธ์ค๊ธฐ(์ผ๋ฐ์ ์ผ๋ก)
ํ๋ ์ด๋ฆ ๋ฐ๊พธ๊ธฐ, ๋ฐ์ดํฐ ํ์ ๋ณ๊ฒฝ ๋ฑ๊ณผ ๊ฐ์ API ๊ณ์ธต์๋ ๊ฑฐ์ ํญ์ ๋ช ๊ฐ์ง ๋น์ฆ๋์ค ๋ก์ง์ด ์์ต๋๋ค.
pages/api
ํธ์ถ์ ํ์ฉํ์ง ์์ ์ด์ ๊ฐ ์๋ค๊ณ ํ์ ํ์ง๋ง ์ค์ API์ ์ฐํ๋ ์ฝ๊ฑฐ๋ ์ ๋ ดํ์ง ์์ต๋๋ค. ๊ทธ๋ฆฌ๊ณ ์ฌ๋ถ์ ๋ช ๋ฐ๋ฆฌ์ด๋ ์ถ๊ฐ ์ฝ๋/๋ณต์ก์ฑ IMO์ ๋ํ ๋น์ฉ์ ๋ฅ๊ฐํ์ง ์์ต๋๋ค.
๋ํ ๋ชจ๋ API์ ๋ํ ์์ฒญ์ด ํ์ฉ๋๋ค๋ ๊ฒ์ด ์ด์ํ๊ฒ ๋๊ปด์ง๋๋ค. ๋๋ง์ ๐คทโโ
unstable_getStaticPaths
ํ๋ฉด ํ์ด์ง๊ฐ ๋ค์ ๋ก๋๋์ด ์๋ฅผ ๋ค์ด redux์์ ํ์ฌ ์ํ๊ฐ ์์ค๋ฉ๋๋ค. ์์ผ๋ก ์ด ํ๋์ด ๋ฐ๋๊น์?
ํธ์ง: ๋งํฌ ๋๋ ๋ผ์ฐํฐ์์ as
์ต์
์ ์ฌ์ฉํ์ฌ ์ด ๋์์ ์ฐํํ ์ ์๋ ๊ฒ ๊ฐ์ต๋๋ค.
<Link
href='/item/[key]'
as={`/item/${itemName}`}
>
router.push(
'/item/[key]',
`/item/${itemName}`
);
@meesvandongen ํญ์ <Link>
์ด ์ ํจํ์ง ์์ผ๋ฉด ๊ธฐ๋ณธ์ ์ผ๋ก <a>
๋ก ์๋ํ๋ ๋ฐฑ์๋ ๋ถ๋ถ์ผ๋ก ์ด๋ํฉ๋๋ค. [key]
์ ๊ฐ์ ๋์ ์กฐ๊ฐ์ ํด๋น ๊ฐ๊ณผ ์์ ์ด๋ฃจ์ด์ผ ํฉ๋๋ค.
@reaktivo
pages/[lang]/blog/[id].js
->getStaticPaths
์์ ์ ์ ์ผ๋ก ๋ ๋๋งํ ๋ชจ๋ URL์ ์ ๊ณตํฉ๋๋ค.
https://github.com/zeit/next.js/issues/9524#issuecomment -562625858
์ด ๊ฒฝ์ฐ index.js๋ฅผ ์ ์ธํ ๋ชจ๋ ํ์ด์ง์ getStaticPaths
๋ฐ getStaticProps
ํจ์๋ฅผ ์ถ๊ฐํด์ผ ํฉ๋๋ค.
์ผ๋ถ mdx ํ์ด์ง๊ฐ ์์ผ๋ฉด ํ๋ก์ ํธ๋ฅผ ์ ์ง ๊ด๋ฆฌํ๊ธฐ๊ฐ ๋ ์ด๋ ต์ต๋๋ค.
์ ์ getStaticPaths
getStaticProps
๋ฉ์๋๋ก์ ๋ณ๊ฒฝ ๋๋ ํธํ์ ๊ณ ๋ คํ์ญ์์ค. https://github.com/zeit/next.js/issues/9524#issuecomment -558617056
๊ทธ๋ ๋ค๋ฉด ํ์ด์ง๋ ๊ณ ์ฐจ ํจ์ ๋๋ ๊ณ ์ฐจ ๊ตฌ์ฑ ์์(HOC)์ ์ํด ๋ํ๋ ์ ์์ต๋๋ค.
์ด๋ฐ ์์ผ๋ก ์ฝ๋๋ ๋ ์ ์ง ๊ด๋ฆฌํ๊ธฐ ์ฝ๊ณ typesscript์ ๋ ํธ๋ฆฌํฉ๋๋ค.
๋๋ฌด ํ๋ค๊ธฐ ๋ ๋์ . ์ด ์ผ๋ง๋ ๊ณจ์น ์ํ ํธ๋ ์ด๋์คํ์ธ๊ฐ.๐
9.2.3-canary.13
์ฌ์ฉํ์ฌ ๋ค์๊ณผ ๊ฐ์ด getStaticPath์์ fallback: false
๋ฅผ ์ฌ์ฉํด ๋ณด์์ต๋๋ค.
return {
fallback: false,
paths: slugs.map(slug => ({params: {slug: slug}}))
}
๊ทธ๋ฌ๋ ๋ค์ ์ค๋ฅ์ ํจ๊ป ์คํจํฉ๋๋ค.
Error: Extra keys returned from unstable_getStaticPaths in /blog/[slug] (fallback) Expected: { paths: [] }
9.2.3-canary.13
์ฌ์ฉํ์ฌ ๋ค์๊ณผ ๊ฐ์ด getStaticPath์์fallback: false
๋ฅผ ์ฌ์ฉํด ๋ณด์์ต๋๋ค.return { fallback: false, paths: slugs.map(slug => ({params: {slug: slug}})) }
๊ทธ๋ฌ๋ ๋ค์ ์ค๋ฅ์ ํจ๊ป ์คํจํฉ๋๋ค.
Error: Extra keys returned from unstable_getStaticPaths in /blog/[slug] (fallback) Expected: { paths: [] }
๋งต์ด ๋ ๋์ ๋ ๋ฒจ์ด ํ์ํ๋ค๊ณ ์๊ฐํ๋ฏ๋ก ๋งต์ ํ์ฌ ๊ฐ์ง๊ณ ์๋ ๊ฐ์ฒด๋ฅผ ๋ฐํํ์ง๋ง ๊ณ ์ ํ ์ฌ๋ฌ๊ทธ๋ฅผ ํฌํจํฉ๋๋ค. ๊ฒฝ๋ก์ ๋งคํํ๋ ๋์ .
์์ง nextjs์์ ๋ด ๋ฒ์ ์ ์ ๋ฐ์ดํธํ์ง ์์์ง๋ง ๋น์ทํด์ผ ํฉ๋๋ค.
return data.map(item => {
return {
params: {
slug: item.slug,
},
}
})
@jorngeorg ๊ณต๊ฐ PR์ ๋๋ค: https://github.com/zeit/next.js/pull/10701
ํ์์ ์ธ ๊ธฐ์ฌ! ์ ์ ๋ ๋๋ง ํ๋ก์ธ์ค๋ฅผ ์ค์ ๋ก ํฅ์์ํต๋๋ค.
๋์ ๊ฒฝ๋ก์์ getStaticProps
๋ํ ํธ์ถ ์์ด "๋์ฒด"๊ฐ ์์ฑ๋๋ค๋ ๋ฌธ์๋ฅผ ์ถ๊ฐํ๋ ๊ฒ์ด ์ข์ต๋๋ค. ์ฆ, props๊ฐ ๋น์ด ์๋ ๊ฒฝ์ฐ๋ฅผ ์ค๋ช
ํ๊ธฐ ์ํด ๊ตฌ์ฑ ์์๋ฅผ ์ฝ๋ฉํด์ผ ํฉ๋๋ค.
๋๋ ๋์ฒด๋ฅผ ์์ฑํ ๋ ์ปจํ
์คํธ ์์ด getStaticProps
๋ฅผ ํธ์ถํ๋๋ก ๋์์ ๋ณ๊ฒฝํ ์ ์์ต๋๋ค. ์ด๊ฒ์ next export
ํ์ฌ ์๋ํ๋ ๋ฐฉ์๊ณผ ์ผ์นํฉ๋๋ค(์: getInitialProps
๋ฅผ ์ปจํ
์คํธ ์์ด ์คํํ์ฌ /p/[id].js
๋ฅผ /p/[id].html
๋ก ๋ด๋ณด๋
๋๋ค).
getStaticProps
-next build
์๊ฐ์ SSG(์ ์ ์์ฑ)๋ฅผ ์ ํํฉ๋๋ค.getServerProps
- ์จ๋๋งจ๋๋ก ๋ ๋๋งํ๋ SSR(์๋ฒ ์ธก ๋ ๋๋ง)์ ์ ํํฉ๋๋ค.
getServerProps์ ์ด๋ฆ์ getServerSideProps๋ก ๋ฐ๊ฟ๋๋ค.
๋์ ๊ฒฝ๋ก์์
getStaticProps
๋ํ ํธ์ถ ์์ด "๋์ฒด"๊ฐ ์์ฑ๋๋ค๋ ๋ฌธ์๋ฅผ ์ถ๊ฐํ๋ ๊ฒ์ด ์ข์ต๋๋ค. ์ฆ, props๊ฐ ๋น์ด ์๋ ๊ฒฝ์ฐ๋ฅผ ์ค๋ช ํ๊ธฐ ์ํด ๊ตฌ์ฑ ์์๋ฅผ ์ฝ๋ฉํด์ผ ํฉ๋๋ค.
์ฐธ๊ณ ํ๋ฉด ์ข์์ ! ๋๋ ๋ํ ๊ทธ๊ฒ์ ๋์ณค๊ธฐ ๋๋ฌธ์ ์ผ๋ถ ๋น๋/๋ฐฐํฌ ์ค๋ฅ๊ฐ ์์์ต๋๋ค.
๋ณ๊ฒฝ ์ฌํญ์ ๋ฐ์ํ๋๋ก RFC๋ฅผ ์ ๋ฐ์ดํธํ์ต๋๋ค.
@timneutkens
- ๋์ผํ ๊ฒฝ๋ก์ ๋ํ ํ์ ์์ฒญ์ ์์ฑ๋ ํ์ด์ง๋ฅผ ์ ๊ณตํฉ๋๋ค.
์ด๊ฒ์ด Next.js๊ฐ ์์ฑ๋ ํ์ด์ง๋ฅผ ์บ์ํ ๊ฒ์์ ์๋ฏธํ๋ค๊ณ ๊ฐ์ ํฉ๋๊น? ์ธ๋ฉ๋ชจ๋ฆฌ ์บ์์ธ๊ฐ์? ์ด ์บ์๊ฐ ์ ํ์ ์ํด ์ ํ๋๊ฑฐ๋ ๋ฉ๋ชจ๋ฆฌ ๋์๊ฐ ๋ฐ์ํ ์ ์์ต๋๊น?
next start
๋ฅผ ์ฌ์ฉํ๋ฉด ํ์ฌ ์บ์ฑ ์์ ์ ์ ์ฌํ lru-cache๋ฅผ ์ฌ์ฉํฉ๋๋ค. ํ์ฌ ๊ธฐ๋ณธ ์ ํ์ 50MB์ด๋ฉฐ ๋์ค์ ๊ตฌ์ฑํ ์ ์์ต๋๋ค. https://github.com/zeit/next.js/ ๋ธ๋กญ/์นด๋๋ฆฌ์/ํจํค์ง/next/next-server/server/spr-cache.ts#L90
ZEIT์์ ํธ์คํธํ ๋ ์ด์ ์์ฑ ๋ฐ ์บ์ฑ์ด CDN/ํ๋ก์์์ ๋ฐ์ํ๋ฏ๋ก ์ฝ๊ฐ ๋ค๋ฅด๊ฒ ์๋ํ๋ฏ๋ก ๋ฉ๋ชจ๋ฆฌ ๋์๋ lru ์ ํ์ ์ด๊ณผํ๋ ๊ฒฝ์ฐ์ ๋ํด ๊ฑฑ์ ํ ํ์๊ฐ ์์ต๋๋ค.
๐ ์ข์, ํฉ๋ฆฌ์ ์ผ๋ก ๋ณด์ธ๋ค. ๊ทธ๊ฒ์ ๋ด๊ฐ ํฉ๋ฆฌ์ ์ธ ๊ธฐ๋ณธ ๋์์ผ๋ก ์ผ๋์ ๋์๋ ๊ฒ์ ๋๋ค.
getStaticProps
-next build
์๊ฐ์ SSG(์ ์ ์์ฑ)๋ฅผ ์ ํํฉ๋๋ค.getServerProps
- ์จ๋๋งจ๋๋ก ๋ ๋๋งํ๋ SSR(์๋ฒ ์ธก ๋ ๋๋ง)์ ์ ํํฉ๋๋ค.10722
getServerProps์ ์ด๋ฆ์ getServerSideProps๋ก ๋ฐ๊ฟ๋๋ค.
๊ทธ๋ฐ๋ฐ ์ ์ด๋ฆ์ ๋ฐ๊พธ๋์? IMHO getServerProps๋ ์ ๋ ฅํ๊ธฐ์ ์ถฉ๋ถํ ์ ํํ๊ณ ์งง์์ Side๋ฅผ ์ถ๊ฐํ๋ ๊ฒ์ด ๋์๊ฒ ์ค๋ณต๋๋ ๋๋์ ๋๋ค.
getStaticPaths ๋ฉ์๋์ ๋ณ๊ฒฝ ์ฌํญ์ด ์๋์ง ๊ถ๊ธํฉ๋๋ค. ๋ด ๋์ ํ์ด์ง๋ ๋ ์ด์ ์ ์ ํ์ด์ง๋ก ์์ฑ๋์ง ์์ต๋๋ค. ์ด์ ๋๋ค ํจ์๋ก ๋ด๋ณด๋ด์ง๋๋ค.
์ด์ ๊ธฐ๋ณธ ๋์์ด ํ์ด์ง๊ฐ ๋จผ์ ๋๋ค๋ก ๋ ๋๋ง๋๊ณ ํน์ ํ์ด์ง๋ฅผ ๋ฐฉ๋ฌธํ ํ์๋ง ํ์ด์ง๊ฐ ์ ์ ํ์ด์ง๋ก ์์ฑ๋๋ ๊ฒ์ด ๋ง์ต๋๊น? (๋์ฒด์์ ์ธ๊ธํ ๊ฒ์ฒ๋ผ)
@erhankaradeniz ํ์ด์ง๊ฐ Lambdas ๊ฐ ๋๋ getStaticPaths
๋ณ๊ฒฝ ์ฌํญ์ด ์์ต๋๋ค. ์ด๊ฒ์ ์ฌ์ฉ์์ ์ค๋ฅ์ผ ๊ฐ๋ฅ์ฑ์ด ์์ต๋๋ค.
๋ฌธ์ ๋ฅผ ์๋ณํ ์ ์๋๋ก ์ฝ๋๋ฅผ ๋ณด์ฌ์ฃผ์๊ฒ ์ต๋๊น?
@Timer ์ง๊ธ์ ๊ฒฝ๋ก์์ ์๋ํ์ง ์๋ ์ด์ ๋ฅผ ์์๋ผ ๋๊น์ง ์ฌ์ ํ params๋ฅผ ์ฌ์ฉํ ์ ์๋ [email protected]์ผ๋ก ๋๋์๊ฐ์ต๋๋ค.
์ด๊ฒ์ด ํ์ฌ ๋ด ๊ฒฝ๋ก๋ฅผ ์์ฑํ ๋ฐฉ๋ฒ์ ๋๋ค.
return cityData.map(city => {
return {
params: {
country: city.countrySlug,
city: city.slug,
},
}
})
๊ทธ๋ฆฌ๊ณ ๋ค๋ฅธ ํ์ด์ง์์๋ ๋ค์์ ์ํํฉ๋๋ค.
return cityData.map(city => {
return {
params: {
country: city.countrySlug,
city: city.slug,
},
}
})
๊ฒฝ๋ก๊ฐ ์๋ ์ ์นด๋๋ฆฌ์ ๋ฆด๋ฆฌ์ค๋ก ๋ณํํ์ง ๋ชปํ์ต๋๋ค. console.logs๊ฐ getStaticPath
๋ด์์ ์คํ๋์ง๋ ์๊ธฐ ๋๋ฌธ์ ๋ญ๊ฐ ์๋ชปํ๊ณ ์๋ ๊ฒ ๊ฐ์ต๋๋ค.
์ค์ฒฉ ๊ฒฝ๋ก ์ฌ์ ๋ ๋๋ง ๋ฐ SSG์ ๋ฌธ์ ๊ฐ ์์ต๋๋ค.
// pages/[lang]/[...slugs].js
export async function getStaticPaths() {
let knex = await import("knex/client").then(m => m.default)
let pages = await knex("page").select(["lang", "url"])
return {
fallback: true,
paths: pages.map(page => {
return {
params: {
lang: page.lang,
slugs: page.url == "/" ? [] : page.url.slice(1).split("/"),
}
}
}),
}
}
~์ผ๋ก ์ด๋๋ค
Error occurred prerendering page "/en/". Read more: https://err.sh/next.js/prerender-error:
Error: The provided export path '/en/' doesn't match the '/[lang]/[...slugs]' page.
ํ ํ์ด์ง์ ๊ฒฝ์ฐ. ์ด๋ค ์ด์ ๋ก NextJS๊ฐ ์ผ์นํ์ง ์์ต๋๋ค.
{lang: "en", slugs: []}
์๊ฒ
/[lang]/[...slugs]
{lang: "en", slugs: ["/"]}
ํ๋ฉด ๋น๋๋์ง๋ง URL์ด ์๋ชป๋ฉ๋๋ค.
โ โ /[lang]/[...slugs] 875 B 204 kB
โ โ /en/credits
โ โ /en/%2F
๊ธฐ๋ก์ ์ํด getServerSideProps
๋ ์ ์ฌํ ์ค์ ์ผ๋ก ์ ์๋ํฉ๋๋ค.
์คํ์ ์ด๋ผ๋ ๊ฑด ์์ง๋ง ์ด ์ค๋ ๋๋ ํผ๋๋ฐฑ์ ์ ๊ณตํ๊ธฐ ์ํ ๊ฒ์ ๋๋ค. ๋ง๋์?
pages/[lang]/[...slugs].js
์ผ์น /en/abcdef
ํ์ง /en
, ํ์ฌ ๋ง๋ค ํ์๊ฐ ๊ทธ๊ฒ์ ์ํด pages/[lang]/index.js
.
์ด์ ๋ํ ๊ธฐ๋ฅ ์์ฒญ์ด ์์ต๋๋ค: https://github.com/zeit/next.js/issues/10488
์ฐ์ , ์ด๊ฒ์ ๊ต์ฅํฉ๋๋ค. ๋๋ Next.js์ ์ด์ ๊ฐ์ ๊ฒ์ ๊ฐ๊ณ ์ถ์๊ธฐ ๋๋ฌธ์ ๋ง์นจ๋ด Gatsby.js์์ ๋ฒ์ด๋ ํ์ด๋ธ๋ฆฌ๋ ์ฑ(์ ์ + ๋์ )์ ๊ฐ์ง ์ ์๊ฒ ๋์์ต๋๋ค.
๐ ๋๋ ์นด๋๋ฆฌ์๋ฅผ ์๋ํ๊ณ ๋ฐ ๊ตฌ์ด ๋ณต์กํ ์ฑ ๋ฒ์ ์ ์ ์๋ํ์ต๋๋ค. ๋๋ ์ฌ๊ธฐ์ ์๋ ๋ชจ๋ ์ฃผ์์ ์ฝ์ง ์์์ง๋ง ๋๋ฌด ํ๋ค๊ธฐ๊ฐ ์์ง ๊ตฌํ๋์๋์ง ํ์ ํ์ง ๋ชปํ๋ค๊ณ ๊ณ ๋ฐฑํฉ๋๋ค.
๐ค getStaticPaths
๋ SSG ๋์์ ๋ํ ์ ์ ๊ฒฝ๋ก๋ฅผ ์ ์ํ๋ setStaticPaths
์ ํจ์ฌ ๋น์ทํฉ๋๋ค. ๊ทธ๋ฐ ์ ์ด ๋๋ฅผ ์กฐ๊ธ ํผ๋์ค๋ฝ๊ฒ ํ๋ค.
๐ง ๋น๋ ์นดํ ๊ณ ๋ฆฌ๋ฅผ ๋ง๋ค์ด ๋น๋ ์๊ฐ์ ๋จ์ถํ ์ ์๋์ง ๊ถ๊ธํฉ๋๋ค. ์ด๊ฒ์ด ์ค์ ์ ๋ณต์กํ๊ฒ ๋ง๋ค ๊ฒ์ด๋ผ๋ ๊ฒ์ ์๊ณ ์์ง๋ง ๊ทธ๋งํ ๊ฐ์น๊ฐ ์์ต๋๋ค. ์ค๋ช ํ๊ฒ ์ต๋๋ค:
blog
๋๋ pages
๋๋ ๋๊ตฐ๊ฐ๊ฐ ์ํ๋ 2020-content
์ค์ ํ๋ setBuildCategory
์ ๊ฐ์ ๊ฒ์ด ์์ผ๋ฉด ์ด๋ป๊ฒ ๋ ๊น์? ๊ทธ๋ฐ ๋ค์ SSG ๋น๋๋ ๋ณ๊ฒฝ๋ ํ์ด์ง์ ๋ฒ์ฃผ๋ฅผ ์ฐพ๊ณ ์บ์ + ์ ๋ ๋ ์กฐํฉ์์๋ง ํด๋น ๋ฒ์ฃผ๋ฅผ ๋ค์ ์์ฑํ๋ ค๊ณ ์๋ํฉ๋๋ค. ์ด์ ๊ฐ์ ๊ฒ์ SSG๋ฅผ ๋น ๋ฅด๊ฒ ๋ง๋ค๊ณ ๋ง์ด ๋ณ๊ฒฝ๋์ง๋ ์์ง๋ง ์ฌ์ ํ ๋ณ๊ฒฝ๋ ์ ์์ผ๋ฏ๋ก ๋ณด๊ดํ ์ ์๋ ํญ๋ชฉ์ ๋ํ ๋ง๋ํ ๋น๋ ์๊ฐ์ ํผํ๋ ๋ฐ ๋์์ด ๋ ์ ์์ต๋๋ค.
๊ทธ๊ฒ์ด ์๋ฏธ๊ฐ ์๋ค๋ฉด; ์ ํ๋ฅผ ๊ฑธ๊ณ ์ด์ ๋ํด ์ฑํ ํ๊ฒ ๋์ด ๊ธฐ์ฉ๋๋ค.
์ฌ์ฉ์ ์ ์ ์๋ฒ ๊ตฌํ์ผ๋ก getServerSideProps
๋ฅผ ์ฒ๋ฆฌํ๋ ๋ฐฉ๋ฒ์ ๋ฌด์์
๋๊น?
if (pathname === '/a') {
app.render(req, res, '/b', query)
}
์์ ์์์ /a
๋ฐฉ๋ฌธํ๋ฉด pages/b.js
ํ์ด์ง๊ฐ ๋ ๋๋ง๋ฉ๋๋ค. ๊ทธ๋ฌ๋ /a
๋ํ ํด๋ผ์ด์ธํธ ์ธก ๋ฆฌ๋๋ ์
์ ์ด ๊ฒฝ์ฐ์ ์กด์ฌํ์ง ์๋ a.json
ํ์ผ์ ๋ค์ด๋ก๋ํ๋ ค๊ณ ์๋ํฉ๋๋ค.
๋ค๋ฅธ JSON ํ์ผ์ ๋ ๋๋งํ๊ธฐ ์ํด /_next/data/{BUILD_ID}/{PAGE}.json
์ ๋ํ ์์ฒญ์ ๋ํด ์ ์ฌํ ์กฐ๊ฑด์ด ์์ด์ผ ํฉ๋๊น?
getStaticPaths์์ fallback: true
๋ฅผ ์ฌ์ฉํ๋ ค๋ฉด req ๊ฐ์ฒด๋ฅผ ์ด๋ป๊ฒ ์ป์ต๋๊น? ํ์ฌ๋ก์๋ ํ ์ ์๋ ๊ฒ์ผ๋ก ๋ณด์
๋๋ค. ๋ด๊ฐ ํ์ํ ์ด์ ๋ ๋ธ๋ผ์ฐ์ ์์ ์ผ๋ถ ์ฟ ํค๋ฅผ ๊ฐ์ ธ์ ๊ฒฝ๋ก๋ฅผ ์ธ์ฆํ๋ ๊ฒ์
๋๋ค.
@tylermcrobert ์์ฒญ์ด ์ ํ ์์ ๋ ์ฟ ํค๋ฅผ ์ก๋ ๊ฒ์ ์ด๋ป๊ฒ ์์ํฉ๋๊น?!
์ค์ ๋ฐฉ๋ฌธ์ ์์ฒญ์ ๋ฐ๋ผ ๋ฐฑ์๋๊ฐ ์๋ ๊ฒฝ๋ก๋ "์ ์ " ๋ฐ "๋์ "์ ์ ์์ ๋ฐ๋ผ ์ ์ ์ผ๋ก ๋ง๋ค ์ ์์ต๋๋ค. ์ ์ ๋ฐ ์ธ์ฆ์ ๊ฒฐํฉํ ์ ์๋ค๋ ๊ฒ์ ๋งํ ๊ฒ๋ ์๊ณ ... ์ธ์ฆ ๋ถ๋ถ์ ํ์ด์ง ๋์ API ๋ฐ ํด๋ผ์ด์ธํธ ์ฝ๋์ ์ํ ๋ฟ์
๋๋ค.
์ฌ์ฉ์ ์ ์ ์๋ฒ ๊ตฌํ์ผ๋ก
getServerSideProps
๋ฅผ ์ฒ๋ฆฌํ๋ ๋ฐฉ๋ฒ์ ๋ฌด์์ ๋๊น?if (pathname === '/a') { app.render(req, res, '/b', query) }
์์ ์์์
/a
๋ฐฉ๋ฌธํ๋ฉดpages/b.js
ํ์ด์ง๊ฐ ๋ ๋๋ง๋ฉ๋๋ค. ๊ทธ๋ฌ๋/a
๋ํ ํด๋ผ์ด์ธํธ ์ธก ๋ฆฌ๋๋ ์ ์ ์ด ๊ฒฝ์ฐ์ ์กด์ฌํ์ง ์๋a.json
ํ์ผ์ ๋ค์ด๋ก๋ํ๋ ค๊ณ ์๋ํฉ๋๋ค.๋ค๋ฅธ JSON ํ์ผ์ ๋ ๋๋งํ๊ธฐ ์ํด
/_next/data/{BUILD_ID}/{PAGE}.json
์ ๋ํ ์์ฒญ์ ๋ํด ์ ์ฌํ ์กฐ๊ฑด์ด ์์ด์ผ ํฉ๋๊น?
Next.js๋ ๋์ ๊ฒฝ๋ก ๋งค๊ฐ๋ณ์๋ฅผ ์ง์ํ๋ฏ๋ก ์ฌ์ฉ์ ์ง์ ์๋ฒ์์ ๋ค์ ๋งคํํ ํ์๊ฐ ๋ ์ด์ ๊ฑฐ์ ์์ต๋๋ค. https://nextjs.org/docs/routing/dynamic-routes
์ด๋ฏธ ์ค๋ช
ํ ์ ๊ทผ ๋ฐฉ์์ <Link>
์๋ํ์ง ์์ผ๋ฏ๋ก(์ ์ฒด ํ์ด์ง ์ ํ์ด ๋ฐ์ํจ) getServerSideProps๊ฐ ์ด๋ฏธ ์๋ํฉ๋๋ค.
@tylermcrobert ์์ฒญ์ด ์ ํ ์์ ๋ ์ฟ ํค๋ฅผ ์ก๋ ๊ฒ์ ์ด๋ป๊ฒ ์์ํฉ๋๊น?!
์ค์ ๋ฐฉ๋ฌธ์ ์์ฒญ์ ๋ฐ๋ผ ๋ฐฑ์๋๊ฐ ์๋ ๊ฒฝ๋ก๋ "์ ์ " ๋ฐ "๋์ "์ ์ ์์ ๋ฐ๋ผ ์ ์ ์ผ๋ก ๋ง๋ค ์ ์์ต๋๋ค. ์ ์ ๋ฐ ์ธ์ฆ์ ๊ฒฐํฉํ ์ ์๋ค๋ ๊ฒ์ ๋งํ ๊ฒ๋ ์๊ณ ... ์ธ์ฆ ๋ถ๋ถ์ ํ์ด์ง ๋์ API ๋ฐ ํด๋ผ์ด์ธํธ ์ฝ๋์ ์ํ ๋ฟ์ ๋๋ค.
์ด ๊ฒฝ์ฐ ๋์ฒด ์ต์ ์ ์คํดํ๊ณ ์๋ ๊ฒ์ผ ์ ์์ต๋๋ค. ๋น์ ์ด ๋งํ๋ ๊ฒ์ ๋น๋ ํ์ ์ปจํ ์คํธ์์ ์์ ํ ์๋ฏธ๊ฐ ์์ต๋๋ค.
๋ฏธ๋ฆฌ ์ ์๋ ๊ฒฝ๋ก๊ฐ ์์ ๋๋ฅผ ์ํ fallback: true
์๋๊ฐ์? ์ด ๊ฒฝ์ฐ ๋ธ๋ผ์ฐ์ ์์ ํด๋ฐฑ(fallback)์ ๋๋ฌํ ๊ฒ์
๋๋ค. ๊ทธ๋ ์ง ์์ต๋๊น?
@tylermcrobert yes fallback: true
์ผ์ด์ค์ ์์ฒญ์ด ์์ง๋ง API๋ "์ต์ ๊ณตํต ๋ถ๋ชจ"๋ก ํตํฉ๋์ด์ผ ํฉ๋๋ค. ๋ชจ๋ ๊ฒ์ด ํ๋์ ์ ์ ์ธํธ๋ก ๊ตฌ์ถ๋ ๋ค์ ์์ ํ ๋ค๋ฅธ ์ ์ ์ธํธ๋ก ์ ์ง์ ์ผ๋ก ์
๋ฐ์ดํธ๋๋ ์์
์์คํ
์ ์์ํ ์ ์์ต๋๋ค. ์ง์ํ๋ ๊ฒ์ ์ฌ์์ด ๋ ๊ฒ์
๋๋ค.
์ด๋ฌํ ์ฆ๋ถ ๋น๋๊ฐ ๋น๋ ๊ฐ์ ์ฌ์ ํ ์บ์๋๋ค๋ ์ ์ ๋์น๊ณ ์๋ค๊ณ ์๊ฐํฉ๋๋ค. ๋ฐ๋ผ์ ์ฒซ ๋ฒ์งธ ๋ฐฉ๋ฌธ์์ ์ญํ ์ ๋ชจ๋ ํ์ ์ฌ์ฉ์์ ๋น๋ ๊ฒฐ๊ณผ์ ์ํฅ์ ๋ฏธ์นฉ๋๋ค! ๋์ ์๊ฐ์ฒ๋ผ ๋ค๋ฆฝ๋๋ค.
@ivan-kleshnin ์ดํดํ๊ณ ํ์คํ ๋์ํฉ๋๋ค. ๋ด๊ฐ ๋ฌป๋ ์ด์ ๋ ๋ด ํน์ ์ฌ์ฉ ์ฌ๋ก ๋๋ฌธ์ ๋๋ค.
๋ฏธ๋ฆฌ๋ณด๊ธฐ ๊ธฐ๋ฅ์ ํ์ฉํ๋ ํค๋๋ฆฌ์ค CMS๋ฅผ ์ฌ์ฉํ๊ณ ์์ผ๋ฏ๋ก ๋ฏธ๋ฆฌ๋ณด๊ธฐ๊ฐ ํ์ํ ํ์ด์ง๋ ๋น๋ ์ ํฌํจ๋์ง ์์ต๋๋ค(๋ฏธ๋ฆฌ๋ณด๊ธฐ ์ค์ธ ํญ๋ชฉ์ด ์ด ์์ ์์ ์กด์ฌํ์ง ์๊ธฐ ๋๋ฌธ์ ๋๋ค). ๋๋ ์ด๊ฒ์ด ๋์ฒด ์ต์ ์ด ๋ค์ด์ค๋ ๊ฒฝ์ฐ๋ผ๊ณ ์๊ฐํ์ต๋๋ค.
ํด๋น ๋ฏธ๋ฆฌ๋ณด๊ธฐ์ ์ก์ธ์คํ๋ ค๋ฉด ์ฟ ํค๋ฅผ ํตํด ์ ๊ณต๋๋ api ๋ฏธ๋ฆฌ๋ณด๊ธฐ ์ฐธ์กฐ์ ์ก์ธ์คํด์ผ ํฉ๋๋ค.
useStaticProps
์์ ํ ํ๊ธฐํด์ผ ํ๋ ๊ฒฝ์ฐ์
๋๊น? ๋ด ๋ฌธ์๋ฅผ ๋ฏธ๋ฆฌ ๋ณผ ์ ์๊ธฐ ๋๋ฌธ์ ์ ์ ๋น๋์ ์ด์ ์ ์๊ณ ์ถ์ง ์์ต๋๋ค.
Gatsby์ ๊ฐ์ ๊ฒ์ ๋นํด ์ด RFC์ ๋งค๋ ฅ์ ํค๋๋ฆฌ์ค CMS๋ก ์์ ํ๋ ๋ฐ ๊ณ ํต์ ๋ ์ฃผ๋ ์ ์ ์ฌ์ดํธ ์์ฑ์ผ๋ก "ํ์ด๋ธ๋ฆฌ๋ ์ ์ด"๋ฅผ ์ ๊ณตํ๋ค๋ ๊ฒ์ ๋๋ค.
๋ฏธ๋ฆฌ๋ณด๊ธฐ ๊ธฐ๋ฅ์ ํ์ฉํ๋ ํค๋๋ฆฌ์ค CMS๋ฅผ ์ฌ์ฉํ๊ณ ์์ผ๋ฏ๋ก ๋ฏธ๋ฆฌ๋ณด๊ธฐ๊ฐ ํ์ํ ํ์ด์ง๋ ๋น๋ ์ ํฌํจ๋์ง ์์ต๋๋ค(๋ฏธ๋ฆฌ๋ณด๊ธฐ ์ค์ธ ํญ๋ชฉ์ด ์ด ์์ ์์ ์กด์ฌํ์ง ์๊ธฐ ๋๋ฌธ์ ๋๋ค). ๋๋ ์ด๊ฒ์ด ๋์ฒด ์ต์ ์ด ๋ค์ด์ค๋ ๊ฒฝ์ฐ๋ผ๊ณ ์๊ฐํ์ต๋๋ค.
๋ ๋นจ๋ฆฌ ์ง์ผ๋ด ์ฃผ์ธ์ ๐ต
๋ฐ๋ผ์ ์ด๊ฒ์ ์ฌ๋ฐ๋ฅด๊ฒ ์ดํดํ๋ฉด ์๋ฅผ ๋ค์ด ์ฌ์ฉ์๊ฐ ๋ฑ๋กํ ๋(์ ํ์ด์ง/์ฌ์ฉ์์ด๋ฏ๋ก ์ ์ ํ์ด์ง๊ฐ ์์ฑ๋์ง ์์) fallback true๋ฅผ ์ฌ์ฉํ ์ ์์ง๋ง ํ๋กํ์ด ๋ฐฉ๋ฌธ์ ๋ฐ์ผ๋ฉด ์๋์ผ๋ก ์์ฑ๋ฉ๋๊น?
์๋ฅดํ ์นด๋ผ๋ฐ๋์ฆ
http://www.erhankaradeniz.com
2020๋ 3์ 4์ผ 20์ 25๋ถ์ Tim Neutkens [email protected]์ด ๋ค์๊ณผ ๊ฐ์ด ์ผ์ต๋๋ค.
๋ฏธ๋ฆฌ๋ณด๊ธฐ ๊ธฐ๋ฅ์ ํ์ฉํ๋ ํค๋๋ฆฌ์ค CMS๋ฅผ ์ฌ์ฉํ๊ณ ์์ผ๋ฏ๋ก ๋ฏธ๋ฆฌ๋ณด๊ธฐ๊ฐ ํ์ํ ํ์ด์ง๋ ๋น๋ ์ ํฌํจ๋์ง ์์ต๋๋ค(๋ฏธ๋ฆฌ๋ณด๊ธฐ ์ค์ธ ํญ๋ชฉ์ด ์ด ์์ ์์ ์กด์ฌํ์ง ์๊ธฐ ๋๋ฌธ์ ๋๋ค). ๋๋ ์ด๊ฒ์ด ๋์ฒด ์ต์ ์ด ๋ค์ด์ค๋ ๊ฒฝ์ฐ๋ผ๊ณ ์๊ฐํ์ต๋๋ค.๋ ๋นจ๋ฆฌ ์ง์ผ๋ด ์ฃผ์ธ์ ๐ต
โ
๋น์ ์ด ์ธ๊ธ๋์๊ธฐ ๋๋ฌธ์ ์ด๊ฒ์ ๋ฐ๋ ๊ฒ์ ๋๋ค.
์ด ์ด๋ฉ์ผ์ ์ง์ ๋ต์ฅํ๊ฑฐ๋ GitHub์์ ๋ณด๊ฑฐ๋ ๊ตฌ๋ ์ ์ทจ์ํ์ธ์.
์ฌ์ฉ์ ๋ฐ์ดํฐ๋ ํด๋น ํด๋ผ์ด์ธํธ ์ธก์ ๊ฐ์ ธ์ค๋ ค๋ ๋์ ์์ ๋๋ค. ๋์ฒด๋ ๋น๋ ์ ์์ฑ๋์ง ์์ ํ์ด์ง๋ฅผ ์ ์ ์ผ๋ก ์์ฑํ๋ ์ฃผ๋ฌธํ ํ์ด์ง๋ฅผ ์ํ ๊ฒ์ ๋๋ค. ์๋ฅผ ๋ค์ด ๋น๋ ์ ์์ 100๊ฐ ๋ธ๋ก๊ทธ ๊ฒ์๋ฌผ์ ์์ฑํ๊ณ ํธ๋ํฝ์ด ์ ์ ๋ค๋ฅธ ๋ธ๋ก๊ทธ ๊ฒ์๋ฌผ์ ์์ฑํ์ง ์์ ์ ์์ต๋๋ค.
๋ฌธ์๋๊ตฌ๋ ๊ณง ์ ๊ณต๋ ๊ฒ์ ๋๋ค.
๋ค, ์ ๊ฐ ์๋ฏธํ ๊ฒ์ ์๋ฆฌ ํ์์ ํ์ด์ง์์ต๋๋ค. ์ค์ ๋ก ํด๋ผ์ด์ธํธ ์ธก์์ ์ฌ์ฉ์ ๋ฐ์ดํฐ๋ฅผ ๊ฐ์ ธ์ฌ ๊ฒ์ ๋๋ค.
@timneutkens ์ ์ ์ผ๋ก ์์ฑ๋ ํน์ ํ์ด์ง๋ฅผ ์ญ์ ํ๊ฑฐ๋ ๋ค์ ์์ฑํ๋ ๋ฐฉ๋ฒ์ด ์์ต๋๊น?
์๋ ํ์ธ์!!! ์ต์ ์ ์์ฉ ํ๋ก๊ทธ๋จ์ฒ๋ผ ๋ค๋ฆฝ๋๋ค. ๋๋ React์ Next๋ฅผ ๋ชจ๋ ์ฌ๋ํฉ๋๋ค!!! ์ฐ๋ฆฌ๊ฐ ์ฌ์ฉํ ์ ์๋๋ก ๋ชจ๋ ๊ฒ์ ์ฐ์ํ๊ณ ๊ฐ๋จํ๊ฒ ๋ง๋ค์์ต๋๋ค!! ๊ทธ๋ฌ๋ ์์ ์๋ ๊ฐ๋ ๋ธ๋ก๊ทธ๊ฐ ํฌํจ๋ฉ๋๋ค. Headless CMS๋ฅผ ์ฟผ๋ฆฌํ ๋ ๊ตฌํ์ ์๋ฅผ ๋ณด๊ณ ํ์ด์ง/๊ฒ์๋ฌผ๋น ๊ฐ์ ธ์ค๊ธฐ๋ฅผ ์ ์ ํญ๋ชฉ์ผ๋ก ๋ด๋ณด๋ด๊ธฐ๋ก ์ํํ๊ณ ์ถ์ต๋๋ค.
// ๊ธ์์ผ์ด ๊ฐ๊น์์ ๊ฑด๋ฐฐ!!!
@timneutkens ์ ๋๋ค์ ๐
์ฐ๋ฆฌ๊ฐ ์์ฃผ ์ ํ๋ ์๋๋ฆฌ์ค ์ค ํ๋๋ ๋์ ๊ฒฝ๋ก ๋๋ ๋ฃจํ์์ ํ๋ก์ ํธ ์์ฑ์ ์ ์ธํ๊ณ next.js ๋๋ gatsby์ ๋ํ ์๋ฒฝํ ์๋ฃจ์ ์ด ์์ง ์์ต๋๋ค.
์ญ์ฌ์ ์ด์ ๋ก ์ฐ๋ฆฌ๋ ๊ฐ๊ฒฉ, ํตํ, ์ง์ ์ ํ๋ฒํธ ๋ฐ ์ธ์ด ์ ํ๊ธฐ๋ฅผ ์ ์ธํ๊ณ ๋์ผ/์ ํํ ํ์ด์ง๋ฅผ ์ ๊ณตํ๋ ์ฌ๋ฌ ๋๋ฉ์ธ์ ์ฒ๋ฆฌํด์ผ ํฉ๋๋ค(์ด๋ฅผ ๋ณ๊ฒฝํ ์๊ฐ์ด ์์ต๋๋ค). ๋ณธ์ง์ ์ผ๋ก ์ด๋ฌํ ๋ง์ผํ ํ์ด์ง์ ๋๋ถ๋ถ์ ๋งค์ฐ ์ ์ ์ด๋ฉฐ ๋งค์ผ ๋๋ ๋งค์ฃผ ๊ตฌ์ถํ๋ ๊ฒ์ผ๋ก ์ถฉ๋ถํฉ๋๋ค(๋ชจ๋ ์์ฒญ์ โโ๋ํด ๋ ๋๋งํ๋๋ก ํ๋ ๊ฒ๊ณผ ๋น๊ต).
๋ด ์ง๋ฌธ/์๊ฐ: (๋ฏธ๋์?) getStaticPaths
๊ฐ ๊ฒฝ๋ก ๋งค๊ฐ๋ณ์๋ ์๋์ง๋ง ์์ฒญ ์์ค์์ ํ์ด์ง๋ฅผ ์ ํํ๋ ๋ฐ ์ฌ์ฉํ ์ ์๋ ํ์ด์ง๋ฅผ ์์ฑํ ์ ์๋ ๋ฐฉ๋ฒ์ด ์์ต๋๊น(์: ์๋ฒ๋ฆฌ์ค ํจ์๋ locale
๊ธฐ๋ฐ์ผ๋ก ์ฌ์ ๋น๋๋ ์ ์ ๊ฒฐ๊ณผ๋ฅผ ๋ฐํํฉ๋๋ค.
๊ตฌ์ฒด์ ์ผ๋ก ์ด๊ฒ์ https://mysite.com/my-product
๋ฐ https://mysite.co.uk/my-product
๊ฐ ๋ ๊ฐ์ ๋ค๋ฅธ ์ ์ ํ์ด์ง๋ฅผ ์ ๊ณตํ์ง๋ง ๋ค์ ์ฑ์ 50๋ฐฐ ์์ฑํ๊ฑฐ๋ ๋ชจ๋ ์์ฒญ์ โโ๋ํด CMS๋ฅผ ๋๋ฅด์ง ์์๋ ๋๋ค๋ ๊ฒ์ ์๋ฏธํฉ๋๋ค.
๋ฏธ๋ฆฌ ๊ฐ์ฌ๋๋ฆฝ๋๋ค. ํนํ ๊ทธ๊ฒ์ด ๋ฏธ๋๋ฅผ ์ํด ํด๊ฒฐ/ํด๊ฒฐ๋ ์ ์๋ ๊ฒ์ด๋ผ๋ฉด ์ฌ๋ฌ๋ถ์ ์๊ฐ์ ๋ฃ๊ณ ์ถ์ต๋๋ค โค๏ธ
SEO๋ฅผ ์ํด ํธ๋ํฝ์ด ๋ง์ ๋ฐฉ๋ฌธ ํ์ด์ง์ ์๋ฒ ๋ถํ๋ฅผ ์ค์ด๊ธฐ ์ํด SSG๋ฅผ ์ฌ์ฉํ๊ณ ์ถ์ง๋ง ์ํ ํ ํ์ฌ ๋ฐ์ดํฐ๋ฅผ ์ฌ์ฉํ๊ณ ์ด ํ์ด์ง๋ก์ ํด๋ผ์ด์ธํธ ์ธก ๋ผ์ฐํ ์ ์ํ๋ ์ฌ์ฉ ์ฌ๋ก์ ๋ํด ์๊ฐํ๊ณ ์์ต๋๋ค. ๊ทธ๊ฒ ๊ฐ๋ฅํ ๊น์?
๋ฐ๋ผ์ ๊ธฐ๋ณธ์ ์ผ๋ก ์ด ํ์ด์ง๋ก์ ํด๋ผ์ด์ธํธ ์ธก ๋ผ์ฐํ
์์ ๋์์ getInitialProps
์ ๊ฐ์์ผ ํฉ๋๋ค(ํ์ฌ ๋ฐ์ดํฐ๋ ํ์ด์ง๊ฐ ํ์๋๊ธฐ ์ ์ ๊ฐ์ ธ์ด). ๊ทธ๋ฆฌ๊ณ ์ด ํ์ด์ง๋ก์ ์๋ฒ ์ธก ๋ผ์ฐํ
์์ ์ ์ html์ด ์ ๊ณต๋๊ณ ์ํ๋์ด์ผ ํ๋ฉฐ (์ ํ ์ฌํญ) ํ์ด์ง์ ์ผ๋ถ ๋ฐ์ดํฐ๋ฅผ ์
๋ฐ์ดํธํ๊ธฐ ์ํด ์ผ๋ถ API ์๋ต์ ๊ฐ์ ธ์์ผ ํฉ๋๋ค.
๋ฐฉ๊ธ unstable_getStaticProps
๋ฅผ ์ฌ์ฉํด ๋ณด์๋๋ฐ ์ฌ๋ฏธ์๋ ์ถฉ๋์ด ๋ฐ์ํ์ต๋๋ค. getStaticProps
์ API ๊ฒฝ๋ก๋ฅผ ์ฌ์ฉํ๋ ๊ฒ์ ์ด๋ ต์ต๋๋ค.
์ฝ๋์ ์๋ฏธ์ ์ฃผ์๋ฅผ ๊ธฐ์ธ์ด์ง ๋ง๊ณ ๋ฐ์ดํฐ ๊ฐ์ ธ์ค๊ธฐ ํ๋ฆ์๋ง ์ฃผ์ํ์ญ์์ค.
// pages/api/healthcheck.ts
import { NextApiResponse, NextApiRequest } from 'next';
export type ApiHealthCheckResponse = {
message: 'ok';
};
const healthCheckHandler = (
req: NextApiRequest,
res: NextApiResponse<ApiHealthCheckResponse | ''>,
) => {
if (req.method === 'GET') {
return res.status(200).json({ message: 'ok' });
}
return res.status(405).send('');
};
export default healthCheckHandler;
// pages/index.js
// ...
export async function unstable_getStaticProps() {
return {
props: {
healthcheck: (await fetch('localhost:3000/api/healthcheck').json())
},
};
}
์๋ฒ๊ฐ ์คํ๋๊ณ ์์ง ์๊ธฐ ๋๋ฌธ์ ํ์ด์ง ๋น๋๊ฐ ๋น๋ ์ ์ถฉ๋ํฉ๋๋ค. getStaticProps
๊ฐ ๋๋ฌด ๋์ ์ธ ๊ฒ๊ณผ ํจ๊ป ์ฌ์ฉ๋์ด์๋ ์ ๋๋ฏ๋ก ์ด๊ฒ์ด ์ ํจํ ์ฌ์ฉ ์ฌ๋ก์ธ์ง ํ์คํ์ง ์์ง๋ง ๊ณต์ ํ ์ ์๋ ํฅ๋ฏธ๋ก์ด ์ฌ๋ก๋ผ๊ณ ์๊ฐํ์ต๋๋ค. ๋ค๋ฅธ API์์ ๋ฐ์ดํฐ๋ฅผ ๊ฐ์ ธ์์ ๋ค์ ํฌ๋งทํ์ญ์์ค.
@martpie ์ด ๋๊ธ์ ํ์ธํ๊ณ ์ถ์ ์๋ ์์ต๋๋ค: https://github.com/zeit/next.js/issues/9524#issuecomment -589772756
Next.js 9.3์์ ์ฐจ์ธ๋ SSG(์ ์ ์ฌ์ดํธ ์์ฑ) ์ง์์ด ์์ ์ ์ผ๋ก ๋ฆด๋ฆฌ์ค๋์์ต๋๋ค!
์ด ๋ฆด๋ฆฌ์ค๋ ๋ํ "๋ฏธ๋ฆฌ๋ณด๊ธฐ ๋ชจ๋"์ ๋ํ ์ง์, ๋๋ ์ ์ ์ผ๋ก ์ฌ์ ๋ ๋๋ง ๋ ํ์ด์ง ์ฐํ ํ ์์๋ ๊ธฐ๋ฅ์ ํฌํจํ๊ณ ์ฃผ๋ฌธํ ๊ถํ์ด ๋ถ์ฌ ๋ ์ฌ์ฉ์์ ํ์ด์ง๋ฅผ ๋ ๋๋งํฉ๋๋ค.
์์ธํ ๋ด์ฉ์ ๋ธ๋ก๊ทธ ๊ฒ์๋ฌผ ์์ ํ์ธํ ์ ์์ต๋๋ค. ๋ ๋ง์ ์์ ์ ์ํํ๋ ค๋ฉด ๋ฌธ์ ๋ก ๋ฐ๋ก ์ด๋ํ์ญ์์ค!
Next.js GitHub ์ปค๋ฎค๋ํฐ์ ์ง๋ฌธ์ ๊ฒ์ํ์ธ์!
์ด๊ฑฐ ๋๋ฐ! ๋ ธ๊ณ ์ ๊ฐ์ฌ๋๋ฆฝ๋๋ค!
์ด ์๋ก์ด ๊ธฐ๋ฅ์ ํ์ฌ saga ๋ฐ redux์์ ์๋ํ์ง ์๋ ๊ฒ ๊ฐ์ต๋๋ค.
๊ฐ์ฅ ์ ์ฉํ ๋๊ธ
Next.js 9.3์์ ์ฐจ์ธ๋ SSG(์ ์ ์ฌ์ดํธ ์์ฑ) ์ง์์ด ์์ ์ ์ผ๋ก ๋ฆด๋ฆฌ์ค๋์์ต๋๋ค!
์ด ๋ฆด๋ฆฌ์ค๋ ๋ํ "๋ฏธ๋ฆฌ๋ณด๊ธฐ ๋ชจ๋"์ ๋ํ ์ง์, ๋๋ ์ ์ ์ผ๋ก ์ฌ์ ๋ ๋๋ง ๋ ํ์ด์ง ์ฐํ ํ ์์๋ ๊ธฐ๋ฅ์ ํฌํจํ๊ณ ์ฃผ๋ฌธํ ๊ถํ์ด ๋ถ์ฌ ๋ ์ฌ์ฉ์์ ํ์ด์ง๋ฅผ ๋ ๋๋งํฉ๋๋ค.
์์ธํ ๋ด์ฉ์ ๋ธ๋ก๊ทธ ๊ฒ์๋ฌผ ์์ ํ์ธํ ์ ์์ต๋๋ค. ๋ ๋ง์ ์์ ์ ์ํํ๋ ค๋ฉด ๋ฌธ์ ๋ก ๋ฐ๋ก ์ด๋ํ์ญ์์ค!