Skip to content
Merged
Show file tree
Hide file tree
Changes from 10 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 6 additions & 6 deletions src/content/docs/ko/guides/actions.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -732,20 +732,20 @@ Astro는 권한 수준과 액션별 속도 제한을 존중하기 위해 액션
다음 예시는 유효한 세션 토큰이 없는 모든 액션 요청을 거부합니다. 검사가 실패하면 "Forbidden" 응답이 반환됩니다. 참고: 이 방법은 세션이 있을 때만 액션에 접근할 수 있도록 보장하지만, 안전한 인증을 *대체하지는* 않습니다.

```ts title="src/middleware.ts"
import { defineMiddleware } from 'astro:middleware';
import { getActionContext } from 'astro:actions';
import { defineMiddleware } from "astro:middleware";
import { getActionContext } from "astro:actions";

export const onRequest = defineMiddleware(async (context, next) => {
const { action } = getActionContext(context);
// 액션이 클라이언트 측 함수에서 호출되었는지 확인
if (action?.calledFrom === 'rpc') {
if (action?.calledFrom === "rpc") {
// 그렇다면, 사용자 세션 토큰을 확인
if (!context.cookies.has('user-session')) {
return new Response('Forbidden', { status: 403 });
if (!context.cookies.has("user-session")) {
return new Response("Forbidden", { status: 403 });
}
}

context.cookies.set('user-session', /* 세션 토큰 */);
context.cookies.set("user-session", "session-token-value");
return next();
});
```
Expand Down
30 changes: 16 additions & 14 deletions src/content/docs/ko/guides/client-side-scripts.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -140,24 +140,26 @@ Astro는 [스크립트 처리 규칙](#스크립트-처리하기)에 따라 이
</astro-heart>

<script>
// 새로운 유형의 HTML 요소에 대한 동작을 정의합니다.
// 새로운 HTML 요소 타입의 동작을 정의합니다.
class AstroHeart extends HTMLElement {
connectedCallback() {
let count = 0;

const heartButton = this.querySelector('button');
const countSpan = this.querySelector('span');

// 버튼을 클릭할 때마다 개수를 업데이트합니다.
heartButton.addEventListener('click', () => {
count++;
countSpan.textContent = count.toString();
});
}
const heartButton = this.querySelector("button");
const countSpan = this.querySelector("span");

// 버튼을 클릭할 때마다 카운트를 업데이트합니다.
if (heartButton && countSpan) {
heartButton.addEventListener("click", () => {
count++;
countSpan.textContent = count.toString();
});
}
}
}

// <astro-heart> 요소에 AstroHeart 클래스를 사용하도록 브라우저에 지시합니다.
customElements.define('astro-heart', AstroHeart);
// 브라우저에 <astro-heart> 요소에 대해 AstroHeart 클래스를 사용하도록 지정합니다.
customElements.define("astro-heart", AstroHeart);
</script>
```

Expand Down Expand Up @@ -193,10 +195,10 @@ const { message = 'Welcome, world!' } = Astro.props;
// data 속성에서 메시지를 읽습니다.
const message = this.dataset.message;
const button = this.querySelector('button');
button.addEventListener('click', () => {
button?.addEventListener('click', () => {
alert(message);
});
}
}
}

customElements.define('astro-greet', AstroGreet);
Expand Down
168 changes: 89 additions & 79 deletions src/content/docs/ko/guides/content-collections.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -209,12 +209,15 @@ slug: my-custom-id/supports/slashes
빌드 타임 컬렉션을 정의할 때 `glob()` 로더의 [`generateID()` 도우미 함수](/ko/reference/content-loader-reference/#generateid)에 옵션을 전달하여 `id` 생성 방식을 조정할 수도 있습니다. 예를 들어, 각 컬렉션 엔트리에 대해 대문자를 소문자로 변환하는 기본 동작을 되돌리고 싶을 수 있습니다:

```js title="src/content.config.ts"
import { glob } from "astro/loaders";
import { defineCollection } from "astro:content";

