콘텐츠로 이동

세션

추가된 버전: 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 패키지를 설치합니다.

    터미널 창
    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
export async function POST(context: APIContext) {
const cart = await context.session?.get('cart') || [];
const data = await context.request.json<{ item: string }>();
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; }'.
---
기여하기 커뮤니티 후원하기