소개
Codeshare 같은 실시간 코드 공유 플랫폼이 어떻게 만들어지는지 궁금해 본 적이 있으신가요? 더 나아가, 그런 서비스를 확장(scaling)하면서도 개발자 경험까지 쾌적하게 유지하는 도전에 뛰어들어 본 적이 있으신가요?
저는 Bytecrowds라는 프로젝트를 시작하면서 이 모든 것을 배워야 했습니다. 텍스트 동시 편집 기능을 위해 Yjs를 사용하기로 결정한 후 남은 과제는 데이터베이스 선택이었습니다. 시중에 선택지가 워낙 많았기에 저는 한 가지 핵심 키워드로 후보를 좁혔습니다. 바로 단순함(simplicity)입니다.
왜 Upstash인가?
사실 Upstash를 알기 전부터 저는 Redis®의 단순하고 직관적인 API에 매력을 느끼고 있었습니다. 다만 Redis®를 주 데이터베이스로 사용하려면 스케일링(캐싱 용도로도 필요할 수 있습니다)과 영속성(persistence) 유지 같은 과제가 따릅니다. 게다가 스폰서십을 확보하기 전 오픈소스 프로젝트라면 비용 관리에 특히 신경 쓸 수밖에 없습니다. 사용하지 않는 시간에도 컴퓨팅 파워 비용을 지불할 여력이 있는가? 갑작스러운 트래픽 폭증이 닥쳤을 때, 새로운 기능 개발이나 버그 수정 대신 몇 시간씩 인프라 작업에 매달릴 준비가 되어 있는가? 솔직히 저는 아니었습니다. 그래서 Upstash를 찾게 되었습니다.
Upstash Redis는 제가 중요하게 여기는 세 가지 조건을 모두 충족했습니다. 사용이 쉽고, 확장이 쉬우며, 유연하다는 점입니다. 여기에 낮은 지연 시간(latency), 서버리스 클라이언트에서 바로 쓸 수 있는 REST SDK(Bytecrowdsにとっても 필수 요건이었습니다), 글로벌 리플리케이션, 그리고 종량제(pay-as-you-go) 요금제까지 갖춰져 있으니, 제가 이 프로젝트에 Upstash를 선택한 이유를 충분히 이해하실 겁니다.
앱 전반에서 Redis® 활용하기
그럼 Redis®가 하나의 프로젝트에서 주 데이터베이스로서 어떻게 여러 서비스의 요구를 충족할 수 있는지 살펴보겠습니다. 맥락을 이해하실 수 있도록 Bytecrowds의 데이터 흐름을 나타낸 다이어그램입니다.

Bytecrowds는 Ably를 통해 클라이언트 간 텍스트를 동기화하고, 요청 IP 주소 기반으로 데이터를 수집하는 자체 애널리틱스 엔진을 사용합니다.
메인 스토리지
각 bytecrowd는 다음 속성을 가진 Redis® 해시(hash) 형태로 저장됩니다.
{
text: string,
language: string,
authorizedEmails: undefined || string array
}
해시의 속성 하나가 변경될 때마다 값을 갱신하되, 갱신 사이에 "x"초의 딜레이를 두었습니다. 운영 환경에서는 현재 100밀리초로 설정되어 있습니다.
인증과 권한 부여
인증(Authentication)
Bytecrowds는 Next.js 기반이기 때문에 GitHub OAuth 연동에는 Auth.js가 탄탄한 선택지였습니다. 덕분에 세션 저장에도 Upstash 어댑터를 활용할 수 있었고, 앱 전체에서 Redis®만으로 일관성 있게 개발을 진행할 수 있었습니다.
권한 부여(Authorization)
Bytecrowds는 필요할 때 authorizedEmails 필드를 생성하는 방식으로 권한을 관리하며, 한번 설정된 이 필드는 API를 통해서는 변경할 수 없습니다. Redis®가 좋은 점 중 하나는 반복적인 작업을 위해 알고리즘적으로 효율적으로 설계된 다양한 내장 명령어를 제공한다는 것입니다. 예를 들어 authorizedEmails가 이미 설정되어 있는지 확인하는 데는 O(1) 복잡도를 가진 HEXISTS 명령어만 있으면 충분합니다.
애널리틱스
Bytecrowds의 애널리틱스 시스템은 두 가지 범주의 데이터를 처리합니다.
- 일별 통계:
년 월 일형식으로 이름 붙인 Redis® 해시로 저장되며, 다음 속성을 가집니다.
{
countries: string array,
hits: integer,
pages: string array,
uniqueVisitors: integer,
addresses: string array,
continents: string array
}
여기서 addresses는 고유 방문자 수(unique visitors)를 산출하기 위해 SHA256으로 해싱한 IP 주소 배열입니다.
- 정렬 집계 데이터:
continents,countries,pages라는 세 개의 키에는 Redis® 정렬 집합(sorted set)을 사용해 데이터를 저장합니다. 각 통계 값과 함께 카운트("score")를 저장해 두면 SORT나 SORT_RO 같은 명령어로 손쉽게 조회하거나 정렬할 수 있습니다. Redis®의 단순함이 또 한번 빛을 발하는 순간입니다.
관련 코드가 궁금하다면 https://github.com/Bytecrowds/analytics/blob/main/src/index.js 를 참고하세요.
참고: 더 복잡한 시나리오라면 이 시스템에 몇 가지 변화를 줄 필요가 있습니다. 예를 들어 원본(raw) 데이터를 처리 전에 먼저 저장해 두거나, Apache Kafka 같은 스트림 처리 도구를 도입하는 방식입니다(Upstash가 이 역시 지원하니 문서를 확인해 보세요).
직접 체험해 보기
Bytecrowds가 실제로 작동하는 모습이 궁금하신가요? https://www.bytecrowds.com 에 접속해 "new bytecrowd" 버튼을 누른 뒤, 생성된 링크를 여러 탭에서 열어 보세요. 코드를 입력하기 시작하면 연결된 모든 클라이언트에 실시간으로 코드가 복제되는 것을 확인할 수 있습니다.
마무리
오픈소스 프로젝트의 유일한 활동 유지보수자로 일하는 것이 얼마나 힘든 일인지는 두말할 필요도 없습니다. 하지만 올바른 도구와 자동 확장되는 인프라가 있다면, 트래픽 폭증 걱정 없이 멋진 프로젝트를 계속 만들어 갈 수 있습니다. 이미 Upstash Redis®를 써볼 마음이 드셨나요? 무료로 계정을 만들어 보세요. 신용카드 등록도 필요 없습니다.
전체 코드는 GitHub 저장소에서 확인할 수 있습니다. 이 글에 대한 질문이나 피드백은 tudor.zgimbau@gmail.com 으로 보내주시면 감사하겠습니다.