const authors = defineCollection({
/* ID에서 대문자를 유지하면서 authors 디렉터리의 모든 JSON 파일을 검색합니다. */
/* authors 디렉터리의 모든 JSON 파일을 가져오되, ID의 대문자는 유지합니다. */
loader: glob({
pattern: '**/*.json',
pattern: "**/*.json",
base: "./src/data/authors",
generateId: ({ entry }) => entry.replace(/\.json$/, ''),
generateId: ({ entry }) => entry.replace(/\.json$/, ""),
}),
});
```
Expand All @@ -224,11 +227,11 @@ const authors = defineCollection({
[`file()` 로더](/ko/reference/content-loader-reference/#file-로더)는 컬렉션에 정의된 단일 로컬 파일에서 여러 엔트리를 가져옵니다. `file()` 로더는 JSON 및 YAML 파일에서 객체의 단일 배열을 자동으로 감지하고 구문 분석하며(파일 확장자 기반), TOML 파일에서는 각 최상위 테이블을 독립적인 엔트리로 처리합니다.

```ts title="src/content.config.ts" {5}
import { defineCollection } from 'astro:content';
import { file } from 'astro/loaders';
import { defineCollection } from "astro:content";
import { file } from "astro/loaders";

const dogs = defineCollection({
loader: file("src/data/dogs.json"),
loader: file("src/data/dogs.json"),
});

export const collections = { dogs };
Expand Down Expand Up @@ -301,8 +304,8 @@ Content Loader API를 사용하여 CMS, 데이터베이스 또는 API 엔드포
그런 다음 컬렉션 구성에서 커스텀 로더를 가져오고 정의하여 필요한 값을 전달할 수 있습니다:

```ts title="src/content.config.ts"
import { defineCollection } from 'astro:content';
import { myLoader } from './loader.ts';
import { defineCollection } from "astro:content";
import { myLoader } from "./loader.ts";

const blog = defineCollection({
loader: myLoader({
Expand All @@ -312,28 +315,15 @@ const blog = defineCollection({
});
```

반환된 항목들은 컬렉션에 저장되며 `getCollection()` 및 `getEntry()` 함수를 사용하여 조회할 수 있습니다.

##### 로더 객체

로딩 프로세스를 더 세밀하게 제어하려면 Content Loader API를 사용하여 로더 객체를 생성할 수 있습니다. 예를 들어, `load` 메서드에 직접 접근할 수 있어 항목을 점진적으로 업데이트하거나 필요할 때만 스토어를 비우는 로더를 만들 수 있습니다.

Astro 통합이나 Vite 플러그인을 만드는 것처럼, [로더를 NPM 패키지로 배포](/ko/guides/integrations/)하여 다른 사람들이 자신의 프로젝트에서 사용할 수 있게 할 수 있습니다.

<ReadMore>전체 [Content Loader API](/ko/reference/content-loader-reference/)와 자체 로더를 구축하는 방법에 대한 예시를 참조하세요.</ReadMore>

### 컬렉션 스키마 정의

