오늘 우리는 @upstash/redis v1.0.0을 공식 발표합니다.
@upstash/redis는 서버리스 환경을 위해 설계된 유일한 커넥션리스(HTTP 기반) Redis 클라이언트로, Cloudflare Workers와 Fastly와도 완벽하게 호환됩니다.
v1.0.0의 새로운 기능은 무엇인가요?
이번 버전 1.0.0은 기존 라이브러리를 완전히 새롭게 재작성한 결과물입니다. 사용자들에게 가장 많이 요청받았던 기능은 파이프라인(pipeline) 지원과 향상된 타입 안정성(type safety)이었습니다.
이러한 새로운 기능들의 특성상 v1은 이전 버전과 하위 호환되지 않지만, 내부 REST API는 변경되지 않았기 때문에 기존 버전도 계속해서 정상적으로 작동합니다.
대부분의 명령어는 redis.setex("key", 2, "value")처럼 여러분이 익숙한 Redis 문법을 그대로 따릅니다. 다만 hset 같은 일부 명령어는 직접 (역)직렬화 작업을 줄일 수 있도록 더 사용하기 쉬운 API를 제공합니다:
await redis.hset("123", {
id: "123",
name: { first: "andreas" },
});
위 코드는 내부적으로 hset 123 id 123 name {"first":"andreas"} 형태로 직렬화되어 Upstash로 전송됩니다. 객체가 자동으로 직렬화되므로 더 이상 직접 처리할 필요가 없습니다.
명령어 사용법이 확실하지 않다면, 에디터가 인텔리센스(intellisense)를 지원하는 경우 타입스크립트가 도움을 줄 것입니다. 또한 모든 기능을 다루는 테스트 코드를 예제 삼아 참고하셔도 좋습니다.
주요 변경 사항은 다음과 같습니다:
- 명시적 인증(explicit authentication)
- 플랫폼별 최적화 (Node.js, Cloudflare Workers, Fastly)
- 개선된 타입 시스템
- 에러 자동 throw
- 파이프라인 지원
명시적 인증
특정 함수만 임포트할 때 자동으로 인증이 진행되던 방식은 실제 동작이 기대와 달라지는 문제를 일으켰고, 충분히 예방할 수 있었던 이슈를 디버깅하느라 불필요한 시간을 낭비하게 만들었습니다. 특히 환경 변수를 각각 다르게 처리하는 여러 플랫폼에서 이런 문제가 두드러졌습니다. 그래서 이제는 클라이언트를 명시적으로 인증하도록 요구합니다.
대부분의 경우 인증 정보를 환경 변수에 저장하고 Redis 클라이언트 설정 시 한 번만 필요로 할 것입니다. @upstash/redis는 이를 위한 편리한 방법을 제공합니다. UPSTASH_REDIS_REST_URL과 UPSTASH_REDIS_REST_TOKEN을 환경 변수로 설정하고 배포 플랫폼에서 로드하기만 하면 됩니다. 올바르게 구성되지 않은 경우 에러가 발생합니다.
Node.js
import { Redis } from "@upstash/redis";
const redis = Redis.fromEnv();
Cloudflare Workers
import { Redis } from "@upstash/redis/cloudflare";
const redis = Redis.fromEnv();
타입스크립트 지원
새 버전은 모든 명령어에 대해 엄격한(strict) 타입을 지원하여, 오류를 나중이 아닌 조기에 발견할 수 있도록 도와줍니다. 타입 지정은 선택 사항이며, 기본적으로 가능한 곳에서는 타입을 자동으로 추론합니다.
import { Redis } from "@upstash/redis";
const redis = new Redis({
/* auth */
});
type User = {
id: string;
email: string;
};
const user = {
id: "abc",
email: "andreas@upstash.com",
};
await redis.set<User>("userKey", user);
const user = await redis.get<User>("userKey");
// -> user는 User 타입으로 지정됨
Redis는 선택적 인자를 가진 수많은 명령어와 다양한 조합을 제공합니다. 타입스크립트를 활용하면 단 한 줄의 코드도 실행하기 전에 잘못된 조합을 미리 검사할 수 있습니다.
redis.set("key", "value", {
ex: 60, // 60초 후 만료
nx: true, // 키가 아직 존재하지 않을 때만 생성
});
에러 처리
이전 버전은 Upstash HTTP API의 원시(raw) 응답을 그대로 반환했습니다. 그래서 에러 존재 여부를 직접 확인하고 throw하는 작업을 개발자가 직접 처리해야 했습니다. 하지만 자바스크립트에서는 무언가 잘못되었을 때 에러가 throw되는 것이 일반적인 관례입니다. 이제 우리는 바로 그렇게 동작하도록 변경했습니다.
앞으로 모든 명령어는 데이터만 반환하며, 문제가 발생하면 자동으로 에러를 throw합니다.
// `v0.2.1`
const { data, error } = await set("key", "value");
if (error) {
throw new Error(error);
}
// '^v1.0.0'
const data = await redis.set("key", "value");
파이프라인(Pipelines)
Upstash는 HTTP를 통해 Redis 명령어를 파이프라이닝하여 요청을 묶어 한 번에 전송할 수 있는 기능을 제공합니다. 이를 통해 실행 시간을 단축하고 비용도 절약할 수 있으며, 특히 서버리스 함수를 사용할 때 그 효과가 큽니다.
:::note 파이프라인 실행은 원자적(atomic)이지 않습니다. 파이프라인 내 각 명령어는 순서대로 실행되지만, 다른 클라이언트가 보낸 명령어가 파이프라인 사이에 끼어들 수 있습니다. :::
기존 redis 인스턴스에서 새 파이프라인을 생성할 수 있습니다.
import { Redis } from "@upstash/redis";
const redis = new Redis({
/* auth */
});
const p = redis.pipeline();
파이프라인 API는 여러 명령어를 체이닝(chaining)할 수 있도록 설계되었습니다. 모든 명령어를 파이프라인에 추가한 후 요청을 전송하면, 각 요소가 동일한 순서의 명령어에 대응하는 배열을 결과로 받게 됩니다.
p.set("key", 2);
// 또는 직접 체이닝
p.incr("key").decrby("key", 2);
const res = await p.exec();
// res[0] => "OK" | p.set("key", 2)의 결과
// res[1] => 3 | p.incr("key")의 결과
// res[2] => 1 | p.decrby("key", 2)의 결과
시작하는 방법
console.upstash.com에 접속해 새 데이터베이스를 생성하세요. 그리고 퀵스타트 가이드의 안내를 따라 진행하면 됩니다.
이전 버전을 사용해 본 적이 있다면 GitHub의 'Migrate to v1' 섹션을 참고하여 마이그레이션을 시작하세요.
향후 계획
Upstash Redis는 최근 redis v6.2와 호환되도록 업데이트되었으며, 여기에는 새로운 명령어 추가와 기존 명령어 확장이 포함되어 있습니다. @upstash/redis도 곧 이를 지원할 예정입니다.
또한 추가 플랫폼으로 근래 Deno 지원도 계획하고 있습니다.
맺음말
이번 업데이트는 큰 변화이며, 여러분의 코드를 수정하기 위한 약간의 작업이 필요할 것입니다. 업데이트 과정에서의 경험을 꼭 알려주세요.
Upstash 제품을 사용하시는 경험을 개선할 수 있는 어떠한 피드백이든 환영합니다. 버그 신고, 기능 요청, 기여에 관심이 있거나 도움이 필요하시다면 GitHub, Discord 또는 Twitter로 언제든지 연락해 주세요.