Skip to content

[FE] [FIX] auth state prob, login page - #226

Merged
discipline24 merged 2 commits into
mainfrom
20260212-FE-#217#218-About-Login-Fucntion
Feb 12, 2026
Merged

discipline24 merged 2 commits into
mainfrom
20260212-FE-#217#218-About-Login-Fucntion

Conversation

@yyunee

@yyunee yyunee commented Feb 12, 2026 •

Copy link
Copy Markdown
Contributor

1) #217 #218

2) 변경 요약 (What & Why)

로그인페이지

  • 이메일 --> 학번 로그인으로 변경
  • 이메일 찾기 기능 삭제
  • 비밀번호 찾기 --> 비밀번호 초기화로 변경
  • 소셜 로그인 기능 주석처리
  • 로그인/로그아웃 관련 라우터 구조를 정리
  • 인증 흐름에 맞게 접근 제어
    ---> 인증 상태에 따른 라우팅이 명확하지 않아 발생한 로그아웃 관련 이슈 해결
    (원인 자체는 sidebar, header, page들 제각각 라우팅을 하는데서 발생)

3) 스크린샷/동영상 (UI 변경 시)

화면 캡처 2026-02-12 204134 화면 캡처 2026-02-12 204219

4) 상세 변경사항 (전부 다)

라우팅/페이지:

  • 로그인/로그아웃 관련 라우터 접근 조건 정리
  • 비밀번호 찾기 → 비밀번호 초기화 페이지로 라우팅 변경
  • 이메일 찾기 페이지/라우트 제거

컴포넌트:

  • 비밀번호 초기화 관련 컴포넌트 구조 정리
  • 이메일 찾기 관련 컴포넌트 제거

상태관리:

  • 인증 상태에 따른 라우팅 분기 로직 정리

API 호출:

  • 비밀번호 초기화 API 흐름에 맞게 호출 방식 수정
  • 이메일 찾기 API 연동 제거

스타일:

  • 이메일 찾기 UI 제거에 따른 불필요한 스타일 정리

기타:

  • 소셜 로그인 관련 코드 임시 주석 처리

5) 참고사항

Summary by CodeRabbit

릴리스 노트

  • 새로운 기능

    • 학번 기반 로그인으로 변경
    • 이메일을 통한 비밀번호 초기화 기능 추가
    • 인증이 필요한 보호된 경로 구현
  • 개선 사항

    • 라우트 구조 재정리로 공개 및 보호된 페이지 분리
    • 새로운 공개 페이지 추가 (/main, /intro, /leaders, /portfolio 등)
    • 인증 상태 관리 개선
  • 버그 수정

    • 로그아웃 기능 관련 오류 수정

1) #217 #218

2) 변경 요약 (What & Why)

로그인페이지

  • 이메일 --> 학번 로그인으로 변경
  • 이메일 찾기 기능 삭제
  • 비밀번호 찾기 --> 비밀번호 초기화로 변경
  • 소셜 로그인 기능 주석처리
  • 로그인/로그아웃 관련 라우터 구조를 정리
  • 인증 흐름에 맞게 접근 제어
    ---> 인증 상태에 따른 라우팅이 명확하지 않아 발생한 로그아웃 관련 이슈 해결
    (원인 자체는 sidebar, header, page들 제각각 라우팅을 하는데서 발생)

3) 스크린샷/동영상 (UI 변경 시)

화면 캡처 2026-02-12 204134 화면 캡처 2026-02-12 204219

4) 상세 변경사항 (전부 다)

라우팅/페이지:

  • 로그인/로그아웃 관련 라우터 접근 조건 정리
  • 비밀번호 찾기 → 비밀번호 초기화 페이지로 라우팅 변경
  • 이메일 찾기 페이지/라우트 제거

컴포넌트:

  • 비밀번호 초기화 관련 컴포넌트 구조 정리
  • 이메일 찾기 관련 컴포넌트 제거

상태관리:

  • 인증 상태에 따른 라우팅 분기 로직 정리

API 호출:

  • 비밀번호 초기화 API 흐름에 맞게 호출 방식 수정
  • 이메일 찾기 API 연동 제거

스타일:

  • 이메일 찾기 UI 제거에 따른 불필요한 스타일 정리

기타:

  • 소셜 로그인 관련 코드 임시 주석 처리

5) 참고사항

Summary by CodeRabbit

릴리스 노트

  • 새로운 기능

    • 학번 기반 로그인으로 변경
    • 이메일을 통한 비밀번호 초기화 기능 추가
    • 인증이 필요한 보호된 경로 구현
  • 개선 사항

    • 라우트 구조 재정리로 공개 및 보호된 페이지 분리
    • 새로운 공개 페이지 추가 (/main, /intro, /leaders, /portfolio 등)
    • 인증 상태 관리 개선
  • 버그 수정

    • 로그아웃 기능 관련 오류 수정

Summary by CodeRabbit

릴리스 노트

  • 새로운 기능

    • 학번 기반 로그인 시스템으로 전환됨
    • 이메일을 통한 비밀번호 초기화 기능 추가
    • QR 코드 기능 지원 추가
    • 인증 필요 페이지 접근 보호 기능 구현
  • 개선 사항

    • 전역 인증 상태 관리 개선
    • 출석 세션 관리 기능 강화

@coderabbitai

coderabbitai Bot commented Feb 12, 2026 •

Copy link
Copy Markdown

워크스루

이메일 기반에서 학번 기반 로그인으로 전환하고, 중앙화된 AuthContext를 통해 인증 상태를 관리하며, ProtectedRoute로 경로 보호를 추가하고, 로그인/비밀번호 재설정 흐름을 업데이트하고, API 프록싱 및 baseURL 설정을 변경하는 인증 시스템 마이그레이션입니다.

변경사항

