본문으로 건너뛰기
Piyak Labs
돌아가기

K-Saju 개발기 3 : 친구들을 K-Pop 그룹으로 캐스팅하기 — 무저장 원칙과 '단톡방 셀프 기입' 사이에서

시리즈 K-Saju 개발기 (3/3)

무엇을 만들었나

K-Saju에 그룹 기능을 붙였다. 플로우는 단순하다.

  1. 누군가 크루를 만들고 링크를 단톡방에 던진다
  2. 각자 링크를 열어 생년월일(+닉네임)만 입력한다
  3. 전원이 모이면 — 사주 기반으로 K-Pop 그룹 캐스팅이 나온다

각자에게 포지션이 배정되고(리더 · 비주얼 · 메인보컬 · 래퍼 · 막내 등 8종), 멤버 전원의 페어별 케미 점수 매트릭스, 그중 최고 케미 듀오와 텐션 라인(케미 최하위 페어 — 40분째 메뉴로 싸우는 그 둘)이 지목된다. 그룹 전체에는 “국민 그룹(완전체)” 같은 그룹 컨셉이 한 줄로 붙는다.

👉 데모: https://ksaju.piyaklabs.com/crew

K-Saju 크루 결과 페이지의 그룹 컨셉 카드, 멤버 포지션 카드, 케미 점수 매트릭스 K-Saju 크루 단체 OG 포스터 예시: 멤버 병아리 캐릭터와 K-Pop 포지션 뱃지

문제: 이 서비스는 아무것도 저장하지 않는다

K-Saju의 아키텍처 원칙은 처음부터 하나였다. 개인정보 무저장, 완전 스테이트리스. 로그인도 DB도 없고, 모든 결과 페이지는 GET 파라미터를 서버에서 렌더링한다. /card?date=1995-08-28, /match?a=...&b=... — URL이 곧 상태의 전부다.

그런데 그룹 기능의 이상적인 UX는 “링크 공유 → 각자 자기 생일 기입 → 누적”이다. 누군가는 참여자 입력을 모아야 하고, 그건 상태다. 원칙과 UX가 정면으로 충돌한다.

검토한 옵션은 세 가지였다.

해법: 로비는 30일, 결과는 영원히

결론은 B와 A의 하이브리드다. 상태를 “모으는 동안”과 “다 모인 뒤”로 쪼개면 긴장이 풀린다.

만든 사람의 삭제 권한은 URL fragment에 담은 adminKey로 처리했다 (/crew/abc123#k=...). fragment는 브라우저가 서버로 전송하지 않으니, 서버 로그 어디에도 관리 키가 남지 않는다. 작지만 마음에 드는 디테일.

어뷰즈 가드는 두 겹: join 요청 직렬화(동시 가입 레이스 방지), IP별 일일 생성/가입 캡.

캐스팅 엔진: 랜덤이 아니라 결정론

포지션 배정을 랜덤으로 하면 재미가 하루를 못 간다. 같은 멤버로 다시 돌리면 같은 결과가 나와야 하고(“이거 진짜야?” → 재검증이 바이럴의 절반이다), 왜 그 포지션인지 근거가 있어야 단톡방에서 싸울 거리가 된다.

// engine/src/groupChemistry.ts — 시그니처만
export function computeGroupChemistry(members: CardPayload[]): GroupChemistryResult;
// 3~7명. 페어와이즈 매트릭스 + 8포지션 캐스팅 + 그룹 컨셉. 순수함수, 결정론.

인원은 3~7명으로 제한했다. 아이돌 그룹 크기의 감성이기도 하고, 페어 수가 C(n,2)로 늘어 매트릭스 가독성과 OG 렌더 부하가 함께 나빠지기 때문이기도 하다.

배운 것


K-Saju는 재미로 보는 K-컬처 엔터테인먼트 서비스입니다. 사주 리딩은 예언이 아니라 콘텐츠로 즐겨주세요. 🐣



이전 글
영화 HOPE에 대한 개인적인 감상평
다음 글
K-Saju 개발기 2: 만들고 나니 진짜 어려운 건 홍보였다

댓글

댓글 불러오는 중...

댓글 남기기

작성하신 댓글은 관리자 승인 후 게시됩니다.