fix(flow): app entry를 no-session 전용으로 단순화

This commit is contained in:
2026-03-16 12:28:28 +09:00
parent 721212ec1f
commit 16d620ee4a
9 changed files with 172 additions and 787 deletions

View File

@@ -175,7 +175,7 @@ review가 가장 유의미한 순간도 바로 여기다.
이 경우:
- `/app` no-session 상태에서는 goal/duration/atmosphere entry stage에 집중
- resume 상태에서는 entry shell 대신 resume card 안의 조용한 secondary entry로 review를 연
- current session이 있으면 `/app` 대신 `/space`로 이동하므로, `/app` review dock은 no-session entry shell에서만 다룬
---

View File

@@ -1,157 +1,65 @@
# 18. Paused Session Re-entry Spec
# 18. Session Routing Spec
Last Updated: 2026-03-15
Last Updated: 2026-03-16
이 문서는 VibeRoom에서 **진행 중인 세션 / 멈춘 세션 / 쉬는 시간**을 어떻게 다르게 취급할지,
그리고 사용자가 `/app`에 들어왔을 때 어떤 경로로 다시 `/space`에 진입해야 하는지를 정의한다.
이 문서는 VibeRoom에서 `/app``/space`의 역할을 어떻게 나눌지 정의한다.
핵심 목적은 하나다.
핵심 원칙은 하나다.
> session state에 따라 `/app`과 `/space`의 역할을 정확히 나누고,
> 사용자가 “지금 내가 어떤 상태인지”를 설명할 수 있는 premium UX를 만든다.
> current session이 있으면 사용자를 `/app`에 세워두지 않고 바로 `/space`로 보낸다.
> current session이 없을 때만 `/app`에서 새 entry를 만든다.
관련 문서:
- `./19_app_atmosphere_entry_spec.md`
- `../space/10_refocus_system_spec.md`
- `../space/11_away_return_recovery_spec.md`
- `../../screens/app/current/19_app_atmosphere_entry_spec.md`
- `../../screens/space/current/13_space_intent_card_collapsed_expanded_spec.md`
- `./15_app_stats_entry_flow_spec.md`
- `../../product/16_product_alignment_audit_plan.md`
- `../../product/17_product_alignment_findings.md`
- `../../product_principles.md`
- `../../current_context.md`
- `../../product/12_core_loop_execution_roadmap.md`
---
## 1. 문제 정의
## 1. 왜 바꾸는가
지금까지의 혼란은 대부분 여기서 시작됐다.
이전 구조는 `/app`
- `세션`
- `타이머`
- `pause`
- `break`
- `return`
- no-session entry shell
- paused resume gate
- takeover decision
- review secondary entry
을 충분히 분리하지 않고 써 왔다.
를 모두 안고 있었다.
그 결과:
문제:
- 사용자는 `타이머가 멈춰 있으면 다 paused인가?`를 헷갈린
- `/app`에서 `resume`이 primary인지, `새로 시작`이 가능한지 흐려진
- `잠시 비우기``break`의 의미가 섞인
- `/app`의 정체성이 흐려진
- 사용자는 `들어가는 화면`인지 `멈춘 세션을 처리하는 화면`인지 헷갈린
- `/space`의 recovery UX와 `/app`의 resume UX가 중복된
이 spec은 그 상태 정의를 먼저 고정한다.
따라서 `/app`은 다시 단순해져야 한다.
---
## 2. 한 줄 정의
> running session은 바로 `/space`로 복귀시키고,
> paused session은 `/app`에서 다시 이어갈지 정하게 하되,
> 사용자가 `이어가기`를 눌렀다면 `/space`에서는 다시 묻지 않고 바로 resume한다.
### `/app`
새 session을 시작하기 위한 atmosphere entry surface
### `/space`
이미 존재하는 session을 계속 다루는 execution surface
---
## 3. 상태 정의
## 3. 라우팅 규칙
### Session
사용자가 현재 책임지고 있는 하나의 focus block.
조건:
- goal이 있다
- 아직 명시적으로 닫지 않았다
- 다시 이어갈 수 있다
### Running Focus
- 현재 focus 타이머가 진행 중
- 사용자는 같은 goal 안에서 작업 중
### Paused Focus
- 사용자가 의도적으로 pause를 눌렀다
- 같은 goal은 아직 살아 있다
- 기본값은 `resume`
### Running Break
- focus block은 끝났다
- break 타이머가 진행 중이다
- 이건 paused session이 아니다
### Return
- 사용자가 pause를 누르지 않고 떠났다가 돌아온 상태
- system이 recovery 선택지를 먼저 제안하는 상태
### Closed Session
- `여기서 마무리하기`로 끝낸 상태
- 더 이상 current session이 아니다
---
## 4. 제품 원칙
### 1. Running은 다시 결정하게 하지 않는다
이미 running이면 사용자의 다음 행동은 “다시 정하기”가 아니라 “복귀”다.
즉:
- `/app`에서 hero를 다시 보여주지 않는다
- 바로 `/space`로 보낸다
### 2. Paused는 자동 재생하지 않는다
pause는 사용자의 명시적 멈춤이다.
즉:
- `/app`에 들어왔다고 자동 resume하지 않는다
- 사용자가 직접 `이어가기`를 눌러야 한다
### 3. Explicit Continue 이후에는 다시 묻지 않는다
사용자가 `/app`에서 `이어가기`를 눌렀다면,
그건 이미 “다시 하겠다”는 결정을 내린 것이다.
즉:
- `/app -> /space -> 다시 start 클릭` 금지
- `/space` 진입과 동시에 resume해야 한다
### 4. `/app`은 decision surface, `/space`는 execution surface
- `/app`: 이어갈지 / 다시 정리할지 / 새 목표로 전환할지
- `/space`: 실제로 일하는 곳
이 둘이 같은 결정을 두 번 요구하면 실패다.
### 5. 새 시작은 current session이 없을 때만 direct
paused session이 있는데 새 목표를 바로 시작하게 하면
회피 루프와 상태 오염이 생긴다.
즉:
- current session이 없을 때만 direct start
- current session이 있을 때 새 start는 explicit takeover flow로만 허용
---
## 5. 라우팅 정책
### Rule A. Running Focus
### Rule A. current session이 있으면 `/space`
상태:
- current session 존재
- `state = running`
- `phase = focus`
- `currentSession` 존재
- `state = running` 또는 `paused`
- `phase = focus` 또는 `break`
처리:
@@ -159,44 +67,10 @@ paused session이 있는데 새 목표를 바로 시작하게 하면
이유:
- 이미 실행 중인 일은 다시 commitment gate에 세우면 안 된
- session이 살아 있는 동안 사용자의 일은 이미 시작된 상태
- `/app`이 끼어들면 execution surface와 decision surface가 섞인다
### Rule B. Running Break
상태:
- current session 존재
- `state = running`
- `phase = break`
처리:
- `/app` 진입 시 즉시 `/space`
이유:
- break도 현재 세션의 일부다
- `/app`에서 다시 decision을 시키면 break/return 의미가 흐려진다
### Rule C. Paused Focus
상태:
- current session 존재
- `state = paused`
- `phase = focus`
처리:
- `/app` 진입
- `resume gate` 노출
이유:
- pause는 사용자의 의도적 멈춤이므로 존중해야 한다
- 하지만 같은 goal을 다시 이어갈지 결정할 여지를 줘야 한다
### Rule D. No Session / Closed Session
### Rule B. current session이 없으면 `/app`
상태:
@@ -204,257 +78,79 @@ paused session이 있는데 새 목표를 바로 시작하게 하면
처리:
- `/app` 진입
- no-session entry shell 노출
- `/app` no-session entry shell 노출
---
## 6. `/app` paused state UX
## 4. `/app`의 역할
### 목적
`/app`은 아래 3가지 결정만 받는다.
사용자가 “멈춘 세션이 아직 살아 있다”는 것을 즉시 이해하고,
한 번의 결정으로 `/space`에 다시 들어가게 만드는 것.
1. goal
2. duration
3. atmosphere
### 정보 구조
포함하지 않음:
resume card 안에는 아래만 둔다.
- 현재 goal
- 마지막 microStep
- 현재 상태 문구
- 예: `잠시 멈춘 세션이 있어요`
- primary CTA
- quiet secondary actions
### Primary CTA
- `이어서 몰입하기`
동작:
- 클릭
- `/space`로 이동
- 자동 resume
### Secondary
- `한 조각 다시 잡기`
- `주간 review 보기`
### Tertiary
- `새 목표로 전환`
중요:
- new start가 아니다
- takeover flow 진입점이다
- server도 current session이 남아 있으면 direct start를 거절해야 한다
- paused resume gate
- takeover sheet
- current session review entry
- running / paused 상태별 CTA
---
## 7. `/space` 재진입 동작
## 5. `/space`의 역할
### Resume CTA 이후
current session이 있는 동안의 모든 판단은 `/space`에서 이뤄진다.
`/app`에서 `이어서 몰입하기`를 눌렀다면:
:
- `/space`로 이동
- 별도의 start 버튼 재요구 금지
- 부드러운 transition 후 자동 resume
- 이어가기
- 잠시 멈춤
- 다시 붙잡기
- 다음 단계 정하기
- 여기서 마무리하기
추천:
- 300~800ms 정도의 soft transition
- 필요하면 아주 짧은 re-entry settle animation
금지:
- `/space`에서 다시 `시작`을 누르게 하는 것
- resume 직후 또 다른 decision tray를 띄우는 것
### Refocus CTA 이후
`한 조각 다시 잡기`를 눌렀다면:
- refocus를 먼저 거친다
- 그 후 `/space` 진입과 함께 자동 resume
즉, refocus는 decision이고, `/space`는 execution이다.
즉 paused session도 `/space` 안에서 다시 다룬다.
---
## 8. Takeover Flow
## 6. Weekly Review entry 규칙
paused session이 있을 때 새 goal direct start는 허용하지 않는다.
### `/app`
대신 아래 흐름으로만 간다.
- current session이 없을 때만 quiet secondary entry로 노출
### Trigger
### `/space`
- `/app` paused state에서 `새 목표로 전환`
- complete 이후 setup 상태에서만 secondary teaser 허용
### Confirm Sheet
질문:
- `현재 멈춘 세션을 어떻게 할까요?`
선택지:
- `이어서 하기`
- `이 세션은 여기서 정리하고 새로 시작`
- `취소`
### 동작 원칙
- `이어서 하기`
- sheet 닫기
- resume card 유지
- `이 세션은 여기서 정리하고 새로 시작`
- current session을 명시적으로 닫는다
- 그 다음 `/app` single-goal start 상태로 전환한다
- `취소`
- sheet 닫기
중요:
- silent abandon 금지
- paused session 위에 새 session을 덮어쓰기 금지
current session이 살아 있는 동안 `/app`에서 review를 여는 flow는 current가 아니다.
---
## 9. Weekly Review와의 관계
## 7. 구현 규칙
paused state에서도 review는 열 수 있어야 한다.
하지만 위계는 아래처럼 고정한다.
### paused state
- primary: `이어서 몰입하기`
- secondary: `한 조각 다시 잡기`
- quiet secondary: `주간 review 보기`
즉:
- review를 숨기면 안 된다
- resume보다 앞세우면 안 된다
1. `/app`은 current session fetch 후 session이 있으면 바로 `/space` redirect
2. `/app` render tree에는 paused gate / takeover sheet를 남기지 않는다
3. `/space`는 paused session이라고 `/app`으로 되돌리지 않는다
4. `/space` recovery는 pause / return / break / complete 안에서 닫는다
---
## 10. 금지사항
## 8. 하지 말아야 할 것
- running session인데 `/app` hero를 보여주는 것
- paused 상태에서 `/app` 진입만으로 자동 resume
- `/app`에서 `이어가기`를 눌렀는데 `/space`에서 다시 start를 요구하는 것
- paused session 위에서 direct new start 허용
- break를 paused session처럼 취급하는 것
- takeover 없이 silent abandon 하는 것
- paused session `/app`에 남기기
- `/app -> /space -> 다시 resume/start` 이중 결정
- `/app`에서 current session goal을 편집하기
- current session이 있는데 `/app`에서 새 entry를 겹쳐 띄우기
---
## 11. 구현 순서
## 9. QA 포인트
### Slice 1. Session Routing Contract
범위:
- `/app` 진입 시 current session state에 따른 route policy 고정
포함:
- `running focus -> /space`
- `running break -> /space`
- `paused focus -> /app`
- `no session -> /app`
완료 조건:
- 상태별 route policy가 코드와 문서에서 동일하다
### Slice 2. `/app` Paused Resume Gate
범위:
- paused state의 resume card UX 정리
포함:
- primary `이어서 몰입하기`
- `한 조각 다시 잡기`
- quiet `주간 review 보기`
- state copy 정리
완료 조건:
- paused 사용자가 다음 행동을 2초 안에 이해할 수 있다
### Slice 3. `/space` Auto-Resume Handoff
범위:
- `/app` resume CTA 이후 `/space` 진입 시 자동 resume
포함:
- explicit continue 이후 double-confirm 제거
- transition quality 보정
완료 조건:
- `/app -> /space -> start` 이중 클릭이 사라진다
### Slice 4. Takeover Flow
범위:
- paused session 위에서 new start를 하고 싶을 때의 명시적 처리
포함:
- confirm sheet
- close-and-start-new 경로
- silent abandon 방지
완료 조건:
- paused session 상태에서 새 목표 전환이 상태 오염 없이 가능하다
### Slice 5. Browser QA
반드시 확인할 시나리오:
1. running focus 상태에서 `/app` 진입
2. running break 상태에서 `/app` 진입
3. paused focus 상태에서 `/app` 진입
4. paused -> `이어서 몰입하기`
5. paused -> `한 조각 다시 잡기`
6. paused -> `주간 review`
7. paused -> `새 목표로 전환`
---
## 12. 성공 기준
- 사용자가 현재 상태를 설명할 수 있다
- running이면 `/space`, paused면 `/app`이라는 규칙이 일관된다
- paused에서의 primary CTA는 항상 `resume`이다
- explicit continue 이후에는 다시 start를 요구하지 않는다
- new start는 current session이 없을 때만 direct다
---
## 13. 최종 판단
VibeRoom이 world-class가 되려면
`멈춤`, `쉬기`, `복귀`, `새 시작`을 같은 것으로 취급하면 안 된다.
가장 중요한 원칙은 이거다.
> 이미 실행 중인 것은 바로 복귀시키고,
> 의도적으로 멈춘 것은 다시 결정하게 하되,
> 다시 하겠다고 결정한 뒤에는 한 번 더 묻지 않는다.
1. current session 없음 -> `/app` entry shell
2. current session running -> `/app` 진입 즉시 `/space`
3. current session paused -> `/app` 진입 즉시 `/space`
4. `/space`에서 pause 후 화면이 `/app`으로 튀지 않음
5. `/space` complete 후 no-session이 되면 다시 `/app` entry shell 접근 가능