스키마는 Zod 유효성 검사를 통해 컬렉션의 프런트매터나 항목 데이터의 일관성을 강제합니다. 스키마는 데이터를 참조하거나 쿼리할 때 데이터가 예측 가능한 형태로 존재함을 **보장합니다**. 만약 어떤 파일이 컬렉션 스키마를 위반하면, Astro는 도움이 되는 오류 메시지를 표시합니다.
:::tip
[Astro 통합 디렉터리](https://astro.build/integrations/?search=&categories%5B%5D=loaders)에서 커뮤니티 제작 및 타사 로더를 찾아보세요.
:::

커스텀 로더를 사용하여 데이터를 가져오면 원격 데이터에서 자동으로 컬렉션이 생성됩니다. 이를 통해 로컬 컬렉션의 모든 이점을 누릴 수 있습니다. 여기에는 [데이터를 쿼리하고 표시](#빌드-타임-컬렉션-쿼리하기)하기 위한 `getCollection()` 및 `render()`와 같은 컬렉션 전용 API 도우미뿐만 아니라 스키마 유효성 검사도 포함됩니다.

Astro 통합 또는 Vite 플러그인을 만드는 것과 유사하게, 다른 사람들이 자신의 프로젝트에서 사용할 수 있도록 [로더를 npm 패키지로 배포](/ko/guides/integrations/)할 수 있습니다.
Astro 통합이나 Vite 플러그인을 만드는 것처럼, [로더를 NPM 패키지로 배포](/ko/guides/integrations/)하여 다른 사람들이 자신의 프로젝트에서 사용할 수 있게 할 수 있습니다.

<ReadMore>고유한 로더를 빌드하는 방법에 대한 예제는 전체 [Content Loader API](/ko/reference/content-loader-reference/) 참조하세요.</ReadMore>
<ReadMore>전체 [Content Loader API](/ko/reference/content-loader-reference/)와 자체 로더를 구축하는 방법에 대한 예시를 참조하세요.</ReadMore>

## 컬렉션 스키마 정의하기

Expand All @@ -348,9 +338,9 @@ Astro가 새 스키마 또는 업데이트된 스키마를 인식하려면 개
`schema`를 제공하는 것은 선택 사항이지만 적극 권장됩니다! 스키마를 사용하기로 선택한 경우 컬렉션 엔트리의 모든 프런트매터 또는 데이터 속성은 [Zod 데이터 타입](/ko/reference/modules/astro-zod/#일반적인-데이터-타입-유효성-검사기)을 사용하여 정의해야 합니다.

```ts title="src/content.config.ts" {7-12,16-20}
import { defineCollection } from 'astro:content';
import { z } from 'astro/zod';
import { glob, file } from 'astro/loaders';
import { defineCollection } from "astro:content";
import { z } from "astro/zod";
import { glob, file } from "astro/loaders";

const blog = defineCollection({
loader: glob({ pattern: "**/*.md", base: "./src/data/blog" }),
Expand All @@ -359,7 +349,7 @@ const blog = defineCollection({
description: z.string(),
pubDate: z.coerce.date(),
updatedDate: z.coerce.date().optional(),
})
}),
});
const dogs = defineCollection({
loader: file("src/data/dogs.json"),
Expand Down Expand Up @@ -394,27 +384,27 @@ Astro에서 Zod를 사용하려면 `"astro/zod"`에서 `z` 유틸리티를 가
일반적인 예는 JSON으로 저장된 재사용 가능한 작성자 프로필이나 동일한 컬렉션에 저장된 관련 게시물 URL을 참조하는 블로그 게시물입니다:

```ts title="src/content.config.ts"
import { defineCollection, reference } from 'astro:content';
import { glob } from 'astro/loaders';
import { z } from 'astro/zod';
import { defineCollection, reference } from "astro:content";
import { glob } from "astro/loaders";
import { z } from "astro/zod";

const blog = defineCollection({
loader: glob({ base: './src/content/blog', pattern: '**/*.{md,mdx}' }),
schema: z.object({
title: z.string(),
// `authors` 컬렉션에서 `id`로 단일 작성자 참조
author: reference('authors'),
// `blog` 컬렉션에서 `id`로 관련 게시물 배열 참조
relatedPosts: z.array(reference('blog')),
})
loader: glob({ base: "./src/content/blog", pattern: "**/*.{md,mdx}" }),
schema: z.object({
title: z.string(),
// `id`를 사용해 `authors` 컬렉션의 작성자 하나를 참조합니다.
author: reference("authors"),
// `id`를 사용해 `blog` 컬렉션의 관련 게시물 목록을 참조합니다.
relatedPosts: z.array(reference("blog")),
}),
});

const authors = defineCollection({
loader: glob({ pattern: '**/*.json', base: "./src/data/authors" }),
schema: z.object({
name: z.string(),
portfolio: z.url(),
})
loader: glob({ pattern: "**/*.json", base: "./src/data/authors" }),
schema: z.object({
name: z.string(),
portfolio: z.url(),
}),
});

export const collections = { blog, authors };
Expand Down Expand Up @@ -497,14 +487,19 @@ const posts = await getCollection('blog');

```astro title="src/pages/blog/post-1.astro" {2,6,10}
---
import { getEntry, render } from 'astro:content';
import { getEntry, render } from "astro:content";

const entry = await getEntry('blog', 'post-1');
const entry = await getEntry("blog", "post-1");

if (!entry) {
throw new Error("Entry not found");
}

const { Content } = await render(entry);
---

<h1>{entry.data.title}</h1>
<p>게시일: {entry.data.published.toDateString()}</p>
<p>Published on: {entry.data.pubDate.toDateString()}</p>
<Content />
```

Expand Down Expand Up @@ -577,29 +572,32 @@ const englishDocsEntries = await getCollection('docs', ({ id }) => {

```astro title="src/pages/blog/adventures-in-space.astro"
---
import { getEntry, getEntries } from 'astro:content';
import { getEntry, getEntries } from "astro:content";

// 먼저 블로그 게시물 쿼리
const blogPost = await getEntry('blog', 'Adventures in Space');
// 먼저 블로그 게시물을 가져옵니다.
const blogPost = await getEntry("blog", "Adventures in Space");

// 단일 참조 항목 검색: 블로그 게시물의 작성자
// `{collection: "authors", id: "ben-holmes"}` 쿼리와 동일
// 블로그 게시물이 존재하지 않으면 오류를 발생시킵니다.
if (!blogPost) {
throw new Error("Blog post not found");
}

// 단일 참조 항목인 블로그 게시물의 작성자를 가져옵니다.
// `{collection: "authors", id: "ben-holmes"}`를 조회하는 것과 동일합니다.
const author = await getEntry(blogPost.data.author);

// 참조된 항목의 배열 검색: 모든 관련 게시물
// `[{collection: "blog", id: "visiting-mars"}, {collection: "blog", id: "leaving-earth-for-the-first-time"}]` 쿼리와 동일
// 참조된 항목 배열인 모든 관련 게시물을 가져옵니다.
// `[{collection: "blog", id: "visiting-mars"}, {collection: "blog", id: "leaving-earth-for-the-first-time"}]`를 조회하는 것과 동일합니다.
const relatedPosts = await getEntries(blogPost.data.relatedPosts);
---

<h1>{blogPost.data.title}</h1>
<p>작성자: {author.data.name}</p>
<p>Author: {author.data.name}</p>

<!-- ... -->

<h2>추천 게시물:</h2>
{relatedPosts.map(post => (
<a href={post.id}>{post.data.title}</a>
))}
<h2>You might also like:</h2>
{relatedPosts.map((post) => <a href={post.id}>{post.data.title}</a>)}
```

## 콘텐츠에서 경로 생성하기
Expand Down Expand Up @@ -810,16 +808,20 @@ Astro는 각 요청 시 라이브 데이터에 액세스하고 하나(또는 그
---
export const prerender = false; // 'server' 모드에서는 필요하지 않음

import { getLiveCollection, getLiveEntry } from 'astro:content';
import { getLiveCollection, getLiveEntry } from "astro:content";

if (!Astro.params.slug) {
return Astro.redirect('/404');
}

// 로더별 필터 사용
const { entries: draftArticles } = await getLiveCollection('articles', {
status: 'draft',
author: 'john-doe',
// 로더별 필터를 사용합니다.
const { entries: draftArticles } = await getLiveCollection("articles", {
status: "draft",
author: "john-doe",
});

// ID로 특정 제품 가져오기
const { entry: product } = await getLiveEntry('products', Astro.params.slug);
// ID를 사용해 특정 제품을 가져옵니다.
const { entry: product } = await getLiveEntry("products", Astro.params.slug);
---
```

Expand All @@ -833,10 +835,14 @@ const { entry: product } = await getLiveEntry('products', Astro.params.slug);
---
export const prerender = false; // 'server' 모드에서는 필요하지 않음

import { getLiveEntry, render } from 'astro:content';
const { entry, error } = await getLiveEntry('articles', Astro.params.id);
if (error) {
return Astro.rewrite('/404');
if (!Astro.params.id) {
return Astro.redirect("/404");
}

import { getLiveEntry, render } from "astro:content";
const { entry, error } = await getLiveEntry("articles", Astro.params.id);
if (!entry || error) {
return Astro.rewrite("/404");
}

const { Content } = await render(entry);
Expand Down Expand Up @@ -864,19 +870,23 @@ const { Content } = await render(entry);
---
export const prerender = false; // 'server' 모드에서는 필요하지 않음

import { LiveEntryNotFoundError } from 'astro/content/runtime';
import { getLiveEntry } from 'astro:content';
import { LiveEntryNotFoundError } from "astro/content/runtime";
import { getLiveEntry } from "astro:content";

const { entry, error } = await getLiveEntry('products', Astro.params.id);
if (!Astro.params.id) {
return Astro.redirect("/404");
}

const { entry, error } = await getLiveEntry("products", Astro.params.id);

if (error) {
if (error instanceof LiveEntryNotFoundError) {
console.error(`제품을 찾을 수 없음: ${error.message}`);
Astro.response.status = 404;
} else {
console.error(`제품 로드 오류: ${error.message}`);
return Astro.redirect('/500');
}
if (error instanceof LiveEntryNotFoundError) {
console.error(`Product not found: ${error.message}`);
Astro.response.status = 404;
} else {
console.error(`Error loading product: ${error.message}`);
return Astro.redirect("/500");
}
}
---
```
Expand Down
2 changes: 1 addition & 1 deletion src/content/docs/ko/guides/fonts.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -317,7 +317,7 @@ export const GET: APIRoute = async (context) => {
},
);

const pngBuffer = await sharp(Buffer.from(svg))
const pngBuffer = await sharp(Buffer.from(svg)) // 타입 안전성을 위해 `@types/node`를 의존성으로 추가해야 합니다.
.resize(600, 400)
.png()
.toBuffer();
Expand Down
Loading
Loading