Cohort / File(s) 요약
인증 컨텍스트 및 경로 보호
frontend/src/contexts/AuthContext.jsx, frontend/src/components/protectedRoute.jsx, frontend/src/App.jsx, frontend/src/main.jsx
AuthContext를 통해 전역 인증 상태 관리를 도입하고, ProtectedRoute 컴포넌트로 인증이 필요한 경로를 보호하며, 앱 구조를 AuthProvider로 감싸서 인증 컨텍스트를 사용 가능하게 함.
인증 유틸리티
frontend/src/utils/auth.js, frontend/src/utils/axios.js
로그인 함수를 이메일 기반에서 학번 기반으로 변경하고, resetPassword 함수를 추가하며, axios baseURL을 환경 변수에서 빈 문자열(현재 도메인)로 변경함.
로그인 및 인증 UI
frontend/src/components/login/LoginForm.jsx, frontend/src/components/login/ResetPasswordModal.jsx, frontend/src/components/Header.jsx, frontend/src/components/Sidebar.jsx
로그인 폼을 학번 입력으로 변경하고, ResetPasswordModal을 이메일 기반으로 전환하며, Header와 Sidebar의 인증 상태를 AuthContext에서 관리하도록 업데이트함. 소셜 로그인 UI 제거.
출석 관리
frontend/src/components/attendancemanage/SessionManagementCard.jsx, frontend/src/contexts/AttendanceContext.jsx, frontend/src/utils/attendanceManage.js
SessionManagementCard를 컨텍스트 의존에서 로컬 상태 및 API 호출 기반으로 변경하고, AttendanceContext에서 null 응답에 대한 가드를 추가하며, 디버그 로그를 추가함.
설정 및 스타일
frontend/package.json, frontend/vite.config.js, frontend/src/components/VerificationModal.module.css
qrcode.react 의존성 추가, Vite 개발 서버에 API 프록싱 설정 추가, VerificationModal의 codeInput 스타일을 높이 30px로 수정함.

시퀀스 다이어그램

sequenceDiagram
    participant User as 사용자
    participant App as App/Router
    participant AuthCtx as AuthContext
    participant API as API 서버
    participant ProtRoute as ProtectedRoute

    User->>App: 앱 방문
    App->>AuthCtx: AuthProvider 초기화
    AuthCtx->>API: GET /api/user/details (로그인 확인)
    alt 인증됨
        API-->>AuthCtx: 성공
        AuthCtx->>AuthCtx: isLoggedIn = true
    else 미인증
        API-->>AuthCtx: 실패
        AuthCtx->>AuthCtx: isLoggedIn = false
    end

    User->>App: 보호된 경로 접근 시도
    App->>ProtRoute: 경로 확인
    alt isLoggedIn === true
        ProtRoute->>ProtRoute: Outlet 렌더링 (자식 경로 허용)
        ProtRoute-->>User: 보호된 콘텐츠 표시
    else isLoggedIn === false
        ProtRoute->>App: Navigate to /login
        App-->>User: 로그인 페이지로 리다이렉트
    end

    User->>App: 로그인 폼 제출 (학번 + 비밀번호)
    App->>API: POST /api/auth/login (studentId, password)
    API-->>App: 인증 성공 (쿠키 설정)
    App->>AuthCtx: login() 호출
    AuthCtx->>AuthCtx: isLoggedIn = true
    AuthCtx-->>App: 로그인 완료
    App-->>User: 대시보드로 리다이렉트
Loading

예상 코드 리뷰 노력

🎯 4 (Complex) | ⏱️ ~50 minutes

관련 이슈

관련 PR

추천 리뷰어

  • DongEun02
  • gxuoo

시

🐰 학번 들고 로그인 하네,
컨텍스트에서 인증 관리 - 깔끔하네!
경로는 보호받고, 상태는 중앙화,
토큰은 쿠키에 몰래 숨겨두고,
유저는 대시보드로 쌩쌩 달린다! 🚀✨

🚥 Pre-merge checks | ✅ 3
✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed 제목이 변경의 핵심을 부분적으로만 반영합니다. '[FE] [FIX]'는 수정임을 나타내지만, 실제 주요 변경은 이메일 기반 로그인에서 학번 기반 로그인으로 전환, 인증 라우팅 구조 개선, 로그아웃 버그 수정을 포함하고 있습니다.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch 20260212-FE-#217#218-About-Login-Fucntion

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

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

@discipline24
discipline24 merged commit 9e49207 into main Feb 12, 2026
1 check was pending

@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: 11

Caution

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

⚠️ Outside diff range comments (1)
frontend/src/components/login/LoginForm.jsx (1)

37-49: ⚠️ Potential issue | 🔴 Critical

필수: AuthContext의 login 함수에서 로그인 후 isLoggedIn 상태 업데이트 필요

frontend/src/contexts/AuthContext.jsx의 login 함수(Line 25-33)를 보면, API 호출 후 setIsLoggedIn(true)를 호출하지 않습니다. 따라서 로그인이 성공하고 nav('/')로 이동해도, isLoggedIn 상태는 여전히 false로 유지되어 라우팅 및 상태 관리에서 문제가 발생합니다.

또한 Line 46-49의 catch 블록에서 AbortError를 필터링하지 않아, 이전 요청이 abort될 때도 에러 토스트가 표시됩니다.

수정 필요

frontend/src/contexts/AuthContext.jsx의 login 함수에서:

  const login = async ({ studentId, password }, signal) => {
    const paylaod = { studentId, password };
    const res = await api.post('/api/auth/login', paylaod, { signal });
+   setIsLoggedIn(true);
    return res.data;
  };

frontend/src/components/login/LoginForm.jsx의 catch 블록에서:

    } catch (err) {
+     if (err.name === 'AbortError') return;
      console.dir(err);
      toast.error('로그인에 실패하였습니다. 학번과 비밀번호를 확인해주세요.');
    }
🤖 Fix all issues with AI agents
In `@frontend/package.json`:
- Line 17: package.json currently lists the qrcode.react dependency but there is
no usage in the codebase; either remove the "qrcode.react" entry from
frontend/package.json to avoid shipping an unused package, or add the actual QR
code implementation that uses that dependency (for example create a QRCode React
component that imports { QRCode } from "qrcode.react" and use it where you need
to render a QR code, e.g., in the PaymentPage or ShareLink component). Ensure
you update any related imports and run the build to confirm no unused-dependency
warnings remain.

