From 16186274d605c5ed2ab5c666a546b0dd2e2a1fec Mon Sep 17 00:00:00 2001 From: Junseong Park <39112954+jsparkdev@users.noreply.github.com> Date: Sat, 20 Jun 2026 10:41:06 +0900 Subject: [PATCH 01/11] actions --- src/content/docs/ko/guides/actions.mdx | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/content/docs/ko/guides/actions.mdx b/src/content/docs/ko/guides/actions.mdx index a532244fd7f1f..60f9bb1a80e17 100644 --- a/src/content/docs/ko/guides/actions.mdx +++ b/src/content/docs/ko/guides/actions.mdx @@ -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(); }); ``` From a56ac679394ccba1cb8de318956a6a96c1405201 Mon Sep 17 00:00:00 2001 From: Junseong Park <39112954+jsparkdev@users.noreply.github.com> Date: Sat, 20 Jun 2026 10:41:57 +0900 Subject: [PATCH 02/11] Update on-demand-rendering.mdx --- src/content/docs/ko/guides/on-demand-rendering.mdx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/content/docs/ko/guides/on-demand-rendering.mdx b/src/content/docs/ko/guides/on-demand-rendering.mdx index 3133e109600da..f5adf0af8f6c5 100644 --- a/src/content/docs/ko/guides/on-demand-rendering.mdx +++ b/src/content/docs/ko/guides/on-demand-rendering.mdx @@ -73,7 +73,7 @@ export const prerender = false 서버 런타임용 어댑터 통합만 추가하세요! 다른 모든 페이지는 빌드 시점에 정적으로 생성됩니다! --> - + ``` 다음 예시는 엔드포인트가 호출될 때마다 임의의 숫자를 표시하기 위해 미리 렌더링하지 않도록 설정하는 것을 보여줍니다: @@ -106,7 +106,7 @@ export const prerender = true `output: 'server'`가 구성되어 있지만 이 페이지는 정적입니다! 사이트의 나머지 부분은 요청 시 렌더링됩니다! --> - + ``` 정적 페이지나 엔드포인트를 미리 렌더링하려면 페이지나 경로에 `export const prerender = true`를 추가하세요: From c5ed5ddc9b1a36e00bc204119981e05bc5965486 Mon Sep 17 00:00:00 2001 From: Junseong Park <39112954+jsparkdev@users.noreply.github.com> Date: Sat, 20 Jun 2026 10:42:39 +0900 Subject: [PATCH 03/11] Update server-islands.mdx --- src/content/docs/ko/guides/server-islands.mdx | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/src/content/docs/ko/guides/server-islands.mdx b/src/content/docs/ko/guides/server-islands.mdx index 8676af8be248d..a32b51f8ea0f5 100644 --- a/src/content/docs/ko/guides/server-islands.mdx +++ b/src/content/docs/ko/guides/server-islands.mdx @@ -98,9 +98,14 @@ import GenericAvatar from '../components/GenericAvatar.astro'; ```astro --- -const referer = Astro.request.headers.get('Referer'); +const referer = Astro.request.headers.get("Referer"); + +if (!referer) { + throw new Error("Referer header is missing"); +} + const url = new URL(referer); -const productId = url.searchParams.get('product'); +const productId = url.searchParams.get("product"); --- ``` From bf4d4a51625d13fb1e90917a52b57060f072679f Mon Sep 17 00:00:00 2001 From: Junseong Park <39112954+jsparkdev@users.noreply.github.com> Date: Sat, 20 Jun 2026 10:43:22 +0900 Subject: [PATCH 04/11] Update sessions.mdx --- src/content/docs/ko/guides/sessions.mdx | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/content/docs/ko/guides/sessions.mdx b/src/content/docs/ko/guides/sessions.mdx index fdc97f88f3c49..2d45e341afb06 100644 --- a/src/content/docs/ko/guides/sessions.mdx +++ b/src/content/docs/ko/guides/sessions.mdx @@ -140,9 +140,11 @@ const cart = await Astro.session?.get('cart'); API 엔드포인트에서는 `context` 객체에서 세션 객체를 사용할 수 있습니다. 예를 들어, 장바구니에 항목을 추가하려면 다음과 같이 할 수 있습니다. ```ts title="src/pages/api/addToCart.ts" "context.session" +import type { APIContext } from "astro"; + export async function POST(context: APIContext) { const cart = await context.session?.get('cart') || []; - const data = await context.request.json<{ item: string }>(); + const data = await context.request.json(); if(!data?.item) { return new Response('Item is required', { status: 400 }); } From f3258116c9b742c6488839874ad340569ee9328e Mon Sep 17 00:00:00 2001 From: Junseong Park <39112954+jsparkdev@users.noreply.github.com> Date: Sat, 20 Jun 2026 10:49:29 +0900 Subject: [PATCH 05/11] Update client-side-scripts.mdx --- .../docs/ko/guides/client-side-scripts.mdx | 30 ++++++++++--------- 1 file changed, 16 insertions(+), 14 deletions(-) diff --git a/src/content/docs/ko/guides/client-side-scripts.mdx b/src/content/docs/ko/guides/client-side-scripts.mdx index 5d2c859ffefc3..60193bba87c06 100644 --- a/src/content/docs/ko/guides/client-side-scripts.mdx +++ b/src/content/docs/ko/guides/client-side-scripts.mdx @@ -140,24 +140,26 @@ Astro는 [스크립트 처리 규칙](#스크립트-처리하기)에 따라 이 ``` @@ -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); From b5430a11863eccd99647221c9fcfbee9c3c57fee Mon Sep 17 00:00:00 2001 From: Junseong Park <39112954+jsparkdev@users.noreply.github.com> Date: Sat, 20 Jun 2026 10:50:56 +0900 Subject: [PATCH 06/11] Update fonts.mdx --- src/content/docs/ko/guides/fonts.mdx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/content/docs/ko/guides/fonts.mdx b/src/content/docs/ko/guides/fonts.mdx index d89d0453fa77a..3f7f09bca4070 100644 --- a/src/content/docs/ko/guides/fonts.mdx +++ b/src/content/docs/ko/guides/fonts.mdx @@ -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(); From 17e233d9a67e291b39d385f6f72492629fda773a Mon Sep 17 00:00:00 2001 From: Junseong Park <39112954+jsparkdev@users.noreply.github.com> Date: Sat, 20 Jun 2026 11:09:16 +0900 Subject: [PATCH 07/11] Update content-collections.mdx --- .../docs/ko/guides/content-collections.mdx | 151 ++++++++++-------- 1 file changed, 87 insertions(+), 64 deletions(-) diff --git a/src/content/docs/ko/guides/content-collections.mdx b/src/content/docs/ko/guides/content-collections.mdx index 75fc4b181da80..ff48cbb4a7832 100644 --- a/src/content/docs/ko/guides/content-collections.mdx +++ b/src/content/docs/ko/guides/content-collections.mdx @@ -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$/, ""), }), }); ``` @@ -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 }; @@ -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({ @@ -348,9 +351,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" }), @@ -359,7 +362,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"), @@ -394,27 +397,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 }; @@ -497,14 +500,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); --- +

{entry.data.title}

-

게시일: {entry.data.published.toDateString()}

+

Published on: {entry.data.pubDate.toDateString()}

``` @@ -577,29 +585,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'); +// 블로그 게시물이 존재하지 않으면 오류를 발생시킵니다. +if (!blogPost) { + throw new Error("Blog post not found"); +} -// 단일 참조 항목 검색: 블로그 게시물의 작성자 -// `{collection: "authors", id: "ben-holmes"}` 쿼리와 동일 +// 단일 참조 항목인 블로그 게시물의 작성자를 가져옵니다. +// `{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); ---

{blogPost.data.title}

-

작성자: {author.data.name}

+

Author: {author.data.name}

-

추천 게시물:

-{relatedPosts.map(post => ( - {post.data.title} -))} +

You might also like:

+{relatedPosts.map((post) => {post.data.title})} ``` ## 콘텐츠에서 경로 생성하기 @@ -810,16 +821,20 @@ Astro는 각 요청 시 라이브 데이터에 액세스하고 하나(또는 그 --- export const prerender = false; // 'server' 모드에서는 필요하지 않음 -import { getLiveCollection, getLiveEntry } from 'astro:content'; +import { getLiveCollection, getLiveEntry } from "astro:content"; -// 로더별 필터 사용 -const { entries: draftArticles } = await getLiveCollection('articles', { - status: 'draft', - author: 'john-doe', +if (!Astro.params.slug) { + return Astro.redirect('/404'); +} + +// 로더별 필터를 사용합니다. +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); --- ``` @@ -833,10 +848,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); @@ -864,19 +883,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"; + +if (!Astro.params.id) { + return Astro.redirect("/404"); +} -const { entry, error } = await getLiveEntry('products', Astro.params.id); +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"); + } } --- ``` From 605f5eff6a59f96781c28687aaa8a7ba432c40bb Mon Sep 17 00:00:00 2001 From: Junseong Park <39112954+jsparkdev@users.noreply.github.com> Date: Sat, 20 Jun 2026 11:10:05 +0900 Subject: [PATCH 08/11] Update images.mdx --- src/content/docs/ko/guides/images.mdx | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/src/content/docs/ko/guides/images.mdx b/src/content/docs/ko/guides/images.mdx index 64363f4f96444..6552f29ae274a 100644 --- a/src/content/docs/ko/guides/images.mdx +++ b/src/content/docs/ko/guides/images.mdx @@ -470,11 +470,12 @@ const links: Link[] = [ ```astro title="src/components/BlogPostImage.astro" --- -import { Image } from 'astro:assets'; +import { Image } from "astro:assets"; -const { src, ...attrs } = Astro.props; +const { alt, src, ...attrs } = Astro.props; --- - + +{alt}