Skip to content

feat(frontend): Phase 6 프론트 기초(PWA) — 디자인·라우팅·인증#6

Open
ca5tlechan wants to merge 4 commits into
mainfrom
feat/phase-6-frontend
Open

feat(frontend): Phase 6 프론트 기초(PWA) — 디자인·라우팅·인증#6
ca5tlechan wants to merge 4 commits into
mainfrom
feat/phase-6-frontend

Conversation

@ca5tlechan

@ca5tlechan ca5tlechan commented Jul 16, 2026

Copy link
Copy Markdown
Owner

Phase 6 — 프론트 기초 (PWA)

CLAUDE.md §7 Phase 6. React + Vite + TS PWA의 뼈대: 디자인 시스템 · 라우팅 · 인증 · 앱 셸. 화면 시안(스터디카페 챌린지 네이비+골드)을 승인받아 그대로 구현했다.

변경

  • 디자인 시스템 (index.css): 챌린지 브랜드 토큰(네이비 주색 + 골드 포인트), 라이트/다크, 공통 컴포넌트(버튼·입력·카드·pill·모바일 셸·하단 탭). 시간 숫자 tabular.
  • 라우팅 (react-router-dom): /login·/signup(공개) + 인증 보호된 앱 셸(/ 홈, /my, /ranking, /school). 미인증 시 /login 리다이렉트.
  • 인증
    • lib/api.ts — fetch 클라이언트(/api 프록시), JWT localStorage 저장·헤더 첨부, ApiError, 타입.
    • lib/auth.tsxAuthProvider(가입→자동로그인, 앱 시작 시 /users/me로 토큰 검증, 만료 토큰 정리), useAuth.
    • ProtectedRoute.
  • 화면
    • 로그인 / 회원가입(학교 select = 무소속 + 목록, 필드 에러 표시, 마스킹 안내).
    • 홈(인사 + 현재 세션 상태 GET /api/sessions/current + 로그아웃).
    • 마이/랭킹/우리학교 = 자리표시(Phase 8~9에서 채움).
  • PWA/메타: manifest(기존) + theme-color(라이트/다크), lang="ko", viewport-fit.

실행 검증 (백엔드 + vite dev, 브라우저)

초기 진입 → /login 리다이렉트 / 회원가입(학교 목록 API 로드) → 가입→자동로그인→홈 / 홈에서 사용자·세션 상태 표시 / 탭 라우팅 + 활성 상태(네이비). 프론트 npm run build 그린(tsc + vite + PWA).

범위 밖(다음)

Phase 7 체크인(html5-qrcode + 데스크톱 수동 토큰), Phase 8 마이페이지 차트, Phase 9 랭킹/우리학교 실제 데이터. (자리표시 3개 페이지가 그 자리.)

Summary by CodeRabbit

  • 새 기능
    • 로그인/회원가입 화면과 인증 상태 기반 보호 라우팅을 추가해 홈/랭킹/우리 학교/마이페이지를 구성했습니다.
    • 앱 전반에 하단 탭 내비게이션과 공용 화면 레이아웃을 적용했습니다.
    • 홈은 현재 세션(공부 중/대기 중)을 표시하고, 로딩·실패 시 재시도 흐름을 제공합니다.
  • 스타일
    • 모바일 중심 디자인 시스템으로 전역 스타일과 라이트/다크 테마(색상 토큰, 메타 정보)를 갱신했습니다.

- 디자인 시스템(index.css): 챌린지 네이비+골드 토큰, 라이트/다크, 공통 컴포넌트
- 라우팅(react-router): /login·/signup + 인증 보호된 앱 셸(홈/마이/랭킹/우리학교), 미인증 리다이렉트
- 인증: fetch 클라이언트(JWT localStorage 저장·첨부), AuthProvider(가입→자동로그인, /me 토큰검증), ProtectedRoute
- 로그인/회원가입(학교 선택·필드검증), 홈(현재 세션 상태), 나머지 탭 자리표시
- PWA theme-color, lang=ko/title

브라우저 검증: 가입→자동로그인→홈, 탭 라우팅·활성 상태, 학교목록 API 연동.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@coderabbitai

coderabbitai Bot commented Jul 16, 2026

Copy link
Copy Markdown

Review Change Stack

📝 Walkthrough

Walkthrough

기존 단일 React 화면을 React Router 기반 구조로 교체하고, API·토큰·인증 컨텍스트와 보호 라우트를 추가했다. 로그인·회원가입·세션·보류 페이지 및 모바일 앱 셸과 디자인 시스템을 구현했다.