In `@frontend/src/components/attendancemanage/SessionManagementCard.jsx`:
- Around line 37-39: selectedSessionId is a string (from e.target.value) but
session.attendanceSessionId in sessionList is a UUID object, so the ===
comparison in currentSession (const currentSession = sessionList.find((session)
=> session.attendanceSessionId === selectedSessionId)) always fails; fix by
normalizing types: when handling the HTML select change assign selectedSessionId
as the string value (keep it as e.target.value) and ensure sessionList IDs are
compared as strings (e.g., map/convert session.attendanceSessionId to
session.attendanceSessionId.toString() before find) or alternatively serialize
API responses so session.attendanceSessionId is already a string; apply the same
normalization in RoundDayPicker.jsx and AddUsersModal.jsx where you compare
selected IDs.

In `@frontend/src/components/Header.jsx`:
- Around line 14-18: The logout flow doesn't flip the AuthContext state so
isLoggedIn remains true; update the AuthContext's logout function (in
frontend/src/contexts/AuthContext.jsx) to call setIsLoggedIn(false) after any
auth cleanup (and before/after clearing tokens or calling backend) so the
context reflects the logged-out state; ensure the logout function exported/used
by Header.jsx is the same function that updates isLoggedIn and, if necessary,
persist the change (e.g., clear storage) so nav('/login') leads to a true
unauthenticated state.

In `@frontend/src/components/login/LoginForm.jsx`:
- Around line 107-112: 현재 로그인 폼의 "비밀번호 초기화" 링크는 클릭 핸들러만 있고 href가 없어 키보드 접근성이
떨어집니다; LoginForm.jsx의 해당 <a>를 대체하거나 수정하여 접근성을 보장하세요: 더 나은 fix는 요소를 <button>으로
교체하고 기존 onClick={() => setModalStep('resetPassword')} 핸들러를 유지하는 것이며, 만약 앵커를 유지해야
한다면 href="#"와 role="button"을 추가하고 onClick에서 event.preventDefault()를 호출해 키보드 포커스와
스크린리더 상호작용을 정상화하세요.

In `@frontend/src/components/login/ResetPasswordModal.jsx`:
- Around line 19-35: The catch block for the reset flow should ignore
intentional AbortError and avoid showing the failure toast or printing
console.dir for aborted requests: inside the try/catch around resetPassword
(which uses abortRef.current.signal), change the catch to detect and return
early for an AbortError (check err.name === 'AbortError' or use DOMException
detection) so that toast.error('비밀번호 재설정 메일 전송에 실패했습니다...') is not shown for
cancellations; remove or wrap console.dir(err) so only real, non-abort errors
are logged (and still trigger the error toast), keeping references to abortRef,
resetPassword, isValidEmail, onClose, toast.success and toast.error to locate
the code to change.

In `@frontend/src/components/protectedRoute.jsx`:
- Around line 4-14: The auth loading flag is initialized incorrectly causing
ProtectedRoute (which uses useAuth()) to redirect to /login before async
checkLogin completes; in AuthContext.jsx change the loading useState initial
value from false to true so the initial render preserves the loading state until
the checkLogin useEffect resolves, ensuring ProtectedRoute's loading check
prevents premature redirection.

In `@frontend/src/contexts/AuthContext.jsx`:
- Around line 7-8: The initial state causes a flicker because loading starts as
false; change the AuthContext initial state so authentication check doesn't
treat the user as unauthenticated during async check — for example, set loading
to true (or isLoggedIn to null) in AuthContext.jsx, ensure checkLogin sets
setIsLoggedIn(...) and then setLoading(false) only after the async result, and
update ProtectedRoute to rely on loading (or null isLoggedIn) to render a loader
instead of redirecting while loading; update uses of isLoggedIn and loading
accordingly to avoid the temporary redirect.
- Around line 25-33: The login function in AuthContext.jsx never updates the
context state after a successful API call; after the API returns (inside login
in AuthContext.jsx) call setIsLoggedIn(true) to update authentication state, and
remove or delegate this logic to the existing login implementation in
frontend/src/utils/auth.js to avoid duplication (either call utils.login from
AuthContext.jsx or consolidate the logic into one login function); ensure you
reference the AuthContext.jsx login function and the setIsLoggedIn state updater
when making the change.
- Around line 35-45: The logout function in AuthContext.jsx removes the user
from localStorage but never updates the auth state, so isLoggedIn remains true;
update the logout handler (logout) to call the context state setters (e.g.,
setIsLoggedIn(false) and setUser(null)) in the finally block after
localStorage.removeItem('user') so the React state reflects logout immediately
(also consider triggering any existing redirect/cleanup logic the context
exposes).

In `@frontend/src/utils/auth.js`:
- Around line 20-23: Rename the misspelled variable `paylaod` to `payload` in
the `login` function (export const login) so the object passed to
`api.post('/api/auth/login', ...)` is correctly named, and update any other
occurrences of `paylaod` (including in AuthContext.jsx around the auth
call/usage) to `payload` so all references match the corrected identifier.

In `@frontend/src/utils/axios.js`:
- Around line 3-6: The api axios instance is created with baseURL: '' causing
inconsistent endpoints and failed token reissue calls that directly use
import.meta.env.VITE_API_URL; update the axios.create call (symbol: api) to use
a single source of truth for the backend URL (e.g. set baseURL to
import.meta.env.VITE_API_URL or a safe fallback) and refactor the token reissue
logic to call the api instance rather than constructing URLs with VITE_API_URL
directly so all requests (including reissue) use the same baseURL configuration.
🧹 Nitpick comments (8)
frontend/vite.config.js (1)

37-45: 하드코딩된 백엔드 IP 주소는 환경 변수로 관리하는 것을 권장합니다.

54.180.175.139:8080이 직접 코드에 포함되어 있어, 서버 IP 변경 시 코드 수정이 필요합니다. 환경 변수(예: VITE_API_URL)를 활용하면 유지보수가 용이합니다. 또한 axios.js의 토큰 재발급 요청에서는 여전히 import.meta.env.VITE_API_URL을 참조하고 있어 불일치가 발생할 수 있습니다.

제안
  server: {
    proxy: {
      '/api': {
-        target: 'http://54.180.175.139:8080', // 예: http://54.180.175.139
+        target: process.env.VITE_API_URL || 'http://54.180.175.139:8080',
         changeOrigin: true,
         secure: false,
      },
    },
  },
frontend/src/utils/attendanceManage.js (1)

21-22: 디버그용 console.log가 남아있습니다.

