Skip to content

[FE] [FEAT] 소셜 로그인 - 리다이렉트 URL을 위한 OAuthSuccess 페이지 구현#107

Merged
DongEun02 merged 2 commits intomainfrom
social-login-api-connect
Nov 14, 2025
Merged

[FE] [FEAT] 소셜 로그인 - 리다이렉트 URL을 위한 OAuthSuccess 페이지 구현#107
DongEun02 merged 2 commits intomainfrom
social-login-api-connect

Conversation

@GamjaIsMine02
Copy link
Contributor

@GamjaIsMine02 GamjaIsMine02 commented Nov 14, 2025

  1. 작업한 이슈번호

  2. 변경 요약 (What & Why)
    무엇을 변경했는지:

  • 소셜 로그인 시 리다이렉트 URL을 위한 OAuthSuccess 페이지 구현

왜 변경했는지(문제/목표):

  • 백엔드에서 넘어오는 리다이렉트 url 문제점 해결을 위해서 변경
  1. 스크린샷/동영상 (UI 변경 시)
    전/후 비교, 반응형(모바일/데스크톱) 캡쳐
    Before:
    After:

  2. 상세 변경사항 (전부 다)
    라우팅/페이지:
    컴포넌트: OAuthSuccess.jsx
    상태관리:
    API 호출:
    스타일:
    기타:

  3. 참고사항

Summary by CodeRabbit

릴리스 노트

  • 새로운 기능

    • OAuth 인증 완료 후 자동/수동 이동을 제공하는 완료 페이지 추가
    • 세션 라운드의 시작 시간 및 가용 시간 편집을 위한 라운드 설정 모달 추가
    • 세션 관리에서 라운드 편집을 트리거하는 동작 추가
  • 개선 사항

    • 모달 헤더에 닫기 버튼 추가 및 UI 구조 개선
    • 시간 입력 필드 및 라운드 관련 레이아웃/스타일 개선

@coderabbitai
Copy link

coderabbitai bot commented Nov 14, 2025

Walkthrough

OAuth 리다이렉트 처리 페이지(/oauth/success)를 추가하고, 출석 회차 편집용 RoundSettingModal 컴포넌트를 도입했으며 관련 라우트·상태·스타일·모달 UI를 연동하도록 AttendanceManage와 여러 컴포넌트들이 수정되었습니다.

Changes

Cohort / File(s) 요약
라우팅 및 OAuth 페이지
frontend/src/App.jsx, frontend/src/pages/OAuthSuccess.jsx
/oauth/success 라우트 등록 및 OAuth 리다이렉트 파라미터 파싱, localStorage 저장, 상태/네비게이션 처리하는 OAuthSuccess 페이지 추가.
회차 설정 모달 컴포넌트
frontend/src/components/attendancemanage/RoundSettingModal.jsx
회차의 시작 시각(시/분/초) 및 이용 가능 분 편집 UI와 유효성 검사, 저장(onSave)/닫기(onClose) 동작을 제공하는 새로운 모달 컴포넌트 추가.
출석 관리 페이지 연동
frontend/src/pages/AttendanceManage.jsx
RoundSettingModal 임포트, editingRound·isModalOpen 상태 추가, handleRoundChange 구현, 세션 기본값 확장 및 모달 열기/닫기 로직과 연동.
세션 관리 카드 변경
frontend/src/components/attendancemanage/SessionManagementCard.jsx
setEditingRoundonClick props 추가; 메뉴 버튼 클릭 시 onClick() 호출 및 편집 대상 설정하도록 수정.
모달 스타일 변경
frontend/src/components/VerificationModal.module.css
h1.findEmailH1 규칙 제거 및 회차 재설정 모달용 timeInputGroup, availableTimeInputGroup 등 신규 CSS 클래스 추가.
FindEmailResultModal 리팩토링
frontend/src/components/login/FindEmailResultModal.jsx
사용하지 않는 handleSubmit 제거, 헤더를 modalHeader 컨테이너로 교체하고 헤더에 닫기 버튼 추가(클로징 핸들러 연결).