Changes

스터디카페 앱 전환

Layer / File(s) Summary
API 계약과 인증 상태
frontend/src/lib/api.ts, frontend/src/lib/auth.tsx, frontend/src/lib/authErrors.ts
API 타입, Bearer 토큰 저장, HTTP 오류 처리, 인증 초기화·로그인·회원가입·로그아웃과 자동 로그인 실패 처리를 추가했다.
라우팅과 보호된 앱 셸
frontend/src/main.tsx, frontend/src/components/AppLayout.tsx, frontend/src/components/ProtectedRoute.tsx, frontend/package.json
공개·보호 경로, 인증 상태별 라우트 분기, Outlet 기반 앱 셸과 하단 탭 네비게이션을 구성했다.
로그인과 회원가입 화면
frontend/src/pages/LoginPage.tsx, frontend/src/pages/SignupPage.tsx
로그인·회원가입 입력, 학교 목록 조회, 서버 필드 오류, 재시도와 요청 상태 처리를 구현했다.
홈 세션 화면과 보류 페이지
frontend/src/pages/HomePage.tsx, frontend/src/components/Placeholder.tsx, frontend/src/pages/MyPage.tsx, frontend/src/pages/RankingPage.tsx, frontend/src/pages/SchoolPage.tsx
현재 세션에 따른 공부 중·대기 중 화면과 마이페이지·랭킹·학교 안내 화면을 추가했다.
모바일 앱 디자인 시스템
frontend/src/index.css, frontend/index.html
모바일 셸, 테마 토큰, 카드·버튼·폼·인증·상태 UI 스타일과 한국어 문서 메타데이터를 추가했다.

Estimated code review effort: 4 (Complex) | ~60 minutes

Sequence Diagram(s)

sequenceDiagram
  participant Browser
  participant RouterProvider
  participant ProtectedRoute
  participant AuthProvider
  participant API
  participant HomePage

  Browser->>RouterProvider: "/" 요청
  RouterProvider->>ProtectedRoute: 인증 라우트 실행
  ProtectedRoute->>AuthProvider: 인증 상태 확인
  AuthProvider->>API: GET /api/auth/me
  API-->>AuthProvider: 사용자 또는 오류
  AuthProvider-->>ProtectedRoute: ready와 user
  ProtectedRoute->>HomePage: 인증된 홈 렌더링
  HomePage->>API: GET /api/sessions/current
  API-->>HomePage: 현재 세션
  HomePage-->>Browser: 공부 중 또는 대기 중 카드 표시
