콘텐츠로 이동
✍️ 수정가능누구나 고쳐도 됩니다. 고치면 하단 frontmatter의 갱신일·작성자·변경요약을 남겨 주세요.작성 Claude · 2026-06-04 · v12 재편·raw 컴파일·인간화

학생 초대 개발 명세 (FRD)

요지

초대 링크로 학생을 스터디룸에 들이는 흐름을 어떻게 구현하는지 정리한다. 핵심은 세 가지다 — 스터디룸마다 초대장을 딱 하나(Opaque Token)만 두고, 링크를 누른 학생을 다섯 갈래로 나눠 처리하며, 가입·로그인·소셜 리다이렉션을 거치는 내내 초대 토큰을 잃지 않게 한다. MVP-C 기능이다.

상위 PRD (링크 · 변경 시 알림)

기획은 prd(바뀌면 이 문서도 갱신), 도메인은 studyroom(룸·정원·멤버)과 member(역할·기가입)다.

기술 접근 · 아키텍처

초대장 발급·상태

스터디룸당 초대장 1개 관리(1:1 테이블). 발급 기준 = 초대 기능 활성화 AND 스터디룸 운영 기간 모두 만족.

상태 설명
Active 정상 사용 가능
Expired 선생님 수동 만료
Disabled 스터디룸 삭제/비활성
  • 토큰: Opaque Token(UUID) + 방 고유 식별자, RDB 검증(Stateless 미사용, 무결성 우선).
  • 토글: OFF→ON = 새 토큰 생성, ON→OFF = 기존 토큰 삭제.
  • 유효성: 토큰 형식 X → Invalid / 식별자 미존재 → Expired / 통과 → Active. (랜덤 UUID 조회 특성상 스터디룸 미존재와 만료는 모두 Expired로 처리.)
  • 수명주기 훅: 스터디룸 생성 시 초대장 생성, 삭제 시 Cascade 삭제.

학생 분기 처리

Case 처리
이미 로그인 학생 초대장 UI → [수락] → 즉시 입장
비로그인(기존 회원) 로그인 페이지 → 로그인 후 초대장 → 수락 → 입장
미가입 사용자 회원가입 유도 → 가입 후 초대장 → 수락 → 입장
이미 가입한 학생 예외 메시지 → 스터디룸 조회(수업노트 탭)
만료/종료/잘못된 링크 상황별 메시지 노출 → 홈 이동

기존 회원 수락 시 도메인 검증 순서: 역할(학생) → 기가입 여부 → 스터디룸 유효성(존재/활성) → 정원 초과. 통과 시 기존 초대 로직으로 멤버 추가(알림 포함). 보호자 계정은 역할 검증에서 차단.

토큰 유지 (신규 회원)

회원가입/로그인 및 소셜 리다이렉션 시 초대 토큰 유지 → 가입 직후 초대장 노출.

  • 이메일 회원가입: FE가 inviteToken 저장 → 가입/로그인 성공 후 저장 토큰으로 수락 API 자동 호출.
  • 소셜 로그인: OAuth 시작 시 state=inviteToken:{token} 포함 → 콜백에서 BE가 state의 토큰 감지 → JWT 쿠키 설정 후 리다이렉트: 기존 회원 → /dashboard?token={inviteToken}, 신규 회원 → /select-role?token={inviteToken}. FE가 URL에서 토큰 읽어 수락 API 자동 호출 → 스터디룸 이동. (소셜 로그인 개발 명세 (FRD) 연계)
  • 토큰 만료(401): 리프레시 재발급 시도 → 실패 시 비회원 플로우 합류.
  • inviteToken 없을 시: 로그인/가입 후 홈 이동.

API · 데이터 모델

API는 세 개로 갈린다 — 누구나 볼 수 있는 초대장 조회, 로그인한 학생만 부르는 수락, 그리고 소셜로 들어온 학생을 위한 콜백이다.

구분 엔드포인트 비고
초대장 조회(공개) GET /api/public/study-rooms/invite/{token} 인증 불필요, 최소 유효성 검증
회원 수락 POST /api/student/study-room-invites/{token}/respond 역할/기초대/정원 순서 검증 후 멤버 추가
소셜 콜백 GET /api/auth/{provider}/callback?state={inviteToken} state에 토큰 있을 시 수락 API redirect

Frontend 라우팅: - 초대장 /invite?token={inviteToken} · 성공 /invite/success?studyRoomId={studyRoomId} · 에러 /invite/error?reason={ROLE_NOT_MATCH|ALREADY_PARTICIPATED|CLOSED|EXPIRED_LINK|INVALID_LINK}

의존성 · 영향 범위

스터디룸(studyroom, 초대장 1:1 테이블·Cascade·정원), 회원(member, 역할·기가입), 소셜 로그인(소셜 로그인 개발 명세 (FRD), state 토큰), 회원가입(회원가입 개발 명세 (FRD), 가입 후 복귀)에 걸쳐 있다.

아직 정하지 못한 건 링크별 만료 기한(TTL)이다. 이걸 넣으려면 토큰을 "링크 복사 시"에 발급하도록 바꾸고 Redis 상태관리를 검토해야 한다. 운영이 끝난 스터디룸의 초대 허용 여부도 미결이다.

테스트 계획

공통 케이스·E2E 전략은 qa-playbook을 따른다. 이 기능에서 꼭 볼 것은 토글 ON/OFF(새 토큰 발급·삭제), 토큰 유효성 분기(Active/Expired/Invalid), 학생 다섯 갈래(로그인/비로그인/미가입/기가입/만료·종료), 가입·로그인·소셜을 거치는 내내 초대 토큰이 유지되는지, 역할→기초대→정원 순서 검증, 그리고 보호자 수락 차단이다.

선생님·학생 양쪽의 GA 퍼널도 심는다 — 선생님은 링크 생성·만료·복사를, 학생은 클릭부터 조회·수락까지를 따라간다.

작업 분해 (이슈 링크)

진행·완료 상태는 status와 GitHub 이슈에서 확인한다.