Skip to content
qetqet910Public

Repository files navigation

날잡아 (NalJapJa)

가능한 날짜를 투표로 모아서 모임 일정을 잡는 서비스. 회원가입 없이, 링크 하나로 끝.

🔗 서비스 바로가기

프로젝트 개요

여러 명이 모일 날짜를 맞추려고 단톡방에서 "이날 되세요?"를 반복하는 번거로움을 줄이기 위해 만들었습니다.

  1. 주최자가 날짜 범위와 최소 인원을 정해 방을 만든다
  2. 링크를 공유한다 (회원가입 불필요)
  3. 참여자가 가능한 날짜를 골라 투표한다
  4. 최소 인원 조건을 만족하는 날짜가 나오면 서버가 자동으로 확정한다

주요 기능

투표 / 확정

  • 회원가입 없이 닉네임만으로 투표, 같은 브라우저에서만 본인 투표 수정 가능 (vote_token 기반)
  • 최소 인원 조건 충족 시 자동 확정 (try_confirm_room — DB 락으로 동시 요청 안전하게 처리)
  • 최다 득표 날짜가 동점이면 서버가 자동으로 재투표 상태로 전환, 동점 후보만 다시 투표받음
  • 닉네임이 중복돼도 차단하지 않고 "이름(2)"로 자동 구분
  • 확정일이 지나면 같은 결과 화면에서 "지난 모임"으로 표시 (축하 애니메이션은 생략)

주최자

  • 방 생성 시 발급된 host_key로만 가능한 강제 확정 / 방 삭제
  • 마감된 방에서 "이 설정으로 새 방 만들기" — 이름·최소 인원을 그대로 복사해 새 방 생성

그 외

  • Supabase Realtime으로 투표 현황 실시간 갱신
  • 링크 복사 / 카카오톡 공유 / Web Share API
  • 다크모드 (라이트 기본, 토글 시 localStorage에 저장)
  • 키보드 전용 사용자를 위한 시간 선택 휠(방향키 지원) + 전역 focus 표시
  • prefers-reduced-motion 대응 — 모션 줄임 설정 시 확정 애니메이션 정지
  • 마감된 방까지 진행됐지만 확정되지 않은 경우 결과 요약 + "새 방 만들기" 안내

기술 스택

영역 사용 기술
프레임워크 Next.js 16 (App Router), React 19, TypeScript
DB / 인증 Supabase (PostgreSQL, Row Level Security, Realtime)
스타일 Tailwind v4 + 커스텀 CSS 변수 / nj-* 클래스 (app/globals.css)
Rate Limit Upstash Redis (미설정 시 인메모리로 자동 폴백)
테스트 Playwright E2E
배포 Netlify (@netlify/plugin-nextjs)
패키지 매니저 pnpm

아키텍처 하이라이트

  • 인증 없는 익명 투표 — supabase.auth를 쓰지 않고 anon key + RLS로만 접근을 제어합니다. 투표 수정 권한은 서버가 발급한 vote_token(UUID, 별도 테이블에 보관, anon SELECT 불가)으로 검증합니다.
  • 주최자 권한 — host_key도 같은 방식으로 별도 테이블에 보관해 일반 SELECT로는 절대 노출되지 않습니다.
  • 동시성 — 자동 확정 로직(try_confirm_room)은 Postgres FOR UPDATE 락으로 동시 투표 요청에도 단 한 번만 확정되도록 보장합니다.
  • 서버가 모든 판단을 내림 — 재투표 여부, 동점 후보, 확정 여부를 전부 서버 RPC가 계산해서 rooms 테이블에 기록합니다. 클라이언트는 그 결과를 그대로 읽기만 합니다.

더 자세한 설계 의도와 트레이드오프는 CLAUDE.md에 정리돼 있습니다.

로드맵

  • 확정 후 알림 — 이메일 또는 Web Push (카카오 알림톡은 사업자 등록·전화번호 수집이 필요해 현재 설계와 맞지 않아 보류)
  • 장소 조율 — 날짜뿐 아니라 모임 장소도 함께 제안/투표

라이선스

BSD 3-Clause License

Releases

Packages

Contributors

Languages