Conversation
1. 리포트 페이지에서 생성 완료 후 다른 페이지로 이동했을 때 우측 하단 모달 띄우지 않도록 수정 2. 개요보다 분석이 먼저 끝나는 경우에도 step2를 채우도록 수정 - 시작 전: 1 - 둘 다 미완료: 2 - overview만 완료: 3 - analysis만 완료: 3 - 둘 다 완료: 4
[DEV] 리포트 생성 요청 시 프로그레스바 기능 추가
Summary of ChangesHello, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed! 이 PR은 리포트 생성 페이지의 사용자 경험을 대폭 개선합니다. 기존의 주기적인 폴링 방식에서 벗어나 Server-Sent Events(SSE)를 활용하여 리포트 생성 진행 상황을 실시간으로 표시하는 프로그레스 바와 모달을 도입했습니다. 이를 통해 사용자는 리포트가 생성되는 동안 현재 단계를 명확하게 인지할 수 있으며, 전역 토스트 알림 시스템 추가로 애플리케이션 전반의 피드백이 강화되었습니다. 전반적인 리포트 상태 관리 로직도 최신 요구사항에 맞춰 재구성되었습니다. Highlights
🧠 New Feature in Public Preview: You can now enable Memory to help Gemini Code Assist learn from your team's feedback. This makes future code reviews more consistent and personalized to your project's style. Click here to enable Memory in your admin console. Changelog
Activity
Using Gemini Code AssistThe full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips. Invoking Gemini You can request assistance from Gemini at any point by creating a comment using either
Customization To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a Limitations & Feedback Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for Github and other Google products, sign up here. You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension. Footnotes
|
There was a problem hiding this comment.
Code Review
이번 PR은 리포트 생성 상태를 추적하는 방식을 기존의 폴링에서 SSE와 react-query 폴링을 조합한 새로운 시스템으로 리팩터링하는 중요한 변경을 포함하고 있습니다. 이를 통해 프로그레스 바와 백그라운드 진행 모달 등 사용자 경험을 크게 개선했습니다. 전반적으로 훌륭한 개선이지만, 몇 가지 유지보수성 및 안정성 측면에서 개선할 수 있는 부분을 발견하여 리뷰에 포함했습니다. 특히 환경 변수 관리, 에러 처리, 상태 관리 로직의 견고성에 대한 제안을 확인해 주시면 좋겠습니다.
| @@ -0,0 +1 @@ | |||
| export const SSE_URL = 'https://api.chaneling.com/sse/connect' | |||
There was a problem hiding this comment.
| }, [currentStep]) | ||
|
|
||
| const channelId = useAuthStore((state) => state.channelId) | ||
| const { mutate: deleteReport } = useDeleteMyReport({ channelId: channelId || 0 }) |
There was a problem hiding this comment.
channelId가 null 또는 undefined일 경우 0을 기본값으로 사용하고 있습니다. 만약 0이 유효한 ID로 처리되거나 백엔드에서 에러를 유발할 수 있다면 의도치 않은 동작을 일으킬 위험이 있습니다. channelId를 그대로 전달하고, deleteReport를 호출하는 useEffect 내부(52번째 줄)에서 channelId의 유효성을 검사하는 것이 더 안전합니다.
// 52번째 줄의 useEffect 내부
if (channelId) {
deleteReport({ reportId: item.reportId });
}| const { mutate: deleteReport } = useDeleteMyReport({ channelId: channelId || 0 }) | |
| const { mutate: deleteReport } = useDeleteMyReport({ channelId }) |
| const tokenRaw = window.localStorage.getItem(LOCAL_STORAGE_KEY.accessToken) | ||
| const token = tokenRaw ? JSON.parse(tokenRaw) : null | ||
|
|
||
| if (!token) return |
There was a problem hiding this comment.
localStorage에 직접 접근하고 있으며, 토큰이 변경될 경우 SSE 연결이 갱신되지 않는 문제가 있습니다. useAuthStore를 사용하여 토큰을 가져오고 useEffect의 의존성 배열에 token을 추가하여 이 문제를 해결하는 것이 좋습니다. 이렇게 하면 코드가 더 안정적이고 예측 가능해집니다.
수정 제안:
- 훅의 최상단에서
const token = useAuthStore((state) => state.accessToken)를 사용하여 토큰을 가져옵니다. useEffect내부에서는if (!enabled || !token) return으로 토큰 유무를 확인합니다.useEffect의 의존성 배열(66번째 줄)에token을 추가합니다.
| onerror(err) { | ||
| if (ctrl.signal.aborted) return | ||
| console.error('SSE Error:', err) | ||
| ctrl.abort() | ||
| throw err | ||
| }, |
There was a problem hiding this comment.
| const renderIcon = () => { | ||
| if (type === 'error') return <ErrorIcon /> | ||
| return <ErrorIcon /> | ||
| } |
There was a problem hiding this comment.
renderIcon 함수에서 type이 'error'일 때와 그렇지 않을 때 모두 ErrorIcon을 반환하고 있어 코드가 중복됩니다. 다른 토스트 타입을 지원할 계획이 없다면 코드를 단순화할 수 있습니다.
| const renderIcon = () => { | |
| if (type === 'error') return <ErrorIcon /> | |
| return <ErrorIcon /> | |
| } | |
| const renderIcon = () => { | |
| // TODO: Add icons for other toast types like 'success' | |
| return <ErrorIcon /> | |
| } |
| } | ||
|
|
||
| // 그 외(진행 중)에는 3초마다 재요청 | ||
| return 3000 |
| useEffect(() => { | ||
| return () => { | ||
| const result = latestResultRef.current | ||
| if (!result) return | ||
|
|
||
| const { overviewStatus, analysisStatus } = result | ||
|
|
||
| const isCompleted = overviewStatus === 'COMPLETED' && analysisStatus === 'COMPLETED' | ||
|
|
||
| // 내가 완료를 직접 보지 않았고, | ||
| // 완료된 상태라면 → background 완료 처리 | ||
| if (isCompleted && !hasSeenCompletionRef.current) { | ||
| addCompletedReport(reportId) | ||
| removeReport(reportId) | ||
| } | ||
| } | ||
| // 의존성 비움 (unmount 전용) | ||
| // eslint-disable-next-line react-hooks/exhaustive-deps | ||
| }, []) |
There was a problem hiding this comment.
✅ Summary
PR에 대한 간단한 요약을 작성합니다.
📝 Description
💬 리뷰 요구 사항