프로덕션 코드에 불필요한 로깅이 포함되어 있습니다. 출석 세션 데이터가 콘솔에 노출될 수 있으므로 제거를 권장합니다.

제안
-    // console.log('API BASE URL:', import.meta.env.VITE_API_URL);
-    console.log(res.data);
     return res.data;
frontend/src/components/login/LoginForm.jsx (1)

6-9: 주석 처리된 import는 제거하는 것을 권장합니다.

SocialLoginButtons, VerificationModal, FindEmailResultModal import가 주석 처리되어 있습니다. PR 설명에 "임시 주석 처리"라고 되어 있지만, VCS가 히스토리를 관리하므로 코드에서 제거하고 필요 시 복원하는 것이 더 깔끔합니다.

frontend/src/components/attendancemanage/SessionManagementCard.jsx (2)

58-66: 버튼 클릭 핸들러가 아무 동작도 하지 않습니다.

openAddRoundsModal()이 주석 처리되어 있어, 세션을 선택한 후 "출석일자 추가" 버튼을 눌러도 아무 일이 일어나지 않습니다. WIP 상태라면 버튼을 disabled 처리하거나 TODO 주석을 명확히 남기는 것이 좋습니다.


42-50: 라운드 조회 TODO — 추후 연결 필요 확인.

selectedSessionId 변경 시 라운드를 비우기만 하고 있으며, 실제 getRounds API 연결이 필요합니다. 이 작업을 추적하기 위한 이슈를 생성할까요?

frontend/src/components/Header.jsx (1)

4-5: 사용하지 않는 import가 남아있습니다.

useState, useEffect (Line 4), api (Line 5)는 AuthContext로 전환 후 더 이상 사용되지 않습니다. 정리하세요.

♻️ 미사용 import 제거
- import { useState, useEffect } from 'react';
- import { api } from '../utils/axios';
frontend/src/components/Sidebar.jsx (2)

3-4: 사용하지 않는 import가 남아있습니다.

useEffect (Line 3), api (Line 4)는 AuthContext로 전환 후 더 이상 사용되지 않습니다. Header.jsx와 동일한 문제입니다.

♻️ 미사용 import 제거
- import { useState, useEffect } from 'react';
+ import { useState } from 'react';
- import { api } from '../utils/axios';

31-35: Header와 Sidebar에서 로그아웃 로직이 중복됩니다.

handleLogout 함수가 Header.jsx와 동일하게 구현되어 있습니다. 추후 useAuth 훅에 navigation과 toast를 포함한 handleLogout을 제공하거나, 커스텀 훅으로 추출하는 것을 고려해보세요.

또한 Line 174에서 handleLogout()이 async 함수인데 await 없이 호출되고 있습니다. 현재 AuthContext의 logout이 내부적으로 에러를 catch하므로 문제는 없지만, 일관성을 위해 await를 추가하거나 .catch() 처리를 권장합니다.

Also applies to: 167-176

Comment thread frontend/package.json
"immer": "^10.2.0",
"lucide-react": "^0.555.0",
"pretendard": "^1.3.9",
"qrcode.react": "^4.2.0",

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# qrcode.react 및 qrcode 사용처 검색
rg -i "qrcode" --type-list | head -20
rg -i "from.*qrcode|import.*qrcode|require.*qrcode" -g '!node_modules' -g '!.next'

Repository: SISC-IT/sisc-web

Length of output: 449


🏁 Script executed:

#!/bin/bash
# qrcode.react 및 qrcode 사용처 검색
rg "qrcode" --type js --type jsx --type ts --type tsx -i

Repository: SISC-IT/sisc-web

Length of output: 87


🏁 Script executed:

#!/bin/bash
# qrcode 사용처 검색
rg "qrcode" --type js --type ts -i

echo "---"
# 다른 방식으로도 검색
rg "import.*qrcode|require.*qrcode" -i

Repository: SISC-IT/sisc-web

Length of output: 63


🏁 Script executed:

#!/bin/bash
# package.json에서 qrcode 의존성 확인
echo "=== package.json에서 qrcode 관련 의존성 ===" 
rg "qrcode" frontend/package.json

echo -e "\n=== 모든 QR 관련 참조 확인 ===" 
rg -i "qr" --type js --type ts

echo -e "\n=== 변경된 파일 목록 ===" 
git ls-files frontend/src --cached

Repository: SISC-IT/sisc-web

Length of output: 10561


qrcode.react 의존성을 제거하거나 사용처를 추가하세요.

qrcode.react 패키지가 package.json에 추가되었지만 코드베이스 전체에서 사용되지 않습니다. 불필요한 의존성은 번들 크기를 증가시키므로 제거하거나, 실제 QR코드 기능이 필요하다면 해당 구현을 함께 추가해주세요.

🤖 Prompt for AI Agents
In `@frontend/package.json` at line 17, package.json currently lists the
qrcode.react dependency but there is no usage in the codebase; either remove the
"qrcode.react" entry from frontend/package.json to avoid shipping an unused
package, or add the actual QR code implementation that uses that dependency (for
example create a QRCode React component that imports { QRCode } from
"qrcode.react" and use it where you need to render a QR code, e.g., in the
PaymentPage or ShareLink component). Ensure you update any related imports and
run the build to confirm no unused-dependency warnings remain.

Comment on lines +37 to 39
const currentSession = sessionList.find(
(session) => session.attendanceSessionId === selectedSessionId
);

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🔴 Critical

🧩 Analysis chain

🏁 Script executed:

# First, let's find the getAttendanceSessions function to see its return type
rg -n "getAttendanceSessions" --type=js --type=jsx --type=ts --type=tsx -A 10 -B 2

Repository: SISC-IT/sisc-web

Length of output: 87


🏁 Script executed:

# Look for TypeScript type definitions related to attendance sessions
fd -e ts -e tsx | xargs rg -l "attendanceSessionId" 2>/dev/null || echo "No TS files found with attendanceSessionId"

Repository: SISC-IT/sisc-web

Length of output: 570


🏁 Script executed:

# Check the complete SessionManagementCard.jsx file to understand the context better
cat -n frontend/src/components/attendancemanage/SessionManagementCard.jsx | head -100

Repository: SISC-IT/sisc-web

Length of output: 3759


🏁 Script executed:

