Computer >> 컴퓨터 >  >> 프로그램 작성 >> Redis

Upstash Redis를 Remix용 세션 저장소로 사용

전체 스택 웹 프레임워크인 Remix는 일반적인 웹 서버 사용 사례를 처리하기 위한 API를 제공합니다. 이 게시물은 세션과 Upstash를 사용하여 세션을 저장하는 이유와 방법에 초점을 맞춥니다.

세션이란 무엇입니까?

<블록 인용>

Remix 문서에는 세션에 대한 아주 좋은 소개가 있습니다. https://remix.run/docs/en/v1/api/remix#sessions

간단히 말해서 세션은 서버와 클라이언트가 사용자 데이터/상태를 공유할 수 있도록 하는 메커니즘입니다. 세션 사용의 예는 사용자 인증 상태 추적, 장바구니 상태, 플래시 메시지 등입니다.

Upstash Redis를 사용하는 이유

세션 데이터는 서버에 저장됩니다. 서버리스 인프라 또는 일부 PASS 인프라(예:Heroku)에 배포할 때 모든 요청(서버리스) 또는 배포(PASS)에서 변경될 수 있으므로 서버의 파일 시스템에 데이터를 유지할 수 없습니다. 데이터를 유지하려면 사용자 데이터를 외부 데이터베이스에 저장해야 합니다. Upstash Redis DB는 다음과 같은 이유로 세션 데이터를 저장하는 훌륭한 솔루션입니다.

  • Redis 세션과 유사하며 본질적으로 key:value가 있습니다. 키가 세션의 ID이고 값이 직렬화된 데이터인 데이터 구조입니다.
  • Redis에는 만료된 세션을 정리할 필요성을 줄이는 만료 메커니즘이 내장되어 있습니다.
  • 세션은 민감한 사용자 데이터를 보유할 수 있으며 Upstash Redis는 저장된 모든 데이터를 암호화합니다.
  • Upstash는 간단한 HTTP REST API를 사용하고 있습니다. HTTP는 서버리스 인프라에서 통신하는 가장 쉬운 방법입니다.

Redis에서 Upstash를 세션 공급자로 사용하는 방법

<블록 인용>

이 게시물은 내가 작성한 Redis Session Storage Using Upstash 예제를 기반으로 합니다. Remix 리포지토리를 자유롭게 복제하고 사용해 보세요.

1단계 - Upstash API 키 가져오기

  • https://upstash.com/으로 이동하여 새 계정 만들기
  • 새 Redis DB 생성
  • UPSTASH_REDIS_REST_URL 복사 &UPSTASH_REDIS_REST_TOKEN .env라는 파일에 저장합니다. Remix 프로젝트의 루트에 있습니다.
  • dotenv 설치 - $ npm install --save-dev dotenv - 이렇게 하면 .env에서 환경 변수를 삽입할 수 있습니다. 방금 만든 파일입니다.
  • package.json으로 이동 파일을 만들고 dev를 바꿉니다. 스크립트 양식 remix dev dotenv/config node_modules/.bin/remix dev로 .

2단계 - 핵심 createSessionStorage 구현 Upstash 세션 구현을 만들기 위해

Remix는 createSessionStorage를 사용하여 자신만의 세션 통합을 구축할 수 있는 훌륭한 API를 제공합니다. . 이 기능을 구현하여 Upstash를 통합할 수 있습니다.

// sessions/upstash.server.ts

import * as crypto from "crypto";

import { createSessionStorage } from "remix";

const upstashRedisRestUrl = process.env.UPSTASH_REDIS_REST_URL;

const headers = {
  Authorization: `Bearer ${process.env.UPSTASH_REDIS_REST_TOKEN}`,
  Accept: "application/json",
  "Content-Type": "application/json",
};

const expiresToSeconds = (expires) => {
  const now = new Date();
  const expiresDate = new Date(expires);
  const secondsDelta = expiresDate.getSeconds() - now.getSeconds();
  return secondsDelta < 0 ? 0 : secondsDelta;
};

