Skip to content

Conversation

@BokyungCodes
Copy link
Contributor

@BokyungCodes BokyungCodes commented Aug 2, 2025

📌 변경 사항 개요

멘토링 때 발견된 헤더, 푸터, 메인 페이지 이슈 해결

📝 상세 내용

  • 헤더 새로고침 이슈에 하이드레이션 반영
  • 헤더 프로필 이미지 실시간 반영
  • 푸터 깃허브 아이콘으로 레포지토리 연결
  • 푸터 링크 비활성화
  • 메인페이지 스켈레톤 UI 도입
  • 검색 방식 파라미터로 변경
  • 검색 후 헤더의 로고 누르면 메인페이지 이동

🔗 관련 이슈

🖼️ 스크린샷(선택사항)

💡 참고 사항

Summary by CodeRabbit

  • New Features

    • GitHub 아이콘 컴포넌트 및 경험 카드/인기 카드 스켈레톤 컴포넌트가 추가되었습니다.
  • 버그 수정

    • 로그인/회원가입 페이지에서 토큰만으로 인한 잘못된 리다이렉트 현상이 제거되어, 클라이언트 측에서 로그인 상태를 정확히 처리합니다.
  • UI/UX 개선

    • 푸터에 소셜 아이콘이 GitHub로 통일되고, 저작권 및 링크 스타일이 변경되었습니다.
    • 프로필 이미지가 명확한 크기와 비율로 표시됩니다.
    • 헤더가 하이드레이션 전 스켈레톤 UI를 보여줍니다.
    • 검색 및 경험/인기 카드 리스트에 스켈레톤 UI가 적용되어 로딩 시 시각적 일관성이 향상되었습니다.
  • 기능 변경

    • 검색 바와 배너, 경험 리스트 등에서 검색어 전달 방식이 콜백에서 URL 쿼리 기반으로 변경되었습니다.
    • 인기 경험 및 경험 리스트의 로딩 및 에러 처리 방식이 개선되어, 상태에 따른 UI가 더 자연스럽게 표시됩니다.
    • 메인 페이지 구조가 단순화되고 서버 컴포넌트로 전환되었습니다.
  • 기타

    • 마이페이지 프로필 및 이미지 수정 시 글로벌 유저 상태와 동기화되어 일관된 사용자 정보 관리가 가능해졌습니다.

@BokyungCodes BokyungCodes linked an issue Aug 2, 2025 that may be closed by this pull request
7 tasks
@BokyungCodes BokyungCodes self-assigned this Aug 2, 2025
@coderabbitai
Copy link

coderabbitai bot commented Aug 2, 2025

Walkthrough

이 변경사항은 검색 기능의 URL 기반 상태 관리로의 전환, 배너/검색바/경험 리스트 컴포넌트의 prop 구조 변경, 로딩/스켈레톤 UI 추가, 헤더/푸터의 UI 및 소셜 아이콘 개편, 마이페이지와 전역 사용자 상태 동기화, 미들웨어의 로그인 상태 판별 로직 개선 등을 포함합니다.

Changes

Cohort / File(s) Change Summary
검색 상태 및 컴포넌트 prop 구조 개선
src/app/(with-header)/page.tsx, src/app/(with-header)/components/BannerSection.tsx, src/app/(with-header)/components/SearchBar.tsx
검색어 상태를 useState에서 URL 쿼리 기반으로 변경. BannerSection과 SearchBar의 prop 구조를 onSearch 콜백에서 keyword string으로 변경. 라우터를 통한 검색 이동 및 prop 동기화 처리.
경험 리스트 및 인기 경험 UI/로딩 개선
src/app/(with-header)/components/ExperienceList.tsx, src/app/(with-header)/components/PopularExperiences.tsx
로딩 시 스켈레톤 카드 렌더링, 에러 메시지/로딩 UI 개선, 그리드 레이아웃 조정, 불필요한 에러 메시지 제거.
스켈레톤 컴포넌트 신규 추가
src/app/(with-header)/components/Skeletons/ExperienceCardSkeleton.tsx, src/app/(with-header)/components/Skeletons/PopularCardSkeleton.tsx
경험 카드/인기 카드용 스켈레톤 컴포넌트 신규 추가 및 스타일링.
푸터 UI 및 소셜 아이콘 개편
src/components/Footer.tsx, public/assets/svg/github.tsx
소셜 아이콘을 GitHub 아이콘 하나로 통합, 관련 아이콘 import 제거 및 신규 아이콘 컴포넌트 추가. 저작권 문구와 링크 스타일 변경.
헤더 UI 및 하이드레이션 처리
src/components/Header.tsx
hasHydrated 상태 기반 스켈레톤 헤더 렌더링, 로고 클릭 시 쿼리 파라미터 초기화 이동 처리, user store 구조 변경.
프로필 드롭다운 이미지 스타일 개선
src/components/ProfileDropdown.tsx
프로필 이미지 크기 및 object-fit 속성 명시로 스타일 개선.
마이페이지-전역 사용자 상태 동기화
src/hooks/useMyPageQueries.ts
프로필 업데이트/이미지 업로드 시 전역 auth store와 동기화 로직 추가.
미들웨어 로그인 상태 판별 개선
src/middleware.ts
로그인/회원가입 진입 시 토큰만으로 리다이렉트하지 않고, 마이페이지 보호만 서버에서 처리하도록 로직 단순화.
신규 BasePage 컴포넌트 추가 및 메인 페이지 리팩토링
src/app/(with-header)/components/BasePage.tsx
검색 쿼리 파라미터를 기반으로 조건부 렌더링 처리하는 BasePage 컴포넌트 신규 추가 및 기존 HomePage를 BasePage로 대체.

Sequence Diagram(s)

sequenceDiagram
    participant User
    participant SearchBar
    participant Router
    participant BannerSection
    participant ExperienceList

    User->>SearchBar: 검색어 입력 후 제출
    SearchBar->>Router: /?q=검색어로 이동
    Router->>BannerSection: keyword prop 전달
    Router->>ExperienceList: keyword prop 전달
    ExperienceList->>ExperienceList: keyword 기반 데이터 fetch 및 렌더링