Loading
🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 8.33% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed 프론트 기초 작업의 핵심인 디자인 시스템, 라우팅, 인증을 잘 요약한 제목입니다.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/phase-6-frontend

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 7

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@frontend/src/index.css`:
- Line 18: 다크 테마의 --primary 색상 대비가 부족하므로 frontend/src/index.css의 다크 테마 토큰에서
--primary를 더 어두운 배경색으로 조정하고, 기본 버튼과 로고 텍스트에 사용되는 전경색 토큰(--primary-ink 등)이 흰색 또는
충분히 대비되는 값이 되도록 업데이트하세요. 동일한 토큰 정의가 있는 81행과 109-112행도 일관되게 수정하세요.
- Line 11: Update every color-scheme declaration in index.css, including the
occurrences near the top, line 28, and line 131, to remove or replace the
unsupported light dark value so all reported Stylelint violations are resolved
while preserving the intended theme behavior.

In `@frontend/src/lib/api.ts`:
- Around line 72-75: 중앙 API 오류 처리와 인증 상태 관리를 일관되게 조정하세요. frontend/src/lib/api.ts
72-75의 응답 처리에서 401/403을 인증 만료 신호로 전달해 토큰과 사용자 상태가 함께 초기화되도록 하고,
frontend/src/lib/auth.tsx 23-27의 인증 검증 로직은 401/403일 때만 인증을 해제하며 네트워크 오류와 5xx 응답은
재시도 가능한 상태로 유지하세요.
- Around line 45-50: Replace the localStorage-based token handling in getToken
and setToken with an HttpOnly, Secure, SameSite cookie issued and managed by the
server, removing client-side token reads and writes. Update the authentication
flow to rely on the server cookie and add the required CSRF protection for
state-changing requests.

In `@frontend/src/lib/auth.tsx`:
- Around line 36-39: Update signup in the auth flow to distinguish successful
account creation from subsequent automatic-login failure. Preserve the
successful signup result and handle login failure separately by guiding the user
to the login flow, or use an API contract that atomically performs signup and
token issuance; do not propagate the login error as a signup failure that
triggers retry.

In `@frontend/src/pages/HomePage.tsx`:
- Around line 14-16: Update the HomePage session-loading flow around
sessionApi.current() to track API failures in a separate error state instead of
swallowing them as a null session. Render a distinct error and retry UI for
request failures, keep the no-active-session message only for successful
responses with no session, and handle authentication errors consistently with
the existing authentication state.

In `@frontend/src/pages/SignupPage.tsx`:
- Around line 22-24: Update the school-loading flow in the SignupPage useEffect
so authApi.schools() failures are surfaced to the user instead of being silently
ignored. Add visible error guidance with a retry action, or prevent signup
submission until the school lookup completes successfully; preserve the existing
school list population on successful requests.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: ba5bee0c-541c-4fa3-ac75-950e75a10b5b

📥 Commits

Reviewing files that changed from the base of the PR and between cfa51c3 and 3206cc2.

⛔ Files ignored due to path filters (2)
  • frontend/package-lock.json is excluded by !**/package-lock.json
  • frontend/src/assets/react.svg is excluded by !**/*.svg
📒 Files selected for processing (17)
  • frontend/index.html
  • frontend/package.json
  • frontend/src/App.css
  • frontend/src/App.tsx
  • frontend/src/components/AppLayout.tsx
  • frontend/src/components/Placeholder.tsx
  • frontend/src/components/ProtectedRoute.tsx
  • frontend/src/index.css
  • frontend/src/lib/api.ts
  • frontend/src/lib/auth.tsx
  • frontend/src/main.tsx
  • frontend/src/pages/HomePage.tsx
  • frontend/src/pages/LoginPage.tsx
  • frontend/src/pages/MyPage.tsx
  • frontend/src/pages/RankingPage.tsx
  • frontend/src/pages/SchoolPage.tsx
  • frontend/src/pages/SignupPage.tsx
💤 Files with no reviewable changes (2)
  • frontend/src/App.css
  • frontend/src/App.tsx

Comment thread frontend/src/index.css
--active:#1f9d63; --danger:#c8402f;
--shadow:0 1px 2px rgba(16,28,54,.05), 0 8px 24px -12px rgba(16,28,54,.2);
--radius:20px; --radius-sm:14px;
color-scheme: light dark;

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win

보고된 Stylelint 오류를 수정해 주세요.

현재 세 규칙 위반으로 스타일 검사가 실패합니다.

제안 수정
   --radius:20px; --radius-sm:14px;
+
   color-scheme: light dark;

-  font-family: -apple-system, "Apple SD Gothic Neo", "Pretendard", system-ui, "Segoe UI", Roboto, sans-serif;
+  font-family: -apple-system, "Apple SD Gothic Neo", Pretendard, system-ui, "Segoe UI", Roboto, sans-serif;

-.dot { width: 7px; height: 7px; border-radius: 50%; background: currentColor; }
+.dot { width: 7px; height: 7px; border-radius: 50%; background: currentcolor; }

Also applies to: 28-28, 131-131

🧰 Tools
🪛 Stylelint (17.14.0)

[error] 11-11: Expected empty line before declaration (declaration-empty-line-before)

(declaration-empty-line-before)

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@frontend/src/index.css` at line 11, Update every color-scheme declaration in
index.css, including the occurrences near the top, line 28, and line 131, to
remove or replace the unsupported light dark value so all reported Stylelint
violations are resolved while preserving the intended theme behavior.

Source: Linters/SAST tools

Comment thread frontend/src/index.css
Comment thread frontend/src/lib/api.ts
Comment on lines +45 to +50
const TOKEN_KEY = 'scr.token';
export const getToken = (): string | null => localStorage.getItem(TOKEN_KEY);
export const setToken = (token: string | null): void => {
if (token) localStorage.setItem(TOKEN_KEY, token);
else localStorage.removeItem(TOKEN_KEY);
};

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔒 Security & Privacy | 🟠 Major | 🏗️ Heavy lift

JWT를 localStorage에 저장하지 마세요.

페이지에서 실행되는 스크립트가 토큰을 읽을 수 있어 XSS 발생 시 계정 탈취로 이어집니다. 가능하면 서버가 발급하는 HttpOnly; Secure; SameSite 쿠키로 전환하고 필요한 CSRF 방어를 적용해 주세요.