# Search for how selectedSessionId is initialized and used throughout the codebase
rg -n "selectedSessionId" frontend/src/components/attendancemanage/SessionManagementCard.jsx -B 2 -A 2

Repository: SISC-IT/sisc-web

Length of output: 1012


🏁 Script executed:

# Check the attendanceManage utility file to understand the return type of getAttendanceSessions
cat -n frontend/src/utils/attendanceManage.js

Repository: SISC-IT/sisc-web

Length of output: 6351


🏁 Script executed:

# Look at the backend entity to understand the data structure
cat -n backend/src/main/java/org/sejongisc/backend/attendance/entity/AttendanceSession.java | head -50

Repository: SISC-IT/sisc-web

Length of output: 1514


🏁 Script executed:

# Check if there are any TypeScript type definitions for API responses
fd -type f \( -name "*.ts" -o -name "*.tsx" \) | xargs rg -l "Session" 2>/dev/null | head -5

Repository: SISC-IT/sisc-web

Length of output: 457


🏁 Script executed:

# Search for how attendanceSessionId is used in the option element
rg -n "value={session.attendanceSessionId}" --type-add 'js:*.jsx' -B 3 -A 3

Repository: SISC-IT/sisc-web

Length of output: 184


🏁 Script executed:

# Let's check if there's any mock data or API response structure defined
rg -n "attendanceSessionId" --type-add 'jsx:*.jsx' -B 2 -A 2 frontend/src/

Repository: SISC-IT/sisc-web

Length of output: 3838


🏁 Script executed:

# Let's look at how the select option values are rendered
cat -n frontend/src/components/attendancemanage/SessionManagementCard.jsx | sed -n '76,95p'

Repository: SISC-IT/sisc-web

Length of output: 816


🏁 Script executed:

# Check if there are any tests or example data that shows the actual data structure
fd -type f \( -name "*.test.*" -o -name "*.mock.*" -o -name "*.spec.*" \) -path "*attendance*" 2>/dev/null | head -10

Repository: SISC-IT/sisc-web

Length of output: 42


🏁 Script executed:

# Let's check how UUID is serialized in the API response by looking at other components that use sessions
rg -n "session\." frontend/src/components/attendancemanage/ -A 1 | head -30

Repository: SISC-IT/sisc-web

Length of output: 2276


🏁 Script executed:

# Let's check how the API response is being used in AttendanceManage.jsx (where console.log is called)
cat -n frontend/src/pages/AttendanceManage.jsx | sed -n '60,75p'

Repository: SISC-IT/sisc-web

Length of output: 575


🏁 Script executed:

# Check if there's a development/local testing setup that shows actual API response structure
fd -type f -name "*.json" | xargs rg -l "attendanceSessionId" 2>/dev/null | head -5

Repository: SISC-IT/sisc-web

Length of output: 517


🏁 Script executed:

# Let's verify the actual behavior by checking if UUID objects could be passed without string conversion
# Look for any custom JSON serializers or type configurations
rg -n "JsonSerialize\|@Serializable\|ObjectMapper" --type=java

Repository: SISC-IT/sisc-web

Length of output: 42


🏁 Script executed:

# Check if there are any actual errors or issues reported related to session selection in other files
rg -n "selectedSessionId\|currentSession" frontend/src/components/attendancemanage/ -B 3 -A 3 | head -50

Repository: SISC-IT/sisc-web

Length of output: 42


🏁 Script executed:

# Let's verify by checking how the select value gets serialized and what the actual API returns
# Check if there's any type declaration or interface for the API response
find frontend/src -type f \( -name "*.ts" -o -name "*.tsx" -o -name "*.d.ts" \) | head -10

Repository: SISC-IT/sisc-web

Length of output: 42


🏁 Script executed:

# Check if the sessionList data is actually being used with type checking anywhere
rg -n "sessionList" frontend/src/components/attendancemanage/SessionManagementCard.jsx -B 2 -A 2

Repository: SISC-IT/sisc-web

Length of output: 701


🏁 Script executed:

# Let's verify by looking at a real scenario - how the selected sessionId is used after selection
cat -n frontend/src/components/attendancemanage/SessionManagementCard.jsx | sed -n '40,70p'

Repository: SISC-IT/sisc-web

Length of output: 1171


🏁 Script executed:

# Check if there are any type mismatches or issues reported in other similar components
cat -n frontend/src/components/attendancemanage/RoundDayPicker.jsx | head -50

Repository: SISC-IT/sisc-web

Length of output: 1850


🏁 Script executed:

# Let's check how the sessions context uses selectedSessionId
cat -n frontend/src/contexts/AttendanceContext.jsx | head -80

Repository: SISC-IT/sisc-web

Length of output: 3024


🏁 Script executed:

# Verify if there's any actual runtime error or console warning about the comparison
rg -n "console" frontend/src/components/attendancemanage/SessionManagementCard.jsx

Repository: SISC-IT/sisc-web

Length of output: 42


🏁 Script executed:

# Let's check the full implementation to see if currentSession is actually being used correctly
cat -n frontend/src/components/attendancemanage/SessionManagementCard.jsx | sed -n '36,120p'

Repository: SISC-IT/sisc-web

Length of output: 3124


🏁 Script executed:

# Check what the actual JSON serialization of UUID looks like by examining test or sample data
rg -n "uuid\|UUID" frontend/src --type-add 'json:*.json' | head -20

Repository: SISC-IT/sisc-web

Length of output: 42


🏁 Script executed:

# Let's verify how React renders the select value when passed a UUID
# Check if there's any explicit toString() or String() conversion
rg -n "toString\|String(" frontend/src/components/attendancemanage/SessionManagementCard.jsx

Repository: SISC-IT/sisc-web

Length of output: 144


🏁 Script executed:

# Let's look at the axios configuration to see if there's any custom serialization
cat -n frontend/src/utils/axios.js

Repository: SISC-IT/sisc-web

Length of output: 1747


🏁 Script executed:

# Check if there's a .env or config file that might show the API structure
fd -type f \( -name ".env*" -o -name "vite.config.*" -o -name "config.*" \) | head -10

Repository: SISC-IT/sisc-web

Length of output: 230


🏁 Script executed:

# Let's check AddUsersModal to see if it has the same pattern and how it uses selectedSessionId
cat -n frontend/src/components/attendancemanage/AddUsersModal.jsx | sed -n '1,80p'

Repository: SISC-IT/sisc-web

Length of output: 2835


🏁 Script executed:

# Check how selectedSessionId is being set in the context (line 70 initialized it)
cat -n frontend/src/contexts/AttendanceContext.jsx | sed -n '65,150p'

Repository: SISC-IT/sisc-web

Length of output: 3566


🏁 Script executed:

# Let's verify the actual behavior by checking if there's any explicit conversion happening elsewhere
rg -n "setSelectedSessionId" frontend/src --type-add 'jsx:*.jsx' -B 2 -A 2

Repository: SISC-IT/sisc-web

Length of output: 2446


selectedSessionId 타입 불일치 — HTML 선택 요소의 값이 UUID 객체를 문자열로 변환하지만 비교 시 UUID 객체와 비교되는 버그

Line 82의 e.target.value는 항상 문자열이며, 백엔드에서 반환되는 session.attendanceSessionId는 UUID 객체입니다. HTML 속성에서 UUID 객체가 렌더링될 때 문자열로 변환되지만, sessionList의 데이터는 여전히 UUID 객체이므로 Line 38의 === 비교가 항상 실패합니다. 결과적으로 currentSession은 항상 undefined가 되어 세션 선택이 작동하지 않습니다.

같은 문제가 RoundDayPicker.jsx(Line 31-33)와 AddUsersModal.jsx(Line 39-41)에서도 발생합니다.

🐛 수정 방안

방법 1: selectedSessionId를 UUID 문자열로 유지 (권장)

- onChange={(e) => setSelectedSessionId(e.target.value)}
+ onChange={(e) => setSelectedSessionId(e.target.value)}
  // sessionList의 UUID를 문자열로 변환하거나, find 비교를 수정
  const currentSession = sessionList.find(
-   (session) => session.attendanceSessionId === selectedSessionId
+   (session) => String(session.attendanceSessionId) === selectedSessionId
  );

방법 2: API 응답에서 UUID를 문자열로 직렬화
백엔드에서 UUID를 JSON 응답 시 문자열로 자동 직렬화하도록 구성하여 프론트엔드에서 문자열로 받기

🤖 Prompt for AI Agents
In `@frontend/src/components/attendancemanage/SessionManagementCard.jsx` around
lines 37 - 39, selectedSessionId is a string (from e.target.value) but
session.attendanceSessionId in sessionList is a UUID object, so the ===
comparison in currentSession (const currentSession = sessionList.find((session)
=> session.attendanceSessionId === selectedSessionId)) always fails; fix by
normalizing types: when handling the HTML select change assign selectedSessionId
as the string value (keep it as e.target.value) and ensure sessionList IDs are
compared as strings (e.g., map/convert session.attendanceSessionId to
session.attendanceSessionId.toString() before find) or alternatively serialize
API responses so session.attendanceSessionId is already a string; apply the same
normalization in RoundDayPicker.jsx and AddUsersModal.jsx where you compare
selected IDs.

Comment on lines +14 to 18
const handleLogout = async () => {
await logout();
toast.success('로그아웃 되었습니다.');
nav('/login');
};

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🔴 Critical

logout() 호출 후 isLoggedIn 상태가 false로 변경되지 않습니다.

AuthContext의 logout 함수(frontend/src/contexts/AuthContext.jsx)가 setIsLoggedIn(false)를 호출하지 않습니다. 로그아웃 후 /login으로 이동하지만, isLoggedIn이 여전히 true이므로 뒤로가기 등으로 보호된 라우트에 접근하면 여전히 인증된 것으로 처리됩니다.

이 문제는 AuthContext의 logout 함수에서 수정해야 합니다.

🐛 AuthContext의 logout 함수에 setIsLoggedIn(false) 추가 필요

frontend/src/contexts/AuthContext.jsx:

  const logout = async () => {
    try {
      await api.post('/api/auth/logout');
    } catch (error) {
      console.log('로그아웃 API 호출 실패:', error.message);
    } finally {
      localStorage.removeItem('user');
+     setIsLoggedIn(false);
    }
  };
🤖 Prompt for AI Agents
In `@frontend/src/components/Header.jsx` around lines 14 - 18, The logout flow
doesn't flip the AuthContext state so isLoggedIn remains true; update the
AuthContext's logout function (in frontend/src/contexts/AuthContext.jsx) to call
setIsLoggedIn(false) after any auth cleanup (and before/after clearing tokens or
calling backend) so the context reflects the logged-out state; ensure the logout
function exported/used by Header.jsx is the same function that updates
isLoggedIn and, if necessary, persist the change (e.g., clear storage) so
nav('/login') leads to a true unauthenticated state.

Comment on lines 107 to 112
<a
className={styles.text}
onClick={() => setModalStep('verifyPhoneForEmail')}
onClick={() => setModalStep('resetPassword')}
>
이메일 찾기
</a>
<span className={styles.divider} aria-hidden="true">
|
</span>
<a
className={styles.text}
onClick={() => setModalStep('verifyPhoneForPassword')}
>
비밀번호 찾기
비밀번호 초기화
</a>

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

<a> 태그에 href 없이 사용 — 접근성 개선 필요.

<a> 태그가 href 없이 onClick만으로 사용되고 있어 키보드 내비게이션이 불가능합니다. <button> 태그를 사용하거나 최소한 href="#"와 role="button"을 추가하세요.