Loading
sequenceDiagram
    participant User
    participant ExperienceList
    participant SkeletonCard

    User->>ExperienceList: 페이지 진입/검색
    ExperienceList->>SkeletonCard: 로딩 중 스켈레톤 카드 8개 렌더
    ExperienceList->>ExperienceList: 데이터 수신 시 실제 카드 렌더
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~18 minutes

Possibly related issues

Suggested reviewers

  • minimo-9
  • evaain706

Poem

토끼가 깡총깡총 뛰며 말해요,
"스켈레톤 카드로 로딩도 예쁘게~
검색은 주소창에서 바로바로!
깃허브 아이콘 하나로 심플하게,
헤더와 푸터도 반짝반짝!
오늘도 버그는 쏙쏙,
코드리뷰는 금방 끝날 거예요!"
🐇✨

Note

⚡️ Unit Test Generation is now available in beta!

Learn more here, or try it out under "Finishing Touches" below.


📜 Recent review details

Configuration used: CodeRabbit UI
Review profile: ASSERTIVE
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 1a52803 and f641aac.

📒 Files selected for processing (2)
  • src/app/(with-header)/components/BasePage.tsx (1 hunks)
  • src/app/(with-header)/page.tsx (1 hunks)
🧰 Additional context used
🧬 Code Graph Analysis (1)
src/app/(with-header)/page.tsx (1)
src/app/(with-header)/components/BasePage.tsx (1)
  • BasePage (8-26)
🔇 Additional comments (4)
src/app/(with-header)/components/BasePage.tsx (2)

1-11: URL 기반 검색 상태 관리 구현이 잘 되었습니다.

useSearchParams를 사용하여 URL의 'q' 파라미터를 읽고 검색 모드를 판별하는 로직이 명확하고 올바르게 구현되었습니다. keyword.trim()을 사용하여 공백만 있는 경우도 적절히 처리하고 있습니다.


13-26: 조건부 렌더링 로직이 명확하고 효율적입니다.

검색 모드일 때와 기본 모드일 때의 컴포넌트 렌더링이 명확하게 분리되어 있습니다. isSearchMode prop을 ExperienceList에 전달하여 컴포넌트가 적절히 동작할 수 있도록 구성되었습니다.

src/app/(with-header)/page.tsx (2)

1-1: 서버 사이드 렌더링 강제 설정이 적절합니다.

export const dynamic = 'force-dynamic'; 설정으로 URL 파라미터 기반 검색 기능이 서버에서 올바르게 동작하도록 보장하고 있습니다. 이는 SEO와 초기 로딩 성능에도 도움이 됩니다.


3-7: 컴포넌트 구조 단순화가 잘 이루어졌습니다.

복잡한 상태 관리 로직을 BasePage 컴포넌트로 분리하여 페이지 컴포넌트가 단순해졌습니다. 이는 관심사의 분리 원칙을 잘 따르고 있으며, 코드의 가독성과 유지보수성을 향상시킵니다.

✨ Finishing Touches
  • 📝 Generate Docstrings
🧪 Generate unit tests
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch fix/113

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
🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Explain this complex logic.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query. Examples:
    • @coderabbitai explain this code block.
    • @coderabbitai modularize this function.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read src/utils.ts and explain its main purpose.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.
    • @coderabbitai help me debug CodeRabbit configuration file.

Support

Need help? Create a ticket on our support page for assistance with any issues or questions.

Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments.

CodeRabbit Commands (Invoked using PR comments)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai full review to do a full review from scratch and review all the files again.
  • @coderabbitai summary to regenerate the summary of the PR.
  • @coderabbitai generate docstrings to generate docstrings for this PR.
  • @coderabbitai generate sequence diagram to generate a sequence diagram of the changes in this PR.
  • @coderabbitai generate unit tests to generate unit tests for this PR.
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai configuration to show the current CodeRabbit configuration for the repository.
  • @coderabbitai help to get help.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Documentation and Community

  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

@BokyungCodes BokyungCodes added 🐞 bug 버그관련 🎨 style 마크업 및 스타일링 💻 chore 사소한 수정(빌드,패키지매니저등) 📬 API 서버 api 통신관련 ✨ Feature 기능구현 🔨 Refactor 코드 리팩토링 labels Aug 2, 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

🔭 Outside diff range comments (2)
src/components/Footer.tsx (1)

10-10: 모바일 버전 저작권 텍스트 업데이트가 누락되었습니다.

데스크톱 버전은 "@NoSleepNoBugs - 2025"로 업데이트되었지만, 모바일 버전은 여전히 "©codeit - 2023"으로 남아있어 일관성이 부족합니다.

다음과 같이 수정해주세요:

-          <div className='text-center md:text-left'>©codeit - 2023</div>
+          <div className='text-center md:text-left'>@NoSleepNoBugs - 2025</div>
src/components/Header.tsx (1)

66-71: 메인 헤더의 로고 링크에 onClick 핸들러가 누락되었습니다.

하이드레이션 후 렌더링되는 메인 헤더의 로고에는 onClick 핸들러가 없어서 검색 후 로고 클릭 시 쿼리 파라미터가 제거되지 않을 것 같습니다.

다음과 같이 수정하여 일관성을 유지하세요:

         <Link
+          onClick={handleLogoClick}
           href='/'
           className='flex items-center gap-2 text-xl font-bold text-gray-800'
         >
📜 Review details

Configuration used: CodeRabbit UI
Review profile: ASSERTIVE
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 214c0a8 and c6df176.