Sequence Diagram(s)

sequenceDiagram
    participant User
    participant Browser
    participant OAuthSuccess
    participant localStorage
    participant Router
    Note over OAuthSuccess: 신규 페이지 흐름
    User->>Browser: OAuth 공급자에서 리다이렉트(`/oauth/success?...`)
    Browser->>OAuthSuccess: 페이지 로드 (query params)
    OAuthSuccess->>OAuthSuccess: 파라미터 파싱 및 검증
    alt error 없음
        OAuthSuccess->>localStorage: accessToken/refreshToken/유저정보 저장
        OAuthSuccess->>OAuthSuccess: 성공 상태 설정
        OAuthSuccess->>Router: 300ms 후 replace(next)
    else error 발생
        OAuthSuccess->>OAuthSuccess: 에러 상태 설정
        OAuthSuccess->>User: 로그인 화면으로 유도 버튼 표시
    end
Loading
sequenceDiagram
    participant User
    participant AttendanceManage
    participant SessionManagementCard
    participant RoundSettingModal
    Note over RoundSettingModal: 회차 편집 모달 흐름
    User->>SessionManagementCard: 메뉴 버튼 클릭
    SessionManagementCard->>AttendanceManage: onClick() 호출\nsetEditingRound(round)
    AttendanceManage->>AttendanceManage: isModalOpen = true
    AttendanceManage->>RoundSettingModal: 렌더(round, onSave, onClose)
    User->>RoundSettingModal: 회차 정보 수정 후 저장
    RoundSettingModal->>AttendanceManage: onSave(updatedRound)
    AttendanceManage->>AttendanceManage: handleRoundChange로 세션 데이터 업데이트
    RoundSettingModal->>AttendanceManage: onClose()
    AttendanceManage->>AttendanceManage: isModalOpen = false
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

  • 주의 검토 대상:
    • OAuthSuccess.jsx의 토큰 저장 방식(localStorage)과 리다이렉트 안전성 검사 로직
    • AttendanceManage.jsx의 라운드/세션 상태 업데이트(특히 rounds 배열 및 기본값 병합)
    • RoundSettingModal.jsx의 입력 유효성 검사와 시간 포맷 변환 로직

Possibly related PRs

Suggested labels

FE

Suggested reviewers

  • gxuoo
  • DongEun02

Poem

🐰 바삭한 키보드 위 달빛 아래,
새로운 페이지에 토큰을 담아둔 채,
모달은 조용히 회차를 고쳐주고,
세션은 다시 숨을 고르네.
토끼가 박수치며 축하하노라 🥕✨

Pre-merge checks and finishing touches

❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. You can run @coderabbitai generate docstrings to improve docstring coverage.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The PR title accurately describes the main change: implementing an OAuthSuccess page for social login redirect URL handling, which aligns with the primary code additions (OAuthSuccess.jsx) and routing changes.
✨ 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 social-login-api-connect

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.

@GamjaIsMine02 GamjaIsMine02 changed the title feat: 소셜 로그인을 위한 OAuthSuccess 페이지 생성 [FE] [FEAT] 소셜 로그인 - 리다이렉트 URL을 위한 OAuthSuccess 페이지 구현 Nov 14, 2025
Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 7

🧹 Nitpick comments (3)
frontend/src/pages/OAuthSuccess.jsx (1)

50-88: UX 개선 제안

현재 구현은 동작하지만 다음 개선사항을 고려하세요:

  1. 인라인 스타일: 프로젝트의 다른 컴포넌트처럼 CSS 모듈을 사용하는 것이 일관성 있습니다.
  2. 로딩 인디케이터: "처리 중..." 텍스트 대신 스피너를 표시하면 더 나은 사용자 경험을 제공합니다.
  3. 접근성: 버튼에 aria-label 추가, 로딩 상태에 role="status" 추가를 고려하세요.

CSS 모듈 파일을 생성하고 적용하는 예시:

// OAuthSuccess.module.css 생성
import styles from './OAuthSuccess.module.css';

return (
  <div className={styles.container}>
    <div className={styles.content}>
      <h2>소셜 로그인</h2>
      <p role="status">{status}</p>
      {!params.error && (
        <button
          className={styles.button}
          onClick={() => nav(safePath, { replace: true })}
          aria-label="다음 페이지로 이동"
        >
          계속하기
        </button>
      )}
      {params.error && (
        <button
          className={styles.button}
          onClick={() => nav('/login', { replace: true })}
        >
          로그인 화면으로
        </button>
      )}
    </div>
  </div>
);
frontend/src/components/attendancemanage/RoundSettingModal.jsx (2)

20-38: 입력 검증 로직 개선 제안

현재 isFormValid는 동작하지만, 다음 개선사항을 고려하세요:

  1. Alert 사용: alert()는 구식 UX입니다. 인라인 에러 메시지를 표시하는 것이 더 좋습니다.
  2. 실시간 검증: 입력 시 실시간으로 검증하면 사용자 경험이 향상됩니다.

인라인 에러 상태를 추가하는 예시:

const [errors, setErrors] = useState({});

const validateField = (name, value) => {
  const num = parseInt(value, 10);
  switch (name) {
    case 'hour':
      return isNaN(num) || num < 0 || num > 23 
        ? '시간은 0-23 사이의 숫자로 입력해주세요.' 
        : '';
    case 'minute':
    case 'second':
      return isNaN(num) || num < 0 || num > 59 
        ? '0-59 사이의 숫자로 입력해주세요.' 
        : '';
    default:
      return '';
  }
};

const handleHourChange = (e) => {
  const value = e.target.value;
  setHh(value);
  setErrors(prev => ({ ...prev, hour: validateField('hour', value) }));
};

// 렌더링 시
{errors.hour && <span className={styles.error}>{errors.hour}</span>}

80-101: 입력 필드 개선 제안

type="text"를 사용하면 사용자가 숫자가 아닌 값을 입력할 수 있습니다. 다음 개선을 고려하세요:

 <input
-  type="text"
+  type="number"
   id="sessionStartTime"
   value={hh}
-  maxLength="2"
+  min="0"
+  max="23"
   onChange={(e) => setHh(e.target.value)}
   placeholder="시(HH)"
 />
 <input
-  type="text"
+  type="number"
   value={mm}
-  maxLength="2"
+  min="0"
+  max="59"
   onChange={(e) => setMm(e.target.value)}
   placeholder="분(MM)"
 />
 <input
-  type="text"
+  type="number"
   value={ss}
-  maxLength="2"
+  min="0"
+  max="59"
   onChange={(e) => setSs(e.target.value)}
   placeholder="초(SS)"
 />

또는 type="text"를 유지하면서 입력 시 숫자만 허용:

const handleNumberInput = (setter, max) => (e) => {
  const value = e.target.value.replace(/\D/g, '').slice(0, 2);
  if (value === '' || parseInt(value) <= max) {
    setter(value);
  }
};

// 사용:
onChange={handleNumberInput(setHh, 23)}
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 30f9df4 and f069e3c.

📒 Files selected for processing (7)
  • frontend/src/App.jsx (1 hunks)
  • frontend/src/components/VerificationModal.module.css (1 hunks)
  • frontend/src/components/attendancemanage/RoundSettingModal.jsx (1 hunks)
  • frontend/src/components/attendancemanage/SessionManagementCard.jsx (2 hunks)
  • frontend/src/components/login/FindEmailResultModal.jsx (1 hunks)
  • frontend/src/pages/AttendanceManage.jsx (4 hunks)
  • frontend/src/pages/OAuthSuccess.jsx (1 hunks)
🧰 Additional context used
🧬 Code graph analysis (2)
frontend/src/App.jsx (1)
frontend/src/pages/OAuthSuccess.jsx (1)
  • OAuthSuccess (16-89)
frontend/src/pages/AttendanceManage.jsx (4)
frontend/src/components/attendancemanage/SessionSettingCard.jsx (2)
  • sessionTitle (5-5)
  • SessionSettingCard (4-126)
frontend/src/components/attendancemanage/SessionManagementCard.jsx (1)
  • SessionManagementCard (3-85)
frontend/src/components/attendancemanage/AttendanceManagementCard.jsx (1)
  • AttendanceManagementCard (3-63)
frontend/src/components/attendancemanage/RoundSettingModal.jsx (1)
  • RoundSettingModal (4-127)
🔇 Additional comments (4)
frontend/src/App.jsx (1)

15-15: LGTM! 라우트 구성이 올바릅니다.

OAuthSuccess 페이지가 /login/signup과 함께 Layout 외부에 올바르게 배치되었습니다. OAuth 콜백 페이지는 메인 레이아웃이 필요하지 않으므로 적절한 구조입니다.

Also applies to: 23-23

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

10-11: 변경사항 확인됨 - 그러나 PR 범위 혼합

새로운 setEditingRoundonClick props가 올바르게 추가되고 사용되었습니다. 메뉴 버튼 클릭 시 모달을 여는 흐름이 적절합니다.

그러나 이 변경사항은 출석 관리 기능과 관련이 있으며, PR의 주요 목적인 "소셜 로그인을 위한 OAuthSuccess 페이지 생성"과는 관련이 없습니다. 관련 없는 변경사항을 별도의 PR로 분리하는 것을 권장합니다.

이 PR에 출석 관리 관련 변경사항이 포함된 이유를 확인하고, 가능하면 별도 PR로 분리하는 것을 고려해주세요.

Also applies to: 68-71

frontend/src/components/login/FindEmailResultModal.jsx (1)

7-16: LGTM! 모달 UX 개선

모달 헤더에 닫기 버튼을 추가한 것은 좋은 UX 개선입니다. 사용자가 헤더의 X 버튼이나 하단의 닫기 버튼 중 편한 방법으로 모달을 닫을 수 있습니다. 사용되지 않는 handleSubmit 함수도 깔끔하게 제거되었습니다.

참고: 이 변경사항은 OAuth 기능과 관련이 없으므로 별도 PR로 분리하는 것을 고려해주세요.

frontend/src/pages/AttendanceManage.jsx (1)

10-10: RoundSettingModal 통합 확인 - PR 범위 문제

RoundSettingModal 통합이 올바르게 구현되었습니다:

  • 모달 상태 관리가 적절합니다
  • handleRoundChange가 immer를 사용하여 상태를 올바르게 업데이트합니다
  • 모달 open/close 핸들러가 명확합니다
  • 조건부 렌더링이 적절합니다

그러나 이 변경사항은 PR의 주요 목적인 "소셜 로그인을 위한 OAuthSuccess 페이지 생성"과 전혀 관련이 없습니다.

출석 관리 기능 개선과 OAuth 로그인 기능을 별도의 PR로 분리하는 것을 강력히 권장합니다. 관련 없는 변경사항을 하나의 PR에 포함하면 다음 문제가 발생합니다:

  1. 코드 리뷰가 어려워짐
  2. 버그 추적이 복잡해짐
  3. 롤백 시 불필요한 변경사항도 함께 롤백됨
  4. Git 히스토리가 불명확해짐

이 PR을 두 개로 분리하는 것을 고려해주세요:

  • PR 1: OAuthSuccess 페이지 (OAuthSuccess.jsx, App.jsx 라우트)
  • PR 2: 출석 관리 회차 수정 기능 (RoundSettingModal, SessionManagementCard, AttendanceManage, 관련 CSS)

Also applies to: 60-61, 94-116, 184-191

Comment on lines +160 to +162
/* .availableTimeInputGroup > input {
width: 200px;
} */
Copy link

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion | 🟠 Major

주석 처리된 코드 제거

사용하지 않는 주석 처리된 CSS를 제거하세요.

 .availableTimeInputGroup {
   display: grid;
   grid-template-columns: 116px auto;
   column-gap: 12px;
   align-items: center;
   justify-content: space-between;
 }
-/* .availableTimeInputGroup > input {
-  width: 200px;
-} */
 .availableTimeInputGroup button {
🤖 Prompt for AI Agents
In frontend/src/components/VerificationModal.module.css around lines 160 to 162,
remove the unused commented-out CSS block ("/* .availableTimeInputGroup > input
{ width: 200px; } */") so the file contains no dead/commented styling; delete
the three lines and run a quick lint/format to ensure no leftover whitespace.

Comment on lines +23 to +48
useEffect(() => {
// 실패 케이스
if (params.error) {
setStatus(`로그인 실패: ${params.error}`);
return;
}

// 토큰 저장
if (params.accessToken) {
localStorage.setItem('accessToken', params.accessToken);
}
if (params.refreshToken) {
localStorage.setItem('refreshToken', params.refreshToken);
}

// (선택) 사용자 정보도 함께 보냈다면 저장해 두기
if (params.userId) localStorage.setItem('userId', params.userId);
if (params.name) localStorage.setItem('userName', params.name);

setStatus('로그인 완료! 이동 중...');
const to = decodeURIComponent(params.next || '/');

// 살짝 지연 후 이동
const t = setTimeout(() => nav(to, { replace: true }), 300);
return () => clearTimeout(t);
}, [params, nav]);
Copy link

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

보안: localStorage를 통한 토큰 저장의 위험성

localStorage에 인증 토큰을 저장하는 것은 XSS 공격에 취약합니다. 다음 개선사항을 고려하세요:

  1. Refresh Token: refreshToken은 httpOnly 쿠키로 저장되어야 하며, 백엔드에서 직접 설정해야 합니다.
  2. Access Token: 메모리 또는 httpOnly가 아닌 secure 쿠키에 저장하되, 짧은 만료 시간을 설정하세요.
  3. 토큰 검증: 저장하기 전에 JWT 형식 검증을 수행하세요.
  4. 에러 처리: localStorage 저장 실패 시 에러 처리가 필요합니다.

백엔드에서 httpOnly 쿠키를 통해 토큰을 설정할 수 있는지 확인하세요. 다음 스크립트로 프로젝트의 인증 패턴을 확인할 수 있습니다:


🏁 Script executed:

#!/bin/bash
# Description: 프로젝트에서 localStorage를 사용한 토큰 저장 패턴 확인

# localStorage.setItem 사용 검색
rg -n "localStorage\.setItem.*[Tt]oken" --type=js --type=jsx -C 3

# 쿠키 관련 코드 검색
rg -n "document\.cookie|httpOnly|secure.*cookie" --type=js --type=jsx -C 3

Length of output: 55


🏁 Script executed:

#!/bin/bash
# Description: 프로젝트에서 localStorage를 사용한 토큰 저장 패턴 확인 (수정된 버전)

# localStorage.setItem 사용 검색 - 파일 확장자 글롭 패턴 사용
echo "=== localStorage 토큰 저장 패턴 ===" 
rg -n "localStorage\.setItem.*[Tt]oken" -g "*.js" -g "*.jsx" -C 3

echo ""
echo "=== 쿠키 관련 코드 ===" 
# 쿠키 관련 코드 검색
rg -n "document\.cookie|httpOnly|secure.*cookie" -g "*.js" -g "*.jsx" -C 3

echo ""
echo "=== localStorage 전체 사용 패턴 ===" 
# localStorage 전체 패턴 확인
rg -n "localStorage\.setItem|localStorage\.getItem" -g "*.js" -g "*.jsx" -C 2

Length of output: 3952


🏁 Script executed:

#!/bin/bash
# Description: JWT 검증, 토큰 만료 처리, 백엔드 통신 패턴 확인

echo "=== JWT 검증 로직 ===" 
rg -n "jwt|JWT|jwtDecode|decode.*token" -g "*.js" -g "*.jsx" -C 2

echo ""
echo "=== 토큰 만료/갱신 로직 ===" 
rg -n "expir|expiresIn|expiresAt|TTL|refresh" -g "*.js" -g "*.jsx" -C 2

echo ""
echo "=== axios 설정 및 백엔드 통신 ===" 
cat frontend/src/utils/axios.js

echo ""
echo "=== 인증 유틸 전체 ===" 
cat frontend/src/utils/auth.js

Length of output: 5806


보안: OAuthSuccess에서의 URL 쿼리 파라미터를 통한 토큰 노출

OAuthSuccess.jsx는 URL 쿼리 파라미터에서 토큰을 직접 수신하고 있는데, 이는 다음과 같은 심각한 보안 위험을 야기합니다:

  1. 토큰 히스토리 노출: 토큰이 브라우저 히스토리에 평문으로 저장됨
  2. 네트워크 로그: Referer 헤더를 통해 프록시/로드밸런서 로그에 토큰 노출 가능
  3. localStorage XSS 취약점: 저장된 토큰이 XSS 공격으로 탈취 가능

필수 개선사항:

  • 백엔드에서 Set-Cookie 헤더로 httpOnly, Secure 쿠키에 토큰 설정 (URL 파라미터 제거)
  • OAuth 콜백 시 짧은 만료 시간의 임시 코드만 전달하고, 백엔드에서 토큰 발급
  • 토큰 저장 전 JWT 형식 검증 필요 (현재 로직 미흡)

현재 frontend/src/utils/axios.js, frontend/src/utils/auth.js에서도 localStorage 기반 토큰 저장이 사용 중이므로, 전체 인증 흐름 재설계를 권장합니다.

🤖 Prompt for AI Agents
In frontend/src/pages/OAuthSuccess.jsx around lines 23 to 48, the component
currently reads accessToken/refreshToken from URL params and writes them to
localStorage which exposes tokens in browser history, referer logs, and to XSS;
change the flow so the page does NOT persist tokens from URL: have the OAuth
callback deliver only a short-lived authorization code or state (not tokens) and
immediately POST that code to your backend endpoint to exchange for tokens; the
backend must set tokens as httpOnly, Secure (and SameSite) cookies via
Set-Cookie and return only non-sensitive redirect data to the client; update
this component to: 1) reject any accessToken/refreshToken params (ignore them),
2) if a code param exists POST it to /auth/callback (or configured endpoint) and
wait for success, 3) on success redirect to the next URL without storing tokens
in localStorage, and 4) remove any localStorage token writes and add a JWT
format check if you must parse token payload client-side (only for non-sensitive
display), and then coordinate corresponding changes in
frontend/src/utils/axios.js and frontend/src/utils/auth.js to rely on
cookie-based auth rather than localStorage.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 2

🧹 Nitpick comments (2)
frontend/src/pages/AttendanceManage.jsx (2)

63-75: 사용하지 않는 주석 처리된 코드 제거

useMemo로 최적화된 currentSessioncurrentParticipants 계산 로직이 주석 처리되어 있습니다. 이 코드가 더 이상 필요하지 않다면 제거하고, 향후 성능 최적화가 필요하다면 주석을 해제하여 사용하세요.


119-120: UUID 생성 시 불필요한 Math.random() 제거

UUID v4는 이미 전역적으로 고유하므로 Math.random()을 추가로 결합할 필요가 없습니다.

다음과 같이 단순화하세요:

-    const sessionId = `session-${uuid()}-${Math.random().toString(36)}`;
-    const roundId = `round-${uuid()}-${Math.random().toString(5)}`;
+    const sessionId = `session-${uuid()}`;
+    const roundId = `round-${uuid()}`;
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between f069e3c and 98f9f1a.

📒 Files selected for processing (3)
  • frontend/src/components/attendancemanage/RoundSettingModal.jsx (1 hunks)
  • frontend/src/pages/AttendanceManage.jsx (4 hunks)
  • frontend/src/pages/OAuthSuccess.jsx (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (2)
  • frontend/src/pages/OAuthSuccess.jsx
  • frontend/src/components/attendancemanage/RoundSettingModal.jsx
🧰 Additional context used
🧬 Code graph analysis (1)
frontend/src/pages/AttendanceManage.jsx (4)
frontend/src/components/attendancemanage/SessionSettingCard.jsx (2)
  • sessionTitle (5-5)
  • SessionSettingCard (4-126)
frontend/src/components/attendancemanage/SessionManagementCard.jsx (1)
  • SessionManagementCard (3-85)
frontend/src/components/attendancemanage/AttendanceManagementCard.jsx (1)
  • AttendanceManagementCard (3-63)
frontend/src/components/attendancemanage/RoundSettingModal.jsx (1)
  • RoundSettingModal (4-135)
🔇 Additional comments (1)
frontend/src/pages/AttendanceManage.jsx (1)

94-116: 회차 수정 및 모달 핸들러 로직 확인 완료

handleRoundChange 함수는 useImmer의 draft 패턴을 올바르게 사용하여 회차 정보를 업데이트하고 있으며, 모달 open/close 핸들러도 적절히 구현되었습니다.

Comment on lines +16 to +25
// 세션의 기본 위치 정보
location: {
lat: 37.5499,
lng: 127.0751,
},
defaultStartTime: '18:30', // 세션의 기본 시간 설정
defaultAvailableMinutes: 30, // 출석 인정 시간 (분 단위)
rewardPoints: 100, // 세션의 리워드
isVisible: true, // 세션 공개 여부
// 세션 회차들
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

새 세션 생성 시 location 필드 누락 확인 필요

sessionData에 location 필드가 추가되었지만, handleAddSession 함수(lines 118-142)에서 새 세션을 생성할 때 이 필드가 설정되지 않습니다. 데이터 일관성을 위해 새 세션에도 기본 location 값을 설정하거나, location이 선택 사항이라면 코드 전반에서 null 체크가 필요합니다.

🤖 Prompt for AI Agents
In frontend/src/pages/AttendanceManage.jsx around lines 16-25 and in
handleAddSession at lines 118-142, the default sessionData includes a location
object but handleAddSession does not set location when creating a new session;
update handleAddSession to include a location property (use the existing
sessionData.location defaults or a shared DEFAULT_LOCATION constant) when
constructing the new session object, and if location is optional, add
null/undefined guards wherever session.location is read (or validate before use)
to avoid runtime errors.

Comment on lines +183 to 189
{isModalOpen && (
<RoundSettingModal
styles={styles}
selectedRound={selectedRound}
onAttendanceChange={handleAttendanceChange}
participants={participants}
onClose={closeModal}
round={editingRound}
onSave={handleRoundChange}
/>
Copy link

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion | 🟠 Major

모달 렌더링 시 null 안전성 검증 추가 권장

isModalOpen이 true이지만 editingRound가 null인 경우, RoundSettingModalparseTime 함수에서 오류가 발생할 수 있습니다. React 18+의 상태 배칭으로 인해 현재 코드가 작동하더라도, 명시적인 null 체크를 추가하면 더욱 안전합니다.

다음과 같이 수정하세요:

-      {isModalOpen && (
+      {isModalOpen && editingRound && (
         <RoundSettingModal
           styles={styles}
           onClose={closeModal}
           round={editingRound}
           onSave={handleRoundChange}
         />
       )}

또한 closeModal 함수에서 editingRound를 null로 리셋하는 것을 고려하세요:

 const closeModal = () => {
   setModalOpen(false);
+  setEditingRound(null);
 };
📝 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
{isModalOpen && (
<RoundSettingModal
styles={styles}
selectedRound={selectedRound}
onAttendanceChange={handleAttendanceChange}
participants={participants}
onClose={closeModal}
round={editingRound}
onSave={handleRoundChange}
/>
{isModalOpen && editingRound && (
<RoundSettingModal
styles={styles}
onClose={closeModal}
round={editingRound}
onSave={handleRoundChange}
/>
)}
🤖 Prompt for AI Agents
In frontend/src/pages/AttendanceManage.jsx around lines 183 to 189, the modal is
rendered when isModalOpen is true but editingRound may be null causing parseTime
errors; update the conditional to require editingRound (e.g., isModalOpen &&
editingRound) before rendering RoundSettingModal, and ensure
handleRoundChange/onSave still work with a non-null round; also modify
closeModal to explicitly set editingRound to null when closing to avoid stale
state.

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