← 목록으로

롤랜챔 | LRC

내전 인원들이 방을 만들어 전적을 쌓고, 포인트로 승부를 예측하는 웹 서비스

2026.08 - 2026.092개월1인 개발
ReactReact RouterPostgreSQLNeon Data APIJest

Preview

프로젝트 이미지 1
프로젝트 이미지 2
프로젝트 이미지 3
프로젝트 이미지 4
프로젝트 이미지 5
프로젝트 이미지 6
프로젝트 이미지 7
프로젝트 이미지 8
1 / 8

Description

롤 내전을 함께하는 사람들을 위한 팀 짜기 도구로 시작해, 전적이 쌓이고 점수를 매기고 싶어지면서 방마다 포인트 경제가 도는 다중 사용자 서비스로 발전한 개인 프로젝트입니다. 기획부터 DB 설계, 프런트엔드 구현, 배포까지 전 과정을 혼자 진행했습니다. Neon Data API를 사용해 브라우저가 Postgres를 직접 호출하는 서버리스 구조를 택했는데, 포인트라는 자산이 생기는 순간부터는 클라이언트를 신뢰할 수 없다는 전제로 권한 모델을 다시 설계해야 했습니다. 읽기는 Row Level Security로, 쓰기는 SECURITY DEFINER 함수로 완전히 분리하고, 그 위에 동시성·멱등성·되돌리기를 구현해 방·전적·포인트 송금·배팅과 정산까지 안정적으로 돌아가는 서비스를 완성했습니다.

Technical Challenges

  • 브라우저가 Postgres를 직접 호출하는 서버리스 구조에서 포인트 자산을 지키기 위해, 읽기는 RLS로 쓰기는 SECURITY DEFINER 함수로 분리한 권한 모델을 설계하고 잔액 테이블의 클라이언트 쓰기 권한을 전부 회수
  • 송금·배팅에서 잔액 확인과 차감을 한 문장으로 합쳐 동시 요청 시 중복 차감되는 경쟁 조건을 제거하고, 정산에 멱등성과 되돌리기(역분개)까지 구현
  • "내가 멤버인 방만 보인다"는 RLS 정책이 멤버 테이블을 다시 참조하며 무한 재귀에 빠지는 문제를, SECURITY DEFINER로 RLS를 우회하는 멤버 판정 함수를 만들어 해결
  • 전적이 참가자를 이름 문자열로 참조해 이름을 바꾸면 기록이 갈라지던 문제를 ID 참조로 전환하면서도, 어댑터 계층을 추가해 300줄 규모의 기존 집계 로직과 테스트를 그대로 재사용
  • 실시간 구독이 없는 REST 환경에서, 트리거로 올라가는 버전 컬럼 하나만 주기적으로 조회해 값이 바뀔 때만 상세 데이터를 받아오는 방식으로 폴링 비용을 최소화
  • 판당 약 12,500포인트가 새로 생겨 인플레이션되는 문제를 월간 초기화로, 배팅 배당은 승리팀엔 패리뮤추얼(제로섬)을 나머지엔 공정값보다 낮은 고정 배당을 적용해 총량이 무너지지 않게 설계

Learnings

  • 버그를 하나씩 고치기보다, 그 버그가 애초에 생길 수 없는 데이터 모델로 바꾸는 방향을 먼저 고려하게 됨
  • 서버 코드가 없는 구조를 택했다면 신뢰 경계가 어디에 있는지부터 규정해야 한다는 것을 체감했고, 이후로는 클라이언트가 신뢰할 수 없는 값(자산·권한)을 다루는 지점을 설계 초기에 먼저 식별하게 됨