diff --git a/.all-contributorsrc b/.all-contributorsrc index 071a7a9..3e9240c 100644 --- a/.all-contributorsrc +++ b/.all-contributorsrc @@ -132,6 +132,87 @@ "contributions": [ "content" ] + }, + { + "login": "yoonncho", + "name": "yoon", + "avatar_url": "https://avatars.githubusercontent.com/u/49135797?v=4", + "profile": "https://github.com/yoonncho", + "contributions": [ + "content" + ] + }, + { + "login": "SoJuSo", + "name": "SeokJu Kim", + "avatar_url": "https://avatars.githubusercontent.com/u/90549862?v=4", + "profile": "https://shqpdltm.tistory.com/", + "contributions": [ + "content" + ] + }, + { + "login": "grapefruit13", + "name": "grapefruit", + "avatar_url": "https://avatars.githubusercontent.com/u/92169354?v=4", + "profile": "https://github.com/grapefruit13", + "contributions": [ + "content" + ] + }, + { + "login": "RedBe-an", + "name": "RedBean", + "avatar_url": "https://avatars.githubusercontent.com/u/161127101?v=4", + "profile": "https://github.com/RedBe-an", + "contributions": [ + "content" + ] + }, + { + "login": "therealjamesjung", + "name": "Jaekyung Jung", + "avatar_url": "https://avatars.githubusercontent.com/u/39877377?v=4", + "profile": "https://velog.io/@therealjamesjung", + "contributions": [ + "content" + ] + }, + { + "login": "ironAiken2", + "name": "SungChul Hong", + "avatar_url": "https://avatars.githubusercontent.com/u/51399982?v=4", + "profile": "https://github.com/ironAiken2", + "contributions": [ + "content" + ] + }, + { + "login": "miraexhoi", + "name": "최미래", + "avatar_url": "https://avatars.githubusercontent.com/u/109408165?v=4", + "profile": "https://linktr.ee/miraexhoi", + "contributions": [ + "content" + ] + }, + { + "login": "Zero-1016", + "name": "Zero", + "avatar_url": "https://avatars.githubusercontent.com/u/115636461?v=4", + "profile": "https://velog.io/@jihyeong00", + "contributions": [ + "content" + ] + }, + { + "login": "yoouyeon", + "name": "Yoon Jeongyeon", + "avatar_url": "https://avatars.githubusercontent.com/u/57761286?v=4", + "profile": "https://github.com/yoouyeon", + "contributions": [ + "content" + ] } ], "contributorsPerLine": 7, diff --git a/README.md b/README.md index 24fd473..d2b5ff8 100644 --- a/README.md +++ b/README.md @@ -18,7 +18,7 @@ - `nextjs.org` -> `nextjs-ko.org` 도메인 변경 만으로 한국어 문서의 동등한 접근을 목표로 합니다. - 현재(2024.07.24) App Router 번역 초안이 완료된 상태입니다. -- Pages Router 부분 번역과 대부분의 문서에 대한 소제목 변경, 어투 변경 등의 전반적인 기여를 필요로 합니다. 많이 참여해주세요..!! +- Pages Router 부분 번역과 대부분의 문서에 대한 소제목 변경, 어투 변경 등의 전반적인 기여를 필요로 합니다. ## 번역에 참여하고 싶나요? @@ -26,26 +26,26 @@ ## Contributors ✨ -[![All Contributors](https://img.shields.io/github/all-contributors/luciancah/nextjs-ko?color=ee8449&style=flat-square)](#contributors) - -Thanks goes to these wonderful people ([emoji key](https://allcontributors.org/docs/en/emoji-key)): +감사합니다 🥰 + ```html + - - - - - - - + + + + + + + - + @@ -53,6 +53,20 @@ Thanks goes to these wonderful people ([emoji key](https://allcontributors.org/d + + + + + + + + + + + + + +
Jinhyung Lee
Jinhyung Lee

📖
MINSU KIM
MINSU KIM

🖋
sanghyeon
sanghyeon

🖋
Hansol Olivia Kim
Hansol Olivia Kim

🖋
gkfyr
gkfyr

🖋
Heesun
Heesun

🖋
Suhyeon Park
Suhyeon Park

🖋
Jinhyung Lee
Jinhyung Lee

📖
MINSU KIM
MINSU KIM

🖋
sanghyeon
sanghyeon

🖋
Hansol Olivia Kim
Hansol Olivia Kim

🖋
gkfyr
gkfyr

🖋
Heesun
Heesun

🖋
Suhyeon Park
Suhyeon Park

🖋
kinsk2839
kinsk2839

🖋
kinsk2839
kinsk2839

🖋
송우영
송우영

🖋
mihee
mihee

🖋
JIYEON KIM
JIYEON KIM

🖋
신종욱
신종욱

🖋
김학재
김학재

🖋
yoon
yoon

🖋
SeokJu Kim
SeokJu Kim

🖋
grapefruit
grapefruit

🖋
RedBean
RedBean

🖋
Jaekyung Jung
Jaekyung Jung

🖋
SungChul Hong
SungChul Hong

🖋
최미래
최미래

🖋
Zero
Zero

🖋
Yoon Jeongyeon
Yoon Jeongyeon