// For more info check https://remix.run/docs/en/v1/api/remix#createsessionstorage
export function createUpstashSessionStorage({ cookie }: any) {
  return createSessionStorage({
    cookie,
    async createData(data, expires) {
      // Create a random id - taken from the core `createFileSessionStorage` Remix function.
      const randomBytes = crypto.randomBytes(8);
      const id = Buffer.from(randomBytes).toString("hex");
      // Call Upstash Redis HTTP API. Set expiration according to the cookie `expired property.
      // Note the use of the `expiresToSeconds` that converts date to seconds.
      await fetch(
        `${upstashRedisRestUrl}/set/${id}?EX=${expiresToSeconds(expires)}`,
        {
          method: "post",
          body: JSON.stringify({ data }),
          headers,
        }
      );
      return id;
    },
    async readData(id) {
      const response = await fetch(`${upstashRedisRestUrl}/get/${id}`, {
        headers,
      });
      try {
        const { result } = await response.json();
        return JSON.parse(result).data;
      } catch (error) {
        return null;
      }
    },
    async updateData(id, data, expires) {
      await fetch(
        `${upstashRedisRestUrl}/set/${id}?EX=${expiresToSeconds(expires)}`,
        {
          method: "post",
          body: JSON.stringify({ data }),
          headers,
        }
      );
    },
    async deleteData(id) {
      await fetch(`${upstashRedisRestUrl}/del/${id}`, {
        method: "post",
        headers,
      });
    },
  });
}

방금 작성한 내용을 설명하겠습니다. sessions/upstash.server.ts라는 파일을 만들었습니다. . 이 파일은 createUpstashSessionStorage라는 함수를 내보냅니다. .이 함수는 매개변수로 cookie를 취합니다. (나중에 자세히 설명) 핵심 Remix createSessionStorage 사용 새 세션 공급자를 구현하는 팩토리 함수입니다.

함수 내에서 우리는 createSessionStorage를 구현했습니다. 새 세션 생성을 위한 프로토콜(createData ), 세션 값 읽기(readData ), 세션 값 업데이트(updateData ) 및 세션 삭제(deleteData ).

각 함수는 REST를 사용합니다. Redis 데이터베이스와 상호 작용하는 Upstash API.

주의 사항:

  • 전달된 쿠키에는 cookie expiration date가 있습니다. js Date에서 체재. expiresToSeconds를 사용합니다. Redis가 기대하는 대로 데이터를 초로 변환하는 함수입니다.
  • 쿠키를 설정할 때 만료 날짜를 설정하는 것을 잊지 마십시오. Redis는 세션이 만료되면 자동으로 삭제합니다.
  • 우리는 crypto를 사용합니다. 고유한 세션 ID를 생성합니다. 고유 ID를 생성하기 위해 다른 대안을 사용할 수 있습니다. 핵심 createFileSessionStorage에서 사용되는 것과 동일하므로 이 옵션을 선택했습니다. 기능.

3단계 - createSessionStorage 사용 앱에서

이제 우리는 세션 스토리지 구현을 만들었으며 이를 사용하는 방법을 보여줍니다.

<블록 인용>

지금부터 Upstash에 특정한 것은 없습니다. 모든 논리는 sessions/upstash.server.ts에 캡슐화됩니다. 파일.

// sessions.server.ts

import { createCookie } from "remix";
import { createUpstashSessionStorage } from "~/sessions/upstash.server";

// This will set the length of the session.
// For the example we use a very short duration to easily demonstrate its functionally.
const EXPIRATION_DURATION_IN_SECONDS = 10;

const expires = new Date();
expires.setSeconds(expires.getSeconds() + EXPIRATION_DURATION_IN_SECONDS);

const sessionCookie = createCookie("__session", {
  secrets: ["r3m1xr0ck1"],
  sameSite: true,
  expires,
});

const { getSession, commitSession, destroySession } =
  createUpstashSessionStorage({ cookie: sessionCookie });

export { getSession, commitSession, destroySession };

sessions.server.ts라는 파일을 만듭니다. 위의 코드를 붙여넣습니다. 이 파일은 getSession 함수 3개를 내보냅니다. , commitSessiondestroySession . 이러한 기능을 통해 앱은 세션과 상호 작용할 수 있습니다. 또한 클라이언트의 세션에 대한 참조를 저장하기 위해 쿠키를 만들었습니다.

