diff --git a/src/content/docs/ko/reference/api-reference.mdx b/src/content/docs/ko/reference/api-reference.mdx index 30aeddd41a188..4379723e99070 100644 --- a/src/content/docs/ko/reference/api-reference.mdx +++ b/src/content/docs/ko/reference/api-reference.mdx @@ -332,9 +332,14 @@ const socialImageURL = new URL('/images/preview.png', Astro.url); ```astro "Astro.response" --- -if (condition) { +import { getPost } from "../api"; + +const post = await getPost(Astro.params.id); + +// 이 ID로 게시물을 찾을 수 없는 경우 +if (!post) { Astro.response.status = 404; - Astro.response.statusText = '찾을 수 없음'; + Astro.response.statusText = "찾을 수 없음"; } --- ``` @@ -384,14 +389,15 @@ Astro.response.headers.set('Set-Cookie', 'a=b; Path=/;'); ```ts "redirect" - import type { APIContext } from 'astro'; - + import type { APIContext } from "astro"; + import { isLoggedIn } from "../utils"; + export function GET({ redirect, request }: APIContext) { - const cookie = request.headers.get('cookie'); + const cookie = request.headers.get("cookie"); if (!isLoggedIn(cookie)) { - return redirect('/login', 302); + return redirect("/login", 302); } else { - // 사용자의 정보를 반환합니다. + // 사용자 정보를 반환합니다. } } ``` @@ -443,10 +449,10 @@ Astro.response.headers.set('Set-Cookie', 'a=b; Path=/;'); ```ts - import type { APIContext } from 'astro'; - - export function GET({ rewrite }: APIContext) { - return rewrite(new URL("../", Astro.url)); + import type { APIContext } from "astro"; + + export function GET({ rewrite, url }: APIContext) { + return rewrite(new URL("../", url)); } ``` @@ -468,14 +474,16 @@ Astro.response.headers.set('Set-Cookie', 'a=b; Path=/;'); ```ts - import type { APIContext } from 'astro'; - - export function GET({ rewrite }: APIContext) { - return rewrite(new Request(new URL("../", Astro.url), { - headers: { - "x-custom-header": JSON.stringify(Astro.locals.someValue) - } - })); + import type { APIContext } from "astro"; + + export function GET({ locals, rewrite, url }: APIContext) { + return rewrite( + new Request(new URL("../", url), { + headers: { + "x-custom-header": JSON.stringify(locals.someValue), + }, + }), + ); } ``` @@ -500,7 +508,8 @@ Astro.response.headers.set('Set-Cookie', 'a=b; Path=/;'); ```ts title="src/middleware.ts" - import { defineMiddleware } from 'astro:middleware'; + import { defineMiddleware } from "astro:middleware"; + import { recordPageVisit } from "./utils/analytics"; export const onRequest = defineMiddleware(async (context, next) => { // URL을 다시 작성하기 전에 원래 경로 이름을 기록합니다. @@ -555,6 +564,8 @@ Astro 컴포넌트와 API 엔드포인트는 렌더링할 때 `locals`에서 값 +Astro 미들웨어를 사용해 [타입 안전성](/ko/guides/middleware/#미들웨어-타입)을 유지하면서 [`locals`에 데이터를 저장하는 방법](/ko/guides/middleware/#contextlocals에-데이터-저장)에 대해 자세히 알아보세요. + ### `preferredLocale`

@@ -908,10 +919,10 @@ Astro 프로젝트에서 세션을 사용하는 방법에 대한 더 자세한 ```ts title="src/pages/api/cart.ts" "session.get('cart')" - import type { APIContext } from 'astro'; + import type { APIContext } from "astro"; export async function GET({ session }: APIContext) { - const cart = await session.get('cart'); + const cart = await session?.get("cart"); return Response.json({ cart }); } ``` @@ -940,14 +951,14 @@ Astro 프로젝트에서 세션을 사용하는 방법에 대한 더 자세한 ```ts title="src/pages/api/add-to-cart.ts" "session.set('cart', cart)" - import type { APIContext } from 'astro'; - + import type { APIContext } from "astro"; + export async function POST({ session, request }: APIContext) { - const cart = await session.get('cart'); + const cart = (await session?.get("cart")) ?? []; const newItem = await request.json(); cart.push(newItem); - // 업데이트된 장바구니를 세션에 저장합니다. - session.set('cart', cart); + // 업데이트된 장바구니를 세션에 저장 + session?.set("cart", cart); return Response.json({ cart }); } ``` @@ -975,13 +986,14 @@ Astro 프로젝트에서 세션을 사용하는 방법에 대한 더 자세한 ```ts title="src/pages/api/login.ts" "session.regenerate()" - import type { APIContext } from 'astro'; + import type { APIContext } from "astro"; + import { doLogin } from "../../lib/auth"; export async function POST({ session }: APIContext) { - // 사용자를 인증합니다... + // 사용자 인증... doLogin(); // 세션 고정 공격을 방지하기 위해 세션 ID를 갱신합니다. - session.regenerate(); + session?.regenerate(); return Response.json({ success: true }); } ``` @@ -1010,10 +1022,10 @@ Astro 프로젝트에서 세션을 사용하는 방법에 대한 더 자세한 ```ts title="src/pages/api/logout.ts" "session.destroy()" - import type { APIContext } from 'astro'; + import type { APIContext } from "astro"; export async function POST({ session }: APIContext) { - session.destroy(); + session?.destroy(); return Response.json({ success: true }); } ``` @@ -1035,27 +1047,26 @@ ID를 사용하여 세션을 로드합니다. 일반적인 사용 환경에서 ```astro title="src/pages/cart.astro" "Astro.session?.load('session-id')" --- // 헤더에서 쿠키 대신 세션을 로드합니다. - const sessionId = Astro.request.headers.get('x-session-id'); - await Astro.session?.load(sessionId); - const cart = await Astro.session?.get('cart'); + const sessionId = Astro.request.headers.get("x-session-id"); + await Astro.session?.load(sessionId ?? "fallback-session-id"); + const cart = await Astro.session?.get("cart"); --- +

장바구니

``` ```ts title="src/pages/api/load-session.ts" "session.load('session-id')" - import type { APIRoute } from 'astro'; + import type { APIRoute } from "astro"; export const GET: APIRoute = async ({ session, request }) => { - // 헤더에서 쿠키 대신 세션을 로드합니다. - const sessionId = request.headers.get('x-session-id'); - await session.load(sessionId); - const cart = await session.get('cart'); + // 쿠키 대신 헤더에서 세션을 로드합니다. + const sessionId = request.headers.get("x-session-id"); + await session?.load(sessionId ?? "fallback-session-id"); + const cart = await session?.get("cart"); return Response.json({ cart }); }; ``` @@ -1078,6 +1089,14 @@ Astro의 CSP 런타임 API는 문서가 로드할 수 있는 리소스를 제어 리소스가 여러 번 삽입되거나 여러 소스(예: [`csp` 구성](/ko/reference/configuration-reference/#securitycsp)에 정의된 것과 다음 CSP 런타임 API를 사용하여 추가된 것)에서 제공되는 경우, Astro는 모든 리소스를 병합하고 중복을 제거하여 `` 요소를 생성합니다. +:::caution[더 구체적인 지시어에 적용하기] +`kind` 옵션(`'element'` 또는 `'attribute'`)을 사용해 소스나 해시를 더 구체적인 지시어에 적용하면, 브라우저는 해당 범위에서는 일반 `script-src` 또는 `style-src` 대신 해당 구체적인 지시어를 사용하며, 일반 지시어로 대체하지 않습니다. + +Astro는 인라인 스크립트와 스타일을 위해 생성한 해시를 더 구체적인 지시어로 자동으로 이동하여 계속 정상적으로 동작하도록 합니다. 하지만 일반(`'default'`) 리소스는 이동하지 **않습니다**. 동일한 지시어 계열에서 일반 리소스와 더 구체적인 리소스 또는 해시를 함께 사용하면, 일반 리소스는 구체적인 범위에 적용되지 않습니다. Astro는 이러한 상황을 감지하면 경고를 출력합니다. + +이 문제를 해결하려면 모든 리소스와 해시를 구체적인 지시어로 이동하세요. +::: + #### `csp.insertDirective()` @@ -1114,7 +1133,7 @@ content="

-**타입:** `(resource: string) => void`
+**타입:** `(resource: string | { resource: string; kind: 'element' | 'attribute' | 'default' }) => void`

@@ -1138,11 +1157,34 @@ content=" > ``` +

+ +또한 `kind` 속성이 있는 객체를 전달하여 리소스를 더 구체적인 지시어에 적용할 수 있습니다. `style-src-elem`에는 `'element'`를, `style-src-attr`에는 `'attribute'`를, `style-src`에는 `'default'`를 사용하세요. (`'default'`는 일반 문자열을 전달하는 것과 동일합니다.) + +```astro title="src/pages/index.astro" +--- +Astro.csp?.insertStyleResource({ resource: "'unsafe-inline'", kind: "attribute" }); +--- +``` + +빌드가 완료되면 이 페이지의 `` 요소는 해당 리소스를 `style-src-attr` 지시어에 추가합니다. 이 지시어는 인라인 `style` 속성에만 적용됩니다. + +```html + +``` + #### `csp.insertStyleHash()`

-**타입:** `(hash: CspHash) => void`
+**타입:** `(hash: CspHash | { hash: CspHash; kind: 'element' | 'attribute' | 'default' }) => void`

@@ -1166,11 +1208,34 @@ content=" > ``` +

+ +또한 `kind` 속성이 있는 객체를 전달하여 해시를 더 구체적인 지시어에 적용할 수 있습니다. `style-src-elem`에는 `'element'`를, `style-src-attr`에는 `'attribute'`를, `style-src`에는 `'default'`를 사용하세요. (`'default'`는 일반 해시를 전달하는 것과 동일합니다.) + +```astro title="src/pages/index.astro" +--- +Astro.csp?.insertStyleHash({ hash: "sha512-styleHash", kind: "element" }); +--- +``` + +빌드가 완료되면 이 페이지의 `` 요소는 해당 해시를 `style-src-elem` 지시어에 추가합니다. `style-src-elem`은 `