As per path instructions, "토큰 저장 방식(XSS 노출 위험)"을 확인해야 합니다.

🧰 Tools
🪛 ast-grep (0.44.1)

[warning] 47-47: Do not store sensitive data (credentials, tokens, PII) in localStorage or sessionStorage; it is readable by any script and persists on the device.
Context: localStorage.setItem(TOKEN_KEY, token)
Note: [CWE-312] Cleartext Storage of Sensitive Information.

(local-storage-sensitive-data-typescript)

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@frontend/src/lib/api.ts` around lines 45 - 50, Replace the localStorage-based
token handling in getToken and setToken with an HttpOnly, Secure, SameSite
cookie issued and managed by the server, removing client-side token reads and
writes. Update the authentication flow to rely on the server cookie and add the
required CSRF protection for state-changing requests.

Sources: Path instructions, Linters/SAST tools

Comment thread frontend/src/lib/api.ts
Comment thread frontend/src/lib/auth.tsx
Comment thread frontend/src/pages/HomePage.tsx Outdated
Comment thread frontend/src/pages/SignupPage.tsx Outdated
- 다크모드 대비: --on-primary 토큰 추가. 밝은 파랑(#5a90e6) 위 흰색은 3.2:1로
  WCAG AA 미달이라 어두운 전경색(#0d1422, 5.7:1)을 쓴다. .btn / .auth .logo 적용
- 인증 만료 중앙 처리: api.ts에 setUnauthorizedHandler 추가. 토큰을 실어 보낸
  요청이 401/403이면 토큰을 지우고 AuthProvider가 user를 비운다.
  (로그인 실패의 401은 토큰 없이 보낸 요청이라 해당 없음)
- 가입 성공 ≠ 자동 로그인 실패 구분: AutoLoginFailedError를 별도 모듈로 분리.
  계정이 이미 만들어졌으므로 재가입이 아니라 로그인으로 안내하고 제출을 막는다
- 부팅 실패 구분: 네트워크/5xx는 토큰을 유지한 채 loadError + 다시 시도,
  401/403만 로그아웃 처리. ProtectedRoute가 로그인으로 튕기지 않는다
- 홈/회원가입 에러 노출: 실패를 '기록 없음'·'무소속 가입'으로 조용히 삼키지 않고
  안내 + 다시 시도 제공
- .dot 색을 currentcolor로 바꿔 pill 색과 항상 일치시킴

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@frontend/src/lib/api.ts`:
- Around line 82-85: Guard the 401/403 handling in api.ts by applying
setToken(null) and unauthorizedHandler only when getToken() still equals the
request’s token. In auth.tsx, manage bootstrap request generations or an
AbortController, apply setUser, setLoadError, and setReady only for the latest
bootstrap, and invalidate in-flight bootstrap work whenever login or logout
starts.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: 000a0e51-bcba-49fc-826a-5448db7018da

📥 Commits

Reviewing files that changed from the base of the PR and between 3206cc2 and d13403b.

📒 Files selected for processing (7)
  • frontend/src/components/ProtectedRoute.tsx
  • frontend/src/index.css
  • frontend/src/lib/api.ts
  • frontend/src/lib/auth.tsx
  • frontend/src/lib/authErrors.ts
  • frontend/src/pages/HomePage.tsx
  • frontend/src/pages/SignupPage.tsx

Comment thread frontend/src/lib/api.ts Outdated
@ca5tlechan

Copy link
Copy Markdown
Owner Author

리뷰 반영했습니다. (커밋 d13403b)