♻️ 접근성 개선 제안
-          <a
-            className={styles.text}
-            onClick={() => setModalStep('resetPassword')}
-          >
-            비밀번호 초기화
-          </a>
+          <button
+            type="button"
+            className={styles.text}
+            onClick={() => setModalStep('resetPassword')}
+          >
+            비밀번호 초기화
+          </button>
📝 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
<a
className={styles.text}
onClick={() => setModalStep('verifyPhoneForEmail')}
onClick={() => setModalStep('resetPassword')}
>
이메일 찾기
</a>
<span className={styles.divider} aria-hidden="true">
|
</span>
<a
className={styles.text}
onClick={() => setModalStep('verifyPhoneForPassword')}
>
비밀번호 찾기
비밀번호 초기화
</a>
<button
type="button"
className={styles.text}
onClick={() => setModalStep('resetPassword')}
>
비밀번호 초기화
</button>
🤖 Prompt for AI Agents
In `@frontend/src/components/login/LoginForm.jsx` around lines 107 - 112, 현재 로그인
폼의 "비밀번호 초기화" 링크는 클릭 핸들러만 있고 href가 없어 키보드 접근성이 떨어집니다; LoginForm.jsx의 해당 <a>를
대체하거나 수정하여 접근성을 보장하세요: 더 나은 fix는 요소를 <button>으로 교체하고 기존 onClick={() =>
setModalStep('resetPassword')} 핸들러를 유지하는 것이며, 만약 앵커를 유지해야 한다면 href="#"와
role="button"을 추가하고 onClick에서 event.preventDefault()를 호출해 키보드 포커스와 스크린리더 상호작용을
정상화하세요.

Comment on lines +19 to 35
abortRef.current?.abort();
abortRef.current = new AbortController();

