RSS

Supabase, QStash, Redis는 무엇이 다를까? 장부·전달 기사·공용 카운터로 이해하기

서버리스 서비스를 구성하다 보면 Supabase, QStash, Redis가 한 화면에 함께 등장합니다. 모두 데이터를 다루는 것처럼 보여 처음에는 무엇을 어디에 써야 하는지 헷갈리기 쉽습니다.

가장 쉬운 구분법은 세 서비스를 장부, 전달 기사, 공용 카운터로 생각하는 것입니다.

먼저 한눈에 보기

서비스 쉬운 비유 해결하는 질문
Supabase 영구 장부 오래 보관해야 하는 사실은 무엇인가?
QStash 할 일 전달 기사 어떤 작업을 나중에 반드시 실행해야 하는가?
Redis 공용 카운터 여러 실행 환경이 잠시 공유해야 하는 값은 무엇인가?

이 세 가지는 경쟁 제품이라기보다 서로 다른 수명의 데이터를 담당하는 도구입니다.

Supabase는 영구적으로 남겨야 하는 장부다

상품, 주문, 고객이 입력한 정보처럼 서비스의 기준이 되는 데이터는 PostgreSQL에 저장해야 합니다. 관계를 맺고, 조건을 검사하고, 트랜잭션으로 여러 변경을 하나의 작업처럼 처리할 수 있기 때문입니다.

예를 들어 주문을 만들 때는 다음 과정이 하나의 트랜잭션 안에서 처리되어야 합니다.

상품 재고 확인
  → 조건부 재고 차감
  → 주문 생성
  → 주문 항목과 당시 가격 저장

중간에 하나라도 실패하면 전체가 취소되어야 합니다. 이런 영구 상태와 정합성은 Redis나 메시지 전달 서비스에 맡길 일이 아닙니다.

특히 재고 수량의 기준값은 Supabase에 두는 편이 안전합니다. Redis는 빠르지만, 여기서 필요한 핵심은 속도보다 주문과 재고가 서로 어긋나지 않는 것입니다.

QStash는 나중에 처리할 일을 전달한다

주문 저장이 끝난 뒤 텔레그램 알림이나 이메일 발송까지 같은 요청에서 기다리면 응답이 느려집니다. 외부 알림 서비스가 잠시 실패했을 뿐인데 주문 요청 자체가 실패한 것처럼 보일 수도 있습니다.

QStash를 사용하면 핵심 처리와 후처리를 분리할 수 있습니다.

주문 요청
  → Supabase에 주문 저장
  → QStash에 주문 후처리 작업 전달
  → 사용자에게 주문 결과 응답

QStash
  → 작업 엔드포인트 호출
  → 실패하면 정해진 정책에 따라 재시도

QStash가 보관하는 것은 서비스의 최종 데이터가 아니라 실행해야 할 작업입니다. 작업이 실패했을 때 다시 전달하고, 예약된 시간에 실행하거나, 순서대로 처리해야 할 때 적합합니다.

대표적인 활용 예시는 다음과 같습니다.

  • 주문 완료 알림
  • 이메일 발송
  • 외부 API 동기화
  • 이미지 변환
  • 예약 작업
  • 실패 시 재시도가 필요한 후처리

QStash가 같은 작업을 재전달할 수 있으므로 처리 함수는 멱등하게 만들어야 합니다. 같은 작업이 두 번 도착해도 결과가 틀어지지 않아야 한다는 뜻입니다.

Redis는 여러 실행 환경이 함께 보는 빠른 메모장이다

Vercel 같은 서버리스 환경에서는 연속된 요청이 같은 인스턴스에서 처리된다는 보장이 없습니다.

첫 번째 요청 → 인스턴스 A
두 번째 요청 → 인스턴스 B
세 번째 요청 → 인스턴스 C

각 인스턴스의 메모리에서 요청 횟수를 세면 A, B, C가 모두 1회라고 생각합니다. 전체 요청이 몇 번이었는지 알 수 없습니다.

Redis에 카운터를 두면 모든 인스턴스가 같은 숫자를 봅니다.

IP 주소별 카운터 증가
  → 1분 만료 시간 설정
  → 10회 이하면 허용
  → 10회 초과면 요청 차단

이런 데이터는 영구 보관할 필요가 없습니다. 잠시 빠르게 공유하고 시간이 지나면 사라져도 되는 값입니다.

Redis가 잘 맞는 예시는 다음과 같습니다.

  • API 요청 횟수 제한
  • 짧은 수명의 캐시
  • 일회용 인증번호
  • 임시 세션
  • 중복 요청 방지 키
  • 여러 인스턴스가 공유해야 하는 짧은 상태

QStash와 Redis는 서로 대체하지 않는다

QStash는 작업 전달과 재시도를 책임집니다. Redis는 값을 빠르게 읽고 쓰며 공유하는 저장소입니다.

Redis 자료구조로 직접 작업 큐를 만들 수도 있지만, 그러면 메시지를 가져갈 실행 주체, 실패 감지, 재시도, 서명 검증, 모니터링까지 직접 운영해야 합니다. 반대로 QStash를 단순 카운터처럼 사용하는 것도 목적에 맞지 않습니다.

따라서 다음처럼 구분하면 됩니다.

  • 실행해야 할 일이라면 QStash
  • 잠깐 공유할 값이라면 Redis
  • 영구적으로 남길 사실이라면 Supabase

작은 프로젝트에서는 무엇부터 붙여야 할까?

모든 서비스를 처음부터 넣을 필요는 없습니다.

관리자만 사용하는 간단한 CRUD라면 Supabase만으로 충분합니다. 주문 후 알림처럼 응답과 분리할 작업이 생기면 QStash를 추가합니다. 공개 API에 여러 인스턴스가 공유해야 하는 요청 제한이 필요해질 때 Redis를 추가하면 됩니다.

예를 들어 다음과 같은 순서가 자연스럽습니다.

  1. Supabase로 상품과 주문을 안전하게 저장한다.
  2. QStash로 주문 후 알림을 요청 흐름에서 분리한다.
  3. Redis로 공개 주문 API의 요청 횟수를 전체 인스턴스 기준으로 제한한다.

기술 선택의 기준은 데이터의 수명이다

새로운 서비스를 도입할 때는 기능 이름보다 데이터가 얼마나 오래 살아야 하는지를 먼저 물어보는 것이 좋습니다.

  • 오래 남아야 하는가?
  • 실패해도 다시 실행해야 하는 일인가?
  • 몇 초 또는 몇 분만 공유하면 되는가?

이 세 질문에 답하면 Supabase, QStash, Redis의 경계가 자연스럽게 보입니다. 도구를 많이 붙이는 것이 좋은 구조가 아니라, 서로 다른 책임을 겹치지 않게 나누는 것이 좋은 구조입니다.

참고 자료