-
Notifications
You must be signed in to change notification settings - Fork 0
03 Screen Flow
이현민 edited this page Jun 15, 2026
·
3 revisions
[모바일/웹] /login
└─ "SNU 구글로 계속하기" 클릭
↓
[Google] OAuth (hd=snu.ac.kr 강제)
↓
[서버] User 레코드 생성 (approved=false)
↓
[모바일/웹] /pending
└─ "관리자 승인 대기 중" 안내
(단톡방에 운영진에게 알리라는 가이드)
↓
[관리자] /admin/members 에서 [승인] 클릭
↓
[부원] 다음 진입 시 정상 사용
[모바일] /sessions/new
├─ 날짜·장소·시작 시간 (오늘 default)
├─ 날씨(자유 텍스트)
├─ 단체사진 1장 업로드 (생성 후 상세 페이지에서 선택)
├─ 코스/메모
└─ [세션 생성]
↓
[모바일] /sessions/[id] ← 자동 리다이렉트
└─ 단톡방에 이 URL 공유 (카톡 OG 미리보기 = 단체사진)
목표 소요: 60~90초.
[모바일] 단톡방 링크 클릭 → /sessions/[id]
└─ 로그인되어 있다면 페이지 진입
↓
[모바일] "내 기록 추가" 버튼
├─ 거리(km) — optional
├─ 기록(분:초) — optional
├─ 노트 — optional
└─ [저장]
↓
[모바일] 본인 행이 참여자 표에 즉시 표시
목표 소요: ≤ 30초.
[웹] /admin/members
└─ 승인 대기 N명 리스트
└─ 각자 [승인] / [거절]
└─ 승인 시 approvedBy / approvedAt 기록
| 경로 | 인증/권한 | 설명 |
|---|---|---|
/login |
비로그인 | Google OAuth 시작 |
/pending |
로그인 + approved=false
|
승인 대기 안내 |
/sessions |
승인된 멤버 | 아카이브 리스트 (최신순 카드) |
/sessions/new |
승인된 멤버 | 세션 생성 — 누구나 호스트 가능 |
/sessions/[id] |
승인된 멤버 | 세션 상세 + 본인 기록 추가/수정 |
/sessions/[id]/edit |
호스트 본인 또는 ADMIN | 세션 본문 수정/삭제 |
/sessions/[id]/opengraph-image |
비로그인 OK (OG 크롤러용) | 단체사진 기반 OG 이미지 |
/me |
본인 | 내 참여 기록 모음, (Week 3) 누적 통계 |
/runners/[id] |
승인된 멤버 | 다른 멤버의 통계 (Week 3) |
/admin/members |
ADMIN | 가입 승인 |
┌─ Header (날짜 · 장소 · 날씨 · 호스트) ────────────┐
│ 2026-05-31 (일) · 서울숲 · ☀️ 22°C │
│ 호스트: 김러너 │
├─────────────────────────────────────────────────┤
│ [단체사진 — full width, aspect 16:9] │
├─────────────────────────────────────────────────┤
│ 참여자 8명 · 총 거리 42.0 km │
├─────────────────────────────────────────────────┤
│ 이름 거리 기록 페이스 [수정] │
│ 김러너 5.0 25:00 5'00" ✏️ (본인) │
│ 박러너 7.0 35:00 5'00" │
│ ... │
│ │
│ [+ 내 기록 추가] ← 본인 행 없을 때만 표시 │
├─────────────────────────────────────────────────┤
│ 코스 메모 (호스트 작성) │
└─────────────────────────────────────────────────┘
권한 표시:
- 호스트/ADMIN이면 헤더에 "세션 수정" 버튼
- 본인 행에만 (나) 표시
- 다른 사람 행은 읽기 전용 (ADMIN 수정은 보류)
- 1페이지 폼 (스텝 UI 안 씀)
- 사진 업로드는 선택. 없어도 생성 가능
- 저장 후 자동
/sessions/[id]리다이렉트
┌─ 승인 대기 (3) ─────────────────────────────────┐
│ 이현민 (peterabcd@snu.ac.kr) 가입 2026-05-31 │
│ [승인] [거절] │
│ ... │
├─ 활동 회원 (12) ─────────────────────────────────┤
│ ... (검색 + 권한 변경) │
└─────────────────────────────────────────────────┘
generator client { provider = "prisma-client-js" }
datasource db { provider = "sqlite"; url = env("DATABASE_URL") }
model User {
id String @id @default(cuid())
name String
email String @unique
emailVerified DateTime?
image String?
approved Boolean @default(false)
approvedById String?
approvedAt DateTime?
approvedBy User? @relation("Approver", fields: [approvedById], references: [id])
approves User[] @relation("Approver")
role String @default("MEMBER") // "MEMBER" | "ADMIN"
joinedAt DateTime @default(now())
accounts Account[]
hostedSessions Session[] @relation("Host")
participations Participation[]
}
model Account {
id String @id @default(cuid())
userId String
type String
provider String
providerAccountId String
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
@@unique([provider, providerAccountId])
}
model Session {
id Int @id @default(autoincrement())
date DateTime
startTime String?
location String
weather String?
groupPhotoPath String?
notes String?
hostId String
host User @relation("Host", fields: [hostId], references: [id])
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
participations Participation[]
@@index([date])
@@index([hostId])
}
model Participation {
id String @id @default(cuid())
sessionId Int
userId String
distanceKm Float?
durationSec Int?
note String?
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
session Session @relation(fields: [sessionId], references: [id], onDelete: Cascade)
user User @relation(fields: [userId], references: [id])
@@unique([sessionId, userId])
@@index([userId])
}-
approved=false인 User도 레코드는 생성. OAuth 직후 승인 대기 상태가 명확. -
role은 별도: ADMIN은 가입 정책과 무관하게 운영 권한. 화이트리스트 승인 ≠ 운영자 승격. -
hostId로 호스트 표현 (role이 아님). 호스트는 "그 세션에 한정된 작성자" 권한이라 User.role과 분리. -
페이스는 저장 안 함.
distanceKm + durationSec둘 다 있으면 derived. 데이터 일관성 우선. -
(sessionId, userId)unique. 본인은 같은 세션에 행 1개만. -
사진은 파일 경로만. 원본 파일은 호스트 볼륨에 저장.
next/image가 서빙 시 webp 캐시.
| 동작 | 본인 | 호스트 | ADMIN |
|---|---|---|---|
| 세션 생성 | ✅ (자동으로 호스트가 됨) | — | ✅ |
| 세션 본문 수정 | ❌ | ✅ | ✅ |
| 세션 삭제 | ❌ | ✅ | ✅ |
| 본인 참여 행 추가/수정/삭제 | ✅ | (본인 행이면) ✅ | ✅ |
| 다른 사람 참여 행 수정 | ❌ | ❌ | 보류 |
| 멤버 승인/거절 | ❌ | ❌ | ✅ |
이 표가 Server Action 권한 체크의 진실의 원천. SKILL.md에서 참조.
-
/sessions/[id]단톡방 공유 →opengraph-image.tsx가 단체사진 + 날짜·장소 합성. - OG 이미지 라우트는 비로그인 fetch 허용 (크롤러용). 단 이미지에 개인 식별 정보 노출 X (이름 X, 페이스 X).
- 모든 입력 ≥ 44px 터치 타깃
- 페이스는 색상 의존 X, 텍스트 명시
- 다크모드는 후속 TODO
- 사진 alt 텍스트: "{date} {location} 단체사진"