🖋
diff --git a/pages/docs/pages/api-reference/functions/get-server-side-props.mdx b/pages/docs/pages/api-reference/functions/get-server-side-props.mdx index 40cc61c..9fcd345 100644 --- a/pages/docs/pages/api-reference/functions/get-server-side-props.mdx +++ b/pages/docs/pages/api-reference/functions/get-server-side-props.mdx @@ -3,11 +3,9 @@ title: getServerSideProps description: API reference for `getServerSideProps`. Learn how to fetch data on each request with Next.js. --- -{/* TODO: 번역이 필요합니다. */} - # getServerSideProps -When exporting a function called `getServerSideProps` (Server-Side Rendering) from a page, Next.js will pre-render this page on each request using the data returned by `getServerSideProps`. This is useful if you want to fetch data that changes often, and have the page update to show the most current data. +페이지에서 `getServerSideProps` (서버 사이드 렌더링)이라는 함수를 내보내면, Next.js는 `getServerSideProps`에서 반환된 데이터를 사용해 각 요청마다 페이지를 사전 렌더링합니다. 이는 자주 변경되는 데이터를 가져오고, 페이지를 최신 데이터로 업데이트하려는 경우 유용합니다. ```tsx filename="pages/index.tsx" switcher import type { InferGetServerSidePropsType, GetServerSideProps } from 'next' @@ -18,10 +16,10 @@ type Repo = { } export const getServerSideProps = (async () => { - // Fetch data from external API + // 외부 API에서 데이터를 가져옵니다. const res = await fetch('https://api.github.com/repos/vercel/next.js') const repo: Repo = await res.json() - // Pass data to the page via props + // props를 통해 페이지에 데이터를 전달합니다. return { props: { repo } } }) satisfies GetServerSideProps<{ repo: Repo }> @@ -38,10 +36,10 @@ export default function Page({ ```jsx filename="pages/index.js" switcher export async function getServerSideProps() { - // Fetch data from external API + // 외부 API에서 데이터를 가져옵니다. const res = await fetch('https://api.github.com/repos/vercel/next.js') const repo = await res.json() - // Pass data to the page via props + // props를 통해 페이지에 데이터를 전달합니다. return { props: { repo } } } @@ -54,45 +52,45 @@ export default function Page({ repo }) { } ``` -You can import modules in top-level scope for use in `getServerSideProps`. Imports used will **not be bundled for the client-side**. This means you can write **server-side code directly in `getServerSideProps`**, including fetching data from your database. +`getServerSideProps`에서 사용하기 위해 상위 레벨 범위에서 모듈을 가져올 수 있습니다. 사용된 임포트는 **클라이언트 사이드에 번들되지 않습니다.** 이는 데이터베이스에서 데이터를 가져오는 것을 포함해 **`getServerSideProps` 내에서 서버 사이드 코드를 직접 작성할 수 있음을 의미합니다**. ## Context parameter -The `context` parameter is an object containing the following keys: - -| Name | Description | -| --------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| `params` | If this page uses a [dynamic route](/docs/pages/building-your-application/routing/dynamic-routes), `params` contains the route parameters. If the page name is `[id].js`, then `params` will look like `{ id: ... }`. | -| `req` | [The `HTTP` IncomingMessage object](https://nodejs.org/api/http.html#http_class_http_incomingmessage), with an additional `cookies` prop, which is an object with string keys mapping to string values of cookies. | -| `res` | [The `HTTP` response object](https://nodejs.org/api/http.html#http_class_http_serverresponse). | -| `query` | An object representing the query string, including dynamic route parameters. | -| `preview` | (Deprecated for `draftMode`) `preview` is `true` if the page is in the [Preview Mode](/docs/pages/building-your-application/configuring/preview-mode) and `false` otherwise. | -| `previewData` | (Deprecated for `draftMode`) The [preview](/docs/pages/building-your-application/configuring/preview-mode) data set by `setPreviewData`. | -| `draftMode` | `draftMode` is `true` if the page is in the [Draft Mode](/docs/pages/building-your-application/configuring/draft-mode) and `false` otherwise. | -| `resolvedUrl` | A normalized version of the request `URL` that strips the `_next/data` prefix for client transitions and includes original query values. | -| `locale` | Contains the active locale (if enabled). | -| `locales` | Contains all supported locales (if enabled). | -| `defaultLocale` | Contains the configured default locale (if enabled). | +`context` 매개변수는 다음 키를 포함하는 객체입니다: + +| Name | Description | +| --------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| `params` | 이 페이지가 [동적 라우트](/docs/pages/building-your-application/routing/dynamic-routes)를 사용하는 경우, `params`에는 라우트 매개변수가 포함됩니다. 페이지 이름이 `[id].js`면, `params`는 `{ id: ... }`와 같이 표시됩니다. | +| `req` | 추가적인 `cookies` prop이 있는 [The HTTP IncomingMessage 객체](https://nodejs.org/api/http.html#http_class_http_incomingmessage)이며, 이는 문자열 값을 가진 쿠키의 문자열 키를 매핑하는 객체입니다. | +| `res` | [The `HTTP` response 객체](https://nodejs.org/api/http.html#http_class_http_serverresponse)입니다. | +| `query` | 동적 라우트 매개변수를 포함한 쿼리 문자열을 나타내는 객체입니다. | +| `preview` | (`draftMode`로 대체 예정) 페이지가 [미리보기 모드](/docs/pages/building-your-application/configuring/preview-mode)에 있는 경우 `preview`는 `true`이고, 그렇지 않으면 `false`입니다. | +| `previewData` | (`draftMode`로 대체 예정) `setPreviewData`에 의해 설정된 [미리보기](/docs/pages/building-your-application/configuring/preview-mode) 데이터입니다. | +| `draftMode` | 페이지가 [Draft Mode](/docs/pages/building-your-application/configuring/draft-mode)에 있는 경우 `draftMode`는 `true`이고, 그렇지 않으면 `false`입니다. | +| `resolvedUrl` | 클라이언트 전환을 위한 `_next/data` 접두사를 제거하고 원래 쿼리 값을 포함하는 요청 `URL`의 정규화된 버전입니다. | +| `locale` | 활성 로케일이 포함됩니다. (활성화된 경우) | +| `locales` | 지원되는 모든 로케일이 포함됩니다. (활성화된 경우) | +| `defaultLocale` | 설정된 기본 로케일이 포함됩니다. (활성화된 경우) | ## getServerSideProps return values -The `getServerSideProps` function should return an object with **any one of the following** properties: +`getServerSideProps` 함수는 **다음 속성 중 하나를 가진 객체**를 반환해야 합니다: ### `props` -The `props` object is a key-value pair, where each value is received by the page component. It should be a [serializable object](https://developer.mozilla.org/docs/Glossary/Serialization) so that any props passed, could be serialized with [`JSON.stringify`](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/JSON/stringify). +`props` 객체는 페이지 컴포넌트가 받는 키-값 쌍입니다. 전달된 모든 props가 [`JSON.stringify`](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/JSON/stringify)로 직렬화될 수 있도록 [직렬화 가능한 객체](https://developer.mozilla.org/docs/Glossary/Serialization)여야 합니다. ```jsx export async function getServerSideProps(context) { return { - props: { message: `Next.js is awesome` }, // will be passed to the page component as props + props: { message: `Next.js is awesome` }, // 페이지 컴포넌트에 props로 전달됩니다. } } ``` ### `notFound` -The `notFound` boolean allows the page to return a `404` status and [404 Page](/docs/pages/building-your-application/routing/custom-error#404-page). With `notFound: true`, the page will return a `404` even if there was a successfully generated page before. This is meant to support use cases like user-generated content getting removed by its author. +`notFound` 불리언 값은 페이지가 `404` 상태와 [404 Page](/docs/pages/building-your-application/routing/custom-error#404-page)를 반환하도록 합니다. `notFound: true`인 경우, 이전에 성공적으로 생성된 페이지가 있어도 페이지는 404를 반환합니다. 이는 사용자 생성 콘텐츠가 작성자에 의해 제거되는 경우와 같은 사용 사례를 지원하기 위함입니다. ```js export async function getServerSideProps(context) { @@ -106,14 +104,14 @@ export async function getServerSideProps(context) { } return { - props: { data }, // will be passed to the page component as props + props: { data }, // 페이지 컴포넌트에 props로 전달됩니다. } } ``` ### `redirect` -The `redirect` object allows redirecting to internal and external resources. It should match the shape of `{ destination: string, permanent: boolean }`. In some rare cases, you might need to assign a custom status code for older `HTTP` clients to properly redirect. In these cases, you can use the `statusCode` property instead of the `permanent` property, but not both. +`redirect` 객체는 내부 및 외부 리소스로 리디렉션을 허용합니다. 이는 `{ destination: string, permanent: boolean }`의 형태와 일치해야 합니다. 드물게, 이전 `HTTP` 클라이언트가 제대로 리디렉션되도록 사용자 정의 상태 코드를 할당해야 할 수도 있습니다. 이러한 경우, `permanent` 속성 대신 `statusCode` 속성을 사용할 수 있지만, 둘 다 사용할 수는 없습니다. ```js export async function getServerSideProps(context) { @@ -130,15 +128,15 @@ export async function getServerSideProps(context) { } return { - props: {}, // will be passed to the page component as props + props: {}, // 페이지 컴포넌트에 props로 전달됩니다. } } ``` ## Version History -| Version | Changes | -| --------- | ----------------------------------------------------------------------------------------------------------- | -| `v13.4.0` | [App Router](/docs/app/building-your-application/data-fetching) is now stable with simplified data fetching | -| `v10.0.0` | `locale`, `locales`, `defaultLocale`, and `notFound` options added. | -| `v9.3.0` | `getServerSideProps` introduced. | +| Version | Changes | +| --------- | ------------------------------------------------------------------------------------------------------------------ | +| `v13.4.0` | [App Router](/docs/app/building-your-application/data-fetching)가 안정화되었고, 단순화된 데이터 페칭을 지원합니다. | +| `v10.0.0` | `locale`, `locales`, `defaultLocale`, 및 `notFound` 옵션이 추가되었습니다. | +| `v9.3.0` | `getServerSideProps`가 도입되었습니다. | diff --git a/pages/docs/pages/api-reference/next-config-js/runtime-configuration.mdx b/pages/docs/pages/api-reference/next-config-js/runtime-configuration.mdx index bcb6dac..ec85166 100644 --- a/pages/docs/pages/api-reference/next-config-js/runtime-configuration.mdx +++ b/pages/docs/pages/api-reference/next-config-js/runtime-configuration.mdx @@ -9,43 +9,43 @@ description: Add client and server runtime configuration to your Next.js app. > **Warning:** > -> - **This feature is deprecated.** We recommend using [environment variables](/docs/pages/building-your-application/configuring/environment-variables) instead, which also can support reading runtime values. -> - You can run code on server startup using the [`register` function](/docs/app/building-your-application/optimizing/instrumentation). -> - This feature does not work with [Automatic Static Optimization](/docs/pages/building-your-application/rendering/automatic-static-optimization), [Output File Tracing](/docs/pages/api-reference/next-config-js/output#automatically-copying-traced-files), or [React Server Components](/docs/app/building-your-application/rendering/server-components). +> - **이 기능은 사용 중단되었습니다.** 대신 [환경 변수](/docs/pages/building-your-application/configuring/environment-variables) 를 사용하는 것을 권장합니다. 이 방법은 런타임 값을 읽는 것도 지원할 수 있습니다. +> - 서버 시작 시 코드를 실행하려면[`register` 함수](/docs/app/building-your-application/optimizing/instrumentation)를 사용할 수 있습니다. +> - 이 기능은 [자동 정적 최적화](/docs/pages/building-your-application/rendering/automatic-static-optimization), [출력 파일 추적](/docs/pages/api-reference/next-config-js/output#automatically-copying-traced-files), or [React 서버 컴포넌트](/docs/app/building-your-application/rendering/server-components) 와 함께 작동하지 않습니다. -To add runtime configuration to your app, open `next.config.js` and add the `publicRuntimeConfig` and `serverRuntimeConfig` configs: +앱에 런타임 구성을 추가하려면 next.config.js를 열고 publicRuntimeConfig 및 serverRuntimeConfig 구성을 추가하십시오: ```js filename="next.config.js" module.exports = { serverRuntimeConfig: { - // Will only be available on the server side + // 서버 측에서만 사용할 수 있습니다. mySecret: 'secret', - secondSecret: process.env.SECOND_SECRET, // Pass through env variables + secondSecret: process.env.SECOND_SECRET, // 환경 변수를 통해 전달 }, publicRuntimeConfig: { - // Will be available on both server and client + // 서버와 클라이언트 모두에서 사용할 수 있습니다. staticFolder: '/static', }, } ``` -Place any server-only runtime config under `serverRuntimeConfig`. +서버 전용 런타임 구성은 serverRuntimeConfig 아래에 배치하십시오. -Anything accessible to both client and server-side code should be under `publicRuntimeConfig`. +클라이언트 및 서버 측 코드에서 모두 접근할 수 있는 항목은 `publicRuntime₩Config` 아래에 배치하십시오. -> A page that relies on `publicRuntimeConfig` **must** use `getInitialProps` or `getServerSideProps` or your application must have a [Custom App](/docs/pages/building-your-application/routing/custom-app) with `getInitialProps` to opt-out of [Automatic Static Optimization](/docs/pages/building-your-application/rendering/automatic-static-optimization). Runtime configuration won't be available to any page (or component in a page) without being server-side rendered. +> `publicRuntimeConfig` 에 의존하는 페이지는 **반드시** `getInitialProps` 또는 `getServerSideProps` 를 사용하거나, [Custom App](/docs/pages/building-your-application/routing/custom-app) 과 함께 `getInitialProps` 를 사용하여 [자동 정적 최적화](/docs/pages/building-your-application/rendering/automatic-static-optimization) 를 선택 해제해야 합니다. 런타임 구성은 서버 측 렌더링이 없는 페이지(또는 페이지 내의 컴포넌트)에는 사용할 수 없습니다. -To get access to the runtime configs in your app use `next/config`, like so: +앱에서 런타임 구성에 액세스하려면 `next/config`를 사용하십시오: ```jsx import getConfig from 'next/config' import Image from 'next/image' -// Only holds serverRuntimeConfig and publicRuntimeConfig +// serverRuntimeConfig와 publicRuntimeConfig만 포함합니다. const { serverRuntimeConfig, publicRuntimeConfig } = getConfig() -// Will only be available on the server-side +// 서버사이드 에서만 사용 가능합니다. console.log(serverRuntimeConfig.mySecret) -// Will be available on both server-side and client-side +// 서버사이드 및 클라이언트사이드에서 모두 사용 가능합니다. console.log(publicRuntimeConfig.staticFolder) function MyImage() { diff --git a/pages/docs/pages/building-your-application/Rendering.mdx b/pages/docs/pages/building-your-application/Rendering.mdx index b6eb504..ba1ab45 100644 --- a/pages/docs/pages/building-your-application/Rendering.mdx +++ b/pages/docs/pages/building-your-application/Rendering.mdx @@ -3,23 +3,21 @@ title: Rendering description: Learn the fundamentals of rendering in React and Next.js. --- -{/* TODO: 번역이 필요합니다. */} - # Rendering -By default, Next.js **pre-renders** every page. This means that Next.js generates HTML for each page in advance, instead of having it all done by client-side JavaScript. Pre-rendering can result in better performance and SEO. +기본적으로 Next.js는 모든 페이지를 **사전 렌더링**합니다. 이는 클라이언트 사이드 JavaScript가 아닌 Next.js가 각 페이지의 HTML을 생성하는 것을 의미합니다. 사전 렌더링은 성능과 SEO(검색 엔진 최적화)를 개선할 수 있습니다. -Each generated HTML is associated with minimal JavaScript code necessary for that page. When a page is loaded by the browser, its JavaScript code runs and makes the page fully interactive (this process is called [hydration](https://react.dev/reference/react-dom/client/hydrateRoot) in React). +생성된 각 HTML에는 해당 페이지에 필요한 최소한의 JavaScript 코드만 포함됩니다. 페이지가 브라우저에서 로드되면, JavaScript 코드가 실행되어 그 페이지를 완전히 인터렉티브하게 만듭니다. (이 과정을 React에서는 [하이드레이션](https://react.dev/reference/react-dom/client/hydrateRoot)이라고 부릅니다.) ### Pre-rendering -Next.js has two forms of pre-rendering: **Static Generation** and **Server-side Rendering**. The difference is in **when** it generates the HTML for a page. +Next.js는 **정적 생성**과 **서버 사이드 렌더링**이라는 두 가지 형태의 사전 렌더링을 지원합니다. 두 방식의 차이는 **언제** 페이지의 HTML이 생성되는가에 있습니다. -- Static Generation: The HTML is generated at **build time** and will be reused on each request. -- Server-side Rendering: The HTML is generated on **each request**. +- 정적 생성: HTML이 **빌드 시점**에 생성되며, 이후 모든 요청에서 재사용됩니다. +- 서버 사이드 렌더링: HTML이 **각 요청 시점**에 생성됩니다. -Importantly, Next.js lets you choose which pre-rendering form you'd like to use for each page. You can create a "hybrid" Next.js app by using Static Generation for most pages and using Server-side Rendering for others. +중요한 점은, Next.js가 각 페이지별로 사용할 사전 렌더링 방식을 선택할 수 있게 해준다는 것입니다. 대부분의 페이지에는 정적 생성을 사용하고, 특정 페이지에서는 서버 사이드 렌더링을 사용함으로써 "하이브리드" Next.js 앱을 만들 수 있습니다. -We recommend using Static Generation over Server-side Rendering for performance reasons. Statically generated pages can be cached by CDN with no extra configuration to boost performance. However, in some cases, Server-side Rendering might be the only option. +성능상의 이유로 서버 사이드 렌더링보다는 정적 생성 방식을 사용하는 것을 권장합니다. 정적으로 생성된 페이지는 추가 설정 없이 CDN에 의해 캐시될 수 있어 성능이 향상됩니다. 그러나 경우에 따라 서버 사이드 렌더링이 유일한 선택일 수 있습니다. -You can also use client-side data fetching along with Static Generation or Server-side Rendering. That means some parts of a page can be rendered entirely by clientside JavaScript. To learn more, take a look at the [Data Fetching](/docs/pages/building-your-application/data-fetching/client-side) documentation. +또한, 정적 생성이나 서버 사이드 렌더링과 함께 클라이언트 사이드 데이터 페칭을 사용할 수도 있습니다. 이는 페이지의 일부가 클라이언트 JavaScript로 완전히 렌더링될 수도 있다는 것을 의미합니다. 자세한 내용은 [데이터 페칭](/docs/pages/building-your-application/data-fetching/client-side) 문서를 참고하세요. diff --git a/pages/docs/pages/building-your-application/configuring/post-css.mdx b/pages/docs/pages/building-your-application/configuring/post-css.mdx index 635052f..9c4f1ac 100644 --- a/pages/docs/pages/building-your-application/configuring/post-css.mdx +++ b/pages/docs/pages/building-your-application/configuring/post-css.mdx @@ -3,46 +3,42 @@ title: PostCSS description: Extend the PostCSS config and plugins added by Next.js with your own. --- -{/* TODO: 번역이 필요합니다. */} - # PostCSS
- Examples + 예시 -- [Tailwind CSS Example](https://github.com/vercel/next.js/tree/canary/examples/with-tailwindcss) +- [Tailwind CSS 예시](https://github.com/vercel/next.js/tree/canary/examples/with-tailwindcss)
## Default Behavior -Next.js compiles CSS for its [built-in CSS support](/docs/pages/building-your-application/styling) using PostCSS. +Next.js는 [내장 CSS 지원](/docs/pages/building-your-application/styling)을 위해 PostCSS를 사용하여 CSS를 컴파일합니다. -Out of the box, with no configuration, Next.js compiles CSS with the following transformations: +별도의 설정 없이도 Next.js는 다음과 같은 변환을 통해 CSS를 컴파일합니다: -- [Autoprefixer](https://github.com/postcss/autoprefixer) automatically adds vendor prefixes to CSS rules (back to IE11). -- [Cross-browser Flexbox bugs](https://github.com/philipwalton/flexbugs) are corrected to behave like [the spec](https://www.w3.org/TR/css-flexbox-1/). -- New CSS features are automatically compiled for Internet Explorer 11 compatibility: - - [`all` Property](https://developer.mozilla.org/docs/Web/CSS/all) - - [Break Properties](https://developer.mozilla.org/docs/Web/CSS/break-after) - - [`font-variant` Property](https://developer.mozilla.org/docs/Web/CSS/font-variant) - - [Gap Properties](https://developer.mozilla.org/docs/Web/CSS/gap) - - [Media Query Ranges](https://developer.mozilla.org/docs/Web/CSS/Media_Queries/Using_media_queries#Syntax_improvements_in_Level_4) +- [Autoprefixer](https://github.com/postcss/autoprefixer)가 CSS 규칙에 자동으로 vender prefixes를 추가합니다 (IE11까지 지원). +- [다양한 브라우저에서 발생하는 Flexbox 버그](https://github.com/philipwalton/flexbugs)가 [명세서](https://www.w3.org/TR/css-flexbox-1/)대로 동작하도록 수정되었습니다. +- 새로운 CSS 기능들이 Internet Explorer 11과 호환되도록 자동으로 컴파일됩니다: + - [`all` 프로퍼티](https://developer.mozilla.org/docs/Web/CSS/all) + - [Break 프로퍼티](https://developer.mozilla.org/docs/Web/CSS/break-after) + - [`font-variant` 프로퍼티](https://developer.mozilla.org/docs/Web/CSS/font-variant) + - [Gap 프로퍼티](https://developer.mozilla.org/docs/Web/CSS/gap) + - [Media Query 범위](https://developer.mozilla.org/docs/Web/CSS/Media_Queries/Using_media_queries#Syntax_improvements_in_Level_4) -By default, [CSS Grid](https://www.w3.org/TR/css-grid-1/) and [Custom Properties](https://developer.mozilla.org/docs/Web/CSS/var) (CSS variables) are **not compiled** for IE11 support. +기본적으로, [CSS Grid](https://www.w3.org/TR/css-grid-1/) 및 [Custom Properties](https://developer.mozilla.org/docs/Web/CSS/var)(CSS 변수)는 IE11 지원을 위해 **컴파일되지 않습니다.** -To compile [CSS Grid Layout](https://developer.mozilla.org/docs/Web/CSS/grid) for IE11, you can place the following comment at the top of your CSS file: +[CSS Grid Layout](https://developer.mozilla.org/docs/Web/CSS/grid)을 IE11에서 컴파일하려면, CSS 파일의 맨 위에 다음 주석을 추가할 수 있습니다: ```css /* autoprefixer grid: autoplace */ ``` -You can also enable IE11 support for [CSS Grid Layout](https://developer.mozilla.org/docs/Web/CSS/grid) -in your entire project by configuring autoprefixer with the configuration shown below (collapsed). -See ["Customizing Plugins"](#customizing-plugins) below for more information. +전체 프로젝트에서 [CSS Grid Layout](https://developer.mozilla.org/docs/Web/CSS/grid)의 IE11 지원을 활성화하려면, 아래 구성에서와 같이 autoprefixer를 설정할 수 있습니다(아래 접혀진 섹션 참조). 자세한 내용은 ["Customizing Plugins"](#customizing-plugins)을 참조하세요.
- Click to view the configuration to enable CSS Grid Layout + CSS Grid Layout을 활성화하기 위한 설정을 보려면 클릭하세요. ```json filename="postcss.config.json" { @@ -67,14 +63,14 @@ See ["Customizing Plugins"](#customizing-plugins) below for more information.
-CSS variables are not compiled because it is [not possible to safely do so](https://github.com/MadLittleMods/postcss-css-variables#caveats). -If you must use variables, consider using something like [Sass variables](https://sass-lang.com/documentation/variables) which are compiled away by [Sass](https://sass-lang.com/). +CSS 변수는 [안전하게 컴파일할 수 없기 때문에](https://github.com/MadLittleMods/postcss-css-variables#caveats) 컴파일되지 않습니다. +변수를 사용해야 한다면 [Sass](https://sass-lang.com/)에 의해 컴파일되는 [Sass 변수](https://sass-lang.com/documentation/variables)와 같은 것을 사용하는 것을 고려해보세요. ## Customizing Target Browsers -Next.js allows you to configure the target browsers (for [Autoprefixer](https://github.com/postcss/autoprefixer) and compiled css features) through [Browserslist](https://github.com/browserslist/browserslist). +Next.js는 [Browserslist](https://github.com/browserslist/browserslist)를 통해 ([Autoprefixer](https://github.com/postcss/autoprefixer) 및 컴파일된 css 기능에 대한) 대상 브라우저를 설정할 수 있습니다. -To customize browserslist, create a `browserslist` key in your `package.json` like so: +browserslist를 사용자 정의하려면, `package.json` 파일에 다음과 같이 `browserslist` 키를 추가하세요: ```json filename="package.json" { @@ -82,23 +78,23 @@ To customize browserslist, create a `browserslist` key in your `package.json` li } ``` -You can use the [browsersl.ist](https://browsersl.ist/?q=%3E0.3%25%2C+not+ie+11%2C+not+dead%2C+not+op_mini+all) tool to visualize what browsers you are targeting. +[browsersl.ist](https://browsersl.ist/?q=%3E0.3%25%2C+not+ie+11%2C+not+dead%2C+not+op_mini+all) 도구를 사용하여 대상으로 하는 브라우저를 시각화할 수 있습니다. ## CSS Modules -No configuration is needed to support CSS Modules. To enable CSS Modules for a file, rename the file to have the extension `.module.css`. +CSS Modules를 지원하기 위해 별도의 설정이 필요하지 않습니다. 파일에 `.module.css` 확장자를 사용하여 CSS Modules를 활성화할 수 있습니다. -You can learn more about [Next.js' CSS Module support here](/docs/pages/building-your-application/styling). +Next.js의 CSS Module 지원에 대한 자세한 내용은 [Next.js' CSS Module support](/docs/pages/building-your-application/styling)를 참조하세요. ## Customizing Plugins -> **Warning**: When you define a custom PostCSS configuration file, Next.js **completely disables** the [default behavior](#default-behavior). -> Be sure to manually configure all the features you need compiled, including [Autoprefixer](https://github.com/postcss/autoprefixer). -> You also need to install any plugins included in your custom configuration manually, i.e. `npm install postcss-flexbugs-fixes postcss-preset-env`. +> **경고**: 사용자 정의 PostCSS 설정 파일을 정의하면 Next.js는 [기본 동작](#default-behavior)을 **완전히 비활성화**합니다. +> 컴파일이 필요한 모든 기능을 수동으로 설정해야 하며, 여기에는 [Autoprefixer](https://github.com/postcss/autoprefixer)도 포함됩니다. +> 또한 사용자 정의 설정에 포함된 모든 플러그인을 수동으로 설치해야 합니다. 예: `npm install postcss-flexbugs-fixes` `postcss-preset-env`. -To customize the PostCSS configuration, create a `postcss.config.json` file in the root of your project. +PostCSS 설정을 사용자 정의하려면, 프로젝트의 루트에 `postcss.config.json` 파일을 생성하세요. -This is the default configuration used by Next.js: +다음은 Next.js에서 사용하는 기본 설정입니다: ```json filename="postcss.config.json" { @@ -120,9 +116,9 @@ This is the default configuration used by Next.js: } ``` -> **Good to know**: Next.js also allows the file to be named `.postcssrc.json`, or, to be read from the `postcss` key in `package.json`. +> **알아두면 좋은 점**: Next.js는 파일 이름을 '.postcssrc.json'으로 지정하거나 package.json의 'postcss' 키에서 읽을 수 있습니다. -It is also possible to configure PostCSS with a `postcss.config.js` file, which is useful when you want to conditionally include plugins based on environment: +PostCSS를 `postcss.config.js` 파일로 구성하는 것도 가능합니다. 이 설정은 환경에 따라 플러그인을 조건부로 포함하고자 할 때 유용합니다: ```js filename="postcss.config.js" module.exports = { @@ -144,16 +140,16 @@ module.exports = { ], ] : [ - // No transformations in development + // development 환경에서는 변환을 수행하지 않습니다. ], } ``` -> **Good to know**: Next.js also allows the file to be named `.postcssrc.js`. +> **알아두면 좋은 점**: Next.js는 파일 이름을 `.postcssrc.js`로 지정할 수도 있습니다. -Do **not use `require()`** to import the PostCSS Plugins. Plugins must be provided as strings. +PostCSS 플러그인을 가져올 때 require()를 사용하지 마세요. 플러그인은 문자열로 지정해야 합니다. -> **Good to know**: If your `postcss.config.js` needs to support other non-Next.js tools in the same project, you must use the interoperable object-based format instead: +> **알아두면 좋은 점**: 동일한 프로젝트에서 `postcss.config.js`가 다른 non-Next.js 도구를 지원해야 하는 경우, 다음과 같이 상호 운용 가능한 객체 기반 형식을 대신 사용해야 합니다: > > ```js > module.exports = { diff --git a/pages/docs/pages/building-your-application/configuring/preview-mode.mdx b/pages/docs/pages/building-your-application/configuring/preview-mode.mdx index ba631a0..d34620f 100644 --- a/pages/docs/pages/building-your-application/configuring/preview-mode.mdx +++ b/pages/docs/pages/building-your-application/configuring/preview-mode.mdx @@ -3,49 +3,47 @@ title: Preview Mode description: Next.js has the preview mode for statically generated pages. You can learn how it works here. --- -{/* TODO: 번역이 필요합니다. */} - # Preview Mode -> **Note**: This feature is superseded by [Draft Mode](/docs/pages/building-your-application/configuring/draft-mode). +> **주의**: 이 기능은 [Draft Mode](/docs/pages/building-your-application/configuring/draft-mode)로 대체되었습니다.
- Examples - -- [WordPress Example](https://github.com/vercel/next.js/tree/canary/examples/cms-wordpress) ([Demo](https://next-blog-wordpress.vercel.app)) -- [DatoCMS Example](https://github.com/vercel/next.js/tree/canary/examples/cms-datocms) ([Demo](https://next-blog-datocms.vercel.app/)) -- [TakeShape Example](https://github.com/vercel/next.js/tree/canary/examples/cms-takeshape) ([Demo](https://next-blog-takeshape.vercel.app/)) -- [Sanity Example](https://github.com/vercel/next.js/tree/canary/examples/cms-sanity) ([Demo](https://next-blog-sanity.vercel.app/)) -- [Prismic Example](https://github.com/vercel/next.js/tree/canary/examples/cms-prismic) ([Demo](https://next-blog-prismic.vercel.app/)) -- [Contentful Example](https://github.com/vercel/next.js/tree/canary/examples/cms-contentful) ([Demo](https://next-blog-contentful.vercel.app/)) -- [Strapi Example](https://github.com/vercel/next.js/tree/canary/examples/cms-strapi) ([Demo](https://next-blog-strapi.vercel.app/)) -- [Prepr Example](https://github.com/vercel/next.js/tree/canary/examples/cms-prepr) ([Demo](https://next-blog-prepr.vercel.app/)) -- [Agility CMS Example](https://github.com/vercel/next.js/tree/canary/examples/cms-agilitycms) ([Demo](https://next-blog-agilitycms.vercel.app/)) -- [Cosmic Example](https://github.com/vercel/next.js/tree/canary/examples/cms-cosmic) ([Demo](https://next-blog-cosmic.vercel.app/)) -- [ButterCMS Example](https://github.com/vercel/next.js/tree/canary/examples/cms-buttercms) ([Demo](https://next-blog-buttercms.vercel.app/)) -- [Storyblok Example](https://github.com/vercel/next.js/tree/canary/examples/cms-storyblok) ([Demo](https://next-blog-storyblok.vercel.app/)) -- [GraphCMS Example](https://github.com/vercel/next.js/tree/canary/examples/cms-graphcms) ([Demo](https://next-blog-graphcms.vercel.app/)) -- [Kontent Example](https://github.com/vercel/next.js/tree/canary/examples/cms-kontent-ai) ([Demo](https://next-blog-kontent.vercel.app//)) -- [Umbraco Heartcore Example](https://github.com/vercel/next.js/tree/canary/examples/cms-umbraco-heartcore) ([Demo](https://next-blog-umbraco-heartcore.vercel.app/)) -- [Plasmic Example](https://github.com/vercel/next.js/tree/canary/examples/cms-plasmic) ([Demo](https://nextjs-plasmic-example.vercel.app/)) -- [Enterspeed Example](https://github.com/vercel/next.js/tree/canary/examples/cms-enterspeed) ([Demo](https://next-blog-demo.enterspeed.com/)) -- [Makeswift Example](https://github.com/vercel/next.js/tree/canary/examples/cms-makeswift) ([Demo](https://nextjs-makeswift-example.vercel.app/)) + 예제 + +- [WordPress 예제](https://github.com/vercel/next.js/tree/canary/examples/cms-wordpress) ([Demo](https://next-blog-wordpress.vercel.app)) +- [DatoCMS 예제](https://github.com/vercel/next.js/tree/canary/examples/cms-datocms) ([Demo](https://next-blog-datocms.vercel.app/)) +- [TakeShape 예제](https://github.com/vercel/next.js/tree/canary/examples/cms-takeshape) ([Demo](https://next-blog-takeshape.vercel.app/)) +- [Sanity 예제](https://github.com/vercel/next.js/tree/canary/examples/cms-sanity) ([Demo](https://next-blog-sanity.vercel.app/)) +- [Prismic 예제](https://github.com/vercel/next.js/tree/canary/examples/cms-prismic) ([Demo](https://next-blog-prismic.vercel.app/)) +- [Contentful 예제](https://github.com/vercel/next.js/tree/canary/examples/cms-contentful) ([Demo](https://next-blog-contentful.vercel.app/)) +- [Strapi 예제](https://github.com/vercel/next.js/tree/canary/examples/cms-strapi) ([Demo](https://next-blog-strapi.vercel.app/)) +- [Prepr 예제](https://github.com/vercel/next.js/tree/canary/examples/cms-prepr) ([Demo](https://next-blog-prepr.vercel.app/)) +- [Agility CMS 예제](https://github.com/vercel/next.js/tree/canary/examples/cms-agilitycms) ([Demo](https://next-blog-agilitycms.vercel.app/)) +- [Cosmic 예제](https://github.com/vercel/next.js/tree/canary/examples/cms-cosmic) ([Demo](https://next-blog-cosmic.vercel.app/)) +- [ButterCMS 예제](https://github.com/vercel/next.js/tree/canary/examples/cms-buttercms) ([Demo](https://next-blog-buttercms.vercel.app/)) +- [Storyblok 예제](https://github.com/vercel/next.js/tree/canary/examples/cms-storyblok) ([Demo](https://next-blog-storyblok.vercel.app/)) +- [GraphCMS 예제](https://github.com/vercel/next.js/tree/canary/examples/cms-graphcms) ([Demo](https://next-blog-graphcms.vercel.app/)) +- [Kontent 예제](https://github.com/vercel/next.js/tree/canary/examples/cms-kontent-ai) ([Demo](https://next-blog-kontent.vercel.app//)) +- [Umbraco Heartcore 예제](https://github.com/vercel/next.js/tree/canary/examples/cms-umbraco-heartcore) ([Demo](https://next-blog-umbraco-heartcore.vercel.app/)) +- [Plasmic 예제](https://github.com/vercel/next.js/tree/canary/examples/cms-plasmic) ([Demo](https://nextjs-plasmic-example.vercel.app/)) +- [Enterspeed 예제](https://github.com/vercel/next.js/tree/canary/examples/cms-enterspeed) ([Demo](https://next-blog-demo.enterspeed.com/)) +- [Makeswift 예제](https://github.com/vercel/next.js/tree/canary/examples/cms-makeswift) ([Demo](https://nextjs-makeswift-example.vercel.app/))
-In the [Pages documentation](/docs/pages/building-your-application/routing/pages-and-layouts) and the [Data Fetching documentation](/docs/pages/building-your-application/data-fetching), we talked about how to pre-render a page at build time (**Static Generation**) using `getStaticProps` and `getStaticPaths`. +[Pages 문서](/docs/pages/building-your-application/routing/pages-and-layouts) 및 [Data Fetching 문서](/docs/pages/building-your-application/data-fetching)에서 `getStaticProps`와 `getStaticPaths`를 사용하여 빌드 타임에 페이지를 사전 렌더링(**정적 생성**)하는 방법에 대해 이야기했습니다. -Static Generation is useful when your pages fetch data from a headless CMS. However, it’s not ideal when you’re writing a draft on your headless CMS and want to **preview** the draft immediately on your page. You’d want Next.js to render these pages at **request time** instead of build time and fetch the draft content instead of the published content. You’d want Next.js to bypass Static Generation only for this specific case. +정적 생성은 페이지가 헤드리스 CMS에서 데이터를 가져올 때 유용합니다. 하지만 헤드리스 CMS에서 초안을 작성하고 페이지에서 바로 **미리보기**를 원할 때는 이상적이지 않습니다. 이러한 경우 Next.js가 이 페이지들을 빌드 타임이 아닌 **요청 타임**에 렌더링하고 게시된 컨텐츠 대신 초안 컨텐츠를 가져오도록 하고 싶을 것입니다. 이와 같이 Next.js가 특정 경우에 정적 생성을 우회하기를 원할 수 있습니다. -Next.js has a feature called **Preview Mode** which solves this problem. Here are instructions on how to use it. +Next.js에는 이러한 문제를 해결하는 **Preview Mode**라는 기능을 제공합니다. 사용 방법은 다음과 같습니다. ## Step 1: Create and access a preview API route -> Take a look at the [API Routes documentation](/docs/pages/building-your-application/routing/api-routes) first if you’re not familiar with Next.js API Routes. +> Next.js API Routes를 잘 모르는 경우 [API Routes 문서](/docs/pages/building-your-application/routing/api-routes)을 먼저 참조하십시오. -First, create a **preview API route**. It can have any name - e.g. `pages/api/preview.js` (or `.ts` if using TypeScript). +먼저 **미리보기 API route**를 만듭니다. 이름은 자유롭게 설정할 수 있습니다 - 예: `pages/api/preview.js` (TypeScript를 사용하는 경우 `.ts`). -In this API route, you need to call `setPreviewData` on the response object. The argument for `setPreviewData` should be an object, and this can be used by `getStaticProps` (more on this later). For now, we’ll use `{}`. +이 API route에서 응답 객체에 `setPreviewData`를 호출해야 합니다. `setPreviewData`의 인수는 객체여야 하며, 이는 `getStaticProps`에서 사용할 수 있습니다(이후에 더 설명함). 지금은 `{}`를 사용하겠습니다. ```js export default function handler(req, res) { @@ -55,119 +53,116 @@ export default function handler(req, res) { } ``` -`res.setPreviewData` sets some **cookies** on the browser which turns on the preview mode. Any requests to Next.js containing these cookies will be considered as the **preview mode**, and the behavior for statically generated pages will change (more on this later). +`res.setPreviewData`는 브라우저에 **쿠키**를 설정하여 preview mode를 활성화합니다. 이러한 쿠키를 포함한 Next.js로의 모든 요청은 **preview mode**로 간주되며, 정적으로 생성된 페이지의 동작이 변경됩니다(이후에 더 설명함). -You can test this manually by creating an API route like below and accessing it from your browser manually: +아래와 같이 API route를 만들고 브라우저에서 직접 액세스하여 수동으로 테스트할 수 있습니다: ```js filename="pages/api/preview.js" -// simple example for testing it manually from your browser. +// 브라우저에서 수동으로 테스트할 수 있는 간단한 예제입니다. export default function handler(req, res) { res.setPreviewData({}) res.end('Preview mode enabled') } ``` -If you open your browser’s developer tools and visit `/api/preview`, you’ll notice that the `__prerender_bypass` and `__next_preview_data` cookies will be set on this request. +브라우저의 개발자 도구를 열고 `/api/preview`를 확인하면 이 요청에 `__prerender_bypass` 및 `__next_preview_data` 쿠키가 설정되는 것을 확인할 수 있습니다. ### Securely accessing it from your Headless CMS -In practice, you’d want to call this API route _securely_ from your headless CMS. The specific steps will vary depending on which headless CMS you’re using, but here are some common steps you could take. +실제로는 헤드리스 CMS에서 이 라우트 핸들러를 _보안_ 방식으로 호출하고 싶을 것입니다. 사용 중인 헤드리스 CMS에 따라 구체적인 단계는 다를 수 있지만, 다음과 같은 일반적인 단계를 따를 수 있습니다. -These steps assume that the headless CMS you’re using supports setting **custom preview URLs**. If it doesn’t, you can still use this method to secure your preview URLs, but you’ll need to construct and access the preview URL manually. +이 단계는 사용 중인 헤드리스 CMS가 **사용자 정의 미리보기 URL** 설정을 지원한다고 가정합니다. 지원하지 않는 경우에도 이 방법을 사용하여 미리보기 URL을 보호할 수 있지만, 미리보기 URL을 수동으로 구성하고 접근해야 합니다. -**First**, you should create a **secret token string** using a token generator of your choice. This secret will only be known by your Next.js app and your headless CMS. This secret prevents people who don’t have access to your CMS from accessing preview URLs. +**먼저**, 원하는 토큰 생성기를 사용하여 **시크릿 토큰 문자열**을 생성해야 합니다. 이 시크릿은 Next.js 앱과 헤드리스 CMS만 알고 있어야 합니다. 이 시크릿은 CMS에 액세스할 수 없는 사람들이 미리보기 URL에 접근하는 것을 방지합니다. -**Second**, if your headless CMS supports setting custom preview URLs, specify the following as the preview URL. This assumes that your preview API route is located at `pages/api/preview.js`. +**두 번째**, 헤드리스 CMS가 사용자 정의 미리보기 URL 설정을 지원하는 경우, 다음을 미리보기 URL로 지정합니다. 이는 미리보기 API route가 `pages/api/preview.js`에 위치한다고 가정합니다. ```bash filename="Terminal" https:///api/preview?secret=&slug= ``` -- `` should be your deployment domain. -- `` should be replaced with the secret token you generated. -- `` should be the path for the page that you want to preview. If you want to preview `/posts/foo`, then you should use `&slug=/posts/foo`. +- ``는 배포 도메인이어야 합니다. +- ``은 생성한 시크릿 토큰으로 교체해야 합니다. +- `` 는 미리보기 하려는 페이지의 경로여야 합니다. `/posts/foo`를 보고자 한다면 `&slug=/posts/foo`를 사용해야 합니다. -Your headless CMS might allow you to include a variable in the preview URL so that `` can be set dynamically based on the CMS’s data like so: `&slug=/posts/{entry.fields.slug}` +사용중인 헤드리스 CMS가 변수 삽입을 지원하는 경우 ``를 CMS 데이터에 따라 동적으로 설정할 수 있습니다: `&slug=/posts/{entry.fields.slug}` -**Finally**, in the preview API route: +**마지막으로**, 미리보기 API route에서: -- Check that the secret matches and that the `slug` parameter exists (if not, the request should fail). -- -- Call `res.setPreviewData`. -- Then redirect the browser to the path specified by `slug`. (The following example uses a [307 redirect](https://developer.mozilla.org/docs/Web/HTTP/Status/307)). +- 시크릿이 일치하고 `slug` 매개변수가 존재하는지 확인합니다(존재하지 않으면 요청이 실패해야 합니다). +- `res.setPreviewData`를 호출합니다. +- 그런 다음 브라우저를 `slug`로 지정된 경로로 리디렉션합니다(다음 예제에서는 [307 redirect](https://developer.mozilla.org/docs/Web/HTTP/Status/307)을 사용합니다). ```js export default async (req, res) => { - // Check the secret and next parameters - // This secret should only be known to this API route and the CMS + // 시크릿과 다음 매개변수를 확인합니다. + // 이 시크릿은 이 API route와 CMS만 알고 있어야 합니다. if (req.query.secret !== 'MY_SECRET_TOKEN' || !req.query.slug) { return res.status(401).json({ message: 'Invalid token' }) } - // Fetch the headless CMS to check if the provided `slug` exists - // getPostBySlug would implement the required fetching logic to the headless CMS + // 제공된 `slug`가 존재하는지 확인하기 위해 헤드리스 CMS를 가져옵니다. + // getPostBySlug는 헤드리스 CMS에 필요한 fetching 로직을 구현합니다. const post = await getPostBySlug(req.query.slug) - // If the slug doesn't exist prevent preview mode from being enabled + // slug가 존재하지 않으면 Preview Mode가 활성화되지 않도록 합니다. if (!post) { return res.status(401).json({ message: 'Invalid slug' }) } - // Enable Preview Mode by setting the cookies + // 쿠키를 설정하여 Preview Mode를 활성화합니다. res.setPreviewData({}) - // Redirect to the path from the fetched post - // We don't redirect to req.query.slug as that might lead to open redirect vulnerabilities + // 가져온 게시물의 경로로 리디렉션합니다. + // req.query.slug로 리디렉션하지 않는 이유는 open redirect 취약점이 발생할 수 있기 때문입니다. res.redirect(post.slug) } ``` -If it succeeds, then the browser will be redirected to the path you want to preview with the preview mode cookies being set. +성공하면 브라우저는 설정된 preview mode 쿠키와 함께 보고자 하는 경로로 리디렉션됩니다. ## Step 2: Update `getStaticProps` -The next step is to update `getStaticProps` to support the preview mode. +다음 단계는 `getStaticProps`를 업데이트하여 preview mode를 지원하는 것입니다. -If you request a page which has `getStaticProps` with the preview mode cookies set (via `res.setPreviewData`), then `getStaticProps` will be called at **request time** (instead of at build time). +Preview mode 쿠키가 설정된 상태로 `getStaticProps`가 있는 페이지를 요청하면 `getStaticProps`가 **빌드 타임**이 아닌 **요청 타임**에 호출됩니다. -Furthermore, it will be called with a `context` object where: +또한, `context` 객체와 함께 호출되며: -- `context.preview` will be `true`. -- `context.previewData` will be the same as the argument used for `setPreviewData`. +- `context.preview`는 `true`입니다. +- `context.previewData`는 `setPreviewData`에 사용된 인수와 동일합니다. ```js export async function getStaticProps(context) { - // If you request this page with the preview mode cookies set: + // preview mode 쿠키가 설정된 상태로 이 페이지를 요청하면: // - // - context.preview will be true - // - context.previewData will be the same as - // the argument used for `setPreviewData`. + // - context.preview는 true가 됩니다. + // - context.previewData는 `setPreviewData`에 사용된 인수와 동일합니다. } ``` -We used `res.setPreviewData({})` in the preview API route, so `context.previewData` will be `{}`. You can use this to pass session information from the preview API route to `getStaticProps` if necessary. +우리는 미리보기 API route에서 `res.setPreviewData({})`를 사용했으므로 `context.previewData`는 `{}`가 됩니다. 필요하다면 미리보기 API route에서 `getStaticProps`로 세션 정보를 전달하는 데 사용할 수 있습니다. -If you’re also using `getStaticPaths`, then `context.params` will also be available. +`getStaticPaths`를 사용하는 경우, `context.params`도 사용할 수 있습니다. ### Fetch preview data -You can update `getStaticProps` to fetch different data based on `context.preview` and/or `context.previewData`. +`getStaticProps`를 업데이트하여 `context.preview` 및/또는 `context.previewData`에 따라 다른 데이터를 가져올 수 있습니다. -For example, your headless CMS might have a different API endpoint for draft posts. If so, you can use `context.preview` to modify the API endpoint URL like below: +예를 들어, 헤드리스 CMS가 초안 게시물에 대해 다른 API 엔드포인트를 가지고 있는 경우, 아래와 같이 API 엔드포인트 URL을 수정하는 데 `context.preview`를 사용할 수 있습니다: ```js export async function getStaticProps(context) { - // If context.preview is true, append "/preview" to the API endpoint - // to request draft data instead of published data. This will vary - // based on which headless CMS you're using. + // context.preview가 true이면, 초안 데이터를 요청하기 위해 API 엔드포인트에 "/preview"를 추가합니다. + // 이는 사용하는 헤드리스 CMS에 따라 다릅니다. const res = await fetch(`https://.../${context.preview ? 'preview' : ''}`) // ... } ``` -That’s it! If you access the preview API route (with `secret` and `slug`) from your headless CMS or manually, you should now be able to see the preview content. And if you update your draft without publishing, you should be able to preview the draft. +이제 미리보기 API route(시크릿 및 slug 포함)를 헤드리스 CMS 또는 수동으로 접근하면 미리보기 컨텐츠를 볼 수 있어야 합니다. 초안을 게시하지 않고 업데이트하더라도 초안을 미리 볼 수 있어야 합니다. -Set this as the preview URL on your headless CMS or access manually, and you should be able to see the preview. +헤드리스 CMS에 이를 미리보기 URL로 설정하거나 수동으로 접근하면 미리보기를 볼 수 있습니다. ```bash filename="Terminal" https:///api/preview?secret=&slug= @@ -175,27 +170,27 @@ https:///api/preview?secret=&slug= ## More Details -> **Good to know**: during rendering `next/router` exposes an `isPreview` flag, see the [router object docs](/docs/pages/api-reference/functions/use-router#router-object) for more info. +> **참고**: 렌더링 중 `next/router`는 `isPreview` 플래그를 노출합니다. 자세한 내용은 [router object docs](/docs/pages/api-reference/functions/use-router#router-object)를 참조하십시오. ### Specify the Preview Mode duration -`setPreviewData` takes an optional second parameter which should be an options object. It accepts the following keys: +`setPreviewData`는 option 객체인 두 번째 매개 변수를 사용합니다. 이는 다음 키들을 사용합니다: -- `maxAge`: Specifies the number (in seconds) for the preview session to last for. -- `path`: Specifies the path the cookie should be applied under. Defaults to `/` enabling preview mode for all paths. +- `maxAge`: 미리보기 세션이 지속되는 시간을 초 단위로 지정합니다. +- `path`: 쿠키가 적용될 경로를 지정합니다. 기본값은 `/`이며, 이는 모든 경로에 대해 preview mode를 활성화합니다. ```js setPreviewData(data, { - maxAge: 60 * 60, // The preview mode cookies expire in 1 hour - path: '/about', // The preview mode cookies apply to paths with /about + maxAge: 60 * 60, // preview mode 쿠키는 1시간 후에 만료됩니다. + path: '/about', // preview mode 쿠키는 /about 경로에 적용됩니다. }) ``` ### Clear the Preview Mode cookies -By default, no expiration date is set for Preview Mode cookies, so the preview session ends when the browser is closed. +기본적으로, preview mode 쿠키에는 만료 날짜가 설정되지 않으므로 브라우저를 닫을 때 미리보기 세션이 종료됩니다. -To clear the Preview Mode cookies manually, create an API route that calls `clearPreviewData()`: +Preview mode 쿠키를 수동으로 제거하려면 `clearPreviewData()`를 호출하는 API route를 만듭니다: ```js filename="pages/api/clear-preview-mode-cookies.js" export default function handler(req, res) { @@ -203,9 +198,9 @@ export default function handler(req, res) { } ``` -Then, send a request to `/api/clear-preview-mode-cookies` to invoke the API Route. If calling this route using [`next/link`](/docs/pages/api-reference/components/link), you must pass `prefetch={false}` to prevent calling `clearPreviewData` during link prefetching. +그런 다음 `/api/clear-preview-mode-cookies` 에 요청을 보내 API Route를 호출합니다. [`next/link`](/docs/pages/api-reference/components/link)를 사용하여 이 라우트를 호출하는 경우 링크 사전 로딩 중에 `clearPreviewData`를 호출하지 않도록 `prefetch={false}`를 설정해야 합니다. -If a path was specified in the `setPreviewData` call, you must pass the same path to `clearPreviewData`: +`setPreviewData` 호출에서 경로를 지정한 경우, 동일한 경로를 `clearPreviewData`에 전달해야 합니다: ```js filename="pages/api/clear-preview-mode-cookies.js" export default function handler(req, res) { @@ -217,17 +212,17 @@ export default function handler(req, res) { ### `previewData` size limits -You can pass an object to `setPreviewData` and have it be available in `getStaticProps`. However, because the data will be stored in a cookie, there’s a size limitation. Currently, preview data is limited to 2KB. +객체를 `setPreviewData`에 전달하여 `getStaticProps`에서 사용할 수 있습니다. 그러나 데이터가 쿠키에 저장되므로 크기 제한이 있습니다. 현재 미리보기 데이터는 2KB로 제한됩니다. ### Works with `getServerSideProps` -The preview mode works on `getServerSideProps` as well. It will also be available on the `context` object containing `preview` and `previewData`. +Preview mode는 `getServerSideProps`에서도 작동합니다. `context` 객체에 `preview` 및 `previewData`가 포함되어 사용할 수 있습니다. -> **Good to know**: You shouldn't set the `Cache-Control` header when using Preview Mode because it cannot be bypassed. Instead, we recommend using [ISR](/docs/pages/building-your-application/data-fetching/incremental-static-regeneration). +> **참고**: Preview Mode를 사용할 때 `Cache-Control` 헤더를 설정하면 우회할 수 없으므로 설정하지 않아야 합니다. 대신, [ISR](/docs/pages/building-your-application/data-fetching/incremental-static-regeneration)을 사용하는 것을 추천합니다. ### Works with API Routes -API Routes will have access to `preview` and `previewData` under the request object. For example: +API Routes는 요청 객체에서 `preview` 및 `previewData`에 접근할 수 있습니다. 예를 들어: ```js export default function myApiRoute(req, res) { @@ -239,7 +234,7 @@ export default function myApiRoute(req, res) { ### Unique per `next build` -Both the bypass cookie value and the private key for encrypting the `previewData` change when `next build` is completed. -This ensures that the bypass cookie can’t be guessed. +우회 쿠키 값과 `previewData` 암호화를 위한 개인 키는 `next build`가 완료될 때 변경됩니다. +이를 통해 우회 쿠키를 추측할 수 없도록 합니다. -> **Good to know**: To test Preview Mode locally over HTTP your browser will need to allow third-party cookies and local storage access. +> **참고**: 로컬에서 HTTP를 통해 Preview Mode를 테스트하려면 브라우저에서 서드 파티 쿠키와 로컬 스토리지 액세스를 허용해야 합니다. diff --git a/pages/docs/pages/building-your-application/data-fetching/forms-and-mutations.mdx b/pages/docs/pages/building-your-application/data-fetching/forms-and-mutations.mdx index c3c27b5..2f19a77 100644 --- a/pages/docs/pages/building-your-application/data-fetching/forms-and-mutations.mdx +++ b/pages/docs/pages/building-your-application/data-fetching/forms-and-mutations.mdx @@ -4,23 +4,21 @@ nav_title: Forms and Mutations description: Learn how to handle form submissions and data mutations with Next.js. --- -{/* TODO: 번역이 필요합니다. */} - # Forms and Mutations -Forms enable you to create and update data in web applications. Next.js provides a powerful way to handle form submissions and data mutations using **API Routes**. +폼은 웹 어플리케이션에서 데이터를 생성하고 업데이트할 수 있게 해줍니다. Next.js는 **API Routes**를 사용하여 폼 제출과 데이터 변형을 처리하는 강력한 방법을 제공합니다. -> **Good to know:** +> **알아두면 좋은 점:** > -> - We will soon recommend [incrementally adopting](/docs/app/building-your-application/upgrading/app-router-migration) the App Router and using [Server Actions](/docs/app/building-your-application/data-fetching/server-actions-and-mutations) for handling form submissions and data mutations. Server Actions allow you to define asynchronous server functions that can be called directly from your components, without needing to manually create an API Route. -> - API Routes [do not specify CORS headers](https://developer.mozilla.org/docs/Web/HTTP/CORS), meaning they are same-origin only by default. -> - Since API Routes run on the server, we're able to use sensitive values (like API keys) through [Environment Variables](/docs/pages/building-your-application/configuring/environment-variables) without exposing them to the client. This is critical for the security of your application. +> - 곧 App Router를 [점진적으로 도입](/docs/app/building-your-application/upgrading/app-router-migration)하고 폼 제출 및 데이터 변형을 처리하기 위해 [Server Actions](/docs/app/building-your-application/data-fetching/server-actions-and-mutations) 사용을 권잘할 예정입니다. Server Actions를 사용하면 API Route를 수동으로 생성할 필요 없이 컴포넌트에서 직접 호출할 수 있는 비동기 서버 함수를 정의할 수 있습니다. +> - API Routes는 [CORS 헤더를 지정하지 않습니다](https://developer.mozilla.org/docs/Web/HTTP/CORS). 이는 기본적으로 동일 출처에서만 작동함을 의미합니다. +> - API Routes는 서버에서 실행되기 때문에 [환경 변수](/docs/pages/building-your-application/configuring/environment-variables)를 통해 API 키와 같은 민감한 값을 클라이언트에 노출하지 않고 사용할 수 있습니다. 이는 어플리케이션의 보안에 매우 중요합니다. ## Examples ### Server-only form -With the Pages Router, you need to manually create API endpoints to handle securely mutating data on the server. +Pages Router를 사용할 경우, 서버에서 데이터를 안전하게 변형하기 위해 API 엔드포인트를 수동으로 생성해야 합니다. ```ts filename="pages/api/submit.ts" switcher import type { NextApiRequest, NextApiResponse } from 'next' @@ -43,7 +41,7 @@ export default function handler(req, res) { } ``` -Then, call the API Route from the client with an event handler: +그 후, 이벤트 핸들러를 사용하여 클라이언트에서 API Route를 호출합니다: ```tsx filename="pages/index.tsx" switcher import { FormEvent } from 'react' @@ -58,7 +56,7 @@ export default function Page() { body: formData, }) - // Handle response if necessary + // 필요에 따라 응답 처리 const data = await response.json() // ... } @@ -83,7 +81,7 @@ export default function Page() { body: formData, }) - // Handle response if necessary + // 필요한 경우 응답 처리 const data = await response.json() // ... } @@ -99,9 +97,9 @@ export default function Page() { ## Form validation -We recommend using HTML validation like `required` and `type="email"` for basic client-side form validation. +기본적인 client-side 폼 검증을 위해 `required`와 `type="email"` 같은 HTML 검증을 사용하는 것을 권장합니다. -For more advanced server-side validation, you can use a schema validation library like [zod](https://zod.dev/) to validate the form fields before mutating the data: +더 정교한 server-side 검증을 위해 [zod](https://zod.dev/)와 같은 스키마 검증 라이브러리를 사용하여 데이터를 변형하기 전에 필드를 검증할 수 있습니다: ```ts filename="pages/api/submit.ts" switcher import type { NextApiRequest, NextApiResponse } from 'next' @@ -135,7 +133,7 @@ export default async function handler(req, res) { ### Error handling -You can use React state to show an error message when a form submission fails: +폼 제출이 실패했을 때 에러 메시지를 표시하기 위해 React state를 사용할 수 있습니다: ```tsx filename="pages/index.tsx" switcher import React, { useState, FormEvent } from 'react' @@ -147,7 +145,7 @@ export default function Page() { async function onSubmit(event: FormEvent) { event.preventDefault() setIsLoading(true) - setError(null) // Clear previous errors when a new request starts + setError(null) // 새 요청이 시작되면 이전 오류를 삭제 try { const formData = new FormData(event.currentTarget) @@ -160,11 +158,11 @@ export default function Page() { throw new Error('Failed to submit the data. Please try again.') } - // Handle response if necessary + // 필요한 경우 응답 처리 const data = await response.json() // ... } catch (error) { - // Capture the error message to display to the user + // 오류 메세지를 캡처하여 사용자에게 표시 setError(error.message) console.error(error) } finally { @@ -196,7 +194,7 @@ export default function Page() { async function onSubmit(event) { event.preventDefault() setIsLoading(true) - setError(null) // Clear previous errors when a new request starts + setError(null) // 새 요청이 시작되면 이전 오류를 삭제 try { const formData = new FormData(event.currentTarget) @@ -209,11 +207,11 @@ export default function Page() { throw new Error('Failed to submit the data. Please try again.') } - // Handle response if necessary + // 필요한 경우 응답 처리 const data = await response.json() // ... } catch (error) { - // Capture the error message to display to the user + // 오류 메세지를 캡처하여 사용자에게 표시 setError(error.message) console.error(error) } finally { @@ -237,7 +235,7 @@ export default function Page() { ## Displaying loading state -You can use React state to show a loading state when a form is submitting on the server: +서버에서 폼이 제출되는 동안 로딩 상태를 표시하기 위해 React state를 사용할 수 있습니다: ```tsx filename="pages/index.tsx" switcher import React, { useState, FormEvent } from 'react' @@ -247,7 +245,7 @@ export default function Page() { async function onSubmit(event: FormEvent) { event.preventDefault() - setIsLoading(true) // Set loading to true when the request starts + setIsLoading(true) // 요청이 시작되면 로딩 상태를 true로 설정 try { const formData = new FormData(event.currentTarget) @@ -256,14 +254,14 @@ export default function Page() { body: formData, }) - // Handle response if necessary + // 필요한 경우 응답 처리 const data = await response.json() // ... } catch (error) { // Handle error if necessary console.error(error) } finally { - setIsLoading(false) // Set loading to false when the request completes + setIsLoading(false) // 요청이 성공적으로 끝난 경우 로딩 상태를 false로 설정 } } @@ -286,7 +284,7 @@ export default function Page() { async function onSubmit(event) { event.preventDefault() - setIsLoading(true) // Set loading to true when the request starts + setIsLoading(true) // 요청이 시작되면 로딩 상태를 true로 설정 try { const formData = new FormData(event.currentTarget) @@ -295,14 +293,14 @@ export default function Page() { body: formData, }) - // Handle response if necessary + // 필요한 경우 응답 처리 const data = await response.json() // ... } catch (error) { // Handle error if necessary console.error(error) } finally { - setIsLoading(false) // Set loading to false when the request completes + setIsLoading(false) // 요청이 성공적으로 끝난 경우 로딩 상태를 false로 설정 } } @@ -319,7 +317,7 @@ export default function Page() { ### Redirecting -If you would like to redirect the user to a different route after a mutation, you can [`redirect`](/docs/pages/building-your-application/routing/api-routes#response-helpers) to any absolute or relative URL: +변형 후 사용자를 다른 라우트로 리디렉션하려는 경우, 모든 absolute URL 또는 relative URL로 [`redirect`](/docs/pages/building-your-application/routing/api-routes#response-helpers)할 수 있습니다: ```ts filename="pages/api/submit.ts" switcher import type { NextApiRequest, NextApiResponse } from 'next' @@ -342,7 +340,7 @@ export default async function handler(req, res) { ### Setting cookies -You can set cookies inside an API Route using the `setHeader` method on the response: +setHeader 메서드를 사용하여 API Route 내의 쿠키를 설정할 수 있습니다: ```ts filename="pages/api/cookie.ts" switcher import type { NextApiRequest, NextApiResponse } from 'next' @@ -365,7 +363,7 @@ export default async function handler(req, res) { ### Reading cookies -You can read cookies inside an API Route using the [`cookies`](/docs/pages/building-your-application/routing/api-routes#request-helpers) request helper: +[`cookies`](/docs/pages/building-your-application/routing/api-routes#request-helpers)를 사용하여 API Route 내의 쿠키를 읽을 수 있습니다: ```ts filename="pages/api/cookie.ts" switcher import type { NextApiRequest, NextApiResponse } from 'next' @@ -388,7 +386,7 @@ export default async function handler(req, res) { ### Deleting cookies -You can delete cookies inside an API Route using the `setHeader` method on the response: +setHeader 메서드를 사용하여 API Route 내의 쿠키를 삭제할 수 있습니다: ```ts filename="pages/api/cookie.ts" switcher import type { NextApiRequest, NextApiResponse } from 'next' diff --git a/pages/docs/pages/building-your-application/data-fetching/incremental-static-regeneration.mdx b/pages/docs/pages/building-your-application/data-fetching/incremental-static-regeneration.mdx index c5fb4e9..fb8c19e 100644 --- a/pages/docs/pages/building-your-application/data-fetching/incremental-static-regeneration.mdx +++ b/pages/docs/pages/building-your-application/data-fetching/incremental-static-regeneration.mdx @@ -3,12 +3,10 @@ title: Incremental Static Regeneration (ISR) description: Learn how to create or update static pages at runtime with Incremental Static Regeneration. --- -{/* TODO: 번역이 필요합니다. */} - # Incremental Static Regeneration (ISR)
- Examples + 예제 - [Next.js Commerce](https://nextjs.org/commerce) - [GitHub Reactions Demo](https://reactions-demo.vercel.app/) @@ -16,11 +14,11 @@ description: Learn how to create or update static pages at runtime with Incremen
-Next.js allows you to create or update static pages _after_ you’ve built your site. Incremental Static Regeneration (ISR) enables you to use static-generation on a per-page basis, **without needing to rebuild the entire site**. With ISR, you can retain the benefits of static while scaling to millions of pages. +Next.js를 사용하면 사이트를 빌드한 _후_ 정적 페이지를 생성하거나 업데이트할 수 있습니다. Incremental Static Regeneration (ISR)을 사용하면 **전체 사이트를 재빌드할 필요 없이** 페이지별로 정적 생성을 사용할 수 있습니다. ISR을 사용하면 정적 페이지의 장점을 유지하면서 수백만 개의 페이지로 확장할 수 있습니다. -> **Good to know**: The [`edge` runtime](/docs/pages/api-reference/edge) is currently not compatible with ISR, although you can leverage `stale-while-revalidate` by setting the `cache-control` header manually. +> **알아두면 좋은 점**: [`edge` runtime](/docs/pages/api-reference/edge)은 현재 ISR과 호환되지 않지만, `cache-control` 헤더를 수동으로 설정하여 `stale-while-revalidate`를 활용할 수 있습니다. -To use ISR, add the `revalidate` prop to `getStaticProps`: +ISR을 사용하려면, `revalidate` prop을 `getStaticProps`에 추가하세요: ```jsx function Blog({ posts }) { @@ -33,9 +31,9 @@ function Blog({ posts }) { ) } -// This function gets called at build time on server-side. -// It may be called again, on a serverless function, if -// revalidation is enabled and a new request comes in +// 이 함수는 빌드 시 서버 측에서 호출됩니다. +// 재검증이 활성화되고 새로운 요청이 들어오면, +// 서버리스 함수에서 다시 호출될 수 있습니다. export async function getStaticProps() { const res = await fetch('https://.../posts') const posts = await res.json() @@ -44,122 +42,122 @@ export async function getStaticProps() { props: { posts, }, - // Next.js will attempt to re-generate the page: - // - When a request comes in - // - At most once every 10 seconds - revalidate: 10, // In seconds + // Next.js는 페이지 재생성을 시도합니다: + // - 요청이 들어올 때 + // - 최대 10초마다 한 번씩 + revalidate: 10, // 초 단위 } } -// This function gets called at build time on server-side. -// It may be called again, on a serverless function, if -// the path has not been generated. +// 이 함수는 빌드 시 서버 측에서 호출됩니다. +// 경로가 생성되지 않은 경우, +// 서버리스 함수에서 다시 호출될 수 있습니다. export async function getStaticPaths() { const res = await fetch('https://.../posts') const posts = await res.json() - // Get the paths we want to pre-render based on posts + // 게시물을 기반으로 사전 렌더링할 경로를 가져옵니다. const paths = posts.map((post) => ({ params: { id: post.id }, })) - // We'll pre-render only these paths at build time. - // { fallback: 'blocking' } will server-render pages - // on-demand if the path doesn't exist. + // 빌드 시 이러한 경로만 사전 렌더링합니다 + // 경로가 존재하지 않는 경우, { fallback: 'blocking' }은 + // 온디맨드로 페이지를 서버 렌더링합니다. return { paths, fallback: 'blocking' } } export default Blog ``` -When a request is made to a page that was pre-rendered at build time, it will initially show the cached page. +빌드 시 사전 렌더링된 페이지에 요청을 하면 처음에는 캐시된 페이지가 표시됩니다. -- Any requests to the page after the initial request and before 10 seconds are also cached and instantaneous. -- After the 10-second window, the next request will still show the cached (stale) page -- Next.js triggers a regeneration of the page in the background. -- Once the page generates successfully, Next.js will invalidate the cache and show the updated page. If the background regeneration fails, the old page would still be unaltered. +- 초기 요청 후 10초 이내에 발생한 페이지에 대한 모든 요청은 캐시되며 즉시 처리됩니다. +- 10초가 지난 후의 다음 요청은 여전히 캐시된 (오래된) 페이지를 표시합니다. +- Next.js는 백그라운드에서 페이지 재생성을 트리거합니다. +- 페이지가 성공적으로 생성되면, Next.js는 캐시를 무효화하고 업데이트된 페이지를 표시합니다. 백그라운드 재생성이 실패하면, 이전 페이지가 그대로 유지됩니다. -When a request is made to a path that hasn’t been generated, Next.js will server-render the page on the first request. Future requests will serve the static file from the cache. ISR on Vercel [persists the cache globally and handles rollbacks](https://vercel.com/docs/concepts/next.js/incremental-static-regeneration?utm_source=next-site&utm_medium=docs&utm_campaign=next-website). +생성되지 않은 경로로 요청이 들어오면, Next.js는 첫 번째 요청에 대해 페이지를 서버 렌더링합니다. 이후의 요청은 캐시에서 정적 파일을 제공합니다. Vercel의 ISR은 [캐시를 전역적으로 유지하고 롤백을 처리합니다](https://vercel.com/docs/concepts/next.js/incremental-static-regeneration?utm_source=next-site&utm_medium=docs&utm_campaign=next-website). -> **Good to know**: Check if your upstream data provider has caching enabled by default. You might need to disable (e.g. `useCdn: false`), otherwise a revalidation won't be able to pull fresh data to update the ISR cache. Caching can occur at a CDN (for an endpoint being requested) when it returns the `Cache-Control` header. +> **알아두면 좋은 점**: 업스트림 데이터 제공자가 기본적으로 캐싱을 활성화했는지 확인하세요. 비활성화해야 할 수도 있습니다(예: `useCdn: false`). 그렇지 않으면 재검증이 ISR 캐시를 업데이트하기 위해 새로운 데이터를 가져올 수 없습니다. 캐싱은 (요청된 엔드포인트에 대해) `Cache-Control` 헤더를 반환할 때 CDN에서 발생할 수 있습니다. ## On-Demand Revalidation -If you set a `revalidate` time of `60`, all visitors will see the same generated version of your site for one minute. The only way to invalidate the cache is from someone visiting that page after the minute has passed. +`revalidate` 시간을 `60`으로 설정하면, 모든 방문자는 1분 동안 동일한 버전의 사이트를 보게 됩니다. 캐시를 무효화하는 유일한 방법은 1분이 지난 후 누군가 해당 페이지를 방문하는 것입니다. -Starting with `v12.2.0`, Next.js supports On-Demand Incremental Static Regeneration to manually purge the Next.js cache for a specific page. This makes it easier to update your site when: +`v12.2.0`부터 Next.js는 특정 페이지에 대한 Next.js 캐시를 수동으로 삭제할 수 있는 온디맨드 Incremental Static Regeneration을 지원합니다. 이를 통해 다음과 같은 경우에 사이트를 더 쉽게 업데이트할 수 있습니다: -- Content from your headless CMS is created or updated -- Ecommerce metadata changes (price, description, category, reviews, etc.) +- 헤드리스 CMS의 콘텐츠가 생성되거나 업데이트된 경우 +- 전자상거래 메타데이터 변경 (가격, 설명, 카테고리, 리뷰 등) -Inside `getStaticProps`, you do not need to specify `revalidate` to use on-demand revalidation. If `revalidate` is omitted, Next.js will use the default value of `false` (no revalidation) and only revalidate the page on-demand when `revalidate()` is called. +`getStaticProps` 내부에서 온디맨드 재검증을 사용하기 위해 `revalidate`를 지정할 필요가 없습니다. `revalidate`를 생략하면, Next.js는 기본값인 `false` (재검증 없음)를 사용하고 `revalidate()`가 호출될 때만 온디맨드로 페이지를 재검증합니다. -> **Good to know**: [Middleware](/docs/pages/building-your-application/routing/middleware) won't be executed for On-Demand ISR requests. Instead, call `revalidate()` on the _exact_ path that you want revalidated. For example, if you have `pages/blog/[slug].js` and a rewrite from `/post-1` -> `/blog/post-1`, you would need to call `res.revalidate('/blog/post-1')`. +> **알아두면 좋은 점**: [Middleware](/docs/pages/building-your-application/routing/middleware)는 온디맨드 ISR 요청에 대해 실행되지 않습니다. 대신, 재검증하려는 _정확한_ 경로에서 `revalidate()`를 호출하세요. 예를 들어 `pages/blog/[slug].js`가 있고 `/post-1` -> `/blog/post-1`의 rewrite가 있는 경우, `res.revalidate('/blog/post-1')`를 호출해야 합니다. ### Using On-Demand Revalidation -First, create a secret token only known by your Next.js app. This secret will be used to prevent unauthorized access to the revalidation API Route. You can access the route (either manually or with a webhook) with the following URL structure: +먼저 Next.js 앱에서만 알 수 있는 비밀 토큰을 생성합니다. 이 비밀 토큰은 재검증 API 라우트에 대한 무단 접근을 방지하는 데 사용됩니다. 다음 URL 구조로 (수동으로 또는 웹훅으로) 경로에 접근할 수 있습니다: ```bash filename="Terminal" https:///api/revalidate?secret= ``` -Next, add the secret as an [Environment Variable](/docs/pages/building-your-application/configuring/environment-variables) to your application. Finally, create the revalidation API Route: +다음으로, 애플리케이션에 비밀 토큰을 [환경 변수](/docs/pages/building-your-application/configuring/environment-variables)로 추가합니다. 마지막으로, 재검증 API 라우트를 생성합니다: ```js filename="pages/api/revalidate.js" export default async function handler(req, res) { - // Check for secret to confirm this is a valid request + // 이 요청이 유효한지 확인하기 위해 비밀 토큰을 확인합니다. if (req.query.secret !== process.env.MY_SECRET_TOKEN) { return res.status(401).json({ message: 'Invalid token' }) } try { - // this should be the actual path not a rewritten path - // e.g. for "/blog/[slug]" this should be "/blog/post-1" + // 이 경로는 rewritten 경로가 아닌 실제 경로여야 합니다. + // 예: "/blog/[slug]"의 경우 "/blog/post-1"이어야 합니다. await res.revalidate('/path-to-revalidate') return res.json({ revalidated: true }) } catch (err) { - // If there was an error, Next.js will continue - // to show the last successfully generated page + // 오류가 발생한 경우 + // Next.js는 마지막으로 성공적으로 생성된 페이지를 계속 표시합니다. return res.status(500).send('Error revalidating') } } ``` -[View our demo](https://on-demand-isr.vercel.app) to see on-demand revalidation in action and provide feedback. +[데모](https://on-demand-isr.vercel.app)에서 온디맨드 재검증이 동작하는 것을 확인하고 피드백을 제공하세요. ### Testing on-Demand ISR during development -When running locally with `next dev`, `getStaticProps` is invoked on every request. To verify your on-demand ISR configuration is correct, you will need to create a [production build](/docs/pages/api-reference/next-cli#build) and start the [production server](/docs/pages/api-reference/next-cli#production): +`next dev`로 로컬에서 실행할 경우, 모든 요청에 대해 `getStaticProps`가 호출됩니다. 온디맨드 ISR 구성이 올바른지 확인하려면 [프로덕션 빌드](/docs/pages/api-reference/next-cli#build)를 생성하고 [프로덕션 서버](/docs/pages/api-reference/next-cli#production)를 시작해야 합니다: ```bash filename="Terminal" $ next build $ next start ``` -Then, you can confirm that static pages have successfully revalidated. +그런 다음, 정적 페이지가 성공적으로 재검증되었는지 확인할 수 있습니다. ## Error handling and revalidation -If there is an error inside `getStaticProps` when handling background regeneration, or you manually throw an error, the last successfully generated page will continue to show. On the next subsequent request, Next.js will retry calling `getStaticProps`. +백그라운드 재생성을 처리할 때 `getStaticProps` 내부에 오류가 발생하거나, 수동으로 오류를 발생시키면 마지막으로 성공적으로 생성된 페이지가 계속 표시됩니다. 다음 후속 요청 시, Next.js는 `getStaticProps` 호출을 다시 시도합니다. ```jsx export async function getStaticProps() { - // If this request throws an uncaught error, Next.js will - // not invalidate the currently shown page and - // retry getStaticProps on the next request. + // 이 요청에서 예기치 않은 오류가 발생하면, + // Next.js는 현재 표시된 페이지를 무효화하지 않고 + // 다음 요청 시 getStaticProps를 다시 시도합니다. const res = await fetch('https://.../posts') const posts = await res.json() if (!res.ok) { - // If there is a server error, you might want to - // throw an error instead of returning so that the cache is not updated - // until the next successful request. + // 서버 오류가 발생한 경우, + // 다음 요청이 성공할 때까지 캐시가 업데이트되지 않도록 + // 반환하는 대신 오류를 발생시키는 것이 좋습니다. throw new Error(`Failed to fetch posts, received status ${res.status}`) } - // If the request was successful, return the posts - // and revalidate every 10 seconds. + // 요청이 성공하면 게시물을 반환하고 + // 10초마다 재검증합니다. return { props: { posts, @@ -171,16 +169,16 @@ export async function getStaticProps() { ## Self-hosting ISR -Incremental Static Regeneration (ISR) works on [self-hosted Next.js sites](/docs/pages/building-your-application/deploying#self-hosting) out of the box when you use `next start`. +Incremental Static Regeneration (ISR)은 `next start`를 사용할 때 [자체 호스팅된 Next.js 사이트](/docs/pages/building-your-application/deploying#self-hosting)에서 기본적으로 작동합니다. -Learn more about [self-hosting Next.js](/docs/pages/building-your-application/deploying#self-hosting). +[Next.js 자체 호스팅](/docs/pages/building-your-application/deploying#self-hosting)에 대해 자세히 알아보세요. ## Version History -| Version | Changes | -| --------- | --------------------------------------------------------------------------------------- | -| `v14.1.0` | Custom `cacheHandler` is stable. | -| `v12.2.0` | On-Demand ISR is stable | -| `v12.1.0` | On-Demand ISR added (beta). | -| `v12.0.0` | [Bot-aware ISR fallback](https://nextjs.org/blog/next-12#bot-aware-isr-fallback) added. | -| `v9.5.0` | Base Path added. | +| 버전 | 변경 사항 | +| --------- | ------------------------------------------------------------------------------------- | +| `v14.1.0` | 커스텀 `cacheHandler` 안정화 | +| `v12.2.0` | 온디맨드 ISR 안정화 | +| `v12.1.0` | 온디맨드 ISR 추가 (베타) | +| `v12.0.0` | [Bot-aware ISR fallback](https://nextjs.org/blog/next-12#bot-aware-isr-fallback) 추가 | +| `v9.5.0` | Base Path 추가 | diff --git a/pages/docs/pages/building-your-application/rendering/automatic-static-optimization.mdx b/pages/docs/pages/building-your-application/rendering/automatic-static-optimization.mdx index c569f30..113606b 100644 --- a/pages/docs/pages/building-your-application/rendering/automatic-static-optimization.mdx +++ b/pages/docs/pages/building-your-application/rendering/automatic-static-optimization.mdx @@ -3,43 +3,41 @@ title: Automatic Static Optimization description: Next.js automatically optimizes your app to be static HTML whenever possible. Learn how it works here. --- -{/* TODO: 번역이 필요합니다. */} - # Automatic Static Optimization -Next.js automatically determines that a page is static (can be prerendered) if it has no blocking data requirements. This determination is made by the absence of `getServerSideProps` and `getInitialProps` in the page. +Next.js는 페이지가 렌더링될 때 반드시 필요한 데이터가 없다면 해당 페이지가 정적(미리 렌더링 가능한 상태)임을 자동으로 결정합니다. 이 결정은 페이지에 `getServerSideProps`와 `getInitialProps`가 없는 경우에 이루어집니다. -This feature allows Next.js to emit hybrid applications that contain **both server-rendered and statically generated pages**. +이 기능을 통해 Next.js는 **서버 렌더링 페이지와 정적 생성 페이지를 모두 포함하는 하이브리드 애플리케이션**을 생성할 수 있습니다. -> Statically generated pages are still reactive: Next.js will hydrate your application client-side to give it full interactivity. +> 정적으로 생성된 페이지도 여전히 반응형입니다: Next.js는 클라이언트 측에서 애플리케이션을 hydrate하여 완전한 상호작용성을 제공합니다. -One of the main benefits of this feature is that optimized pages require no server-side computation, and can be instantly streamed to the end-user from multiple CDN locations. The result is an _ultra fast_ loading experience for your users. +이 기능의 주요 이점 중 하나는 최적화된 페이지가 서버 측 계산을 필요로 하지 않으며, 여러 CDN 위치에서 최종 사용자에게 즉시 스트리밍될 수 있다는 점입니다. 그 결과 사용자에게 _초고속_ 로딩 경험을 제공할 수 있습니다. ## How it works -If `getServerSideProps` or `getInitialProps` is present in a page, Next.js will switch to render the page on-demand, per-request (meaning [Server-Side Rendering](/docs/pages/building-your-application/rendering/server-side-rendering)). +만약 페이지에 `getServerSideProps` 또는 `getInitialProps`가 포함되어 있으면, Next.js는 해당 페이지를 요청이 있을 때마다 즉시 렌더링하도록 전환합니다.([Server-Side Rendering](/docs/pages/building-your-application/rendering/server-side-rendering)을 의미합니다.) -If the above is not the case, Next.js will **statically optimize** your page automatically by prerendering the page to static HTML. +위의 경우가 아니라면, Next.js는 페이지를 정적 HTML로 사전 렌더링하여 자동으로 **정적 최적화**를 수행합니다. -During prerendering, the router's `query` object will be empty since we do not have `query` information to provide during this phase. After hydration, Next.js will trigger an update to your application to provide the route parameters in the `query` object. +사전 렌더링 중에는 이 단계에서 제공할 `query` 정보가 없기 때문에 라우터의 `query` 객체가 비어있게 됩니다. hydration 이후, Next.js는 애플리케이션 업데이트를 트리거하여 `query` 객체에 라우트 매개변수를 제공합니다. -The cases where the query will be updated after hydration triggering another render are: +hydration 이후 query가 업데이트되어 다른 렌더링을 트리거하는 경우는 다음과 같습니다: -- The page is a [dynamic-route](/docs/pages/building-your-application/routing/dynamic-routes). -- The page has query values in the URL. -- [Rewrites](/docs/pages/api-reference/next-config-js/rewrites) are configured in your `next.config.js` since these can have parameters that may need to be parsed and provided in the `query`. +- 페이지가 [dynamic-route](/docs/pages/building-your-application/routing/dynamic-routes)인 경우. +- URL에 query 값이 있는 경우. +- `next.config.js`에 [Rewrites](/docs/pages/api-reference/next-config-js/rewrites)가 구성된 경우, `query`에서 파싱되어 제공되어야 할 매개변수를 가질 수 있기 때문입니다. -To be able to distinguish if the query is fully updated and ready for use, you can leverage the `isReady` field on [`next/router`](/docs/pages/api-reference/functions/use-router#router-object). +query가 완전히 업데이트되고 사용할 준비가 되었는지 확인하려면 [`next/router`](/docs/pages/api-reference/functions/use-router#router-object)의 `isReady` 필드를 활용할 수 있습니다. -> **Good to know**: Parameters added with [dynamic routes](/docs/pages/building-your-application/routing/dynamic-routes) to a page that's using [`getStaticProps`](/docs/pages/building-your-application/data-fetching/get-static-props) will always be available inside the `query` object. +> **알아두면 좋은 점**: [`getStaticProps`](/docs/pages/building-your-application/data-fetching/get-static-props)를 사용하는 페이지에 [dynamic routes](/docs/pages/building-your-application/routing/dynamic-routes)로 추가된 매개변수는 항상 query 객체 내에서 사용할 수 있습니다. -`next build` will emit `.html` files for statically optimized pages. For example, the result for the page `pages/about.js` would be: +`next build`는 정적으로 최적화된 페이지에 대해 `.html` 파일을 생성합니다. 예를 들어, `pages/about.js` 페이지의 결과는 다음과 같습니다: ```bash filename="Terminal" .next/server/pages/about.html ``` -And if you add `getServerSideProps` to the page, it will then be JavaScript, like so: +그리고 페이지에 `getServerSideProps`를 추가하게 되면, 다음과 같이 JavaScript로 생성됩니다: ```bash filename="Terminal" .next/server/pages/about.js @@ -47,6 +45,6 @@ And if you add `getServerSideProps` to the page, it will then be JavaScript, lik ## Caveats -- If you have a [custom `App`](/docs/pages/building-your-application/routing/custom-app) with `getInitialProps` then this optimization will be turned off in pages without [Static Generation](/docs/pages/building-your-application/data-fetching/get-static-props). -- If you have a [custom `Document`](/docs/pages/building-your-application/routing/custom-document) with `getInitialProps` be sure you check if `ctx.req` is defined before assuming the page is server-side rendered. `ctx.req` will be `undefined` for pages that are prerendered. -- Avoid using the `asPath` value on [`next/router`](/docs/pages/api-reference/functions/use-router#router-object) in the rendering tree until the router's `isReady` field is `true`. Statically optimized pages only know `asPath` on the client and not the server, so using it as a prop may lead to mismatch errors. The [`active-class-name` example](https://github.com/vercel/next.js/tree/canary/examples/active-class-name) demonstrates one way to use `asPath` as a prop. +- 만약 `getInitialProps`가 있는 [custom `App`](/docs/pages/building-your-application/routing/custom-app)이 있는 경우, [Static Generation](/docs/pages/building-your-application/data-fetching/get-static-props)이 없는 페이지에서는 이 최적화가 비활성화됩니다. +- 만약 `getInitialProps`가 있는 [custom `Document`](/docs/pages/building-your-application/routing/custom-document)를 사용하고 있다면, 페이지가 서버 사이드 렌더링인지 확인하기 위해 `ctx.req`가 정의되어 있는지 확인 해야 합니다. 사전 렌더링된 페이지의 경우 `ctx.req`는 `undefined`로 나타납니다. +- 라우터의 `isReady` 필드가 `true`가 될 때까지 렌더링 트리에서 [`next/router`](/docs/pages/api-reference/functions/use-router#router-object)의 `asPath` 값 사용을 피해야 합니다. 정적으로 최적화된 페이지는 서버가 아닌 클라이언트에서만 `asPath`를 알기 때문에, 이를 prop으로 사용하면 불일치 오류가 발생할 수 있습니다. [`active-class-name` example](https://github.com/vercel/next.js/tree/canary/examples/active-class-name) 예제는 `asPath`를 prop으로 사용하는 한 가지 방법을 보여줍니다. diff --git a/pages/docs/pages/building-your-application/routing/custom-document.mdx b/pages/docs/pages/building-your-application/routing/custom-document.mdx index 7de7b32..fb88a42 100644 --- a/pages/docs/pages/building-your-application/routing/custom-document.mdx +++ b/pages/docs/pages/building-your-application/routing/custom-document.mdx @@ -3,13 +3,11 @@ title: Custom Document description: Extend the default document markup added by Next.js. --- -{/* TODO: 번역이 필요합니다. */} - # Custom Document -A custom `Document` can update the `` and `` tags used to render a [Page](/docs/pages/building-your-application/routing/pages-and-layouts). +사용자 정의 `Document`는 [페이지](/docs/pages/building-your-application/routing/pages-and-layouts)를 렌더링하는 데 사용되는 `` 및 `` 태그를 업데이트할 수 있습니다. -To override the default `Document`, create the file `pages/_document` as shown below: +기본 `Document`를 오버라이드 하려면 아래와 같이 `pages/_document` 파일을 생성하세요. ```tsx filename="pages/_document.tsx" switcher import { Html, Head, Main, NextScript } from 'next/document' @@ -43,22 +41,22 @@ export default function Document() { } ``` -> **Good to know** +> **알아두면 유용한 정보** > -> - `_document` is only rendered on the server, so event handlers like `onClick` cannot be used in this file. -> - ``, ``, `
` and `` are required for the page to be properly rendered. +> - `_document`는 서버에서만 렌더링되므로, 이 파일에서는 `onClick`과 같은 이벤트 핸들러를 사용할 수 없습니다. +> - 페이지가 제대로 렌더링되려면 ``, ``, `
` 및 ``가 필요합니다. ## Caveats -- The `` component used in `_document` is not the same as [`next/head`](/docs/pages/api-reference/components/head). The `` component used here should only be used for any `` code that is common for all pages. For all other cases, such as `` tags, we recommend using [`next/head`](/docs/pages/api-reference/components/head) in your pages or components. -- React components outside of `<Main />` will not be initialized by the browser. Do _not_ add application logic here or custom CSS (like `styled-jsx`). If you need shared components in all your pages (like a menu or a toolbar), read [Layouts](/docs/pages/building-your-application/routing/pages-and-layouts#layout-pattern) instead. -- `Document` currently does not support Next.js [Data Fetching methods](/docs/pages/building-your-application/data-fetching) like [`getStaticProps`](/docs/pages/building-your-application/data-fetching/get-static-props) or [`getServerSideProps`](/docs/pages/building-your-application/data-fetching/get-server-side-props). +- `_document`에 사용된 `<Head />` 컴포넌트는 [`next/head`](/docs/pages/api-reference/components/head)와 동일하지 않습니다. 여기에 사용된 `<Head />` 컴포넌트는 모든 페이지에 공통으로 적용되는 `<head>` 코드에만 사용해야 합니다. `<title>` 태그와 같은 다른 모든 경우에는 페이지 또는 컴포넌트에서 [`next/head`](/docs/pages/api-reference/components/head)를 사용하는 것이 좋습니다. +- `<Main />` 외부의 React 컴포넌트는 브라우저에서 초기화되지 않습니다. 여기에 애플리케이션 로직이나 커스텀 CSS(예: `styled-jsx`)를 _추가하지 마세요_. 모든 페이지에 공유되는 컴포넌트(메뉴 또는 툴바)가 필요한 경우 [레이아웃](/docs/pages/building-your-application/routing/pages-and-layouts#layout-pattern)을 대신 참고하세요. +- `Document`는 현재 [`getStaticProps`](/docs/pages/building-your-application/data-fetching/get-static-props) 또는 [`getServerSideProps`](/docs/pages/building-your-application/data-fetching/get-server-side-props)와 같은 Next.js [데이터 패칭 메서드](/docs/pages/building-your-application/data-fetching)를 지원하지 않습니다. ## Customizing `renderPage` -Customizing `renderPage` is advanced and only needed for libraries like CSS-in-JS to support server-side rendering. This is not needed for built-in `styled-jsx` support. +`renderPage` 커스터마이징은 고급 기술이며 서버 사이드 렌더링을 지원하기 위해 CSS-in-JS와 같은 라이브러리에서만 필요합니다. 내장된 `styled-jsx` 지원에는 필요하지 않습니다. -**We do not recommend using this pattern.** Instead, consider [incrementally adopting](/docs/app/building-your-application/upgrading/app-router-migration) the App Router, which allows you to more easily fetch data for [pages and layouts](/docs/app/building-your-application/routing/layouts-and-templates). +**이 패턴을 사용하지 않는 것이 좋습니다.** 대신 [페이지와 레이아웃](/docs/app/building-your-application/routing/layouts-and-templates)에 대한 데이터를 더 쉽게 가져올 수 있는 App Router를 [점진적으로 도입](/docs/app/building-your-application/upgrading/app-router-migration)하는 것을 고려하세요. ```tsx filename="pages/_document.tsx" switcher import Document, { @@ -76,16 +74,16 @@ class MyDocument extends Document { ): Promise<DocumentInitialProps> { const originalRenderPage = ctx.renderPage - // Run the React rendering logic synchronously + // React 렌더링 로직을 동기적으로 실행합니다. ctx.renderPage = () => originalRenderPage({ - // Useful for wrapping the whole react tree + // 전체 React 트리를 래핑하는 데 유용합니다. enhanceApp: (App) => App, - // Useful for wrapping in a per-page basis + // 페이지별로 래핑하는 데 유용합니다. enhanceComponent: (Component) => Component, }) - // Run the parent `getInitialProps`, it now includes the custom `renderPage` + // 부모의 `getInitialProps`를 실행하며, 이제 커스텀 `renderPage`가 포함됩니다. const initialProps = await Document.getInitialProps(ctx) return initialProps @@ -114,16 +112,16 @@ class MyDocument extends Document { static async getInitialProps(ctx) { const originalRenderPage = ctx.renderPage - // Run the React rendering logic synchronously + // React 렌더링 로직을 동기적으로 실행합니다. ctx.renderPage = () => originalRenderPage({ - // Useful for wrapping the whole react tree + // 전체 React 트리를 래핑하는 데 유용합니다. enhanceApp: (App) => App, - // Useful for wrapping in a per-page basis + // 페이지별로 래핑하는 데 유용합니다. enhanceComponent: (Component) => Component, }) - // Run the parent `getInitialProps`, it now includes the custom `renderPage` + // 부모의 `getInitialProps`를 실행하며, 이제 커스텀 `renderPage`가 포함됩니다. const initialProps = await Document.getInitialProps(ctx) return initialProps @@ -145,7 +143,7 @@ class MyDocument extends Document { export default MyDocument ``` -> **Good to know** +> **알아두면 유용한 정보** > -> - `getInitialProps` in `_document` is not called during client-side transitions. -> - The `ctx` object for `_document` is equivalent to the one received in [`getInitialProps`](/docs/pages/api-reference/functions/get-initial-props#context-object), with the addition of `renderPage`. +> - `_document`의 `getInitialProps`는 클라이언트 측 전환 중에는 호출되지 않습니다. +> - `_document`의 `ctx` 객체는 [`getInitialProps`](/docs/pages/api-reference/functions/get-initial-props#context-object)에서 받은 것과 동일하며, `renderPage`가 추가되어 있습니다. diff --git a/pages/docs/pages/building-your-application/routing/linking-and-navigating.mdx b/pages/docs/pages/building-your-application/routing/linking-and-navigating.mdx index 74a72db..978362e 100644 --- a/pages/docs/pages/building-your-application/routing/linking-and-navigating.mdx +++ b/pages/docs/pages/building-your-application/routing/linking-and-navigating.mdx @@ -3,13 +3,11 @@ title: Linking and Navigating description: Learn how navigation works in Next.js, and how to use the Link Component and `useRouter` hook. --- -{/* TODO: 번역이 필요합니다. */} - # Linking and Navigating -The Next.js router allows you to do client-side route transitions between pages, similar to a single-page application. +Next.js 라우터를 사용하면 싱글 페이지 애플리케이션과 유사하게 페이지 간에 클라이언트 측 라우트 전환을 할 수 있습니다. -A React component called `Link` is provided to do this client-side route transition. +이 클라이언트 측 라우트 전환을 위해서 `Link`라는 React 컴포넌트가 제공됩니다. ```jsx import Link from 'next/link' @@ -33,17 +31,17 @@ function Home() { export default Home ``` -The example above uses multiple links. Each one maps a path (`href`) to a known page: +위의 예에서는 여러 개의 링크를 사용합니다. 각 링크는 알려진 페이지에 대한 경로(`href`)를 매핑합니다: - `/` → `pages/index.js` - `/about` → `pages/about.js` - `/blog/hello-world` → `pages/blog/[slug].js` -Any `<Link />` in the viewport (initially or through scroll) will be prefetched by default (including the corresponding data) for pages using [Static Generation](/docs/pages/building-your-application/data-fetching/get-static-props). The corresponding data for [server-rendered](/docs/pages/building-your-application/data-fetching/get-server-side-props) routes is fetched _only when_ the `<Link />` is clicked. +[Static Generation](/docs/pages/building-your-application/data-fetching/get-static-props)을 사용하는 페이지에서 (초기 화면 또는 스크롤을 통해 나타나는) 뷰포트의 모든 `<Link />`는 기본적으로 (해당 데이터를 포함하여) 미리 가져와집니다. [서버에서 렌더링된](/docs/pages/building-your-application/data-fetching/get-server-side-props) 라우트에 해당하는 데이터는 `<Link />`가 클릭 되었을 때 _만_ 가져와집니다. ## Linking to dynamic paths -You can also use interpolation to create the path, which comes in handy for [dynamic route segments](/docs/pages/building-your-application/routing/dynamic-routes). For example, to show a list of posts which have been passed to the component as a prop: +보간을 이용해서 경로를 생성할 수 있는데, 이는 [동적 라우트 세그먼트](/docs/pages/building-your-application/routing/dynamic-routes)에 유용합니다. 예를 들어, 컴포넌트에 prop으로 전달된 게시글 목록을 표시하려면: ```jsx import Link from 'next/link' @@ -65,9 +63,9 @@ function Posts({ posts }) { export default Posts ``` -> [`encodeURIComponent`](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/encodeURIComponent) is used in the example to keep the path utf-8 compatible. +> 이 예제에서는 경로를 utf-8과 호환되도록 만들기 위해서 [`encodeURIComponent`](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/encodeURIComponent) 가 사용되었습니다. -Alternatively, using a URL Object: +또는, URL 객체를 사용할 수도 있습니다: ```jsx import Link from 'next/link' @@ -94,29 +92,29 @@ function Posts({ posts }) { export default Posts ``` -Now, instead of using interpolation to create the path, we use a URL object in `href` where: +이제 보간을 사용하여 경로를 만드는 대신 `href`에서 URL 객체를 사용합니다: -- `pathname` is the name of the page in the `pages` directory. `/blog/[slug]` in this case. -- `query` is an object with the dynamic segment. `slug` in this case. +- `pathname`은 `pages` 디렉터리에 있는 페이지의 이름입니다. 이 예제에서는 `/blog/[slug]`입니다. +- `query`는 동적 세그먼트가 있는 객체입니다. 이 예제에서는 `slug`입니다. ## Injecting the router <details> - <summary>Examples</summary> + <summary>예제</summary> -- [Dynamic Routing](https://github.com/vercel/next.js/tree/canary/examples/dynamic-routing) +- [동적 라우팅](https://github.com/vercel/next.js/tree/canary/examples/dynamic-routing) </details> -To access the [`router` object](/docs/pages/api-reference/functions/use-router#router-object) in a React component you can use [`useRouter`](/docs/pages/api-reference/functions/use-router) or [`withRouter`](/docs/pages/api-reference/functions/use-router#withrouter). +React 컴포넌트에서 [`router` 객체](/docs/pages/api-reference/functions/use-router#router-object)에 접근하기 위해서 [`useRouter`](/docs/pages/api-reference/functions/use-router) 또는 [`withRouter`](/docs/pages/api-reference/functions/use-router#withrouter)를 사용할 수 있습니다. -In general we recommend using [`useRouter`](/docs/pages/api-reference/functions/use-router). +일반적으로는 [`useRouter`](/docs/pages/api-reference/functions/use-router)를 사용하는 것을 권장합니다. ## Imperative Routing -[`next/link`](/docs/pages/api-reference/components/link) should be able to cover most of your routing needs, but you can also do client-side navigations without it, take a look at the [documentation for `next/router`](/docs/pages/api-reference/functions/use-router). +[`next/link`](/docs/pages/api-reference/components/link) 가 대부분의 라우팅 요구사항을 충족할 수 있지만, [`next/router` 문서](/docs/pages/api-reference/functions/use-router)를 참고해서 이것 없이도 클라이언트 측 탐색을 할 수 있습니다. -The following example shows how to do basic page navigations with [`useRouter`](/docs/pages/api-reference/functions/use-router): +아래의 예제는 [`useRouter`](/docs/pages/api-reference/functions/use-router)를 이용해서 기본적인 페이지 탐색 방법을 보여줍니다: ```jsx import { useRouter } from 'next/router' @@ -135,61 +133,62 @@ export default function ReadMore() { ## Shallow Routing <details> - <summary>Examples</summary> + <summary>예제</summary> -- [Shallow Routing](https://github.com/vercel/next.js/tree/canary/examples/with-shallow-routing) +- [얕은 라우팅](https://github.com/vercel/next.js/tree/canary/examples/with-shallow-routing) </details> -Shallow routing allows you to change the URL without running data fetching methods again, that includes [`getServerSideProps`](/docs/pages/building-your-application/data-fetching/get-server-side-props), [`getStaticProps`](/docs/pages/building-your-application/data-fetching/get-static-props), and [`getInitialProps`](/docs/pages/api-reference/functions/get-initial-props). +얕은 라우팅을 사용하면 데이터 가져오기 메서드인 [`getServerSideProps`](/docs/pages/building-your-application/data-fetching/get-server-side-props), [`getStaticProps`](/docs/pages/building-your-application/data-fetching/get-static-props), 그리고 [`getInitialProps`](/docs/pages/api-reference/functions/get-initial-props) 을 다시 실행하지 않고 URL을 변경할 수 있습니다. -You'll receive the updated `pathname` and the `query` via the [`router` object](/docs/pages/api-reference/functions/use-router#router-object) (added by [`useRouter`](/docs/pages/api-reference/functions/use-router) or [`withRouter`](/docs/pages/api-reference/functions/use-router#withrouter)), without losing state. +([`useRouter`](/docs/pages/api-reference/functions/use-router) 또는 [`withRouter`](/docs/pages/api-reference/functions/use-router#withrouter) 에서 추가된) [`router` 객체](/docs/pages/api-reference/functions/use-router#router-object)를 통해서 state를 잃지 않고 업데이트된 `pathname`을 받을 수 있습니다. -To enable shallow routing, set the `shallow` option to `true`. Consider the following example: +얕은 라우팅을 사용하기 위해서 `shallow` 옵션을 `true`로 설정합니다. 다음 예를 확인하세요: ```jsx import { useEffect } from 'react' import { useRouter } from 'next/router' -// Current URL is '/' +// 현재 URL은 '/'입니다. function Page() { const router = useRouter() useEffect(() => { - // Always do navigations after the first render + // 항상 첫번째 랜더링 이후에 탐색을 수행합니다. router.push('/?counter=10', undefined, { shallow: true }) }, []) useEffect(() => { - // The counter changed! + // 카운터가 바뀌었습니다! }, [router.query.counter]) } export default Page ``` -The URL will get updated to `/?counter=10` and the page won't get replaced, only the state of the route is changed. +URL은 `/?counter=10` 으로 업데이트되며 페이지는 교체되지 않고 라우트의 상태만 변경됩니다. -You can also watch for URL changes via [`componentDidUpdate`](https://react.dev/reference/react/Component#componentdidupdate) as shown below: +아래와 같이 [`componentDidUpdate`](https://react.dev/reference/react/Component#componentdidupdate)를 통해 URL 변경 사항을 확인할 수 있습니다: ```jsx componentDidUpdate(prevProps) { const { pathname, query } = this.props.router // verify props have changed to avoid an infinite loop + // 무한 반복을 피하기 위해 props가 변경되었는지 확인합니다. if (query.counter !== prevProps.router.query.counter) { - // fetch data based on the new query + // 새 쿼리를 기반으로 데이터를 가져옵니다. } } ``` ### Caveats -Shallow routing **only** works for URL changes in the current page. For example, let's assume we have another page called `pages/about.js`, and you run this: +얕은 라우팅은 현재 페이지의 URL 변경에 대해서**만** 동작합니다. 예를 들어, `pages/about.js`라는 다른 페이지가 있고 이것을 실행한다고 가정해 보겠습니다: ```js router.push('/?counter=10', '/about?counter=10', { shallow: true }) ``` -Since that's a new page, it'll unload the current page, load the new one and wait for data fetching even though we asked to do shallow routing. +새 페이지이므로 얕은 라우팅을 요청했음에도 불구하고 현재 페이지를 언로드하고 새 페이지를 로드한 후 데이터 가져오기를 기다립니다. -When shallow routing is used with middleware it will not ensure the new page matches the current page like previously done without middleware. This is due to middleware being able to rewrite dynamically and can't be verified client-side without a data fetch which is skipped with shallow, so a shallow route change must always be treated as shallow. +미들웨어와 함께 얕은 라우팅을 사용하면 이전에 미들웨어 없이 사용했던 것처럼 새로운 페이지가 현재 페이지와 일치하는지 보장할 수 없습니다. 이는 미들웨어가 동적으로 다시 작성할 수 있기 때문이며, 이를 클라이언트 측에서 얕은 라우팅으로 건너뛴 데이터 가져오기 없이는 확인할 수 없으므로 얕은 라우트 변경은 항상 얕은 것으로 처리되어야 합니다. diff --git a/pages/docs/pages/building-your-application/styling/css-modules.mdx b/pages/docs/pages/building-your-application/styling/css-modules.mdx index 68027ed..220221a 100644 --- a/pages/docs/pages/building-your-application/styling/css-modules.mdx +++ b/pages/docs/pages/building-your-application/styling/css-modules.mdx @@ -4,8 +4,168 @@ description: Style your Next.js Application using CSS Modules. source: app/building-your-application/styling/stylesheets --- -{/* TODO: 번역이 필요합니다. */} +{/* 이 문서의 내용은 app과 pages 라우터 간에 공유됩니다. Pages Router에 특정한 내용을 추가하려면 `<PagesOnly>Content</PagesOnly>` 컴포넌트를 사용할 수 있습니다. 모든 공유 내용은 컴포넌트로 감싸지 않아야 합니다. */} # CSS Modules -{/* DO NOT EDIT. The content of this doc is generated from the source above. To edit the content of this page, navigate to the source page in your editor. You can use the `<PagesOnly>Content</PagesOnly>` component to add content that is specific to the Pages Router. Any shared content should not be wrapped in a component. */} +<PagesOnly> + +<details open> + <summary>Examples</summary> + +- [Basic CSS Example](https://github.com/vercel/next.js/tree/canary/examples/basic-css) + +</details> + +</PagesOnly> + +Next.js는 다음을 포함한 다양한 유형의 스타일시트를 지원합니다: + +- [CSS Modules](https://nextjs.org/docs/pages/building-your-application/styling/css-modules#css-modules) +- [Global Styles](https://nextjs.org/docs/pages/building-your-application/styling/css-modules#global-styles) +- [External Stylesheets](https://nextjs.org/docs/pages/building-your-application/styling/css-modules#external-stylesheets) + +## CSS Modules + +Next.js는 `.module.css` 확장자를 사용하여 CSS Modules를 기본적으로 지원합니다. + +CSS Modules는 고유한 클래스 이름을 자동으로 생성하여 CSS를 로컬 범위로 지정합니다. 이를 통해 충돌을 걱정하지 않고 다른 파일에서 동일한 클래스 이름을 사용할 수 있습니다. 이러한 동작은 CSS Modules를 컴포넌트 수준의 CSS를 포함하는 이상적인 방법으로 만듭니다. + +## Example + +예를 들어, `components/` 폴더에 재사용 가능한 `Button` 컴포넌트를 고려해 보겠습니다: + +먼저, 다음 내용으로 `components/Button.module.css`를 생성합니다: + +```css filename="Button.module.css" +/* +다른 .css 또는 .module.css 파일과 충돌하는 것에 대해 걱정할 필요가 없습니다! +*/ +.error { + color: white; + background-color: red; +} +``` + +그런 다음, 위의 CSS 파일을 가져와서 사용하는 `components/Button.js`를 생성합니다: + +```js filename="components/Button.js" +import styles from './Button.module.css' + +export function Button() { + return ( + <button + type="button" + // "error" 클래스가 가져온 `styles` 객체의 속성으로 접근되는 것을 주목하세요. + className={styles.error} + > + Destroy + </button> + ) +} +``` + +CSS Modules는 **`.module.css` 및 `.module.sass` 확장자를 가진 파일에만 활성화됩니다.** + +프로덕션에서는 모든 CSS Module 파일이 자동으로 **여러 축소되고 코드 분할된** `.css` 파일로 연결됩니다. 이러한 `.css` 파일은 애플리케이션의 주요 실행 경로를 나타내며, 애플리케이션을 렌더링하는 데 필요한 최소한의 CSS만 로드되도록 보장합니다 + +## Global Styles + +애플리케이션에 스타일시트를 추가하려면 `pages/_app.js` 내에서 CSS 파일을 가져오세요. + +예를 들어, `styles.css`라는 다음 스타일시트를 고려해 보겠습니다: + +```css filename="styles.css" +body { + font-family: 'SF Pro Text', 'SF Pro Icons', 'Helvetica Neue', 'Helvetica', + 'Arial', sans-serif; + padding: 20px 20px 60px; + max-width: 680px; + margin: 0 auto; +} +``` + +[`pages/_app.js`](https://nextjs.org/docs/pages/building-your-application/routing/custom-app) 파일이 없으면 생성한 후, `styles.css` 파일을 [`불러옵니다`](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Statements/import). + +```js filename="pages/_app.js" +import '../styles.css' + +// 해당 내보내기는 새 `pages/_app.js` 파일에서 필요합니다. +export default function MyApp({ Component, pageProps }) { + return <Component {...pageProps} /> +} +``` + +이 스타일(`styles.css`)은 애플리케이션의 모든 페이지와 컴포넌트에 적용됩니다. 스타일시트의 전역적 특성 때문에 충돌을 피하기 위해, **오직 [`pages/_app.js`](https://nextjs.org/docs/pages/building-your-application/routing/custom-app) 내에서만 가져올 수 있습니다.** + +개발 시, 이러한 방식으로 스타일시트를 표현하면 스타일을 편집할 때 즉시 반영되어 애플리케이션 상태를 유지할 수 있습니다. + +프로덕션에서는 모든 CSS 파일이 자동으로 단일 축소된 `.css` 파일로 결합됩니다. CSS가 결합되는 순서는 `_app.js` 파일에 CSS가 가져오는 순서와 일치합니다. 자체 CSS를 포함하는 가져온 JS 모듈에 특별히 주의하세요; JS 모듈의 CSS는 가져온 CSS 파일과 동일한 순서 규칙에 따라 결합됩니다. 예를 들어: + +```js +import '../styles.css' +// ErrorBoundary의 CSS는 styles.css의 전역 CSS에 의존하므로, styles.css 이후에 가져옵니다. +import ErrorBoundary from '../components/ErrorBoundary' + +export default function MyApp({ Component, pageProps }) { + return ( + <ErrorBoundary> + <Component {...pageProps} /> + </ErrorBoundary> + ) +} +``` + +## External Stylesheets + +Next.js는 JavaScript 파일에서 CSS 파일 [`가져오기`](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Statements/import)를 허용합니다. 이는 Next.js가 import의 개념을 JavaScript 이상으로 확장했기 때문입니다. + +### Import styles from `node_modules` + +Next.js **9.5.4**부터 애플리케이션 내 어디에서나 `node_modules`에서 CSS 파일을 가져오는 것이 허용됩니다. + +전역 스타일시트의 경우, `bootstrap` 또는 `nprogress`와 같이 파일을 `pages/_app.js` 내에서 가져와야 합니다. 예를 들어: + +```js filename="pages/_app.js" +import 'bootstrap/dist/css/bootstrap.css' + +export default function MyApp({ Component, pageProps }) { + return <Component {...pageProps} /> +} +``` + +서드 파티 컴포넌트에서 필요한 CSS를 가져오려면, 해당 컴포넌트에서 가져올 수 있습니다. 예를 들어: + +```js filename="components/example-dialog.js" +import { useState } from 'react' +import { Dialog } from '@reach/dialog' +import VisuallyHidden from '@reach/visually-hidden' +import '@reach/dialog/styles.css' + +function ExampleDialog(props) { + const [showDialog, setShowDialog] = useState(false) + const open = () => setShowDialog(true) + const close = () => setShowDialog(false) + + return ( + <div> + <button onClick={open}>Open Dialog</button> + <Dialog isOpen={showDialog} onDismiss={close}> + <button className="close-button" onClick={close}> + <VisuallyHidden>Close</VisuallyHidden> + <span aria-hidden>×</span> + </button> + <p>Hello there. I am a dialog</p> + </Dialog> + </div> + ) +} +``` + +## Additional Features + +Next.js는 스타일 추가의 개발자 경험을 개선하기 위해 추가 기능을 포함합니다: + +- `next dev`로 로컬에서 실행할 때, 로컬 스타일시트(전역 또는 CSS 모듈)는 [Fast Refresh](https://nextjs.org/docs/architecture/fast-refresh)를 활용하여 수정사항이 저장될 때 즉시 반영됩니다. +- `next build`로 프로덕션 빌드를 할 때, CSS 파일은 더 적은 수의 축소된 `.css` 파일로 번들링되어 스타일을 검색하는 데 필요한 네트워크 요청 수를 줄입니다. +- JavaScript를 비활성화하면, 스타일은 프로덕션 빌드(`next start`)에서 여전히 로드됩니다. 그러나, [Fast Refresh](https://nextjs.org/docs/architecture/fast-refresh)를 활성화하기 위해 `next dev`에는 여전히 JavaScript가 필요합니다. diff --git a/pages/docs/pages/building-your-application/upgrading/version-10.mdx b/pages/docs/pages/building-your-application/upgrading/version-10.mdx index e9c9769..9ecd4ea 100644 --- a/pages/docs/pages/building-your-application/upgrading/version-10.mdx +++ b/pages/docs/pages/building-your-application/upgrading/version-10.mdx @@ -7,9 +7,9 @@ description: Upgrade your Next.js Application from Version 9 to Version 10. # Version 10 -There were no breaking changes between versions 9 and 10. +버전 9에서 10으로의 변경 사항은 없습니다. -To upgrade to version 10, run the following command: +버전 10으로 업그레이드하려면 다음 명령어를 실행하세요: ```bash filename="Terminal" npm i next@10 @@ -27,4 +27,4 @@ pnpm up next@10 bun add next@10 ``` -> **Good to know:** If you are using TypeScript, ensure you also upgrade `@types/react` and `@types/react-dom` to their corresponding versions. +> **참고:** TypeScript를 사용하는 경우, `@types/react` 와 `@types/react-dom` 도 해당 버전으로 업그레이드해야 합니다. diff --git a/pages/docs/pages/building-your-application/upgrading/version-11.mdx b/pages/docs/pages/building-your-application/upgrading/version-11.mdx index a287598..408d6dc 100644 --- a/pages/docs/pages/building-your-application/upgrading/version-11.mdx +++ b/pages/docs/pages/building-your-application/upgrading/version-11.mdx @@ -7,7 +7,7 @@ description: Upgrade your Next.js Application from Version 10 to Version 11. # Version 11 -To upgrade to version 11, run the following command: +버전 11로 업그레이드하려면 다음 명령어를 실행하세요: ```bash filename="Terminal" npm i next@11 react@17 react-dom@17 @@ -25,23 +25,23 @@ pnpm up next@11 react@17 react-dom@17 bun add next@11 react@17 react-dom@17 ``` -> **Good to know:** If you are using TypeScript, ensure you also upgrade `@types/react` and `@types/react-dom` to their corresponding versions. +> **참고:** TypeScript를 사용하는 경우, `@types/react` 와 `@types/react-dom` 도 해당 버전으로 업그레이드해야 합니다. ### Webpack 5 -Webpack 5 is now the default for all Next.js applications. If you did not have a custom webpack configuration, your application is already using webpack 5. If you do have a custom webpack configuration, you can refer to the [Next.js webpack 5 documentation](/docs/messages/webpack5) for upgrade guidance. + 이제 모든 Next.js 애플리케이션에 대해 Webpack 5가 기본값으로 설정됩니다. 커스텀 Webpack 구성을 하지 않았다면, 애플리케이션은 이미 Webpack 5를 사용 중입니다. 커스텀 Webpack 구성이 있는 경우, 업그레이드 지침은 [Next.js webpack 5 문서](/docs/messages/webpack5)를 참조하세요. ### Cleaning the `distDir` is now a default -The build output directory (defaults to `.next`) is now cleared by default except for the Next.js caches. You can refer to [the cleaning `distDir` RFC](https://github.com/vercel/next.js/discussions/6009) for more information. +빌드 출력 디렉토리(기본값은 `.next`)가 이제 기본적으로 Next.js 캐시를 제외하고 정리됩니다. 자세한 내용은 [빌드 출력 디렉토리 정리 RFC](https://github.com/vercel/next.js/discussions/6009)를 참조하세요. -If your application was relying on this behavior previously you can disable the new default behavior by adding the `cleanDistDir: false` flag in `next.config.js`. +애플리케이션이 이전에 이 동작에 의존하고 있었다면 `next.config.js` 에 `cleanDistDir: false` 플래그를 추가하여 새로운 기본 동작을 비활성화할 수 있습니다. ### `PORT` is now supported for `next dev` and `next start` -Next.js 11 supports the `PORT` environment variable to set the port the application runs on. Using `-p`/`--port` is still recommended but if you were prohibited from using `-p` in any way you can now use `PORT` as an alternative: +Next.js 11은 애플리케이션이 실행되는 포트를 설정하기 위해 `PORT` 환경 변수를 지원합니다. 여전히 `-p/--port` 사용이 권장되지만, 어떤 이유로든 `-p` 를 사용할 수 없는 경우 `PORT` 를 대안으로 사용할 수 있습니다: -Example: +예시: ``` PORT=4000 next start @@ -49,7 +49,7 @@ PORT=4000 next start ### `next.config.js` customization to import images -Next.js 11 supports static image imports with `next/image`. This new feature relies on being able to process image imports. If you previously added the `next-images` or `next-optimized-images` packages you can either move to the new built-in support using `next/image` or disable the feature: +Next.js 11은 `next/image` 를 사용한 정적 이미지 가져오기를 지원합니다. 이 새로운 기능은 이미지 가져오기를 처리할 수 있어야 합니다. 이전에 `next-images` 또는 `next-optimized-images` 패키지를 추가했다면 새로운 내장 지원을 사용하거나 기능을 비활성화할 수 있습니다: ```js filename="next.config.js" module.exports = { @@ -61,43 +61,43 @@ module.exports = { ### Remove `super.componentDidCatch()` from `pages/_app.js` -The `next/app` component's `componentDidCatch` was deprecated in Next.js 9 as it's no longer needed and has since been a no-op. In Next.js 11, it was removed. +`next/app` 컴포넌트의 `componentDidCatch` 는 더 이상 필요하지 않기 때문에 `Next.js` 9에서 사용 중단되었으며, 이후로는 no-op이었습니다. Next.js 11에서는 이것이 제거되었습니다. -If your `pages/_app.js` has a custom `componentDidCatch` method you can remove `super.componentDidCatch` as it is no longer needed. +만약 `pages/_app.js` 에 커스텀 `componentDidCatch` 메서드가 있다면, 더 이상 필요하지 않으므로 `super.componentDidCatch` 를 제거할 수 있습니다. ### Remove `Container` from `pages/_app.js` -This export was deprecated in Next.js 9 as it's no longer needed and has since been a no-op with a warning during development. In Next.js 11 it was removed. +이 익스포트는 더 이상 필요하지 않기 때문에 Next.js 9에서 사용 중단되었으며, 개발 중 경고와 함께 no-op이었습니다. Next.js 11에서는 이것이 제거되었습니다. -If your `pages/_app.js` imports `Container` from `next/app` you can remove `Container` as it was removed. Learn more in [the documentation](/docs/messages/app-container-deprecated). +만약 pages/\_app.js가 next/app에서 Container를 가져오고 있다면, Container를 제거할 수 있습니다. 자세한 내용은 [문서](/docs/messages/app-container-deprecated)를 참조하세요. ### Remove `props.url` usage from page components -This property was deprecated in Next.js 4 and has since shown a warning during development. With the introduction of `getStaticProps` / `getServerSideProps` these methods already disallowed the usage of `props.url`. In Next.js 11, it was removed completely. +이 속성은 Next.js 4에서 사용 중단되었으며, 이후 개발 중 경고를 표시했습니다. `getStaticProps` / `getServerSideProps` 도입으로 이 메서드들은 이미 `props.url` 사용을 금지했습니다. Next.js 11에서는 이것이 완전히 제거되었습니다. -You can learn more in [the documentation](/docs/messages/url-deprecated). +자세한 내용은 [문서](/docs/messages/url-deprecated)를 참조하세요. ### Remove `unsized` property on `next/image` -The `unsized` property on `next/image` was deprecated in Next.js 10.0.1. You can use `layout="fill"` instead. In Next.js 11 `unsized` was removed. +`next/image` 의 `unsized` 속성은 Next.js 10.0.1에서 사용 중단되었습니다. 대신 `layout="fill"` 을 사용할 수 있습니다. Next.js 11에서는 `unsized` 가 제거되었습니다. ### Remove `modules` property on `next/dynamic` -The `modules` and `render` option for `next/dynamic` were deprecated in Next.js 9.5. This was done in order to make the `next/dynamic` API closer to `React.lazy`. In Next.js 11, the `modules` and `render` options were removed. +`next/dynamic` 의 `modules` 및 `render` 옵션은 Next.js 9.5에서 사용 중단되었습니다. 이는 `next/dynamic` API를 `React.lazy` 와 더 가깝게 만들기 위함이었습니다. Next.js 11에서는 `modules` 및 `render` 옵션이 제거되었습니다. -This option hasn't been mentioned in the documentation since Next.js 8 so it's less likely that your application is using it. +이 옵션은 Next.js 8 이후 문서에서 언급되지 않았기 때문에 애플리케이션에서 사용 중일 가능성은 적습니다. -If your application does use `modules` and `render` you can refer to [the documentation](/docs/messages/next-dynamic-modules). +만약 애플리케이션이 `modules` 와 `render` 를 사용하고 있다면, [문서](/docs/messages/next-dynamic-modules)를 참조하세요. ### Remove `Head.rewind` -`Head.rewind` has been a no-op since Next.js 9.5, in Next.js 11 it was removed. You can safely remove your usage of `Head.rewind`. +`Head.rewind` 는 Next.js 9.5 이후로 no-op이었으며, Next.js 11에서는 제거되었습니다. `Head.rewind` 사용을 안전하게 제거할 수 있습니다. ### Moment.js locales excluded by default -Moment.js includes translations for a lot of locales by default. Next.js now automatically excludes these locales by default to optimize bundle size for applications using Moment.js. +Moment.js는 기본적으로 많은 로케일에 대한 번역을 포함합니다. Next.js는 이제 Moment.js를 사용하는 애플리케이션의 번들 크기를 최적화하기 위해 기본적으로 이러한 로케일을 제외합니다. -To load a specific locale use this snippet: +특정 로케일을 로드하려면 다음 코드를 사용하세요: ```js import moment from 'moment' @@ -106,11 +106,11 @@ import 'moment/locale/ja' moment.locale('ja') ``` -You can opt-out of this new default by adding `excludeDefaultMomentLocales: false` to `next.config.js` if you do not want the new behavior, do note it's highly recommended to not disable this new optimization as it significantly reduces the size of Moment.js. +새로운 동작을 원하지 않는 경우 `next.config.js` 에 `excludeDefaultMomentLocales: false` 를 추가하여 이 새로운 기본값을 옵트아웃할 수 있지만, 이 새로운 최적화를 비활성화하지 않는 것이 번들 크기를 크게 줄이기 때문에 매우 권장됩니다. ### Update usage of `router.events` -In case you're accessing `router.events` during rendering, in Next.js 11 `router.events` is no longer provided during pre-rendering. Ensure you're accessing `router.events` in `useEffect`: +렌더링 중에 `router.events` 에 접근하는 경우, Next.js 11에서는 프리렌더링 중 `router.events` 가 더 이상 제공되지 않습니다. `useEffect` 에서 `router.events` 에 접근하는지 확인하세요: ```js useEffect(() => { @@ -124,29 +124,29 @@ useEffect(() => { router.events.on('routeChangeStart', handleRouteChange) - // If the component is unmounted, unsubscribe - // from the event with the `off` method: + // 컴포넌트가 언마운트되면 이벤트에서 구독 해제 + // `off` 메서드를 사용하여: return () => { router.events.off('routeChangeStart', handleRouteChange) } }, [router]) ``` -If your application uses `router.router.events` which was an internal property that was not public please make sure to use `router.events` as well. +애플리케이션이 공개되지 않은 내부 속성인 `router.router.events` 를 사용하는 경우 `router.events` 를 사용해야 합니다. ## React 16 to 17 -React 17 introduced a new [JSX Transform](https://reactjs.org/blog/2020/09/22/introducing-the-new-jsx-transform.html) that brings a long-time Next.js feature to the wider React ecosystem: Not having to `import React from 'react'` when using JSX. When using React 17 Next.js will automatically use the new transform. This transform does not make the `React` variable global, which was an unintended side-effect of the previous Next.js implementation. A [codemod is available](/docs/pages/building-your-application/upgrading/codemods#add-missing-react-import) to automatically fix cases where you accidentally used `React` without importing it. +React 17은 JSX를 사용할 때 import React from 'react'를 생략할 수 있는 새로운 [JSX Transform](https://reactjs.org/blog/2020/09/22/introducing-the-new-jsx-transform.html)를 도입했습니다. React 17을 사용할 때 Next.js는 자동으로 새로운 변환을 사용합니다. 이 변환은 이전 Next.js 구현의 의도하지 않은 부작용이었던 React 변수를 전역으로 만들지 않습니다. React를 임포트하지 않고 실수로 사용한 경우 자동으로 수정할 수 있는 [codemod가 제공](/docs/pages/building-your-application/upgrading/codemods#add-missing-react-import)됩니다. -Most applications already use the latest version of React, with Next.js 11 the minimum React version has been updated to 17.0.2. +대부분의 애플리케이션은 이미 최신 버전의 React를 사용하고 있으며, Next.js 11에서는 최소 React 버전이 17.0.2로 업데이트되었습니다. -To upgrade you can run the following command: +업그레이드하려면 다음 명령어를 실행하세요: ``` npm install react@latest react-dom@latest ``` -Or using `yarn`: +또는 `yarn` 을 사용하여: ``` yarn add react@latest react-dom@latest diff --git a/pages/docs/pages/building-your-application/upgrading/version-12.mdx b/pages/docs/pages/building-your-application/upgrading/version-12.mdx index dfe2cd0..b291f96 100644 --- a/pages/docs/pages/building-your-application/upgrading/version-12.mdx +++ b/pages/docs/pages/building-your-application/upgrading/version-12.mdx @@ -3,41 +3,33 @@ title: Version 12 description: Upgrade your Next.js Application from Version 11 to Version 12. --- -{/* TODO: 번역이 필요합니다. */} - # Version 12 -To upgrade to version 12, run the following command: +버전 `12` 으로 업그레이드하려면 아래의 커맨드를 실행하세요: -```bash filename="Terminal" +```bash npm i next@12 react@17 react-dom@17 eslint-config-next@12 -``` -```bash filename="Terminal" yarn add next@12 react@17 react-dom@17 eslint-config-next@12 -``` -```bash filename="Terminal" pnpm up next@12 react@17 react-dom@17 eslint-config-next@12 -``` -```bash filename="Terminal" bun add next@12 react@17 react-dom@17 eslint-config-next@12 ``` -> **Good to know:** If you are using TypeScript, ensure you also upgrade `@types/react` and `@types/react-dom` to their corresponding versions. +> **알아두면 좋은 사항:** TypeScript를 사용하는 경우, `@types/react` 및 `@types/react-dom`도 해당 버전으로 업그레이드해야 합니다. ### Upgrading to 12.2 -[Middleware](/docs/messages/middleware-upgrade-guide) - If you were using Middleware prior to `12.2`, please see the [upgrade guide](/docs/messages/middleware-upgrade-guide) for more information. +[Middleware](/docs/messages/middleware-upgrade-guide) - `12.2` 이전에 Middleware를 사용한 경우, 자세한 내용은 [업그레이드 가이드](/docs/messages/middleware-upgrade-guide)를 참조하세요. ### Upgrading to 12.0 -[Minimum Node.js Version](https://nodejs.org/en/) - The minimum Node.js version has been bumped from `12.0.0` to `12.22.0` which is the first version of Node.js with native ES Modules support. +[Minimum Node.js Version](https://nodejs.org/en/) - 최소 Node.js 버전이 `12.0.0`에서 `12.22.0`으로 상향 조정되었습니다. 이는 Node.js의 첫 번째 네이티브 ES 모듈 지원 버전입니다. -[Minimum React Version](https://react.dev/learn/add-react-to-an-existing-project) - The minimum required React version is `17.0.2`. To upgrade you can run the following command in the terminal: +[Minimum React Version](https://react.dev/learn/add-react-to-an-existing-project) - 최소 요구 React 버전은 `17.0.2`입니다. 업그레이드하려면 터미널에서 다음 명령어를 실행할 수 있습니다: -```bash filename="Terminal" +```bash npm install react@latest react-dom@latest yarn add react@latest react-dom@latest @@ -49,23 +41,23 @@ bun add react@latest react-dom@latest #### SWC replacing Babel -Next.js now uses the Rust-based compiler [SWC](https://swc.rs/) to compile JavaScript/TypeScript. This new compiler is up to 17x faster than Babel when compiling individual files and up to 5x faster Fast Refresh. +Next.js는 이제 Rust 기반 컴파일러인 [SWC](https://swc.rs/)를 사용하여 JavaScript/TypeScript를 컴파일합니다. 이 새로운 컴파일러는 개별 파일을 컴파일할 때 Babel보다 최대 17배 빠르고, Fast Refresh에서는 최대 5배 빠릅니다. -Next.js provides full backward compatibility with applications that have [custom Babel configuration](/docs/pages/building-your-application/configuring/babel). All transformations that Next.js handles by default like styled-jsx and tree-shaking of `getStaticProps` / `getStaticPaths` / `getServerSideProps` have been ported to Rust. +Next.js는 [커스텀 Babel 구성](/docs/pages/building-your-application/configuring/babel)을 가진 애플리케이션과의 완전한 하위 호환성을 제공합니다. Next.js가 기본적으로 처리하는 styled-jsx 및 `getStaticProps` / `getStaticPaths` / `getServerSideProps`의 트리 쉐이킹과 같은 모든 변환은 Rust로 포팅되었습니다. -When an application has a custom Babel configuration, Next.js will automatically opt-out of using SWC for compiling JavaScript/Typescript and will fall back to using Babel in the same way that it was used in Next.js 11. +애플리케이션이 커스텀 Babel 구성을 가지고 있는 경우, Next.js는 JavaScript/Typescript를 컴파일할 때 SWC 대신 Babel을 사용하도록 자동으로 옵트아웃됩니다. -Many of the integrations with external libraries that currently require custom Babel transformations will be ported to Rust-based SWC transforms in the near future. These include but are not limited to: +현재 커스텀 Babel 변환이 필요한 외부 라이브러리와의 많은 통합은 가까운 미래에 Rust 기반 SWC 변환으로 포팅될 예정입니다. 여기에는 다음이 포함되지만 이에 국한되지 않습니다: - Styled Components - Emotion - Relay -In order to prioritize transforms that will help you adopt SWC, please provide your `.babelrc` on [this feedback thread](https://github.com/vercel/next.js/discussions/30174). +SWC 채택을 도울 수 있는 변환을 우선시하기 위해, [이 피드백 스레드](https://github.com/vercel/next.js/discussions/30174)에 `.babelrc`를 제공해주세요. #### SWC replacing Terser for minification -You can opt-in to replacing Terser with SWC for minifying JavaScript up to 7x faster using a flag in `next.config.js`: +JavaScript를 최대 7배 빠르게 압축하기 위해 `next.config.js`에서 플래그를 사용하여 Terser를 SWC로 교체할 수 있습니다: ```js filename="next.config.js" module.exports = { @@ -73,31 +65,31 @@ module.exports = { } ``` -Minification using SWC is an opt-in flag to ensure it can be tested against more real-world Next.js applications before it becomes the default in Next.js 12.1. If you have feedback about minification, please leave it on [this feedback thread](https://github.com/vercel/next.js/discussions/30237). +SWC를 사용한 압축은 Next.js 12.1에서 기본값이 되기 전에 더 많은 실제 Next.js 애플리케이션에 대해 테스트할 수 있도록 옵트인 플래그입니다. 압축에 대한 피드백이 있는 경우, [이 피드백 스레드](https://github.com/vercel/next.js/discussions/30237)에 남겨주세요. #### Improvements to styled-jsx CSS parsing -On top of the Rust-based compiler we've implemented a new CSS parser based on the one used for the styled-jsx Babel transform. This new parser has improved handling of CSS and now errors when invalid CSS is used that would previously slip through and cause unexpected behavior. +Rust 기반 컴파일러 외에도 styled-jsx Babel 변환에 사용된 새로운 CSS 파서를 구현했습니다. 이 새로운 파서는 CSS 처리 능력을 개선했으며, 이전에는 잘못된 CSS가 통과되어 예기치 않은 동작을 유발할 수 있었던 경우를 오류로 처리합니다. -Because of this change invalid CSS will throw an error during development and `next build`. This change only affects styled-jsx usage. +이 변경으로 인해 잘못된 CSS는 개발 중 및 `next build` 중에 오류를 발생시킵니다. 이 변경은 styled-jsx 사용에만 영향을 미칩니다. #### `next/image` changed wrapping element -`next/image` now renders the `<img>` inside a `<span>` instead of `<div>`. +`next/image`는 이제 `<div>` 대신 `<span>` 내부에 `<img>`를 렌더링합니다. -If your application has specific CSS targeting span such as `.container span`, upgrading to Next.js 12 might incorrectly match the wrapping element inside the `<Image>` component. You can avoid this by restricting the selector to a specific class such as `.container span.item` and updating the relevant component with that className, such as `<span className="item" />`. +애플리케이션에 `.container span`과 같은 span을 타겟팅하는 특정 CSS가 있는 경우, Next.js 12로 업그레이드하면 `<Image>` 컴포넌트 내부의 래핑 요소가 잘못 일치할 수 있습니다. 이 문제를 피하려면 `.container span.item`과 같이 선택기를 특정 클래스에 제한하고 해당 클래스 이름으로 관련 컴포넌트를 업데이트하세요, 예를 들어 `<span className="item" />`. -If your application has specific CSS targeting the `next/image` `<div>` tag, for example `.container div`, it may not match anymore. You can update the selector `.container span`, or preferably, add a new `<div className="wrapper">` wrapping the `<Image>` component and target that instead such as `.container .wrapper`. +애플리케이션에 `next/image` `<div>` 태그를 타겟팅하는 특정 CSS가 있는 경우, 예를 들어 `.container div`, 더 이상 일치하지 않을 수 있습니다. 선택기를 `.container span`으로 업데이트하거나, 선호되는 방법으로 `<Image>` 컴포넌트를 래핑하는 새로운 `<div className="wrapper">`를 추가하고 이를 타겟팅하세요, 예를 들어 `.container .wrapper`. -The `className` prop is unchanged and will still be passed to the underlying `<img>` element. +`className` prop은 변경되지 않으며, 여전히 기본 `<img>` 요소에 전달됩니다. -See the [documentation](/docs/pages/building-your-application/optimizing/images#styling) for more info. +자세한 내용은 [문서](/docs/pages/building-your-application/optimizing/images#styling)를 참조하세요. #### HMR connection now uses a WebSocket -Previously, Next.js used a [server-sent events](https://developer.mozilla.org/docs/Web/API/Server-sent_events) connection to receive HMR events. Next.js 12 now uses a WebSocket connection. +이전에는 Next.js가 HMR 이벤트를 수신하기 위해 [server-sent events](https://developer.mozilla.org/docs/Web/API/Server-sent_events) 연결을 사용했습니다. Next.js 12는 이제 WebSocket 연결을 사용합니다. -In some cases when proxying requests to the Next.js dev server, you will need to ensure the upgrade request is handled correctly. For example, in `nginx` you would need to add the following configuration: +Next.js dev 서버로 요청을 프록시할 때 업그레이드 요청이 올바르게 처리되도록 해야 할 경우가 있습니다. 예를 들어, `nginx`에서 다음 구성을 추가해야 합니다: ```nginx location /_next/webpack-hmr { @@ -108,7 +100,7 @@ location /_next/webpack-hmr { } ``` -If you are using Apache (2.x), you can add the following configuration to enable web sockets to the server. Review the port, host name and server names. +Apache (2.x)를 사용하는 경우, 서버에 웹 소켓을 활성화하려면 다음 구성을 추가할 수 있습니다. 포트, 호스트 이름 및 서버 이름을 검토하세요. ``` <VirtualHost *:443> @@ -129,7 +121,7 @@ If you are using Apache (2.x), you can add the following configuration to enable </VirtualHost> ``` -For custom servers, such as `express`, you may need to use `app.all` to ensure the request is passed correctly, for example: +`express`와 같은 커스텀 서버의 경우, 요청이 올바르게 전달되도록 `app.all`을 사용해야 할 수 있습니다. 예를 들어: ```js app.all('/_next/webpack-hmr', (req, res) => { @@ -139,18 +131,18 @@ app.all('/_next/webpack-hmr', (req, res) => { #### Webpack 4 support has been removed -If you are already using webpack 5 you can skip this section. +이미 webpack 5를 사용 중인 경우, 이 섹션을 건너뛸 수 있습니다. -Next.js has adopted webpack 5 as the default for compilation in Next.js 11. As communicated in the [webpack 5 upgrading documentation](/docs/messages/webpack5) Next.js 12 removes support for webpack 4. +Next.js는 Next.js 11에서 기본 컴파일러로 webpack 5를 채택했습니다. [webpack 5 업그레이드 문서](/docs/messages/webpack5)에 명시된 바와 같이 Next.js 12는 webpack 4에 대한 지원을 제거합니다. -If your application is still using webpack 4 using the opt-out flag, you will now see an error linking to the [webpack 5 upgrading documentation](/docs/messages/webpack5). +opt-out 플래그를 사용하여 여전히 webpack 4를 사용 중인 애플리케이션의 경우, 이제 [webpack 5 업그레이드 문서](/docs/messages/webpack5)로 연결되는 오류가 표시됩니다. #### `target` option deprecated -If you do not have `target` in `next.config.js` you can skip this section. +`next.config.js`에 `target`이 없는 경우, 이 섹션을 건너뛸 수 있습니다. -The target option has been deprecated in favor of built-in support for tracing what dependencies are needed to run a page. +target 옵션은 페이지를 실행하는 데 필요한 종속성을 추적하는 기본 제공 지원으로 대체되었습니다. -During `next build`, Next.js will automatically trace each page and its dependencies to determine all of the files that are needed for deploying a production version of your application. +`next build` 중에 Next.js는 각 페이지와 해당 종속성을 자동으로 추적하여 애플리케이션의 프로덕션 버전을 배포하는 데 필요한 모든 파일을 결정합니다. -If you are currently using the `target` option set to `serverless`, please read the [documentation on how to leverage the new output](/docs/pages/api-reference/next-config-js/output). +현재 `serverless`로 설정된 `target` 옵션을 사용하는 경우, 새로운 출력 활용 방법에 대한 [문서](/docs/pages/api-reference/next-config-js/output)를 읽어보세요. diff --git a/pages/docs/pages/building-your-application/upgrading/version-13.mdx b/pages/docs/pages/building-your-application/upgrading/version-13.mdx index 2b89736..f60c9d0 100644 --- a/pages/docs/pages/building-your-application/upgrading/version-13.mdx +++ b/pages/docs/pages/building-your-application/upgrading/version-13.mdx @@ -49,7 +49,7 @@ Next.js 12는 임시 import인 `next/future/image`로 이미지 컴포넌트에 Next.js 13부터 이러한 새로운 동작은 `next/image`의 기본 동작이 되었습니다. -새로은 Image 컴포넌트로 마이그레이션하는 데 도움이 되는 두 가지 codemod가 있습니다: +새로운 Image 컴포넌트로 마이그레이션하는 데 도움이 되는 두 가지 codemod가 있습니다: - [next-image-to-legacy-image](/docs/pages/building-your-application/upgrading/codemods#next-image-to-legacy-image): 이 codemod는 `next/image` import를 `next/legacy/image`로 안전하게 자동으로 이름을 변경하여 Next.js 12와 동일한 동작을 유지합니다. Next.js 13으로 빠르게 자동으로 업데이트를 하려면 이 codemod를 실행하는 것이 좋습니다. diff --git a/pages/index.mdx b/pages/index.mdx index eb6efce..0960dbf 100644 --- a/pages/index.mdx +++ b/pages/index.mdx @@ -4,7 +4,7 @@ Next.js 공식 문서 한글 번역 프로젝트입니다. by [@luciancah](https ### 문서 버전 -현재 번역중인 버전은 [Next.js Canary(15)](https://github.com/vercel/next.js/tree/canary/docs)을 기반으로 하고 있습니다. +현재 번역중인 버전은 [Next.js v15.0.0-canary.82](https://github.com/vercel/next.js/tree/canary/docs)을 기반으로 하고 있습니다. 해당 버전 문서 API가 일부 호환성을 가지고 있지만, 14버전 이전의 문서 또한 추후에 번역할 예정입니다. @@ -265,5 +265,162 @@ Next.js 공식 문서 한글 번역 프로젝트입니다. by [@luciancah](https </a> </td> </tr> + <tr> + <td align="center" valign="top" width="14.28%"> + <a href="https://github.com/yoonncho"> + <img + src="https://avatars.githubusercontent.com/u/49135797?v=4?s=100" + width="100px;" + alt="yoon" + /> + <br /> + <sub> + <b>yoon</b> + </sub> + </a> + <br /> + <a href="#content-yoonncho" title="Content"> + 🖋 + </a> + </td> + <td align="center" valign="top" width="14.28%"> + <a href="https://shqpdltm.tistory.com/"> + <img + src="https://avatars.githubusercontent.com/u/90549862?v=4?s=100" + width="100px;" + alt="SeokJu Kim" + /> + <br /> + <sub> + <b>SeokJu Kim</b> + </sub> + </a> + <br /> + <a href="#content-SoJuSo" title="Content"> + 🖋 + </a> + </td> + <td align="center" valign="top" width="14.28%"> + <a href="https://github.com/grapefruit13"> + <img + src="https://avatars.githubusercontent.com/u/92169354?v=4?s=100" + width="100px;" + alt="grapefruit" + /> + <br /> + <sub> + <b>grapefruit</b> + </sub> + </a> + <br /> + <a href="#content-grapefruit13" title="Content"> + 🖋 + </a> + </td> + <td align="center" valign="top" width="14.28%"> + <a href="https://github.com/RedBe-an"> + <img + src="https://avatars.githubusercontent.com/u/161127101?v=4?s=100" + width="100px;" + alt="RedBean" + /> + <br /> + <sub> + <b>RedBean</b> + </sub> + </a> + <br /> + <a href="#content-RedBe-an" title="Content"> + 🖋 + </a> + </td> + <td align="center" valign="top" width="14.28%"> + <a href="https://velog.io/@therealjamesjung"> + <img + src="https://avatars.githubusercontent.com/u/39877377?v=4?s=100" + width="100px;" + alt="Jaekyung Jung" + /> + <br /> + <sub> + <b>Jaekyung Jung</b> + </sub> + </a> + <br /> + <a href="#content-therealjamesjung" title="Content"> + 🖋 + </a> + </td> + <td align="center" valign="top" width="14.28%"> + <a href="https://github.com/ironAiken2"> + <img + src="https://avatars.githubusercontent.com/u/51399982?v=4?s=100" + width="100px;" + alt="SungChul Hong" + /> + <br /> + <sub> + <b>SungChul Hong</b> + </sub> + </a> + <br /> + <a href="#content-ironAiken2" title="Content"> + 🖋 + </a> + </td> + <td align="center" valign="top" width="14.28%"> + <a href="https://linktr.ee/miraexhoi"> + <img + src="https://avatars.githubusercontent.com/u/109408165?v=4?s=100" + width="100px;" + alt="최미래" + /> + <br /> + <sub> + <b>최미래</b> + </sub> + </a> + <br /> + <a href="#content-miraexhoi" title="Content"> + 🖋 + </a> + </td> + </tr> + <tr> + <td align="center" valign="top" width="14.28%"> + <a href="https://velog.io/@jihyeong00"> + <img + src="https://avatars.githubusercontent.com/u/115636461?v=4?s=100" + width="100px;" + alt="Zero" + /> + <br /> + <sub> + <b>Zero</b> + </sub> + </a> + <br /> + <a href="#content-Zero-1016" title="Content"> + 🖋 + </a> + </td> + <td align="center" valign="top" width="14.28%"> + <a href="https://github.com/yoouyeon"> + <img + src="https://avatars.githubusercontent.com/u/57761286?v=4?s=100" + width="100px;" + alt="Yoon Jeongyeon" + /> + <br /> + <sub> + <b>Yoon Jeongyeon</b> + </sub> + </a> + <br /> + <a href="#content-yoouyeon" title="Content"> + 🖋 + </a> + </td> + </tr> </tbody> </table>