Computer >> 컴퓨터 >  >> 프로그래밍 >> Redis

SvelteKit과 Redis(Upstash)로 만드는 TODO 앱 완벽 가이드

이 글에서는 SvelteKit서버리스 Redis(Upstash)를 활용하여 간단한 TODO 애플리케이션을 만들어 보겠습니다.

SvelteKit은 아름다운 개발 경험과 유연한 파일 시스템 기반 라우팅을 갖춘, 모든 규모의 웹 애플리케이션을 구축하기 위한 프레임워크입니다.

프로젝트 생성

먼저 아래 명령어를 실행하여 프로젝트를 생성합니다:

npm init svelte@next todo-app-with-redis

프로젝트가 준비되었다면, 이제 의존성 패키지를 설치하고 개발 서버를 실행해 보겠습니다:

npm install
npm run dev

사용자 인터페이스(UI) 만들기

TODO 항목을 담을 간단한 폼과 리스트를 생성합니다. 우선은 하드코딩된 데이터로 화면을 구성하고, 이후 데이터베이스와 연결하게 됩니다.

// src/routes/index.svelte

<script lang="ts">
  import type {Todo} from "../lib/types";
  import TodoItem from "../components/Todo.svelte";

  export let todos: Todo[] = [
    {
      id: '1',
      text: 'Create database',
      status: true
    },
    {
      id: '2',
      text: 'Copy database url',
      status: false
    }
  ];

  const uncheckedTodos = todos.filter((todo) => !todo.status);
  const checkedTodos = todos.filter((todo) => todo.status);
</script>

<main class="container">
  <form class="new" action="/" method="post">
    <input
      type="text"
      name="text"
      autofocus
      aria-label="Add todo"
      class="input"
      placeholder="What needs to be done?"
    />
  </form>

  {#if uncheckedTodos.length}
    <div class="todos">
      {#each uncheckedTodos as todo (todo.id)}
        <TodoItem {todo}/>
      {/each}
    </div>
  {/if}

  {#if checkedTodos.length}
    <div class="todos todos-done">
      {#each checkedTodos as todo (todo.id)}
        <TodoItem {todo}/>
      {/each}
    </div>
  {/if}
</main>

다음은 개별 TODO 항목을 렌더링하는 컴포넌트입니다:

// src/components/Todo.svelte

<script lang="ts">
  import type {Todo} from "../lib/types";

  export let todo: Todo;
</script>

<div class="todo">
  <form action="/?_method=PATCH" method="post">
    <input type="hidden" name="todo" value={JSON.stringify(todo)}/>
    <button
      class="checkbox"
      aria-label="Mark todo as {todo.status ? 'not done' : 'done'}"
    >
      {todo.status ? "✓" : ""}
    </button>
  </form>

  <span class="text">{todo.text}</span>

  <form action="/?_method=DELETE" method="post">
    <input type="hidden" name="id" value={todo.id}/>
    <button class="delete" aria-label="Delete todo">✕</button>
  </form>
</div>

여기까지 완료하면 다음과 같은 화면을 볼 수 있습니다:

데이터베이스 준비하기

데이터는 Upstash Redis에 저장할 예정입니다. 먼저 Upstash 콘솔에서 새로운 데이터베이스를 생성하세요. Upstash는 HTTP 기반 클라이언트를 제공하며, 이는 서버리스(Serverless) 환경에서 특히 잘 동작합니다. 필요한 패키지를 설치합니다:

npm install @upstash/redis

Upstash 콘솔에서 Redis 데이터베이스를 생성한 후, UPSTASH_REDIS_REST_URLUPSTASH_REDIS_REST_TOKEN 값을 복사하여 .env 파일에 붙여넣습니다.

UPSTASH_REDIS_REST_URL=https://global-renewing-gecko-31543.upstash.io
UPSTASH_REDIS_REST_TOKEN=AXs3ACsjfg684jJBFQgN34je7RFJ58wYjg4NjMt=

환경 변수를 사용하려면 dotenv 패키지도 설치가 필요합니다.

npm install dotenv

이제 lib/redis.ts 파일을 생성하고, 아래와 같이 Redis 인스턴스를 초기화합니다:

// src/lib/redis.ts

import "dotenv/config";
import { Redis } from "@upstash/redis";

export const databaseName =
  process.env.NODE_ENV === "development"
    ? "redis-with-svelte-kit-dev"
    : "redis-with-svelte-kit";

const redis = new Redis({
  url: process.env.UPSTASH_REDIS_REST_URL,
  token: process.env.UPSTASH_REDIS_REST_TOKEN,
});

export default redis;

API 만들기

SvelteKit의 라우트 폴더에서 js/ts 파일은 API 백엔드 역할을 합니다. 즉, index.svelte가 프론트엔드라면 index.ts는 백엔드입니다.

index.ts 파일을 생성하고 필요한 API 메서드들을 추가해 보겠습니다.

// src/routes/index.ts

import redis, { databaseName } from "../lib/redis";
import type { RequestHandler } from "@sveltejs/kit";

const redirect = {
  status: 303,
  headers: {
    location: "/",
  },
};

export const get: RequestHandler = async () => {
  // 페이지가 로드될 때마다 실행됨
  return { body: { todos: [] } };
};

export const post: RequestHandler = async ({ request }) => {
  // 폼: TODO 생성
  return redirect;
};

export const patch: RequestHandler = async ({ request }) => {
  // 폼: TODO 수정
  return redirect;
};

export const del: RequestHandler = async ({ request }) => {
  // 폼: TODO 삭제
  return redirect;
};

POST — TODO 항목 생성

TODO 항목 생성 기능을 구현해 보겠습니다:

// src/routes/index.ts

export const post: RequestHandler = async ({ request }) => {
  const form = await request.formData();
  const text = form.get("text");
  const id = Date.now().toString();

  const todo = JSON.stringify({ text, status: false });

  await redis.hset(databaseName, id, todo);
  return redirect;
};

GET — TODO 목록 불러오기

이제 저장된 TODO 항목들을 조회하여 목록으로 표시합니다:

// src/routes/index.ts

export const get: RequestHandler = async () => {
  let todos = [];

  const data = await redis.hgetall(databaseName);
  if (!data) return { body: { todos } };

  // 데이터 정규화
  todos = Object.keys(data)
    .map((key) => ({
        id: key,
        text: data[key]["text"],
        status: data[key]["status"],
    }))
    // id = 타임스탬프이므로 내림차순 정렬
    .sort((a, b) => parseInt(b.id) - parseInt(a.id));

  return { body: { todos } };
};

본문의 간결함을 위해 할 일 삭제완료 처리 코드는 여기에 포함하지 않았지만, GitHub 저장소에서 전체 코드를 확인하실 수 있습니다.

마무리

이제 모든 준비가 끝났습니다! 위 과정을 거치면 SvelteKit과 Upstash Redis가 연동된 TODO 앱이 완성됩니다.

전체 소스 코드는 GitHub에서 확인할 수 있으며, 데모 앱도 함께 제공됩니다.

필자는 동일한 TODO 애플리케이션을 Next.js로도 구현할 계획입니다. 이후 두 프레임워크에서의 개발 경험을 비교하여 공유할 예정이니 많은 관심 부탁드립니다.

최신 소식을 받아보시려면 Twitter와 Discord에서 저희를 팔로우해 주세요!