if (!isValidEmail(email)) {
toast.error('이메일 형식이 올바르지 않습니다.');
return;
}
if (password.length < 8) {
toast.error('비밀번호는 8자 이상이어야 합니다.');
return;
try {
await resetPassword({ email }, abortRef.current.signal);
toast.success('비밀번호 재설정 메일을 전송했습니다.');
onClose();
} catch (err) {
console.dir(err);
toast.error(
'비밀번호 재설정 메일 전송에 실패했습니다. 다시 시도해주세요.'
);
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

AbortError가 사용자에게 에러 토스트로 노출됩니다.

Line 19에서 이전 요청을 abort하면, 이전 요청의 catch 블록에서 AbortError가 잡히면서 "비밀번호 재설정 메일 전송에 실패했습니다" 토스트가 표시됩니다. AbortError는 의도된 취소이므로 필터링해야 합니다.

또한 Line 31의 console.dir(err)는 디버그 코드이므로 제거하거나 조건부로 변경하는 것을 권장합니다.

🐛 AbortError 필터링 수정 제안
    } catch (err) {
-     console.dir(err);
-     toast.error(
-       '비밀번호 재설정 메일 전송에 실패했습니다. 다시 시도해주세요.'
-     );
+     if (err.name === 'AbortError') return;
+     toast.error(
+       '비밀번호 재설정 메일 전송에 실패했습니다. 다시 시도해주세요.'
+     );
    }
📝 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
abortRef.current?.abort();
abortRef.current = new AbortController();
if (!isValidEmail(email)) {
toast.error('이메일 형식이 올바르지 않습니다.');
return;
}
if (password.length < 8) {
toast.error('비밀번호는 8자 이상이어야 합니다.');
return;
try {
await resetPassword({ email }, abortRef.current.signal);
toast.success('비밀번호 재설정 메일을 전송했습니다.');
onClose();
} catch (err) {
console.dir(err);
toast.error(
'비밀번호 재설정 메일 전송에 실패했습니다. 다시 시도해주세요.'
);
}
abortRef.current?.abort();
abortRef.current = new AbortController();
if (!isValidEmail(email)) {
toast.error('이메일 형식이 올바르지 않습니다.');
return;
}
try {
await resetPassword({ email }, abortRef.current.signal);
toast.success('비밀번호 재설정 메일을 전송했습니다.');
onClose();
} catch (err) {
if (err.name === 'AbortError') return;
toast.error(
'비밀번호 재설정 메일 전송에 실패했습니다. 다시 시도해주세요.'
);
}
🤖 Prompt for AI Agents
In `@frontend/src/components/login/ResetPasswordModal.jsx` around lines 19 - 35,
The catch block for the reset flow should ignore intentional AbortError and
avoid showing the failure toast or printing console.dir for aborted requests:
inside the try/catch around resetPassword (which uses abortRef.current.signal),
change the catch to detect and return early for an AbortError (check err.name
=== 'AbortError' or use DOMException detection) so that toast.error('비밀번호 재설정 메일
전송에 실패했습니다...') is not shown for cancellations; remove or wrap console.dir(err)
so only real, non-abort errors are logged (and still trigger the error toast),
keeping references to abortRef, resetPassword, isValidEmail, onClose,
toast.success and toast.error to locate the code to change.

Comment on lines +7 to +8
const [isLoggedIn, setIsLoggedIn] = useState(false);
const [loading, setLoading] = useState(false);

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🔴 Critical

loading 초기값이 false로 설정되어 인증 확인 전에 비인증 상태로 렌더링됩니다.

checkLogin이 비동기로 실행되는 동안 loading=false, isLoggedIn=false 상태이므로, ProtectedRoute가 로그인 페이지로 잠깐 리다이렉트하는 플리커 현상이 발생합니다.

수정
- const [loading, setLoading] = useState(false);
+ const [loading, setLoading] = useState(true);
🤖 Prompt for AI Agents
In `@frontend/src/contexts/AuthContext.jsx` around lines 7 - 8, The initial state
causes a flicker because loading starts as false; change the AuthContext initial
state so authentication check doesn't treat the user as unauthenticated during
async check — for example, set loading to true (or isLoggedIn to null) in
AuthContext.jsx, ensure checkLogin sets setIsLoggedIn(...) and then
setLoading(false) only after the async result, and update ProtectedRoute to rely
on loading (or null isLoggedIn) to render a loader instead of redirecting while
loading; update uses of isLoggedIn and loading accordingly to avoid the
temporary redirect.

Comment on lines +25 to +33
const login = async ({ studentId, password }, signal) => {
const paylaod = { studentId, password };

const res = await api.post('/api/auth/login', paylaod, { signal });
// 토큰은 자동으로 쿠키에 저장됨 (백엔드가 Set-Cookie 헤더로 전송)
// res.data에는 유저 정보만 있음 (accessToken, refreshToken 제거됨)

return res.data;
};

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🔴 Critical

login() 성공 후 isLoggedIn 상태가 업데이트되지 않습니다.

로그인 API 호출이 성공해도 setIsLoggedIn(true)가 호출되지 않아, 인증 상태가 갱신되지 않습니다. 또한 이 로직은 frontend/src/utils/auth.js의 login 함수와 중복됩니다.

수정
  const login = async ({ studentId, password }, signal) => {
-   const paylaod = { studentId, password };
-   const res = await api.post('/api/auth/login', paylaod, { signal });
+   const payload = { studentId, password };
+   const res = await api.post('/api/auth/login', payload, { signal });
+   setIsLoggedIn(true);
    return res.data;
  };
🤖 Prompt for AI Agents
In `@frontend/src/contexts/AuthContext.jsx` around lines 25 - 33, The login
function in AuthContext.jsx never updates the context state after a successful
API call; after the API returns (inside login in AuthContext.jsx) call
setIsLoggedIn(true) to update authentication state, and remove or delegate this
logic to the existing login implementation in frontend/src/utils/auth.js to
avoid duplication (either call utils.login from AuthContext.jsx or consolidate
the logic into one login function); ensure you reference the AuthContext.jsx
login function and the setIsLoggedIn state updater when making the change.

Comment on lines +35 to +45
const logout = async () => {
try {
await api.post('/api/auth/logout');
} catch (error) {
// 로그아웃 API 실패해도 무시 (토큰이 없을 수 있음)
console.log('로그아웃 API 호출 실패:', error.message);
} finally {
// localStorage 유저 정보 삭제
localStorage.removeItem('user');
}
};

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🔴 Critical

logout() 후 isLoggedIn 상태가 false로 설정되지 않습니다.

로그아웃 후에도 isLoggedIn이 true로 유지되어 보호된 라우트에 접근 가능한 상태가 됩니다. 이 PR의 목적이 로그아웃/인증 상태 버그 수정인 점을 고려하면 핵심적인 누락입니다.

수정
  const logout = async () => {
    try {
      await api.post('/api/auth/logout');
    } catch (error) {
      console.log('로그아웃 API 호출 실패:', error.message);
    } finally {
      localStorage.removeItem('user');
+     setIsLoggedIn(false);
    }
  };
📝 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
const logout = async () => {
try {
await api.post('/api/auth/logout');
} catch (error) {
// 로그아웃 API 실패해도 무시 (토큰이 없을 수 있음)
console.log('로그아웃 API 호출 실패:', error.message);
} finally {
// localStorage 유저 정보 삭제
localStorage.removeItem('user');
}
};
const logout = async () => {
try {
await api.post('/api/auth/logout');
} catch (error) {
// 로그아웃 API 실패해도 무시 (토큰이 없을 수 있음)
console.log('로그아웃 API 호출 실패:', error.message);
} finally {
// localStorage 유저 정보 삭제
localStorage.removeItem('user');
setIsLoggedIn(false);
}
};
🤖 Prompt for AI Agents
In `@frontend/src/contexts/AuthContext.jsx` around lines 35 - 45, The logout
function in AuthContext.jsx removes the user from localStorage but never updates
the auth state, so isLoggedIn remains true; update the logout handler (logout)
to call the context state setters (e.g., setIsLoggedIn(false) and setUser(null))
in the finally block after localStorage.removeItem('user') so the React state
reflects logout immediately (also consider triggering any existing
redirect/cleanup logic the context exposes).

Comment on lines +20 to 23
export const login = async ({ studentId, password }, signal) => {
const paylaod = { studentId, password };

const res = await api.post('/api/auth/login', paylaod, { signal });

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

오타: paylaod → payload

Line 21과 Line 23에서 paylaod로 오타가 있습니다. 동일한 오타가 AuthContext.jsx Line 26에도 존재합니다.

수정
 export const login = async ({ studentId, password }, signal) => {
-  const paylaod = { studentId, password };
-  const res = await api.post('/api/auth/login', paylaod, { signal });
+  const payload = { studentId, password };
+  const res = await api.post('/api/auth/login', payload, { signal });
📝 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
export const login = async ({ studentId, password }, signal) => {
const paylaod = { studentId, password };
const res = await api.post('/api/auth/login', paylaod, { signal });
export const login = async ({ studentId, password }, signal) => {
const payload = { studentId, password };
const res = await api.post('/api/auth/login', payload, { signal });
🤖 Prompt for AI Agents
In `@frontend/src/utils/auth.js` around lines 20 - 23, Rename the misspelled
variable `paylaod` to `payload` in the `login` function (export const login) so
the object passed to `api.post('/api/auth/login', ...)` is correctly named, and
update any other occurrences of `paylaod` (including in AuthContext.jsx around
the auth call/usage) to `payload` so all references match the corrected
identifier.

Comment on lines 3 to 6
export const api = axios.create({
baseURL: import.meta.env.VITE_API_URL,
baseURL: '',
withCredentials: 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.

⚠️ Potential issue | 🔴 Critical

baseURL과 토큰 재발급 요청 간의 URL 불일치 문제

api 인스턴스는 baseURL: ''으로 설정되어 Vite 프록시를 통해 요청하지만, 토큰 재발급(Line 20)은 import.meta.env.VITE_API_URL을 직접 사용합니다. VITE_API_URL이 미설정 시 "undefined/api/auth/reissue"로 요청되어 토큰 갱신이 실패합니다.

또한 프로덕션 빌드에서는 Vite 프록시가 동작하지 않으므로, baseURL: ''로는 실제 백엔드에 요청이 도달하지 않습니다.

제안: 일관된 URL 관리
 export const api = axios.create({
-  baseURL: '',
+  baseURL: import.meta.env.VITE_API_URL || '',
   withCredentials: true,
 });

또는 재발급 요청도 api 인스턴스를 통하도록 변경:

-        await axios.post(
-          `${import.meta.env.VITE_API_URL}/api/auth/reissue`,
-          {},
+        await axios.post(
+          '/api/auth/reissue',
+          {},
           { withCredentials: true }
         );

Also applies to: 19-23

🤖 Prompt for AI Agents
In `@frontend/src/utils/axios.js` around lines 3 - 6, The api axios instance is
created with baseURL: '' causing inconsistent endpoints and failed token reissue
calls that directly use import.meta.env.VITE_API_URL; update the axios.create
call (symbol: api) to use a single source of truth for the backend URL (e.g. set
baseURL to import.meta.env.VITE_API_URL or a safe fallback) and refactor the
token reissue logic to call the api instance rather than constructing URLs with
VITE_API_URL directly so all requests (including reissue) use the same baseURL
configuration.

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.

2 participants