Skip to content

[feat] 로딩(Spinner) 컴포넌트 개발 및 적용#75

Merged
haruyam15 merged 2 commits intodevelopfrom
feat/loading-74
Feb 12, 2026
Merged

[feat] 로딩(Spinner) 컴포넌트 개발 및 적용#75
haruyam15 merged 2 commits intodevelopfrom
feat/loading-74

Conversation

@haruyam15
Copy link
Contributor

@haruyam15 haruyam15 commented Feb 11, 2026

🚀 풀 리퀘스트 제안

로딩(Spinner) 컴포넌트를 개발하고
로딩중 상태일때 로딩 UI를 적용합니다

📋 작업 내용

  • 공용 Spinner 컴포넌트 신규 구현 및 전역 로딩 UI에 적용
  • 주제(Topic) 영역 스켈레톤 로딩(TopicSkeleton) 컴포넌트 추가
  • 기존 텍스트 기반 로딩(<p>Loading...</p>) 을 Spinner로 교체
  • 각 페이지·피처 컴포넌트의 로딩 상태 UI 개선

🔧 변경 사항

  • src/shared/ui/Spinner.tsx — SVG 기반 스피너 컴포넌트 신규 추가 (height: full | fit 옵션 지원)
  • src/features/topics/components/TopicSkeleton.tsx — 주제 영역 스켈레톤 컴포넌트 신규 추가
  • src/routes/PrivateRoute.tsx — 인증 확인 중 로딩 UI를 Spinner로 교체
  • src/pages/Gatherings/*, src/pages/Meetings/*, src/pages/PreOpinions/* — 각 페이지 로딩 상태 UI 개선
  • src/features/book, src/features/topics 컴포넌트 로딩 처리 개선

📸 스크린샷 (선택 사항)

image

📄 기타

Spinner의 height="full" 의 경우 페이지 레벨에서 header높이를 제외하고 중앙정렬을 지원합니다
기본값은 height="fit"입니다. 위치 조절이 필요하시면 div컴포넌트로 감싸서 사용하시면 됩니다
image

Summary by CodeRabbit

릴리스 노트

  • 새로운 기능

    • 주제 제안으로 이동하는 네비게이션 버튼 추가
    • 주제용 스켈레톤 컴포넌트 추가
  • UI 개선

    • 모든 로딩 상태를 텍스트에서 통일된 스피너로 교체하여 시각적 경험 향상
  • 주의 / 공개 API 변경

    • 주제 헤더에 식별자 전달 필드가 추가됨
    • 제안된 주제 목록의 페이지 크기 옵션이 제거됨

@haruyam15 haruyam15 self-assigned this Feb 11, 2026
@haruyam15 haruyam15 added the feat 새로운 기능 추가 label Feb 11, 2026
@haruyam15 haruyam15 linked an issue Feb 11, 2026 that may be closed by this pull request
@coderabbitai
Copy link

coderabbitai bot commented Feb 11, 2026

Walkthrough

로딩 UI를 텍스트에서 재사용 가능한 Spinner로 통일하고, TopicHeader에 제안하기 네비게이션(gatheringId, meetingId) 로직을 추가하며 ProposedTopicList의 pageSize prop을 제거했습니다.

Changes

Cohort / File(s) Summary
Spinner 컴포넌트 추가
src/shared/ui/Spinner.tsx, src/shared/ui/index.ts
새로운 Spinner 컴포넌트 및 재수출 추가. height prop으로 'full' 또는 'fit' 지원.
로딩 상태 UI 교체
src/features/book/components/BookInfo.tsx, src/features/gatherings/components/GatheringBookshelfSection.tsx, src/features/gatherings/components/GatheringMeetingSection.tsx, src/pages/Gatherings/GatheringDetailPage.tsx, src/pages/Gatherings/GatheringListPage.tsx, src/pages/Gatherings/GatheringSettingPage.tsx, src/pages/PreOpinions/PreOpinionListPage.tsx, src/routes/PrivateRoute.tsx
여러 로딩 분기에서 텍스트 기반 로더를 Spinner로 교체.
TopicSkeleton 및 인덱스 내보내기
src/features/topics/components/TopicSkeleton.tsx, src/features/topics/components/index.ts
새로운 TopicSkeleton 컴포넌트 추가 및 public export 등록.
TopicHeader 네비게이션 추가
src/features/topics/components/TopicHeader.tsx
gatheringId, meetingId props 추가 및 "제안하기" 버튼에 ROUTES.TOPICS_CREATE 네비게이션 연결.
ProposedTopicList prop 변경
src/features/topics/components/ProposedTopicList.tsx
pageSize prop 및 기본값 제거; TopicListSkeleton에 명시적 count 전달 삭제.
MeetingDetailPage 로직 변경
src/pages/Meetings/MeetingDetailPage.tsx
useMeetingDetail 반환명 변경(isLoading→meetingLoading), 에러별 effect 추가, 제안/확정 토픽 로딩 조건에 TopicSkeleton 사용, TopicHeader/ProposedTopicList에 gatheringId/meetingId 전달 및 pageSize 제거.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly related PRs

Suggested reviewers

  • choiyoungae
  • mgYang53
🚥 Pre-merge checks | ✅ 2 | ❌ 1
❌ 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%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed PR 제목이 주요 변경사항을 명확하게 반영합니다. 로딩 스피너 컴포넌트 개발 및 적용이 변경사항의 핵심이며, 제목이 이를 정확하게 요약하고 있습니다.

✏️ 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 feat/loading-74

No actionable comments were generated in the recent review. 🎉


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.

@haruyam15
Copy link
Contributor Author

@coderabbitai review

@coderabbitai
Copy link

coderabbitai bot commented Feb 11, 2026

✅ Actions performed

Review triggered.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

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

🤖 Fix all issues with AI agents
In `@src/shared/ui/Spinner.tsx`:
- Line 14: In Spinner.tsx the SVG group uses the invalid JSX attribute
`clip-path`; update it to the camelCase `clipPath` so React recognizes the
property and the clipping is applied (search for the <g clip-path=...>
occurrence and replace with <g clipPath=...>, and scan the file for any other
hyphenated SVG attributes to convert to camelCase).
- Around line 25-27: The hardcoded clipPath id in Spinner.tsx causes collisions
when multiple Spinner components render; modify the Spinner component to
generate a unique id (e.g., via React.useId() or a useId hook) and use that id
for both the <clipPath id=...> and any referencing attributes (e.g.,
clipPath="url(#...)" or maskHref) so each Spinner instance gets a unique
clipPath; update the Spinner component's JSX to compute const clipId =
`clip-${id}` (or similar) and substitute that symbol where the static
"clip0_3797_13505" was used.
🧹 Nitpick comments (2)
src/features/book/components/BookInfo.tsx (1)

17-23: 주석 처리된 코드가 남아있습니다.

Line 17의 // if (isLoading) return <BookInfoSkeleton /> — 향후 스켈레톤 구현 예정이라면 TODO 주석으로 명시하거나, 불필요하다면 제거하는 게 좋겠습니다.

src/pages/Meetings/MeetingDetailPage.tsx (1)

66-77: alert() 대신 openError 모달 패턴 사용을 권장합니다.

다른 모든 페이지(GatheringDetailPage, GatheringSettingPage, PreOpinionListPage 등)에서는 useGlobalModalStoreopenError로 에러를 처리하고 있습니다. 이 파일만 브라우저 alert()를 사용하면 UX 일관성이 깨집니다.

또한 Line 76의 주석 처리된 navigate 코드는 의도가 불분명하므로 정리가 필요합니다.

♻️ openError 패턴으로 전환 제안
+import { useGlobalModalStore } from '@/store'
+
 export default function MeetingDetailPage() {
   const { gatheringId, meetingId } = useParams<{ gatheringId: string; meetingId: string }>()
+  const { openError } = useGlobalModalStore()

   // 에러 처리
   useEffect(() => {
     if (proposedError) {
-      alert(`제안된 주제 조회 실패: ${proposedError.userMessage}`)
+      openError('오류', `제안된 주제 조회 실패: ${proposedError.userMessage}`)
     }
     if (confirmedError) {
-      alert(`확정된 주제 조회 실패: ${confirmedError.userMessage}`)
+      openError('오류', `확정된 주제 조회 실패: ${confirmedError.userMessage}`)
     }
     if (meetingError) {
-      alert(`약속 조회 실패: ${meetingError.userMessage}`)
+      openError('오류', `약속 조회 실패: ${meetingError.userMessage}`)
     }
-    // navigate(ROUTES.GATHERING_DETAIL(gatheringId), { replace: true })
-  }, [proposedError, confirmedError, meetingError])
+  }, [proposedError, confirmedError, meetingError, openError])

Copy link
Contributor

@mgYang53 mgYang53 left a comment

Choose a reason for hiding this comment

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

수고하셨습니다! 👍

Copy link
Contributor

@choiyoungae choiyoungae left a comment

Choose a reason for hiding this comment

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

고생하셨습니다~!

@haruyam15 haruyam15 merged commit b17aa47 into develop Feb 12, 2026
2 checks passed
@haruyam15 haruyam15 deleted the feat/loading-74 branch February 16, 2026 08:51
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

feat 새로운 기능 추가

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[feat] 로딩 컴포넌트 개발 및 적용

3 participants