비즈니스 요구에 따라 만료 기간을 설정합니다. 자세한 내용은 https://developer.mozilla.org/en-US/docs/Web/HTTP/Cookies

를 참조하세요.

Remix 경로에서 세션 사용

Remix를 사용하여 경로당 세션 사용량을 정의할 수 있습니다. 다음 예에서는 session을 사용합니다. routes/index.tsx . 이 예제에서는 세션 API를 사용하는 방법만 보여주었습니다. 세션을 특정 비즈니스 로직에 연결하는 것은 이 게시물의 범위를 벗어납니다.

<블록 인용>

인증을 위해 세션을 사용하는 방법에 대한 예를 찾고 있다면 https://github.com/remix-run/remix/tree/main/examples/remix-auth-form

을 참조하십시오.
// routes/index.tsx

import type { LoaderFunction } from "remix";
import { json, useLoaderData } from "remix";
import { commitSession, getSession } from "~/sessions.server";

export const loader: LoaderFunction = async ({ request }) => {
  // Get the session from the cookie
  const session = await getSession(request.headers.get("Cookie"));
  const myStoredData = session.get("myStoredData");
  // If no session found (was never created or was expired) create a new session.
  if (!myStoredData) {
    session.set("myStoredData", "Some data");
    return json(
      {
        message: "Created new session",
      },
      {
        headers: {
          "Set-Cookie": await commitSession(session),
        },
      }
    );
  }
  // If session was found, present the session info.
  return json({
    message: `Showing Session info: ${myStoredData}`,
  });
};

export default function () {
  const data = useLoaderData();
  return <div>{data.message}</div>;
}

이 예제는 사용자 세션의 두 가지 가능한 상태(사용자에게 세션이 있거나 사용자에게 세션이 없음)를 처리하는 방법을 보여줍니다. 사용자에게 세션이 없는 경우 앱의 인덱스 파일로 이동하면 새 세션이 생성되고 일부 더미 데이터가 저장됩니다. 사용자에게 유효한(만료되지 않은) 세션이 있는 경우 경로에 세션의 데이터가 표시됩니다.

4단계 - 배포

이제 Upstash를 사용하여 세션을 구현했으므로 원하는 배포 전략을 자유롭게 선택할 수 있습니다.

<블록 인용>

Upstash 환경 변수를 설정하는 것을 잊지 마십시오.

부록

createFileSessionStorage 사용 로컬 개발 및 createUpstashSessionStorage용 스테이징/프로덕션

오프라인 상태에서 개발할 수 있기를 원할 가능성이 높습니다. 로컬에서 개발할 때 createUpstashSessionStorage를 대체할 수 있습니다. createFileSessionStorage 사용 현재 NODE_ENV 감지 .

Upstash 구현이 작동하는지 테스트한 후 sessions/upstash.server.ts를 변경합니다. 다음과 같이 파일:

이 섹션 변경:

// from sessions/upstash.server.t

const { getSession, commitSession, destroySession } =
  createUpstashSessionStorage({ cookie: sessionCookie });

함께:

// from sessions/upstash.server.ts

const { getSession, commitSession, destroySession } = (process.env.NODE_ENV === "development") ?
createFileSessionStorage({ cookie: sessionCookie, dir: './sessions' });
:  createUpstashSessionStorage({ cookie: sessionCookie });

이제 로컬에서 개발할 때 Upstash를 호출하는 대신 로컬 파일 시스템을 사용하게 됩니다.

결론

이 게시물에서 우리는 Upstash Redis DB를 사용하여 세션 스토리지 데이터를 호스팅하는 방법을 보았습니다. Remix API는 특정 세션 스토리지 구현을 정말 잘 캡슐화하여 통합을 앞으로 나아가게 합니다. 예제를 가지고 놀고 싶다면 https://github.com/remix-run/remix/tree/main/examples/redis-upstash-session

의 Remix 소스 코드에서 확인할 수 있습니다.

즐기세요.