반영

  1. 다크모드 대비 (a11y)--on-primary 토큰 도입. 다크 --primary(#5a90e6) 위 흰색은 3.2:1로 AA 미달이라 어두운 전경색(#0d1422, 5.7:1)으로 교체. .btn, .auth .brand .logo에 적용. 브라우저 computed style로 확인 완료.
  2. 401/403 중앙 처리api.tssetUnauthorizedHandler. 토큰을 실어 보낸 요청이 401/403일 때만 토큰 삭제 + user 초기화. 로그인 실패의 401은 토큰 없이 보낸 요청이라 무관.
  3. 가입 성공 ≠ 자동 로그인 실패AutoLoginFailedError(별도 모듈)로 구분. 계정은 이미 생성됐으므로 재가입 유도 대신 로그인 안내 + 제출 버튼 비활성화(중복 409 방지).
  4. 부팅 실패 구분 — 네트워크/5xx는 토큰 유지 + loadError + 다시 시도, 401/403만 로그아웃. ProtectedRoute가 유효한 토큰을 가진 사용자를 로그인 화면으로 튕기지 않음.
  5. 에러 은폐 제거 — 홈의 catch → 기록 없음, 회원가입의 catch → 조용히 무소속을 각각 안내 + 다시 시도로 교체. 학교 목록 실패/복구 경로는 fetch를 실패시켜 실제로 태워 확인.
  6. .dot currentcolor 적용.

보류 (근거)

  • localStorage JWT → HttpOnly 쿠키: 스펙 §2에서 JWT Bearer 인증으로 확정된 사안이고, 배포 시 프론트/백엔드 오리진이 분리돼 SameSite·CSRF 토큰까지 함께 설계해야 합니다. Phase 6(프론트 기초) 범위를 넘고 백엔드 인증 필터 변경을 수반하므로, 배포 단계(Phase 12)에서 오리진 구성이 확정된 뒤 함께 다루는 편이 안전하다고 판단했습니다.
  • color-scheme: light dark / -apple-system font-family: 둘 다 표준 CSS이며 의도된 설정입니다.

린트·타입체크·빌드 통과, 가입→자동 로그인→홈 해피패스 브라우저 검증 완료.

만료 토큰이 남은 채 /login 에 들어오면 부트스트랩의 me() 가 백그라운드로 떠 있는데,
그 401이 도착하기 전에 로그인에 성공하면 뒤늦은 401이 방금 발급받은 토큰을 지우고
로그아웃시켰다. (재현 확인: 로그인 직후 user=null, token=null)

- api.ts: 보낸 토큰이 아직 현재 토큰일 때만(getToken() === token) 토큰을 정리하고
  unauthorizedHandler 를 호출한다. 경쟁이 없는 정상 만료 처리는 그대로 동작
- auth.tsx: 부트스트랩에 세대(generation) 번호를 둬, 늦게 도착한 검증 결과가
  setUser/setLoadError/setReady 를 덮어쓰지 못하게 한다. 로그인·로그아웃·만료 처리는
  세대를 올려 진행 중인 검증을 무효화하고 ready 를 직접 확정한다
  (retry 연타로 부트스트랩이 겹쳐도 마지막 것만 반영됨)
- 401/403 시 토큰 정리 주체를 api 계층 하나로 통일 (bootstrap 의 중복 setToken 제거)

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@ca5tlechan

Copy link
Copy Markdown
Owner Author

지적하신 경쟁 조건 반영했습니다. (커밋 d2dfcb9) — 타당한 지적이었고, 실제로 재현됐습니다.

재현 시나리오: 만료 토큰이 남은 채 /login 진입 → 부트스트랩의 me() 가 백그라운드로 떠 있음 → 그 401이 도착하기 전에 로그인 성공 → 뒤늦게 온 401이 방금 발급받은 토큰을 지우고 로그아웃.

수정 전 코드로 재현 (401 응답 600ms 지연, 그 사이 로그인 성공):

userAfterLogin: "경쟁", tokenAfterLogin: "T2"
userAfterStale401: null, tokenAfterStale401: null   ← 로그인 직후 튕김

수정 후 같은 시나리오:

userAfterStale401: "경쟁", tokenAfterStale401: "T2", ready: true

수정 내용

  1. api.ts — 보낸 토큰이 아직 현재 토큰일 때만(getToken() === token) 토큰 정리 + unauthorizedHandler 호출. 경쟁이 없는 정상 만료는 그대로 동작하는 것도 확인했습니다:
    • 경쟁 시: token='T2' 유지, 핸들러 호출 0회
    • 정상 만료: token=null, 핸들러 호출 1회
  2. auth.tsx — 부트스트랩에 세대(generation) 번호 도입. 늦게 도착한 검증 결과는 setUser/setLoadError/setReady 를 건드리지 못합니다. 로그인·로그아웃·만료 처리는 세대를 올려 진행 중인 검증을 무효화하고 ready 를 직접 확정합니다(무효화로 ready 가 영영 false 로 남는 일 방지). retry 연타로 부트스트랩이 겹쳐도 마지막 것만 반영됩니다.
  3. 401/403 시 토큰 정리 주체를 api 계층 하나로 통일했습니다(부트스트랩의 중복 setToken(null) 제거).

AbortController 대신 세대 번호를 쓴 이유: fetch 취소가 목적이 아니라 늦게 온 결과를 무시하는 것이 목적이고, 응답이 이미 도착한 뒤의 상태 반영까지 막아야 하기 때문입니다.

린트·타입체크·빌드 통과. 로그인→홈, 새로고침 세션 유지, 로그아웃 해피패스도 브라우저에서 재확인했습니다.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@frontend/src/lib/auth.tsx`:
- Around line 69-73: 인증 만료 처리의 setUnauthorizedHandler에서 사용자와 준비 상태를 갱신할 때 이전
부트스트랩 오류도 함께 초기화하세요. 해당 콜백에 loadError를 null로 재설정하는 상태 업데이트를 추가해 401/403 이후 로그인
화면에 이전 오류가 남지 않도록 하세요.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: 34a6938a-6881-4798-aeeb-01d2729d944b

📥 Commits

Reviewing files that changed from the base of the PR and between d13403b and d2dfcb9.

📒 Files selected for processing (2)
  • frontend/src/lib/api.ts
  • frontend/src/lib/auth.tsx

Comment thread frontend/src/lib/auth.tsx
Comment on lines +69 to +73
setUnauthorizedHandler(() => {
invalidateBootstrap();
setUser(null);
setReady(true);
});

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

인증 만료 시 loadError도 초기화하세요.

재시도 가능한 부트스트랩 오류가 남아 있던 중 401/403이 발생하면, 사용자와 준비 상태만 갱신되어 이전 오류 안내가 로그인 상태에도 남습니다.

수정 예시
 setUnauthorizedHandler(() => {
   invalidateBootstrap();
   setUser(null);
+  setLoadError(false);
   setReady(true);
 });

As per path instructions, “API 에러 처리, 상태관리 일관성, 타입 안전성을 확인한다.”

📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
setUnauthorizedHandler(() => {
invalidateBootstrap();
setUser(null);
setReady(true);
});
setUnauthorizedHandler(() => {
invalidateBootstrap();
setUser(null);
setLoadError(false);
setReady(true);
});
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@frontend/src/lib/auth.tsx` around lines 69 - 73, 인증 만료 처리의
setUnauthorizedHandler에서 사용자와 준비 상태를 갱신할 때 이전 부트스트랩 오류도 함께 초기화하세요. 해당 콜백에
loadError를 null로 재설정하는 상태 업데이트를 추가해 401/403 이후 로그인 화면에 이전 오류가 남지 않도록 하세요.

Source: Path instructions

재시도를 연달아 눌러 먼저 뜬 검증이 5xx로 loadError를 남긴 뒤 다른 검증이 401로
돌아오면, 토큰은 정리됐는데도 ProtectedRoute가 loadError를 먼저 보고 로그인 대신
'연결 문제' 화면에 머물렀다. (재현 확인: 401 도착 후에도 loadError=true)

만료는 확정된 상태이므로 unauthorizedHandler에서 loadError도 해제한다.
login/logout이 이미 하던 것과 동일한 처리다.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
frontend/src/lib/auth.tsx (1)

80-87: 🔒 Security & Privacy | 🟠 Major | 🏗️ Heavy lift

JWT를 localStorage에 저장하지 마세요. frontend/src/lib/auth.tsx:83setToken(res.token)frontend/src/lib/api.ts:45-49를 통해 Bearer 토큰을 localStorage에 남깁니다. XSS가 한 번만 나도 세션 탈취로 이어지므로, HttpOnly·Secure·SameSite 쿠키 또는 BFF 방식으로 바꿔야 합니다.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@frontend/src/lib/auth.tsx` around lines 80 - 87, Update the login flow in
login so res.token is no longer persisted through setToken or localStorage;
migrate authentication to an HttpOnly, Secure, SameSite cookie or BFF-backed
session, and update the related authApi/API handling to use that session while
preserving user and readiness state updates.

Source: Path instructions

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Outside diff comments:
In `@frontend/src/lib/auth.tsx`:
- Around line 80-87: Update the login flow in login so res.token is no longer
persisted through setToken or localStorage; migrate authentication to an
HttpOnly, Secure, SameSite cookie or BFF-backed session, and update the related
authApi/API handling to use that session while preserving user and readiness
state updates.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: 028a4d79-8ebd-4cbd-b901-fcc2c51ff516

📥 Commits

Reviewing files that changed from the base of the PR and between d2dfcb9 and 56b5306.

📒 Files selected for processing (1)
  • frontend/src/lib/auth.tsx

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant