Skip to content

feat: 슬라이드, 리액션, 프로젝트 API 연결 (#130)#133

Merged
AndyH0ng merged 34 commits intodevelopfrom
feat/script-api-130
Feb 9, 2026
Merged

feat: 슬라이드, 리액션, 프로젝트 API 연결 (#130)#133
AndyH0ng merged 34 commits intodevelopfrom
feat/script-api-130

Conversation

@AndyH0ng
Copy link
Copy Markdown
Member

@AndyH0ng AndyH0ng commented Feb 8, 2026

📌 관련 이슈

✨ 변경 내용

  • 영상 타임스탬프랑 리액션 연결 완
  • 홈화면 프로젝트 검색 및 필터링 API 연결 완
  • 홈화면 이름변경/삭제 API 연결 완
  • 댓글 부분 API 연결 완
  • 스크립트 부분 API 연결 완
  • 리액션 부분 API 연결 완
  • 프레젠테이션 API 연결 완 (POST /presentations 제외)
  • 슬라이드 API 연결 완 (GET /presentations/:projectId 제외, 아직 백엔드 미구현)

💡 참고 사항

스크린샷, 참고 링크, 추가 설명 등 (없으면 생략 가능)

@github-actions github-actions bot added component 컴포넌트 관련 변경 page 페이지 관련 변경 types 타입 정의 변경 labels Feb 8, 2026
@github-actions github-actions bot added store 상태 관리 변경 hooks 커스텀 훅 변경 labels Feb 8, 2026
@gemini-code-assist
Copy link
Copy Markdown
Contributor

Summary of Changes

Hello @AndyH0ng, 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은 애플리케이션의 핵심 기능인 댓글, 리액션, 프로젝트 관리, 슬라이드 및 스크립트 기능에 대한 백엔드 API 연동을 완료하는 데 중점을 둡니다. 이를 통해 사용자들은 영상 피드백, 프로젝트 검색 및 관리, 슬라이드별 스크립트 및 댓글 상호작용 등 다양한 기능을 원활하게 사용할 수 있게 됩니다. 전반적인 데이터 흐름을 개선하고, 사용자 인터페이스와 백엔드 간의 연결성을 강화하여 안정적인 서비스 기반을 마련합니다.

Highlights

  • 영상 타임스탬프 및 리액션 API 연결: 영상 타임스탬프와 리액션 기능이 백엔드 API와 완전히 연결되었습니다. 이제 사용자는 영상 특정 시점에 리액션을 남기고 타임라인을 통해 확인할 수 있습니다.
  • 홈 화면 프로젝트 관리 API 연결: 홈 화면에서 프로젝트 검색, 필터링, 이름 변경, 삭제 기능이 백엔드 API와 연결되어 사용자 경험이 향상되었습니다.
  • 댓글 및 스크립트 API 연결: 댓글 및 스크립트 관련 기능이 백엔드 API와 연결되어 슬라이드별 댓글 작성, 수정, 삭제 및 스크립트 관리가 가능해졌습니다.
  • 프레젠테이션 및 슬라이드 API 연결: 프레젠테이션 및 슬라이드 관련 API가 연결되었습니다. (단, POST /presentationsGET /presentations/:projectId는 제외)
  • DTO 및 훅 리팩토링: 댓글, 리액션, 프레젠테이션 관련 DTO 구조가 개선되었고, 관련 TanStack Query 훅들이 재구성 및 문서화되었습니다. 특히 댓글 목록은 무한 스크롤을 지원하도록 변경되었습니다.
Changelog
  • src/api/dto/comments.dto.ts
    • 댓글 및 답글 관련 DTO 구조를 재정의하고, 요청/응답 타입을 세분화했습니다.
    • 답글 목록 조회 DTO에 페이지네이션 정보를 추가했습니다.
    • 댓글/답글 수정 및 삭제 응답 DTO에 updatedTargetType, deletedTargetType 등 상세 정보를 포함하도록 변경했습니다.
  • src/api/dto/index.ts
    • 새롭게 정의된 댓글, 리액션, 프레젠테이션 DTO들을 index.ts에서 내보내도록 업데이트했습니다.
    • 사용되지 않는 DTO들을 제거하여 코드의 간결성을 높였습니다.
  • src/api/dto/presentations.dto.ts
    • 프로젝트 제목 수정 DTO를 UpdateProjectRequestDto로 변경하고, 응답 DTO를 추가했습니다.
    • 프로젝트 목록 조회 요청 DTO에 검색, 필터링, 정렬을 위한 필드를 추가했습니다.
    • 프로젝트 삭제 응답 DTO를 추가했습니다.
  • src/api/dto/reactions.dto.ts
    • 영상 리액션 토글 응답 DTO에 reactionIdvideoId 필드를 추가했습니다.
    • 영상 리액션 구간 집계 및 타임라인 마커를 위한 새로운 DTO들을 정의했습니다.
  • src/api/dto/video.dto.ts
    • 영상 관련 DTO에서 CreateCommentDto를 제거했습니다.
    • StartVideoResponseDtovideoId 타입을 number에서 string으로 변경했습니다.
  • src/api/endpoints/comments.ts
    • 댓글 및 답글 생성, 수정, 삭제 API 엔드포인트 함수들을 새로운 DTO에 맞춰 업데이트했습니다.
    • getReplies 함수에 페이지네이션 파라미터(page, limit)를 추가하고, GetReplyListResponseDto를 반환하도록 변경했습니다.
  • src/api/endpoints/presentations.ts
    • getPresentations 함수에 GetPresentationsRequestDto 파라미터를 추가하여 필터링 및 페이지네이션을 지원하도록 변경했습니다.
    • updatePresentationdeletePresentation 함수들을 새로운 DTO에 맞춰 업데이트했습니다.
  • src/api/endpoints/videoReactions.ts
    • 영상 리액션 특정 시점 조회(getVideoReactions) 및 타임라인 조회(getVideoReactionTimeline) API 엔드포인트를 추가했습니다.
  • src/api/endpoints/videos.ts
    • 영상 관련 API 엔드포인트 함수들의 videoId 타입을 number에서 string으로 변경했습니다.
    • 영상 타임스탬프 댓글 생성(createVideoComment) 엔드포인트를 추가했습니다.
  • src/api/queryClient.ts
    • 프로젝트 목록 조회(queryKeys.presentations.list) 쿼리 키에 필터링 파라미터를 포함하도록 업데이트했습니다.
    • 영상 리액션(queryKeys.reactions.video) 쿼리 키에 구간 집계 및 타임라인 관련 키를 추가했습니다.
  • src/components/comment/Comment.tsx
    • 댓글 ID 참조를 comment.id에서 comment.commentId로 변경하여 일관성을 확보했습니다.
    • 댓글 수정/삭제 버튼의 스타일을 조정했습니다.
  • src/components/comment/CommentList.tsx
    • 댓글 목록 렌더링 시 key 속성을 comment.id에서 comment.commentId로 변경했습니다.
  • src/components/comment/CommentPopover.tsx
    • 댓글 팝오버 렌더링 시 key 속성을 comment.id에서 comment.commentId로 변경했습니다.
  • src/components/common/TitleEditorPopover.tsx
    • 제목 표시 spantitleClassName prop을 추가하여 커스텀 스타일링을 지원하도록 했습니다.
    • 버튼 스타일링에 min-w-0을 추가하고 텍스트 색상을 text-black으로 변경했습니다.
  • src/components/feedback/ProgressBar.tsx
    • 프로그레스바의 세그먼트 하이라이트 key 속성에 indextopReactionType을 추가하여 고유성을 강화했습니다.
  • src/components/feedback/ScriptSection.tsx
    • slides prop의 타입을 SlideListItem에서 SlideDetail로 변경했습니다.
  • src/components/feedback/SlideViewer.tsx
    • script prop을 추가하고 이를 SlideInfoPanel로 전달하도록 변경했습니다.
  • src/components/feedback/slide/SlideInfoPanel.tsx
    • slide prop의 타입을 SlideListItem에서 script?: string으로 변경하고, 전달받은 script를 표시하도록 업데이트했습니다.
  • src/components/feedback/video/VideoPlaybackBar.tsx
    • useVideoReactionTimeline 훅을 통합하여 영상 리액션 타임라인 데이터를 기반으로 세그먼트 하이라이트를 생성하도록 로직을 변경했습니다.
  • src/components/insight/FeedbackDistributionSection.tsx
    • 리액션 관련 훅 import 경로를 useReactions에서 useSlideReactions로 변경했습니다.
  • src/components/slide/SlideWorkspace.tsx
    • useSlideCommentsQuery를 제거하고 useScriptuseSlideCommentsLoader 훅을 통합하여 슬라이드 스크립트 및 댓글 로딩 로직을 개선했습니다.
  • src/components/slide/script/CommentPopover.tsx
    • 댓글 관련 훅 import 경로를 useComments에서 useSlideCommentsActions로 변경했습니다.
    • 댓글 ID 참조를 comment.id에서 comment.commentId로 변경했습니다.
  • src/components/slide/script/SlideTitle.tsx
    • 제목 표시 spanmin-w-0max-w-40 truncate 스타일을 적용했습니다.
    • TitleEditorPopovertitleClassName prop을 전달하도록 변경했습니다.
  • src/components/video/RecordingSection.tsx
    • useScript 훅을 통합하여 현재 슬라이드의 스크립트를 가져오도록 변경했습니다.
    • 프레젠테이션 제목 표시 spanmin-w-0max-w-60 truncate 스타일을 적용했습니다.
  • src/constants/video.ts
    • FEEDBACK_WINDOW 상수를 5초에서 2초로 변경하여 피드백 그룹화 윈도우를 조정했습니다.
  • src/hooks/index.ts
    • 새롭게 추가되거나 이름이 변경된 훅들(useSlideCommentsActions, useSlideCommentsLoader, useSlideReactions, useScript)을 내보내도록 업데이트했습니다.
    • 이전 useComments 훅을 제거했습니다.
  • src/hooks/queries/useCommentQueries.ts
    • 해당 파일이 제거되었으며, 관련 기능은 useSlideCommentsQuery.tsuseSlideCommentsActions.ts로 분리되었습니다.
  • src/hooks/queries/usePresentations.ts
    • 모든 내보내기 함수에 JSDoc 주석을 추가하여 문서화를 강화했습니다.
    • usePresentationsWithFilters 훅을 추가하여 필터링 가능한 프로젝트 목록 조회를 지원합니다.
    • 프로젝트 수정 및 삭제 Mutation 훅의 캐시 업데이트 로직을 개선하여 UI 즉시 반영 및 효율성을 높였습니다.
  • src/hooks/queries/useReaction.ts
    • 모든 내보내기 함수에 JSDoc 주석을 추가하여 문서화를 강화했습니다.
    • useToggleReaction 훅이 영상 리액션 관련 쿼리 캐시를 무효화하도록 업데이트했습니다.
  • src/hooks/queries/useScript.ts
    • 해당 파일의 JSDoc 주석이 제거되었습니다. (이제 src/hooks/index.ts에서 통합 관리)
  • src/hooks/queries/useShares.ts
    • 해당 파일의 JSDoc 주석이 제거되었습니다.
  • src/hooks/queries/useSlideCommentsQuery.ts
    • 슬라이드 댓글 목록을 무한 스크롤 방식으로 조회하는 새로운 훅을 추가했습니다.
    • DTO를 Comment 타입으로 변환하고, 현재 사용자의 댓글을 isMine으로 표시하는 로직을 포함합니다.
  • src/hooks/queries/useSlides.ts
    • 모든 내보내기 함수에 JSDoc 주석을 추가하여 문서화를 강화했습니다.
  • src/hooks/queries/useVideoReactionQueries.ts
    • 모든 내보내기 함수에 JSDoc 주석을 추가하여 문서화를 강화했습니다.
    • useVideoReactionWindowuseVideoReactionTimeline 훅을 추가하여 영상 리액션 데이터를 조회합니다.
  • src/hooks/useAnalytics.ts
    • 파일 이름을 src/hooks/useAnalytics.ts에서 src/hooks/queries/useAnalytics.ts로 변경하고, 모든 내보내기 함수에 JSDoc 주석을 추가하여 문서화를 강화했습니다.
  • src/hooks/useComments.ts
    • 파일 이름을 src/hooks/useComments.ts에서 src/hooks/useSlideCommentsActions.ts로 변경하고, 모든 내보내기 함수에 JSDoc 주석을 추가하여 문서화를 강화했습니다.
    • 댓글 ID 참조를 comment.id에서 comment.commentId로 변경하고, deleteCommentApi 호출 시 객체 형태로 commentId를 전달하도록 수정했습니다.
  • src/hooks/useExitTracker.ts
    • useRecordExit 훅의 import 경로를 업데이트하고, JSDoc 주석을 추가하여 문서화를 강화했습니다.
  • src/hooks/useFeedbackWebSocket.ts
    • WebSocket 페이로드의 videoIdNumber 타입에서 string 타입으로 변경하여 일관성을 확보했습니다.
  • src/hooks/useMediaStream.ts
    • 모든 내보내기 함수에 JSDoc 주석을 추가하여 문서화를 강화했습니다.
  • src/hooks/usePresentationDeletion.ts
    • 모든 내보내기 함수에 JSDoc 주석을 추가하여 문서화를 강화했습니다.
    • 프로젝트 삭제 성공 시 토스트 메시지에 API 응답 메시지를 사용하도록 변경했습니다.
  • src/hooks/usePresentationList.ts
    • 모든 내보내기 함수에 JSDoc 주석을 추가하여 문서화를 강화했습니다.
  • src/hooks/useReactions.ts
    • 파일 이름을 src/hooks/useReactions.ts에서 src/hooks/useSlideReactions.ts로 변경하고, 모든 내보내기 함수에 JSDoc 주석을 추가하여 문서화를 강화했습니다.
  • src/hooks/useRecorder.ts
    • 모든 내보내기 함수에 JSDoc 주석을 추가하여 문서화를 강화했습니다.
  • src/hooks/useSlideCommentsLoader.ts
    • 슬라이드 댓글을 로딩하고 Zustand 스토어에 주입하는 새로운 훅을 추가했습니다. 무한 스크롤 및 댓글 초기화 로직을 포함합니다.
  • src/hooks/useSlideNavigation.ts
    • 모든 내보내기 함수에 JSDoc 주석을 추가하여 문서화를 강화했습니다.
  • src/hooks/useUploadFile.ts
    • 모든 내보내기 함수에 JSDoc 주석을 추가하여 문서화를 강화했습니다.
  • src/hooks/useVideoComments.ts
    • 영상 댓글 관리 훅의 JSDoc 주석을 업데이트하고, 댓글 ID 참조를 comment.id에서 comment.commentId로 변경하여 일관성을 확보했습니다.
  • src/hooks/useVideoReactions.ts
    • 영상 리액션 관리 훅의 JSDoc 주석을 업데이트하고, useVideoReactionWindow 훅을 통합하여 리액션 요약 데이터를 가져오도록 변경했습니다.
  • src/hooks/useVideoSync.ts
    • 모든 내보내기 함수에 JSDoc 주석을 추가하여 문서화를 강화했습니다.
  • src/hooks/useVideoUpload.ts
    • 모든 내보내기 함수에 JSDoc 주석을 추가하여 문서화를 강화했습니다.
    • uploadVideo 함수의 반환 타입을 number | null에서 string | null로 변경했습니다.
  • src/mocks/handlers.ts
    • 목록 조회 시 maxDuration 필터링을 추가하고, 댓글 및 답글 관련 Mock 데이터 처리 로직을 새로운 DTO 및 commentId 기준으로 업데이트했습니다.
    • 영상 관련 Mock 데이터의 videoId 타입을 number에서 string으로 변경했습니다.
    • 리액션 관련 Mock 데이터에 기본값을 추가하여 안정성을 높였습니다.
  • src/mocks/slides.ts
    • Mock 슬라이드 데이터의 SlideListItem 타입을 SlideDetail로 변경하고, 댓글 ID를 commentId로 업데이트했습니다.
  • src/mocks/videos.ts
    • Mock 영상 데이터의 videoId 타입을 number에서 string으로 변경하고, 댓글 ID를 commentId로 업데이트했습니다.
  • src/pages/FeedbackSlidePage.tsx
    • 슬라이드 피드백 페이지에서 댓글 및 스크립트 로딩을 위한 새로운 훅들을 통합하고, SlideViewerscript prop을 전달하도록 변경했습니다.
    • 슬라이드 초기화 로직을 개선하고, 댓글 업데이트 핸들러를 제거했습니다.
  • src/pages/FeedbackVideoPage.tsx
    • useFeedbackVideo 훅의 import 경로를 업데이트하고, 댓글 업데이트 핸들러를 제거했습니다.
  • src/pages/HomePage.tsx
    • 홈 페이지에서 프로젝트 목록 로딩 로직을 usePresentationsusePresentationsWithFilters 훅으로 전환하여 API 기반 필터링 및 정렬을 지원하도록 변경했습니다.
  • src/pages/InsightPage.tsx
    • 인사이트 페이지에서 분석 훅들의 import 경로를 업데이트하고, 리액션 요약 로직을 간소화했습니다.
  • src/pages/feedback/useFeedbackVideo.ts
    • 파일 이름을 src/hooks/useFeedbackVideo.ts에서 src/pages/feedback/useFeedbackVideo.ts로 변경하고, TEST_VIDEO_ID 타입을 number에서 string으로 변경했습니다.
  • src/stores/slideStore.ts
    • 슬라이드 스토어의 slide 상태 타입을 SlideListItem에서 SlideDetail로 변경하고, 댓글 ID 참조를 id에서 commentId로 업데이트했습니다.
  • src/stores/videoFeedbackStore.ts
    • 영상 피드백 스토어에서 댓글 ID 참조를 id에서 commentId로 업데이트하여 일관성을 확보했습니다.
  • src/types/comment.ts
    • Comment 인터페이스의 id 필드 이름을 commentId로 변경했습니다.
  • src/types/index.ts
    • SlideDetail 타입을 내보내도록 추가했습니다.
  • src/types/presentation.ts
    • ProjectUpdateResponse 인터페이스를 제거했습니다.
  • src/types/recording.ts
    • 녹화 관련 타입에서 SlideListItemSlideDetail로 변경했습니다.
  • src/types/slide.ts
    • SlideDetail 인터페이스를 SlideListItem을 확장하는 형태로 정의하고, script, comments, history, emojiReactions 필드를 SlideDetail로 이동했습니다.
  • src/types/video.ts
    • VideoFeedback 인터페이스의 videoId 타입을 number에서 string으로 변경했습니다.
  • src/types/websocket.ts
    • WebSocket 페이로드의 videoId 타입을 number에서 string으로 변경하여 일관성을 확보했습니다.
  • src/utils/comment.ts
    • 댓글 생성, 답글 추가, 댓글 수정, 댓글 삭제, 플랫-트리 변환, 최상위 부모 ID 찾기 등 모든 댓글 유틸리티 함수에서 댓글 ID 참조를 id에서 commentId로 변경했습니다.
    • addReplyToTreedeleteFromTree 함수를 제거했습니다.
Activity
Using Gemini Code Assist

The 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 /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands on the current page.

Feature Command Description
Code Review /gemini review Performs a code review for the current pull request in its current state.
Pull Request Summary /gemini summary Provides a summary of the current pull request in its current state.
Comment @gemini-code-assist Responds in comments when explicitly tagged, both in pull request comments and review comments.
Help /gemini help Displays a list of available commands.

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 .gemini/ folder in the base of the repository. Detailed instructions can be found here.

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

  1. Review the Privacy Notices, Generative AI Prohibited Use Policy, Terms of Service, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution.

@AndyH0ng AndyH0ng self-assigned this Feb 8, 2026
@AndyH0ng
Copy link
Copy Markdown
Member Author

AndyH0ng commented Feb 8, 2026

@claude 코드 리뷰해줘

@claude
Copy link
Copy Markdown

claude bot commented Feb 8, 2026

Claude finished @AndyH0ng's task in 1m 53s —— View job


코드 리뷰 완료 ✅

전반적으로 잘 구조화된 API 통합 작업입니다! 27개의 커밋으로 69개 파일을 체계적으로 리팩토링하고 API 연결을 완료하셨네요. 특히 DTO 정의, 쿼리 훅 구조화, 무한 스크롤 구현 등이 잘 되어 있습니다.


🔴 Critical Issues

1. 중복된 Nullish Coalescing 연산자 (자동화 리뷰에서 발견)

파일: src/api/endpoints/videos.ts:21

serverId: dto.replyId ?? dto.replyId ?? '',

동일한 dto.replyId를 두 번 체크하고 있습니다. 의도는 아마 dto.commentId 또는 dto.replyId 중 하나를 사용하는 것으로 보이는데, 현재는 무의미한 중복입니다.

수정 제안:

// commentId와 replyId 중 하나를 사용하려는 의도였다면:
serverId: dto.commentId ?? dto.replyId ?? '',
// 또는 replyId만 사용하려면:
serverId: dto.replyId ?? '',

Fix this →


🟡 Type Safety Issues

2. commentId 타입 불일치

파일: src/api/endpoints/videos.ts:106, src/hooks/useVideoComments.ts

답글 생성 API에서 commentIdnumber 타입으로 받고 있는데, 전체 시스템에서는 commentIdstring으로 사용합니다.

// src/api/endpoints/videos.ts:105-106
export async function createCommentReply(
  commentId: number,  // ❌ number
  data: { content: string },
)

// 하지만 다른 곳에서는:
// src/types/comment.ts:2
commentId: string;  // ✅ string

수정 제안: 일관성을 위해 commentId: string으로 변경하거나, 백엔드가 정말 number를 요구한다면 호출 시점에 변환 로직을 추가해야 합니다.

3. 비디오 댓글 변환 함수의 타입 안전성 부족

파일: src/api/endpoints/videos.ts:16-24

commentDtoToModel 함수가 replyId만 체크하고 commentId는 체크하지 않아, 일반 댓글 생성 시 serverId가 항상 빈 문자열이 될 수 있습니다.

function commentDtoToModel(dto: CreateVideoCommentRequestDto & { replyId?: string }): {
  serverId: string;
  content: string;
} {
  return {
    serverId: dto.replyId ?? dto.replyId ?? '',  // ❌ 중복 + commentId 누락
    content: dto.content,
  };
}

실제 API 응답이 commentId 또는 replyId를 반환한다면, 타입 정의가 이를 반영해야 합니다.


🟠 Code Quality & Best Practices

4. 무한 스크롤에서 페이지네이션 상태 관리 누락

파일: src/hooks/useSlideCommentsLoader.ts:25-26

무한 스크롤을 구현했지만, "더 불러오기" 로직이 없어 초기 페이지만 로드됩니다.

// 현재 코드:
useEffect(() => {
  if (comments.length > 0) {
    setComments(comments);
  }
}, [comments, setComments]);

제안: 스크롤 이벤트나 "더보기" 버튼을 통해 fetchNextPage()를 호출하는 로직을 추가해야 합니다. 또는 초기 로딩만 의도한 것이라면 "무한 스크롤"이라는 네이밍이 오해를 유발할 수 있습니다.

5. 에러 핸들링 불일치

일부 mutation에서는 onError에서 토스트를 표시하지만, 일부는 하지 않습니다.

예시:

  • useSlideCommentsActions.ts: 모든 mutation에 에러 토스트
  • usePresentations.ts:111: 삭제만 에러 토스트, 수정은 없음

제안: 일관된 에러 처리 전략을 수립하세요 (모든 mutation에 에러 토스트 또는 상위에서 일괄 처리).

6. TODO 주석 정리 필요

파일: src/api/endpoints/videos.ts:26, 56

// TODO: 레거시?
// TODO: 연결?

의미가 불명확한 TODO가 남아있습니다. API 연결이 완료되었다면 제거하거나, 아직 미완성이라면 구체적으로 작성해주세요.


🟢 Good Practices

다음 부분들은 정말 잘 구현되었습니다:

  1. 체계적인 DTO 구조화 (src/api/dto/comments.dto.ts)

    • Request/Response DTO 명확히 분리
    • 페이지네이션 정보 포함
    • 타입별 구분 (comment vs reply)
  2. Optimistic UI 구현 (useSlideCommentsActions.ts)

    • 즉시 UI 업데이트 후 API 호출
    • 실패 시 이전 상태로 롤백
    • 사용자 경험 향상
  3. 쿼리 키 팩토리 패턴 (queryClient.ts)

    • 계층적 쿼리 키로 세밀한 캐시 제어
    • 무효화 로직이 명확함
  4. JSDoc 문서화 (모든 새 훅)

    • 각 훅의 역할과 사용법이 명확히 문서화됨
  5. 일관된 네이밍 변경 (idcommentId)

    • 전체 코드베이스에서 일관성 확보

🔵 Minor Issues

7. 빈 파일 제거 필요

파일: src/hooks/queries/useOpinions.ts (0 줄)

삭제 예정인 것으로 보이는데 커밋에 남아있습니다.

8. Magic Number 사용

파일: src/constants/video.ts:1

export const FEEDBACK_WINDOW = 2000; // 2초 → 5초에서 변경

값 변경의 이유가 주석에 없습니다. 왜 2초로 변경했는지 문서화하면 좋겠습니다.

9. Unused Import 가능성

여러 파일에서 import가 추가/제거되었는데, 빌드 시 lint 오류가 없는지 확인해주세요.


📋 Testing Recommendations

  1. 댓글 생성/수정/삭제 테스트

    • 서버 ID가 없는 로컬 댓글 처리
    • 서버 ID가 있는 댓글 처리
    • 실패 시 롤백 동작
  2. 무한 스크롤 테스트

    • 다음 페이지 불러오기
    • 마지막 페이지 도달 시 동작
  3. 타입 체크

    npm run type-check
  4. Edge Cases

    • 빈 댓글 목록
    • 네트워크 오류
    • 동시 다발적 mutation

📊 Summary

구분 개수
Critical 1
Type Safety 2
Code Quality 3
Minor 3
Total Issues 9

권장 조치:

  1. ✅ Critical issue #1을 우선 수정
  2. ⚠️ Type safety issues (chore/프로젝트 세팅 #2, Closed #3) 검토 후 수정
  3. 📝 TODO 주석 정리
  4. 🧪 엣지 케이스 테스트

전반적으로 잘 작성된 PR이고, 대부분 minor한 이슈들입니다. Critical 이슈 하나만 수정하면 머지해도 좋을 것 같습니다! 🚀


Copy link
Copy Markdown
Contributor

@gemini-code-assist gemini-code-assist bot left a comment

Choose a reason for hiding this comment

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

Code Review

이번 PR은 슬라이드, 리액션, 프로젝트, 댓글, 스크립트 등 애플리케이션의 다양한 부분을 백엔드 API에 연결하는 작업을 포함하고 있습니다. DTO, API 엔드포인트 함수, React 컴포넌트 및 훅을 업데이트하는 등 광범위한 변경이 이루어졌습니다. 더 구조화된 API와 데이터 흐름을 위한 리팩토링은 훌륭한 개선입니다. 영상 댓글 API 구현에서 수정이 필요한 치명적인 문제 하나와 영상 피드백 페이지에서 누락된 것으로 보이는 기능 하나를 발견했습니다. 전반적으로 프론트엔드와 백엔드를 통합하는 데 있어 중요한 진전이라고 생각합니다.

@AndyH0ng
Copy link
Copy Markdown
Member Author

AndyH0ng commented Feb 9, 2026

@claude 코드 리뷰해봐

@claude
Copy link
Copy Markdown

claude bot commented Feb 9, 2026

Claude finished @AndyH0ng's task in 3m 14s —— View job


코드 리뷰 완료 ✅

전반적으로 매우 체계적이고 잘 구조화된 API 통합 작업입니다! 30개 커밋, 69개 파일 변경으로 슬라이드, 리액션, 프로젝트, 댓글, 스크립트 등 핵심 기능들을 백엔드와 성공적으로 연결하셨습니다. 특히 DTO 정의, 쿼리 훅 구조화, Optimistic UI 패턴 구현이 인상적입니다.


🔴 Critical Issues

1. 존재하지 않는 DTO 타입 사용

파일: src/api/endpoints/videos.ts:4

CommentResponseDto 타입이 import되어 사용되고 있지만, 실제로는 정의되지 않은 타입입니다.

// ❌ 현재 코드 (videos.ts:4)
import type {
  ChunkUploadResponseDto,
  CommentResponseDto,  // 이 타입은 존재하지 않음
  FinishVideoRequestDto,
  ...
} from '@/api/dto';

// videos.ts:16
function commentDtoToModel(dto: CommentResponseDto): { ... }

실제로 src/api/dto/comments.dto.ts에는 다음 타입들이 존재합니다:

  • CreateCommentResponseDto (line 56)
  • CreateReplyCommentResponseDto (line 73)

영향: 이 코드는 TypeScript 컴파일 에러를 발생시킵니다.

해결 방법:

  1. CommentResponseDto 타입을 union으로 정의하거나
  2. 함수별로 적절한 타입(CreateCommentResponseDto 또는 CreateReplyCommentResponseDto)을 사용
// 옵션 1: Union 타입 추가 (comments.dto.ts)
export type CommentResponseDto = CreateCommentResponseDto | CreateReplyCommentResponseDto;

// 옵션 2: 개별 함수에서 정확한 타입 사용 (videos.ts)
export async function createVideoComment(...): Promise<...> {
  const response = await apiClient.post<ApiResponse<CreateCommentResponseDto>>(...);
  ...
}

export async function createCommentReply(...): Promise<...> {
  const response = await apiClient.post<ApiResponse<CreateReplyCommentResponseDto>>(...);
  ...
}

Fix this →


🟡 Major Issues

2. 모바일 레이아웃에서 댓글 수정 기능 누락

파일: src/pages/FeedbackVideoPage.tsx:210

데스크톱 레이아웃(line 161)에는 onUpdateComment={updateComment}가 있지만, 모바일 레이아웃(line 210)에서는 제거되었습니다.

// ✅ 데스크톱 (line 156-163)
<CommentList
  comments={comments}
  onAddReply={addReply}
  onGoToRef={handleGoToTimeRef}
  onDeleteComment={deleteComment}
  onUpdateComment={updateComment}  // ✅ 있음
  isLoading={isLoading}
/>

// ❌ 모바일 (line 205-210)
<CommentList
  comments={comments}
  onAddReply={addReply}
  onGoToRef={handleGoToTimeRef}
  onDeleteComment={deleteComment}
  // ❌ onUpdateComment 누락!
/>

영향: 모바일 사용자는 댓글을 수정할 수 없습니다.

해결 방법: 의도적인 변경이 아니라면 모바일 레이아웃에도 onUpdateComment prop 추가

Fix this →

3. 무한 스크롤 구현 불완전

파일: src/hooks/useSlideCommentsLoader.ts

useSlideCommentsQuery가 무한 스크롤 기능(fetchNextPage, hasNextPage)을 제공하지만, 실제로 사용되는 곳이 없습니다.

// useSlideCommentsLoader.ts:43
return { isLoading, fetchNextPage, hasNextPage, isFetchingNextPage };

이 값들이 반환되지만, 실제 컴포넌트에서 스크롤 이벤트나 "더보기" 버튼과 연결되지 않아 초기 페이지만 로드됩니다.

제안:

  1. 정말 무한 스크롤이 필요하다면 컴포넌트에서 fetchNextPage 호출 로직 추가
  2. 초기 로딩만 필요하다면 "무한 스크롤"이라는 주석/네이밍 수정

🟠 Code Quality Issues

4. 타입 불일치: commentId 타입

파일: src/api/endpoints/videos.ts:98, 118

deleteVideoComment 함수는 commentIdnumber로 받지만, 시스템 전체에서는 string을 사용합니다.

// videos.ts:118
export async function deleteVideoComment(commentId: number): Promise<void>
//                                                 ^^^^^^ number

// types/comment.ts:2
export interface Comment {
  commentId: string;  // string
  ...
}

해결: 일관성을 위해 string으로 통일

5. 에러 핸들링 불일치

파일: 여러 mutation 훅

일부 mutation에는 onError에서 토스트를 표시하지만, 일부는 하지 않습니다.

// ✅ useSlideCommentsActions.ts - 모든 mutation에 에러 토스트
onError: () => {
  showToast.error('댓글 등록에 실패했습니다.', '잠시 후 다시 시도해주세요.');
}

// ❌ usePresentations.ts:55-74 - updatePresentation에는 에러 핸들링 없음
export function useUpdatePresentation() {
  return useMutation({
    mutationFn: ...,
    onSuccess: ...,
    // onError 없음
  });
}

제안: 모든 mutation에 일관된 에러 처리 전략 적용

6. Magic Number 사용

파일: src/constants/video.ts:1

export const FEEDBACK_WINDOW = 2000; // 5초 → 2초로 변경

값을 5초에서 2초로 변경한 이유가 주석에 없습니다. 왜 변경했는지 문서화하면 좋겠습니다.


🟢 Excellent Practices

다음 부분들은 정말 잘 구현되었습니다:

1. 체계적인 DTO 구조화 (src/api/dto/comments.dto.ts)

  • Request/Response DTO 명확히 분리
  • 페이지네이션 정보 포함
  • 타입별 구분 (comment vs reply)
  • 명확한 JSDoc 주석

2. Optimistic UI 구현 (useSlideCommentsActions.ts)

const previousComments = flatComments ?? [];
addCommentStore(content, currentSlideIndex);

createCommentMutate(..., {
  onError: () => {
    setComments(previousComments);  // 롤백
    showToast.error(...);
  },
});
  • 즉시 UI 업데이트 → 사용자 경험 향상
  • 실패 시 이전 상태로 롤백
  • 에러 토스트로 사용자에게 명확히 알림

3. 쿼리 키 팩토리 패턴 (queryClient.ts)

queryKeys = {
  slides: {
    all: ['slides'],
    list: (projectId) => ['slides', 'list', projectId],
    detail: (slideId) => ['slides', 'detail', slideId],
  },
};
  • 계층적 쿼리 키로 세밀한 캐시 제어
  • 무효화 로직이 명확함

4. JSDoc 문서화

모든 새로운 훅과 함수에 JSDoc 주석 추가:

/**
 * 프로젝트 목록 조회 (필터/검색/정렬 지원)
 */
export function usePresentationsWithFilters(params: GetPresentationsRequestDto)

5. 일관된 네이밍 변경 (idcommentId)

전체 코드베이스에서 comment.idcomment.commentId로 일관되게 변경하여 명확성 확보

6. 스마트 캐시 업데이트 (usePresentations.ts:55-74)

// Detail 캐시는 기존 데이터에 title/updatedAt만 반영
queryClient.setQueryData(..., (old) =>
  old ? { ...old, title: ..., updatedAt: ... } : old
);
// 목록은 무효화하여 최신 데이터 보장
void queryClient.invalidateQueries({ queryKey: queryKeys.presentations.lists() });

🔵 Minor Issues

7. Unused Variables

일부 주석 처리된 코드가 남아있습니다:

  • HomePage.tsx:19: //const navigate = useNavigate();
  • HomePage.tsx:15: // const MAX_SIZE_MB = 1_000;

프로덕션 전에 정리하면 좋겠습니다.

8. TODO 주석 정리 필요

의미 불명확한 TODO가 남아있습니다:

  • useSlideCommentsActions.ts:142: // TODO: 서버에서 broadcastNewComment 호출 후 제거

명확하게 작성하거나 완료 후 제거해주세요.


📊 Summary

구분 개수
Critical (빌드 실패 가능) 1
Major (기능 누락) 2
Code Quality 3
Minor 2
Total Issues 8

✅ 권장 조치 순서

  1. Critical chore: 프로젝트 세팅 #1 수정 (CommentResponseDto 타입 문제) - 빌드 실패 방지
  2. Major chore/프로젝트 세팅 #2 확인 (모바일 댓글 수정 기능) - 의도 확인 후 수정
  3. Major Closed #3 검토 (무한 스크롤) - 필요하면 구현, 아니면 네이밍 정리
  4. 나머지 Code Quality 이슈들은 시간 날 때 개선

🎉 전체 평가

이 PR은 대규모 API 통합 작업치고 매우 잘 구조화되어 있습니다:

✅ DTO 레이어가 명확히 분리됨
✅ TanStack Query 패턴이 일관되게 적용됨
✅ Optimistic UI로 사용자 경험 향상
✅ 캐시 무효화 전략이 체계적
✅ JSDoc으로 문서화 잘 됨

Critical 이슈 1개만 수정하면 머지 가능한 상태입니다! 나머지 이슈들은 점진적으로 개선하셔도 됩니다. 수고하셨습니다! 🚀


AndyH0ng and others added 4 commits February 9, 2026 15:09
- 영상 상세/목록/슬라이드 타임라인 응답 DTO 추가
- 존재하지 않는 CommentResponseDto를 올바른 DTO로 교체
- getVideoDetail, getVideoSlides에 제네릭 타입 파라미터 적용
- useFeedbackVideo에서 any 접근 제거 및 타입 추론 활용

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Copy link
Copy Markdown
Collaborator

@kimyw1018 kimyw1018 left a comment

Choose a reason for hiding this comment

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

pr단위가 너무 큽니다

@AndyH0ng
Copy link
Copy Markdown
Member Author

AndyH0ng commented Feb 9, 2026

pr단위가 너무 큽니다

고쳐보겠습니다ㅜㅜ

@AndyH0ng AndyH0ng merged commit 7fc257b into develop Feb 9, 2026
9 checks passed
@AndyH0ng AndyH0ng deleted the feat/script-api-130 branch February 9, 2026 06:24
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

component 컴포넌트 관련 변경 hooks 커스텀 훅 변경 page 페이지 관련 변경 store 상태 관리 변경 types 타입 정의 변경

Projects

None yet

Development

Successfully merging this pull request may close these issues.

feat: 대본 API 연결 및 훅 정리

2 participants