diff --git a/src/content/docs/ko/reference/container-reference.mdx b/src/content/docs/ko/reference/container-reference.mdx new file mode 100644 index 0000000000000..36ee8c310218a --- /dev/null +++ b/src/content/docs/ko/reference/container-reference.mdx @@ -0,0 +1,401 @@ +--- +title: Astro 컨테이너 API (실험적) +sidebar: + label: 컨테이너 API (실험적) +i18nReady: true +--- +import Since from '~/components/Since.astro' + +

+ +컨테이너 API를 사용하면 Astro 컴포넌트를 독립적으로 렌더링할 수 있습니다. + +이 실험적인 서버 측 API는 다양한 잠재적 미래 활용 가능성을 열어주지만, 현재는 `vitest`와 같은 `vite` 환경에서 [`.astro` 컴포넌트 출력을 테스트](/ko/guides/testing/#vitest-및-컨테이너-api)할 수 있도록 범위가 제한되어 있습니다. + +또한 요청 시 렌더링되는 페이지나 `vite` 외부(예: PHP 또는 Elixir 애플리케이션 내부)의 기타 "셸" 환경에서 컨테이너를 생성하기 위한 [렌더링 스크립트를 수동으로 직접 로드](#렌더러-직접-추가하기)할 수 있습니다. + +이 API를 사용하면 [새 컨테이너를 생성](#create)하고, [문자열](#rendertostring) 또는 [`Response`](#rendertoresponse)를 반환하는 Astro 컴포넌트를 렌더링할 수 있습니다. + +이 API는 실험적이며, [마이너 또는 패치 릴리스](/ko/upgrade-astro/#의미론적-버전-관리)에서도 호환성을 깨뜨리는 변경 사항이 발생할 수 있습니다. 변경 사항은 [Astro 변경 로그](https://github.com/withastro/astro/blob/main/packages/astro/CHANGELOG.md)를 참조하세요. 이 페이지는 항상 최신 버전의 Astro에 대한 정보로 업데이트됩니다. + +## `create()` + +컨테이너의 새 인스턴스를 생성합니다. + +```js +import { experimental_AstroContainer } from "astro/container"; + +const container = await experimental_AstroContainer.create(); +``` + +다음 옵션을 가진 객체를 받습니다. + +```ts +export type AstroContainerOptions = { + streaming?: boolean; + renderers?: AddServerRenderer[]; +}; + +export type AddServerRenderer = + | { + renderer: NamedSSRLoadedRendererValue; + name: never; + } + | { + renderer: SSRLoadedRendererValue; + name: string; + }; +``` + +### `streaming` 옵션 + +**타입:** `boolean` + +[HTML 스트리밍](/ko/guides/on-demand-rendering/#html-스트리밍)을 사용한 컴포넌트 렌더링을 활성화합니다. + +### `renderers` 옵션 + +**타입:** `AddServerRenderer[]` + +컴포넌트에 필요한 로드된 클라이언트 렌더러 목록입니다. `.astro` 컴포넌트가 공식 Astro 통합(예: React, Vue 등)을 사용하여 [UI 프레임워크 컴포넌트](/ko/guides/framework-components/) 또는 MDX를 렌더링하는 경우에 이를 사용하세요. + +정적 애플리케이션이나 런타임 시 컨테이너가 호출되지 않는 경우(예: `vitest`를 사용하여 테스트하는 경우)에는 컨테이너 API를 통해 렌더러를 자동으로 추가할 수 있습니다. + +[요청 시 렌더링되는 애플리케이션](/ko/guides/on-demand-rendering/)이나 런타임 시 또는 다른 "셸"(예: PHP, Ruby, Java 등)에서 컨테이너가 호출되는 경우, 렌더러를 수동으로 직접 가져와야 합니다. + +#### 컨테이너 API를 통해 렌더러 추가하기 + +각각의 공식 Astro 통합에 대해 `getContainerRenderer()` 도우미 함수를 가져와 사용하면 해당 클라이언트 및 서버 렌더링 스크립트를 노출할 수 있습니다. 이 함수는 `@astrojs/react`, `@astrojs/preact`, `@astrojs/solid-js`, `@astrojs/svelte`, `@astrojs/vue`, `@astrojs/mdx`에서 사용할 수 있습니다. + +`@astrojs` npm 조직 외부의 렌더러 패키지의 경우, 해당 문서에서 `getContainerRenderer()` 또는 유사한 함수가 제공되는지 확인하세요. + +`vite` (`vitest`, Astro 통합 등)를 사용할 때, 렌더러는 가상 모듈 `astro:container`의 `loadRenderers()` 함수를 통해 로드됩니다. + +:::caution +`vite` 외부 또는 요청을 통해 사용하기 위해서는 [렌더러를 수동으로 직접 로드](#렌더러-직접-추가하기)해야 합니다. +::: + +다음은 React 컴포넌트와 Svelte 컴포넌트를 렌더링하는 Astro 컴포넌트를 렌더링하는 데 필요한 객체를 제공하는 예시입니다. + +```js +import { getContainerRenderer as reactContainerRenderer } from "@astrojs/react"; +import { getContainerRenderer as svelteContainerRenderer } from "@astrojs/svelte"; +import { loadRenderers } from "astro:container"; + +const renderers = await loadRenderers([reactContainerRenderer(), svelteContainerRenderer()]); +const container = await experimental_AstroContainer.create({ + renderers +}) +const result = await container.renderToString(ReactWrapper); +``` + +#### 렌더러 직접 추가하기 + +컨테이너가 런타임 시 또는 다른 "셸"에서 호출될 때는 `astro:container` 가상 모듈의 도우미 함수를 사용할 수 없습니다. 필요한 서버 및 클라이언트 렌더러를 수동으로 직접 가져와 `addServerRenderer` 및 `addClientRenderer`를 사용하여 컨테이너에 저장해야 합니다. + +프로젝트 빌드에는 서버 렌더러가 필요하며, 사용된 모든 프레임워크별로 컨테이너에 저장되어야 합니다. [`client:*` 지시어](/ko/reference/directives-reference/#클라이언트-지시어)를 사용하여 클라이언트 측 컴포넌트를 하이드레이션하려면 클라이언트 렌더러가 추가로 필요합니다. + +프레임워크당 하나의 가져오기 구문이 필요합니다. 렌더러를 가져오면 서버 렌더러와 클라이언트 렌더러 모두 컨테이너에서 사용할 수 있게 됩니다. 그러나 **반드시 클라이언트 렌더러보다 서버 렌더러를 컨테이너에 먼저 추가해야 합니다.** 이렇게 하면 전체 컨테이너가 먼저 렌더링된 후 상호작용 가능한 컴포넌트를 하이드레이션할 수 있습니다. + +다음은 정적 Vue 컴포넌트와 `.mdx` 페이지를 표시하기 위해 필요한 서버 렌더러를 수동으로 직접 가져오는 예시입니다. 또한 상호작용 가능한 React 컴포넌트를 위해 서버 및 클라이언트 렌더러를 모두 추가합니다. + +```js +import reactRenderer from "@astrojs/react/server.js"; +import vueRenderer from "@astrojs/vue/server.js"; +import mdxRenderer from "@astrojs/mdx/server.js"; + +const container = await experimental_AstroContainer.create(); +container.addServerRenderer({renderer: vueRenderer}); +container.addServerRenderer({renderer: mdxRenderer}); + +container.addServerRenderer({ renderer: reactRenderer }); +container.addClientRenderer({ name: "@astrojs/react", entrypoint: "@astrojs/react/client.js" }); +``` + +## `renderToString()` + +이 함수는 컨테이너에서 특정 컴포넌트를 렌더링합니다. Astro 컴포넌트를 인수로 받아들이며, Astro 컴포넌트가 렌더링한 HTML/콘텐츠를 나타내는 문자열을 반환합니다. + +```js +import { experimental_AstroContainer } from "astro/container"; +import Card from "../src/components/Card.astro"; + +const container = await experimental_AstroContainer.create(); +const result = await container.renderToString(Card); +``` + +이 함수는 내부적으로 [`renderToResponse()`](#rendertoresponse)와 `Response.text()`를 호출합니다. + +또한 두 번째 인자로 [여러 옵션](#렌더링-옵션)을 포함할 수 있는 객체를 받습니다. + +## `renderToResponse()` + +컴포넌트를 렌더링하고, `Response` 객체를 반환합니다. + +```js +import { experimental_AstroContainer } from "astro/container"; +import Card from "../src/components/Card.astro"; + +const container = await experimental_AstroContainer.create(); +const result = await container.renderToResponse(Card); +``` + +또한 두 번째 인자로 [여러 옵션](#렌더링-옵션)을 포함할 수 있는 객체를 받습니다. + +## 렌더링 옵션 + +[`renderToResponse()`](#rendertoresponse)와 [`renderToString()`](#rendertostring) 모두 두 번째 인자로 객체를 받습니다. + +```ts +export type ContainerRenderOptions = { + slots?: Record; + props?: Record; + request?: Request; + params?: Record; + locals?: App.Locals; + routeType?: "page" | "endpoint"; +}; +``` + +이러한 선택적 값들은 Astro 컴포넌트를 올바르게 렌더링하는 데 필요한 추가 정보를 제공하기 위해 렌더링 함수에 전달될 수 있습니다. + +### `slots` + +**타입:** `Record` + +[``](/ko/basics/astro-components/#슬롯)로 렌더링할 콘텐츠를 전달하는 옵션입니다. + +Astro 컴포넌트가 하나의 기본 슬롯을 렌더링하는 경우, `default`를 키로 사용하는 객체를 전달하세요. + +```js name="Card.test.js" +import Card from "../src/components/Card.astro"; + +const result = await container.renderToString(Card, { + slots: { default: "어떤 값" } +}); +``` + +컴포넌트가 명명된 슬롯을 렌더링하는 경우, 슬롯 이름을 객체 키로 사용하세요. + +```astro name="Card.astro" +--- +--- +
+ + +
+``` + +```js name="Card.test.js" +import Card from "../src/components/Card.astro"; + +const result = await container.renderToString(Card, { + slots: { + header: "Header content", + footer: "Footer" + } +}); +``` + +컴포넌트를 계단식으로 렌더링할 수도 있습니다. + +```astro name="Card.astro" +--- +--- +
+ + +
+``` + +```js name="Card.test.js" +import Card from "../src/components/Card.astro"; +import CardHeader from "../src/components/CardHeader.astro"; +import CardFooter from "../src/components/CardFooter.astro"; + +const result = await container.renderToString(Card, { + slots: { + header: await container.renderToString(CardHeader), + footer: await container.renderToString(CardFooter) + } +}); +``` + +### `props` 옵션 + +**타입:** `Record` + +Astro 컴포넌트에 [속성](/ko/basics/astro-components/#컴포넌트-props)을 전달하는 옵션입니다. + +```js name="Card.test.js" +import Card from "../src/components/Card.astro"; + +const result = await container.renderToString(Card, { + props: { name: "환영합니다!" } +}); +``` + +```astro name="Card.astro" +--- +// TypeScript 지원을 위해 사용합니다. +interface Props { + name: string; +}; + +const { name } = Astro.props; +--- +
+ {name} +
+``` + +### `request` 옵션 + +**타입:** `Request` + +컴포넌트가 렌더링할 경로/URL에 대한 정보를 포함하는 `Request`를 전달하는 옵션입니다. + +컴포넌트에서 `Astro.url` 또는 `Astro.request`와 같은 정보를 읽어야 할 때 이 옵션을 사용합니다. + +가능한 헤더나 쿠키도 주입할 수 있습니다. + +```js file="Card.test.js" +import Card from "../src/components/Card.astro"; + +const result = await container.renderToString(Card, { + request: new Request("https://example.com/blog", { + headers: { + "x-some-secret-header": "test-value" + } + }) +}); +``` + +### `params` 옵션 + +**타입:** `Record` + +[동적 라우트를 생성하는](/ko/guides/routing/#동적-라우트) Astro 컴포넌트에 경로 매개변수 정보를 전달하기 위한 객체입니다. + +컴포넌트가 단일 라우트를 동적으로 생성하기 위해 `Astro.params` 값이 필요한 경우 이 옵션을 사용합니다. + +```astro name="Card.astro" +--- +const { locale, slug } = Astro.params; +--- +
+``` + +```js file="LocaleSlug.test.js" +import LocaleSlug from "../src/components/[locale]/[slug].astro"; + +const result = await container.renderToString(LocaleSlug, { + params: { + locale: "en", + slug: "getting-started" + } +}); +``` + +### `locals` 옵션 + +**타입:** `App.Locals` + +컴포넌트를 렌더링하기 위해 [`Astro.locals`](/ko/reference/api-reference/#locals)에 정보를 전달하는 옵션입니다. + +로그인 상태와 같이 요청의 라이프사이클 동안 저장된 정보가 컴포넌트 렌더링에 필요한 경우 이 옵션을 사용합니다. + +```astro name="Card.astro" +--- +const { checkAuth } = Astro.locals; +const isAuthenticated = checkAuth(); +--- +{isAuthenticated ? 로그인 되었습니다. : 로그인하세요. } +``` + +```js file="Card.test.js" +import Card from "../src/components/Card.astro"; + +test("User is in", async () => { + const result = await container.renderToString(Card, { + locals: { + checkAuth() { return true; } + } + }); + + // 결과에 "로그인 되었습니다."라는 문자열이 포함되어야 합니다. +}); + + +test("User is out", async () => { + const result = await container.renderToString(Card, { + locals: { + checkAuth() { return false; } + } + }); + + // 결과에 "로그인하세요."라는 문자열이 포함되어야 합니다. +}); +``` + +### `routeType` 옵션 + +**타입:** `"page" | "endpoint"` + +[엔드포인트](/ko/guides/endpoints/)를 렌더링하고 있다는 것을 명시하기 위해 `renderToResponse()`와 함께 사용할 수 있는 옵션입니다. + +```js +container.renderToString(Endpoint, { routeType: "endpoint" }); +``` + +```js file="endpoint.test.js" +import * as Endpoint from "../src/pages/api/endpoint.js"; + +const response = await container.renderToResponse(Endpoint, { + routeType: "endpoint" +}); +const json = await response.json(); +``` + +`POST`, `PATCH` 등 메서드에 대한 엔드포인트 테스트를 수행하려면 `request` 옵션을 사용하여 올바른 함수를 호출해야 합니다. + +```js file="endpoint.js" +export function GET() {} + +// 이 코드를 테스트해야 합니다. +export function POST() {} +``` + +```js file="endpoint.test.js" ins={5-7} +import * as Endpoint from "../src/pages/api/endpoint.js"; + +const response = await container.renderToResponse(Endpoint, { + routeType: "endpoint", + request: new Request("https://example.com", { + method: "POST" // 테스트를 위해 POST 메서드를 지정합니다. + }) +}); +const json = await response.json(); +``` + +### `partial` 옵션 + +

+ +**타입:** `boolean`
+**기본값:** `true`
+ +

+ +컨테이너 API가 컴포넌트를 [페이지 부분](/ko/basics/astro-pages/#페이지-부분-page-partials)처럼 렌더링할지 여부입니다. 이는 일반적으로 `components.boolean`을 렌더링할 때 원하는 동작이므로 전체 페이지 셸 없이도 컴포넌트를 렌더링할 수 있습니다. + +``을 포함한 전체 Astro 페이지로 컴포넌트를 렌더링하려면 `partial`을 `false`로 설정하여 이 동작을 비활성화할 수 있습니다. + +```js name="Card.test.js" ins={4} +import Blog from "../src/pages/Blog.astro"; + +const result = await container.renderToString(Card, { + partial: false +}); +console.log(result) // HTML의 시작 부분에 ``를 포함합니다. +```