⛔ Files ignored due to path filters (1)
  • public/assets/img/main-banner.jpg is excluded by !**/*.jpg
📒 Files selected for processing (13)
  • public/assets/svg/github.tsx (1 hunks)
  • src/app/(with-header)/components/BannerSection.tsx (3 hunks)
  • src/app/(with-header)/components/ExperienceList.tsx (6 hunks)
  • src/app/(with-header)/components/PopularExperiences.tsx (3 hunks)
  • src/app/(with-header)/components/SearchBar.tsx (1 hunks)
  • src/app/(with-header)/components/Skeletons/ExperienceCardSkeleton.tsx (1 hunks)
  • src/app/(with-header)/components/Skeletons/PopularCardSkeleton.tsx (1 hunks)
  • src/app/(with-header)/page.tsx (1 hunks)
  • src/components/Footer.tsx (2 hunks)
  • src/components/Header.tsx (3 hunks)
  • src/components/ProfileDropdown.tsx (1 hunks)
  • src/hooks/useMyPageQueries.ts (5 hunks)
  • src/middleware.ts (2 hunks)
🧰 Additional context used
🧬 Code Graph Analysis (3)
src/middleware.ts (1)
src/app/(non-header)/login/action.ts (1)
  • Login (41-100)
src/app/(with-header)/components/ExperienceList.tsx (3)
src/app/api/experiences/getExperiences.ts (2)
  • ExperienceListResult (19-22)
  • getExperiences (28-51)
src/app/(with-header)/components/Skeletons/ExperienceCardSkeleton.tsx (1)
  • ExperienceCardSkeleton (1-15)
src/app/(with-header)/components/ExperienceCard.tsx (1)
  • ExperienceCard (11-44)
src/app/(with-header)/components/PopularExperiences.tsx (3)
src/app/api/experiences/getPopularExperiences.ts (1)
  • getPopularExperiences (11-21)
src/app/(with-header)/components/Skeletons/PopularCardSkeleton.tsx (1)
  • PopularCardSkeleton (1-15)
src/app/(with-header)/components/PopularCard.tsx (1)
  • PopularCard (11-40)
🪛 Biome (2.1.2)
public/assets/svg/github.tsx

[error] 4-11: Alternative text title element cannot be empty

For accessibility purposes, SVGs should have an alternative text, provided via title element. If the svg element has role="img", you should add the aria-label or aria-labelledby attribute.

(lint/a11y/noSvgWithoutTitle)

🪛 GitHub Actions: CI
src/hooks/useMyPageQueries.ts

[error] 51-51: @typescript-eslint/no-unused-vars: 'setGlobalUser' is assigned a value but never used. Allowed unused vars must match /^[A-Z_]/u.

src/app/(with-header)/page.tsx

[error] 3-3: @typescript-eslint/no-unused-vars: 'useRouter' is defined but never used. Allowed unused vars must match /^[A-Z_]/u.


[error] 3-3: unused-imports/no-unused-imports: 'useRouter' is defined but never used.

🔇 Additional comments (34)
public/assets/svg/github.tsx (1)

1-21: 전반적인 컴포넌트 구조는 적절합니다.

GitHub 아이콘 SVG 컴포넌트의 구현이 잘 되어있고, props 구조와 기본값 설정이 적절합니다.

src/components/Footer.tsx (3)

14-19: 내비게이션 링크 기능이 제거된 이유를 확인해주세요.

Privacy Policy와 FAQ 링크가 앵커 태그에서 일반 div로 변경되어 클릭 기능이 사라졌습니다. 의도적인 변경인지 확인이 필요합니다.

만약 일시적으로 링크를 비활성화하려는 것이라면, 다음과 같이 접근성을 고려한 구현을 권장합니다:

-            <div className='transition-colors'>
+            <button className='transition-colors cursor-not-allowed opacity-50' disabled>
              Privacy Policy
-            </div>
+            </button>

Also applies to: 31-36


41-43: GitHub 링크 구현이 적절합니다.

새 탭에서 열리도록 하는 target='_blank'와 보안을 위한 rel='noopener noreferrer' 속성이 올바르게 설정되었고, 호버 효과도 잘 적용되었습니다.


1-1: GitHub 아이콘 컴포넌트 import 경로가 적절합니다.

새로 생성된 IconGithub 컴포넌트가 올바르게 import되고 사용되었습니다.

src/app/(with-header)/components/Skeletons/ExperienceCardSkeleton.tsx (1)

1-15: 스켈레톤 컴포넌트 구현이 잘 되었습니다.

실제 ExperienceCard와 동일한 구조를 가지고 있으며, 반응형 높이값도 적절히 설정되어 있습니다. animate-pulse 클래스를 사용한 로딩 애니메이션과 회색 배경으로 로딩 상태를 명확하게 표현했습니다.

src/app/(with-header)/components/Skeletons/PopularCardSkeleton.tsx (1)

1-15: 인기 카드 스켈레톤 구현이 우수합니다.

그라디언트 오버레이와 절대 위치 지정을 통해 실제 PopularCard의 구조를 잘 모방했습니다. 반응형 크기 조정과 적절한 텍스트 플레이스홀더 배치로 로딩 중에도 일관된 UI를 제공합니다.

src/components/ProfileDropdown.tsx (1)

45-45: 프로필 이미지 스타일링 개선이 적절합니다.

명시적인 크기 지정(w-32 h-32)과 object-cover 속성 추가로 이미지의 일관된 크기와 비율을 보장합니다. 다양한 크기의 프로필 이미지가 깔끔하게 표시될 것입니다.

src/app/(with-header)/components/ExperienceList.tsx (4)

11-11: 스켈레톤 컴포넌트 import 추가가 적절합니다.

로딩 상태 개선을 위한 ExperienceCardSkeleton 컴포넌트를 올바르게 import했습니다.


30-40: useQuery 간소화와 키워드 처리 개선이 좋습니다.

error 구조분해를 제거하고 keyword 처리를 undefined로 명시적으로 설정한 것이 깔끔합니다. API 호출 시 falsy 값 처리가 더 명확해졌습니다.


57-59: 검색 결과 없음 메시지 조건 개선이 우수합니다.

!isLoading 조건을 추가하여 로딩 중에는 "검색 결과가 없습니다" 메시지가 표시되지 않도록 한 것이 사용자 경험을 개선합니다.


92-108: 스켈레톤 로딩 구현이 훌륭합니다.

항상 그리드 컨테이너를 렌더링하고 로딩 상태에 따라 스켈레톤 또는 실제 카드를 조건부로 렌더링하는 방식이 레이아웃 안정성을 크게 향상시킵니다. 8개의 스켈레톤 카드로 일관된 로딩 경험을 제공합니다.

src/app/(with-header)/components/BannerSection.tsx (4)

5-9: Props 인터페이스 변경이 아키텍처 개선에 적절합니다.

onSearch 콜백에서 keyword 문자열로 변경한 것은 URL 기반 상태 관리로의 전환을 잘 반영합니다. 컴포넌트가 더 단순해지고 props drilling이 줄어듭니다.


18-18: 배너 이미지 경로 업데이트가 적절합니다.

테스트 이미지(/test/image1.png)에서 실제 메인 배너 이미지(/assets/img/main-banner.jpg)로 변경한 것이 프로덕션 준비에 적합합니다.


27-32: 배너 콘텐츠 업데이트가 매력적입니다.

오로라와 북극 감성을 테마로 한 새로운 텍스트가 시각적으로 매력적이고 브랜드 메시지를 잘 전달합니다. 이모지 사용도 친근한 느낌을 줍니다.


35-35: SearchBar props 전달 방식 개선이 일관성 있습니다.

keyword prop을 전달하는 방식이 다른 컴포넌트들의 변경사항과 일관성을 유지하며, URL 기반 검색 상태 관리 패턴에 잘 맞습니다.

src/components/Header.tsx (5)

4-4: useRouter 임포트가 적절히 추가되었습니다.

로고 클릭 시 쿼리 파라미터를 제거하여 검색어를 초기화하는 기능을 위해 useRouter가 올바르게 추가되었습니다.


16-16: 사용자 스토어 구조분해할당이 개선되었습니다.

hasHydrated 상태를 포함하여 한 번의 호출로 필요한 값들을 구조분해할당하는 것이 더 효율적입니다.


23-25: 로고 클릭 핸들러가 올바르게 구현되었습니다.

검색 후 로고 클릭 시 메인 페이지로 이동하면서 쿼리 파라미터를 제거하여 검색어를 초기화하는 기능이 명확하게 구현되었습니다.


38-60: 하이드레이션 전 스켈레톤 UI가 잘 구현되었습니다.

하이드레이션 완료 전까지 스켈레톤 UI를 보여주어 레이아웃 시프트를 방지하고 사용자 경험을 개선하는 좋은 접근법입니다. 스켈레톤의 크기와 애니메이션도 적절합니다.


44-50: 스켈레톤 상태에서도 로고 클릭 기능이 유지됩니다.

하이드레이션 전에도 로고 클릭으로 메인 페이지 이동이 가능하도록 handleLogoClick이 연결된 것이 좋습니다.

src/app/(with-header)/components/SearchBar.tsx (5)

5-6: 필요한 훅들이 적절히 임포트되었습니다.

useRouter와 useEffect 임포트가 새로운 URL 기반 상태 관리 패턴에 맞게 올바르게 추가되었습니다.


8-10: 인터페이스가 URL 기반 상태 관리에 맞게 개선되었습니다.

콜백 기반에서 keyword prop을 받는 방식으로 변경되어 더 예측 가능하고 URL과 동기화된 상태 관리가 가능해졌습니다.


12-14: 컴포넌트 초기화가 올바르게 구현되었습니다.

keyword prop으로 searchValue를 초기화하고 useRouter를 클라이언트에서 적절히 선언했습니다.


17-22: 검색 제출 로직이 잘 구현되었습니다.

빈 검색어 검증, URL 인코딩, 라우터 네비게이션이 모두 적절히 처리되었습니다. 쿼리 파라미터를 사용한 상태 관리 패턴이 일관성 있게 적용되었습니다.


25-27: 외부 keyword 변경에 대한 동기화가 적절합니다.

useEffect를 통해 외부에서 keyword prop이 변경될 때 내부 상태를 동기화하는 것이 올바른 패턴입니다.

src/middleware.ts (3)

7-8: 미들웨어 로직 변경에 대한 명확한 문서화가 되었습니다.

기존 로그인/회원가입 페이지 접근 차단 로직을 제거한 이유가 주석으로 잘 설명되어 있습니다.


21-24: 하이드레이션 타이밍 문제에 대한 적절한 해결책입니다.

서버 사이드에서 accessToken 존재 여부만으로 로그인 상태를 판단하면 클라이언트 하이드레이션 전에 잘못된 리다이렉트가 발생할 수 있습니다. 이를 클라이언트 사이드로 위임하는 것이 올바른 접근법입니다.


27-33: 보호된 경로에 대한 접근 제어가 적절히 유지되었습니다.

/mypage 경로에 대한 토큰 기반 접근 제어 로직은 그대로 유지되어 필요한 보안 기능은 계속 작동합니다.

src/hooks/useMyPageQueries.ts (2)

12-12: 전역 상태 동기화를 위한 스토어 임포트가 적절합니다.

마이페이지에서 업데이트된 사용자 정보를 헤더에 반영하기 위한 전역 상태 동기화 접근법이 좋습니다.


96-96: useUploadProfileImage의 전역 상태 동기화가 올바르게 구현되었습니다.

setGlobalUser 선언과 의존성 배열 추가가 적절히 처리되었습니다.

Also applies to: 150-150

src/app/(with-header)/page.tsx (2)

9-11: URL 기반 상태 관리로의 전환이 잘 구현되었습니다.

useSearchParams를 사용하여 URL에서 검색 키워드를 가져오고 검색 모드를 판단하는 로직이 명확하고 올바릅니다.


15-23: 컴포넌트 구조와 조건부 렌더링이 적절합니다.

keyword를 BannerSection으로 전달하고 검색 모드에 따라 다른 UI를 보여주는 로직이 잘 구현되었습니다.

src/app/(with-header)/components/PopularExperiences.tsx (2)

7-11: import 구문 정리가 잘 되었습니다.

아이콘 import를 그룹화하고 새로운 PopularCardSkeleton 컴포넌트를 추가한 것이 좋습니다. 코드 구성이 더욱 명확해졌습니다.


41-41: JSX 주석 추가로 가독성 향상

섹션별로 주석을 추가하여 코드 가독성이 개선되었습니다.

Also applies to: 50-50

@@ -0,0 +1,20 @@
import React from 'react';

const IconGithub = ({ size = 24, color = '#fff', ...props }) => (
Copy link

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

TypeScript 타입 정의 추가가 필요합니다.

컴포넌트의 props에 대한 TypeScript 인터페이스가 없어 타입 안전성이 보장되지 않습니다.

다음과 같이 props 타입을 정의해주세요:

+interface IconGithubProps extends React.SVGProps<SVGSVGElement> {
+  size?: number;
+  color?: string;
+}
+
-const IconGithub = ({ size = 24, color = '#fff', ...props }) => (
+const IconGithub: React.FC<IconGithubProps> = ({ size = 24, color = '#fff', ...props }) => (
📝 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 IconGithub = ({ size = 24, color = '#fff', ...props }) => (
interface IconGithubProps extends React.SVGProps<SVGSVGElement> {
size?: number;
color?: string;
}
const IconGithub: React.FC<IconGithubProps> = ({ size = 24, color = '#fff', ...props }) => (
🤖 Prompt for AI Agents
In public/assets/svg/github.tsx at line 3, the IconGithub component lacks
TypeScript type definitions for its props, reducing type safety. Define a
TypeScript interface for the props specifying size as a number and color as a
string, then apply this interface to the component's props parameter to ensure
proper type checking.

Comment on lines +4 to +17
<svg
width={size}
height={size}
viewBox="0 0 98 96"
fill={color}
xmlns="http://www.w3.org/2000/svg"
{...props}
>
<path
fillRule="evenodd"
clipRule="evenodd"
d="M48.854 0C21.839 0 0 22 0 49.217c0 21.756 13.993 40.172 33.405 46.69 2.427.49 3.316-1.059 3.316-2.362 0-1.141-.08-5.052-.08-9.127-13.59 2.934-16.42-5.867-16.42-5.867-2.184-5.704-5.42-7.17-5.42-7.17-4.448-3.015.324-3.015.324-3.015 4.934.326 7.523 5.052 7.523 5.052 4.367 7.496 11.404 5.378 14.235 4.074.404-3.178 1.699-5.378 3.074-6.6-10.839-1.141-22.243-5.378-22.243-24.283 0-5.378 1.94-9.778 5.014-13.2-.485-1.222-2.184-6.275.486-13.038 0 0 4.125-1.304 13.426 5.052a47 47 0 0 1 12.214-1.63c4.125 0 8.33.571 12.213 1.63 9.302-6.356 13.427-5.052 13.427-5.052 2.67 6.763.97 11.816.485 13.038 3.155 3.422 5.015 7.822 5.015 13.2 0 18.905-11.404 23.06-22.324 24.283 1.78 1.548 3.316 4.481 3.316 9.126 0 6.6-.08 11.897-.08 13.526 0 1.304.89 2.853 3.316 2.364 19.412-6.52 33.405-24.935 33.405-46.691C97.707 22 75.788 0 48.854 0"
/>
</svg>
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue

접근성 개선을 위해 title 요소 또는 aria-label 추가가 필요합니다.

정적 분석 도구에서 지적한 대로, 접근성을 위해 SVG에 대한 대체 텍스트가 필요합니다.

다음 중 하나의 방법으로 해결할 수 있습니다:

  <svg
    width={size}
    height={size}
    viewBox="0 0 98 96"
    fill={color}
    xmlns="http://www.w3.org/2000/svg"
+   aria-label="GitHub"
    {...props}
  >
+   <title>GitHub</title>
    <path
📝 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
<svg
width={size}
height={size}
viewBox="0 0 98 96"
fill={color}
xmlns="http://www.w3.org/2000/svg"
{...props}
>
<path
fillRule="evenodd"
clipRule="evenodd"
d="M48.854 0C21.839 0 0 22 0 49.217c0 21.756 13.993 40.172 33.405 46.69 2.427.49 3.316-1.059 3.316-2.362 0-1.141-.08-5.052-.08-9.127-13.59 2.934-16.42-5.867-16.42-5.867-2.184-5.704-5.42-7.17-5.42-7.17-4.448-3.015.324-3.015.324-3.015 4.934.326 7.523 5.052 7.523 5.052 4.367 7.496 11.404 5.378 14.235 4.074.404-3.178 1.699-5.378 3.074-6.6-10.839-1.141-22.243-5.378-22.243-24.283 0-5.378 1.94-9.778 5.014-13.2-.485-1.222-2.184-6.275.486-13.038 0 0 4.125-1.304 13.426 5.052a47 47 0 0 1 12.214-1.63c4.125 0 8.33.571 12.213 1.63 9.302-6.356 13.427-5.052 13.427-5.052 2.67 6.763.97 11.816.485 13.038 3.155 3.422 5.015 7.822 5.015 13.2 0 18.905-11.404 23.06-22.324 24.283 1.78 1.548 3.316 4.481 3.316 9.126 0 6.6-.08 11.897-.08 13.526 0 1.304.89 2.853 3.316 2.364 19.412-6.52 33.405-24.935 33.405-46.691C97.707 22 75.788 0 48.854 0"
/>
</svg>
<svg
width={size}
height={size}
viewBox="0 0 98 96"
fill={color}
xmlns="http://www.w3.org/2000/svg"
aria-label="GitHub"
{...props}
>
<title>GitHub</title>
<path
fillRule="evenodd"
clipRule="evenodd"
d="M48.854 0C21.839 0 0 22 0 49.217c0 21.756 13.993 40.172 33.405 46.69 2.427.49 3.316-1.059 3.316-2.362 0-1.141-.08-5.052-.08-9.127-13.59 2.934-16.42-5.867-16.42-5.867-2.184-5.704-5.42-7.17-5.42-7.17-4.448-3.015.324-3.015.324-3.015 4.934.326 7.523 5.052 7.523 5.052 4.367 7.496 11.404 5.378 14.235 4.074.404-3.178 1.699-5.378 3.074-6.6-10.839-1.141-22.243-5.378-22.243-24.283 0-5.378 1.94-9.778 5.014-13.2-.485-1.222-2.184-6.275.486-13.038 0 0 4.125-1.304 13.426 5.052a47 47 0 0 1 12.214-1.63c4.125 0 8.33.571 12.213 1.63 9.302-6.356 13.427-5.052 13.427-5.052 2.67 6.763.97 11.816.485 13.038 3.155 3.422 5.015 7.822 5.015 13.2 0 18.905-11.404 23.06-22.324 24.283 1.78 1.548 3.316 4.481 3.316 9.126 0 6.6-.08 11.897-.08 13.526 0 1.304.89 2.853 3.316 2.364 19.412-6.52 33.405-24.935 33.405-46.691C97.707 22 75.788 0 48.854 0"
/>
</svg>
🧰 Tools
🪛 Biome (2.1.2)

[error] 4-11: Alternative text title element cannot be empty

For accessibility purposes, SVGs should have an alternative text, provided via title element. If the svg element has role="img", you should add the aria-label or aria-labelledby attribute.

(lint/a11y/noSvgWithoutTitle)

🤖 Prompt for AI Agents
In public/assets/svg/github.tsx around lines 4 to 17, the SVG element lacks
accessibility features such as a title element or aria-label, which are needed
for screen readers. To fix this, add a <title> element inside the SVG with a
descriptive text or add an aria-label attribute to the SVG tag describing the
image. This will provide alternative text for assistive technologies and improve
accessibility.

Comment on lines +30 to 40
const { data, isLoading } = useQuery<ExperienceListResult>({
queryKey: ['experiences', currentPage, selectedCategory, sortOption, keyword],
queryFn: () =>
getExperiences({
page: currentPage,
sort: sortOption,
category: selectedCategory,
keyword,
keyword: keyword || undefined,
}),
placeholderData: (prev) => prev,
});
Copy link

Choose a reason for hiding this comment

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

💡 Verification agent

🧩 Analysis chain

에러 처리 고려사항

error 구조분해를 제거했는데, 사용자에게 API 에러 상황을 알려주는 방법을 고려해보시기 바랍니다. 현재는 로딩이 실패해도 빈 목록만 표시됩니다.

다음 스크립트로 에러 처리 패턴을 확인해보겠습니다:


🏁 Script executed:

#!/bin/bash
# Description: Check error handling patterns in similar components

# Search for error handling in other list components
rg -A 10 -B 5 "useQuery.*error" --type tsx

Length of output: 72


다음 스크립트로 TSX 파일들에서 useQuery 호출 및 error 구조분해/사용 패턴을 확인해 보겠습니다.


🏁 Script executed:

#!/bin/bash
# Description: TSX 컴포넌트에서 useQuery 호출 및 error 구조분해 패턴 검색

# 1. useQuery 사용 파일 목록
echo "■ useQuery 사용 TSX 파일:"
rg -l "useQuery(" -g '*.tsx' || true

echo ""
# 2. useQuery 호출 내 error 구조분해 또는 error 사용 패턴
echo "■ useQuery 호출에서 error 구조분해/사용 패턴:"
rg -n -C2 "{[^}]*error" -g '*.tsx' || true

Length of output: 378


TSX 파일에서 useQuery 호출과 error 구조분해/사용 패턴을 올바르게 검색하도록 정규식을 수정한 스크립트를 실행해 보겠습니다.


🏁 Script executed:

#!/bin/bash
# TSX 컴포넌트에서 useQuery 호출 및 error 구조분해/사용 패턴 검색

echo "■ useQuery 사용 파일:"
rg -l "useQuery" -g '*.tsx' || true

echo ""
echo "■ useQuery 호출 라인:"
rg -n "useQuery" -g '*.tsx' || true

echo ""
echo "■ error 구조분해 사용 패턴 (예: const { data, error } = useQuery(...)):"
rg -n "const \\{[^\\}]*error[^\\}]*\\}" -g '*.tsx' || true

Length of output: 2270


ExperienceList.tsx에 에러 핸들링 추가 필요

다른 목록 컴포넌트(e.g. PopularExperiences.tsx)에서는 useQuery 호출 시 error를 구조분해하고 에러 UI를 렌더링하고 있습니다. ExperienceList도 동일하게 처리해 주세요.

• 파일: src/app/(with-header)/components/ExperienceList.tsx

  • 30번째 줄:
    - const { data, isLoading } = useQuery<ExperienceListResult>({
    + const { data, isLoading, error } = useQuery<ExperienceListResult>({
  • error가 있을 때 사용자에게 안내 메시지나 에러 컴포넌트를 보여주도록 추가 처리
    if (error) {
      return <ErrorMessage message="경험 목록을 불러오는 중 오류가 발생했습니다. 다시 시도해 주세요." />;
    }
🤖 Prompt for AI Agents
In src/app/(with-header)/components/ExperienceList.tsx around lines 30 to 40,
the useQuery hook destructures data and isLoading but does not handle the error
state. Update the destructuring to also include error from useQuery, then add a
conditional check for error. If error exists, return an ErrorMessage component
with a user-friendly message indicating that loading the experience list failed
and suggesting to retry.

Comment on lines +55 to +80
{error ? (
<p className="text-red-500 text-sm">인기 체험을 불러오는 데 실패했습니다 😢</p>
) : isLoading || !data ? (
Array.from({ length: 4 }).map((_, idx) => (
<div key={idx} className="flex-shrink-0 card">
<PopularCardSkeleton />
</div>
))
) : (
data.activities.map((exp) => (
<div key={exp.id} className='flex-shrink-0 card'>
<Link
href={`/activities/${exp.id}`}
className='flex-shrink-0 card'
>
<PopularCard
imageUrl={exp.bannerImageUrl}
price={exp.price}
rating={exp.rating}
reviews={exp.reviewCount}
title={exp.title}
/>
</Link>
</div>
))
)}
Copy link

Choose a reason for hiding this comment

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

🧹 Nitpick (assertive)

로딩 상태 처리 개선이 우수합니다.

early return 패턴에서 조건부 렌더링으로 변경한 것이 좋습니다. 다음과 같은 장점이 있습니다:

  • 일관된 레이아웃 구조 유지
  • 로딩 중 4개의 스켈레톤 UI로 사용자 경험 향상
  • 에러 상태에 대한 명확한 피드백 제공

다만 한 가지 개선사항이 있습니다:

65-68번 라인에서 card 클래스가 중복 적용되고 있습니다:

-            <div key={exp.id} className='flex-shrink-0 card'>
-              <Link
-                href={`/activities/${exp.id}`}
-                className='flex-shrink-0 card'
-              >
+            <div key={exp.id} className='flex-shrink-0 card'>
+              <Link href={`/activities/${exp.id}`}>
📝 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
{error ? (
<p className="text-red-500 text-sm">인기 체험을 불러오는 데 실패했습니다 😢</p>
) : isLoading || !data ? (
Array.from({ length: 4 }).map((_, idx) => (
<div key={idx} className="flex-shrink-0 card">
<PopularCardSkeleton />
</div>
))
) : (
data.activities.map((exp) => (
<div key={exp.id} className='flex-shrink-0 card'>
<Link
href={`/activities/${exp.id}`}
className='flex-shrink-0 card'
>
<PopularCard
imageUrl={exp.bannerImageUrl}
price={exp.price}
rating={exp.rating}
reviews={exp.reviewCount}
title={exp.title}
/>
</Link>
</div>
))
)}
{error ? (
<p className="text-red-500 text-sm">인기 체험을 불러오는 데 실패했습니다 😢</p>
) : isLoading || !data ? (
Array.from({ length: 4 }).map((_, idx) => (
<div key={idx} className="flex-shrink-0 card">
<PopularCardSkeleton />
</div>
))
) : (
data.activities.map((exp) => (
<div key={exp.id} className='flex-shrink-0 card'>
<Link href={`/activities/${exp.id}`}>
<PopularCard
imageUrl={exp.bannerImageUrl}
price={exp.price}
rating={exp.rating}
reviews={exp.reviewCount}
title={exp.title}
/>
</Link>
</div>
))
)}
🤖 Prompt for AI Agents
In src/app/(with-header)/components/PopularExperiences.tsx between lines 55 and
80, the 'card' class is applied twice on the same element in lines 65-68,
causing redundant class usage. Remove the duplicate 'card' class from either the
wrapping div or the Link component to avoid unnecessary repetition while
preserving the intended styling and layout.

export const useUpdateProfile = () => {
const queryClient = useQueryClient();
const { setUser, setLoading, setError } = useMyPageStore();
const setGlobalUser = useUserStore((state) => state.setUser); // 헤더 상태 갱신 함수
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue

useUpdateProfile에서 setGlobalUser가 사용되지 않고 있습니다.

파이프라인 오류에서 보듯이 setGlobalUser가 선언되었지만 사용되지 않고 있습니다. 프로필 업데이트 후 전역 상태도 동기화해야 합니다.

useEffect 내에서 setGlobalUser를 호출하도록 수정하세요:

     if (mutation.isSuccess && mutation.data) {
       setUser(mutation.data);
+      setGlobalUser(mutation.data); // 전역 상태도 동기화
       setLoading(false);
       // 캐시 업데이트
       queryClient.setQueryData(QUERY_KEYS.PROFILE, mutation.data);
       alert('프로필이 성공적으로 업데이트되었습니다!');
     }

그리고 의존성 배열에도 setGlobalUser를 추가해야 합니다:

   }, [
     mutation.isPending,
     mutation.isSuccess,
     mutation.isError,
     mutation.data,
     mutation.error,
     queryClient,
     setUser,
+    setGlobalUser,
     setLoading,
     setError,
   ]);
📝 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 setGlobalUser = useUserStore((state) => state.setUser); // 헤더 상태 갱신 함수
useEffect(() => {
if (mutation.isSuccess && mutation.data) {
setUser(mutation.data);
setGlobalUser(mutation.data); // 전역 상태도 동기화
setLoading(false);
// 캐시 업데이트
queryClient.setQueryData(QUERY_KEYS.PROFILE, mutation.data);
alert('프로필이 성공적으로 업데이트되었습니다!');
}
}, [
mutation.isPending,
mutation.isSuccess,
mutation.isError,
mutation.data,
mutation.error,
queryClient,
setUser,
setGlobalUser,
setLoading,
setError,
]);
🧰 Tools
🪛 GitHub Actions: CI

[error] 51-51: @typescript-eslint/no-unused-vars: 'setGlobalUser' is assigned a value but never used. Allowed unused vars must match /^[A-Z_]/u.

🤖 Prompt for AI Agents
In src/hooks/useMyPageQueries.ts at line 51, the setGlobalUser function is
declared but not used, causing the global user state to not update after profile
changes. To fix this, call setGlobalUser inside the useEffect hook that handles
profile updates to synchronize the global state, and add setGlobalUser to the
useEffect dependency array to ensure proper effect execution.

Comment on lines +128 to +132
setLoading(false);
setGlobalUser(updatedUser); // [추가] 헤더 상태(authStore)도 동기화

queryClient.setQueryData(QUERY_KEYS.PROFILE, updatedUser);

Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue

코드 중복이 발생했습니다.

Lines 128-132에서 setLoading(false)와 queryClient.setQueryData 호출이 중복되어 있습니다.

중복된 코드를 제거하세요:

       setUser(updatedUser);
       queryClient.setQueryData(QUERY_KEYS.PROFILE, updatedUser);

-      setLoading(false);
       setGlobalUser(updatedUser); // [추가] 헤더 상태(authStore)도 동기화

-      queryClient.setQueryData(QUERY_KEYS.PROFILE, updatedUser);
-
       setLoading(false);
       alert('프로필 이미지가 성공적으로 업로드되었습니다!');
📝 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
setLoading(false);
setGlobalUser(updatedUser); // [추가] 헤더 상태(authStore)도 동기화
queryClient.setQueryData(QUERY_KEYS.PROFILE, updatedUser);
setUser(updatedUser);
queryClient.setQueryData(QUERY_KEYS.PROFILE, updatedUser);
setGlobalUser(updatedUser); // [추가] 헤더 상태(authStore)도 동기화
setLoading(false);
alert('프로필 이미지가 성공적으로 업로드되었습니다!');
🤖 Prompt for AI Agents
In src/hooks/useMyPageQueries.ts around lines 128 to 132, the calls to
setLoading(false) and queryClient.setQueryData are duplicated. Remove the
redundant calls so that each function is only called once to eliminate code
duplication.

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

📜 Review details

Configuration used: CodeRabbit UI
Review profile: ASSERTIVE
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between c6df176 and 345904c.

📒 Files selected for processing (1)
  • src/app/(with-header)/page.tsx (1 hunks)
🧰 Additional context used
🪛 GitHub Actions: CI
src/app/(with-header)/page.tsx

[warning] 3-17: simple-import-sort/imports and react/jsx-sort-props: Run autofix to sort imports; shorthand props must be listed before all other props.

Comment on lines 16 to 18
{isSearchMode ? (
<ExperienceList keyword={keyword} isSearchMode />
) : (
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue

JSX prop 순서로 인한 react/jsx-sort-props 경고 수정

Shorthand prop(값 없이 존재 자체가 true인 prop)은 다른 prop보다 앞에 와야 합니다.

-        <ExperienceList keyword={keyword} isSearchMode />
+        <ExperienceList isSearchMode keyword={keyword} />
📝 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
{isSearchMode ? (
<ExperienceList keyword={keyword} isSearchMode />
) : (
{isSearchMode ? (
<ExperienceList isSearchMode keyword={keyword} />
) : (
🤖 Prompt for AI Agents
In src/app/(with-header)/page.tsx around lines 16 to 18, the shorthand prop
isSearchMode should be placed before the keyword prop to comply with the
react/jsx-sort-props rule. Reorder the props so that isSearchMode appears first,
followed by keyword.

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: 1

♻️ Duplicate comments (2)
src/hooks/useMyPageQueries.ts (2)

51-87: 이전 리뷰 코멘트의 문제가 여전히 해결되지 않았습니다.

setGlobalUser가 여전히 사용되지 않고 있어 프로필 업데이트 후 전역 상태가 동기화되지 않습니다. useEffect 내에서 setGlobalUser를 호출해야 합니다.

mutation.isSuccess 블록에서 setGlobalUser를 호출하도록 수정하세요:

     if (mutation.isSuccess && mutation.data) {
       setUser(mutation.data);
+      setGlobalUser(mutation.data); // 전역 상태도 동기화
       setLoading(false);
       // 캐시 업데이트
       queryClient.setQueryData(QUERY_KEYS.PROFILE, mutation.data);
       alert('프로필이 성공적으로 업데이트되었습니다!');
     }

129-133: 코드 중복이 발생했습니다.

Lines 129, 132, 134에서 setLoading(false)와 queryClient.setQueryData 호출이 중복되어 있습니다.

중복된 코드를 제거하세요:

       setUser(updatedUser);
       queryClient.setQueryData(QUERY_KEYS.PROFILE, updatedUser);

-      setLoading(false);
       setGlobalUser(updatedUser); // [추가] 헤더 상태(authStore)도 동기화

-      queryClient.setQueryData(QUERY_KEYS.PROFILE, updatedUser);
-
       setLoading(false);
       alert('프로필 이미지가 성공적으로 업로드되었습니다!');
📜 Review details

Configuration used: CodeRabbit UI
Review profile: ASSERTIVE
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 345904c and 1a52803.

📒 Files selected for processing (1)
  • src/hooks/useMyPageQueries.ts (6 hunks)
🧰 Additional context used
🧬 Code Graph Analysis (1)
src/hooks/useMyPageQueries.ts (1)
src/app/(with-header)/mypage/profile/page.tsx (1)
  • ProfilePage (14-183)
🪛 GitHub Actions: CI
src/hooks/useMyPageQueries.ts

[warning] 3-3: simple-import-sort/imports: Run autofix to sort these imports.

🔇 Additional comments (1)
src/hooks/useMyPageQueries.ts (1)

97-97: 전역 상태 동기화 구현이 올바릅니다.

useUploadProfileImage hook에서 setGlobalUser 함수를 올바르게 선언했습니다. 이는 프로필 이미지 업로드 후 헤더의 사용자 상태를 실시간으로 업데이트하는 데 필요합니다.

import { UpdateProfileRequest } from '@/types/mypageTypes';
import useMyPageStore from '@/stores/MyPage/useMyPageStore';
import { useEffect } from 'react';
import useUserStore from '@/stores/authStore';
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue

Import 정렬 문제 수정이 필요합니다.

파이프라인 실패 로그에서 지적된 대로 import 구문의 정렬을 수정해야 합니다.

-import useUserStore from '@/stores/authStore';

이 import를 다른 import들과 함께 정렬된 순서로 배치하세요.

Committable suggestion skipped: line range outside the PR's diff.

🤖 Prompt for AI Agents
In src/hooks/useMyPageQueries.ts at line 12, the import statement for
useUserStore is not properly sorted. Rearrange this import together with the
other import statements in the file so that all imports are in a consistent,
sorted order, typically alphabetically or following the project's import sorting
conventions.

Copy link
Contributor

@evaain706 evaain706 left a comment

Choose a reason for hiding this comment

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

수고하셨습니다!
헤더 플리커링 이슈도 hasHydrated를 사용해서 잘 해결해주셨고
푸터와 스켈레톤도 잘 수정해주셨네요!

Copy link
Contributor

@minimo-9 minimo-9 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

@LeeCh0129 LeeCh0129 left a comment

Choose a reason for hiding this comment

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

고생하셨습니다!

@BokyungCodes BokyungCodes merged commit d5609e8 into develop Aug 3, 2025
2 checks passed
@BokyungCodes BokyungCodes deleted the fix/113 branch August 3, 2025 10:08
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

📬 API 서버 api 통신관련 🐞 bug 버그관련 💻 chore 사소한 수정(빌드,패키지매니저등) ✨ Feature 기능구현 🔨 Refactor 코드 리팩토링 🎨 style 마크업 및 스타일링

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[fix] 헤더, 푸터, 메인 페이지 이슈 수정

5 participants