콘텐츠로 이동

세션

추가된 버전: astro@5.7.0

세션은 요청 시 렌더링되는 페이지에 대한 요청 간에 데이터를 공유하는 데 사용됩니다.

cookies와는 달리 세션은 서버에 저장되므로 크기 제한이나 보안 문제에 대한 걱정 없이 더 많은 양의 데이터를 저장할 수 있습니다. 사용자 데이터, 장바구니, 양식 상태와 같은 것들을 저장하는 데 유용하며, 클라이언트 측 JavaScript 없이 작동합니다.

src/components/CartButton.astro
---
export const prerender = false; // 'server' 출력에는 필요하지 않습니다.
const cart = await Astro.session?.get('cart');
---
<a href="/checkout">🛒 {cart?.length ?? 0} items</a>

세션 데이터를 저장하기 위해 스토리지 드라이버가 필요합니다. Node, CloudflareNetlify 어댑터는 자동으로 기본 드라이버를 구성하지만, 현재 다른 어댑터를 사용하기 위해서는 드라이버를 수동으로 지정해야 합니다.

astro.config.mjs
import { defineConfig, sessionDrivers } from 'astro/config'
import vercel from '@astrojs/vercel'
export default defineConfig({
adapter: vercel()
session: {
driver: sessionDrivers.lruCache({
max: 800,
}),
}
})

스토리지 드라이버 설정 및 기타 구성 가능한 옵션에 대한 자세한 내용은 session 구성 옵션을 참조하세요.

기본적으로 세션 드라이버는 빌드 시점에 구성되며, 사용된 모든 환경 변수는 빌드 결과물에 포함됩니다. 즉, 런타임에는 구성을 재정의할 수 없습니다.

다른 구성이 필요한 경우 (예: 외부 서비스에 연결), 이를 별도의 파일에 정의하세요. 그런 다음 해당 파일을 드라이버의 진입점으로 사용하세요.

다음 예시는 Unstorage 호환성을 활용하여 고유한 진입점에서 Redis 드라이버를 구성하는 방법을 보여줍니다.

  1. unstorage 패키지를 설치합니다.

    Terminal window
    npm install unstorage
  2. 드라이버 구성을 위한 파일 (예: src/session-driver.ts)을 만들고 드라이버 인스턴스를 반환하는 기본 함수를 내보냅니다.

    src/session-driver.ts
    import type { SessionDriver } from "astro";
    import redisDriver from "unstorage/drivers/redis";
    import { REDIS_HOST, REDIS_PORT } from "astro:env";
    export default function (): SessionDriver {
    return redisDriver({
    host: REDIS_HOST,
    port: REDIS_PORT,
    });
    }
  3. Astro 설정에서 이 파일을 드라이버의 진입점으로 사용합니다.

    astro.config.mjs
    import { defineConfig, envField, sessionDrivers } from "astro/config";
    import vercel from "@astrojs/vercel";
    export default defineConfig({
    adapter: vercel(),
    env: {
    REDIS_HOST: envField.string({ context: "server", access: "public", default: "localhost" }),
    REDIS_PORT: envField.number({ context: "server", access: "public", default: 6379 }),
    },
    session: {
    driver: {
    entrypoint: new URL('./src/session-driver.ts', import.meta.url),
    }
    }
    });

session 객체를 사용하면 저장된 사용자 상태(예: 장바구니에 항목 추가) 및 세션 ID(예: 로그아웃 시 세션 ID 쿠키 삭제)와 상호 작용할 수 있습니다. 이 객체는 Astro 컴포넌트 및 페이지에서는 Astro.session으로, API 엔드포인트, 미들웨어 및 액션에서는 context.session 객체로 접근할 수 있습니다.

세션은 처음 사용될 때 자동으로 생성되며, session.regenerate()를 사용하여 언제든지 재생성하거나 session.destroy()를 사용하여 파괴할 수 있습니다.

대부분의 사용 사례에서는 session.get()session.set()만 사용하면 됩니다.

자세한 내용은 세션 API 참조를 확인하세요.

.astro 컴포넌트 및 페이지에서는 전역 Astro 객체를 통해 세션 객체에 접근할 수 있습니다. 예를 들어, 장바구니에 담긴 상품의 수를 표시하려면 다음과 같이 할 수 있습니다.

src/components/CartButton.astro
---
export const prerender = false; // 'server' 출력에는 필요하지 않습니다.
const cart = await Astro.session?.get('cart');
---
<a href="/checkout">🛒 {cart?.length ?? 0} items</a>

API 엔드포인트에서는 context 객체에서 세션 객체를 사용할 수 있습니다. 예를 들어, 장바구니에 항목을 추가하려면 다음과 같이 할 수 있습니다.

src/pages/api/addToCart.ts
import type { APIContext } from "astro";
export async function POST(context: APIContext) {
const cart = await context.session?.get('cart') || [];
const data = await context.request.json();
if(!data?.item) {
return new Response('Item is required', { status: 400 });
}
cart.push(data.item);
await context.session?.set('cart', cart);
return Response.json(cart);
}

액션에서는 context 객체에서 세션 객체를 사용할 수 있습니다. 예를 들어, 장바구니에 항목을 추가하려면 다음과 같이 할 수 있습니다.

src/actions/addToCart.ts
import { defineAction } from 'astro:actions';
import { z } from 'astro/zod';
export const server = {
addToCart: defineAction({
input: z.object({ productId: z.string() }),
handler: async (input, context) => {
const cart = await context.session?.get('cart');
cart.push(input.productId);
await context.session?.set('cart', cart);
return cart;
},
}),
};

미들웨어에서는 context 객체에서 세션 객체를 사용할 수 있습니다. 예를 들어, 세션에 마지막 방문 시간을 설정하려면 다음과 같이 할 수 있습니다.

src/middleware.ts
import { defineMiddleware } from 'astro:middleware';
export const onRequest = defineMiddleware(async (context, next) => {
context.session?.set('lastVisit', new Date());
return next();
});

기본적으로 세션 데이터는 타입이 지정되지 않으며, 어떤 키든 임의의 데이터를 저장할 수 있습니다. 값은 콘텐츠 컬렉션 및 액션에서 사용되는 것과 동일한 라이브러리인 devalue를 사용하여 직렬화 및 역직렬화됩니다. 이는 지원되는 타입이 동일하며, 문자열, 숫자, Date, Map, Set, URL, 배열 및 일반 객체를 포함한다는 의미입니다.

선택적으로 src/env.d.ts 파일을 만들고 App.SessionData 타입 선언을 추가하여 세션 데이터의 TypeScript 타입을 정의할 수 있습니다.

src/env.d.ts
declare namespace App {
interface SessionData {
user: {
id: string;
name: string;
};
cart: string[];
}
}

이렇게 하면 편집기에서 타입 검사 및 자동 완성 기능을 사용하여 세션 데이터에 접근할 수 있습니다.

src/components/CartButton.astro
---
const cart = await Astro.session?.get('cart');
// const cart: string[] | undefined
const something = await Astro.session?.get('something');
// const something: any
Astro.session?.set('user', { id: 1, name: 'Houston' });
// Error: Argument of type '{ id: number; name: string }' is not assignable to parameter of type '{ id: string; name: string; }'.
---
기여하기 커뮤니티 후원하기