Skip to content

Conversation

@WonJuneKim
Copy link
Collaborator

@WonJuneKim WonJuneKim commented Mar 13, 2025

💡 작업 내용

  • 모바일 마이페이지 구현
  • 마이페이지 커스텀 훅 재조정
  • 마이페이지 무한 스크롤 재조정
  • 추가 컴포넌트 구현
  • 모바일 라우팅 설정

💡 자세한 설명

작업한 내용들이 git 오류로 인해..... push가 안되어서 해결하다가 그냥 새로 클론을 받고 수동 커밋을 해버린 슬픈 사연이 있습니다.... 이것만 며칠을 트라이했네요 ㅠ(force push 는 위험성이 너무 크다고 판단하여 새롭게 클론 후 구현)

✅ 모바일에서의 쿼리 호출

  const gameBookmarksQ = useMyGameBookmarksQuery({
    enabled: activeTab === 'balanceGame' && activeButton === 'saved',
  });
  const gameVotesQ = useMyGameVotesQuery(member!.id, {
    enabled: activeTab === 'balanceGame' && activeButton === 'voted',
  });

와 같이 enabled 속성을 넣어서 특정 조건(state)이 만족되어야 쿼리가 실행되도록 설정하였습니다. 이는 모바일의 경우 웹과 다르게 Outlet을 이용한 구조가 아닌, 단일 페이지이기 때문에 처리한 부분입니다.

(실제 영상)

default.mp4
default.mp4

✅ 마이페이지 전체 쿼리 수정

  • 웹과 모바일 모두 사용할 수 있게 InfinityQuery의 구조를 변경하였습니다. 해당 수정 사항을 통해 웹과 모바일 모두 무한 데이터 형태를 호출합니다.

✅ MenuTap props 수정

  • MenuTap의 경우 모바일에서 아이콘 컴포넌트 까지 넣어야 하고, atoms 라는 basic한 컴포넌트이기 때문에 label로 받는 타입을 기존 string 에서 ReactNode 로 변경하였습니다.
  • 해당 수정 사항에 영향을 받는 다른 컴포넌트들도 수정을 해주었습니다.
  • 이에 대한 파생 효과로 기존 label 값으로 mapping 하던 로직을 id 를 추가 부여해 이에 따른 mapping 을 수행하도록 처리하였습니다.

✅ 기타

  • 모바일 마이페이지의 경우 데이터를 response를 받은 이후 후처리 하는 과정에서 타입 단언을 사용하게 되었습니다. 최대한 지양해야하는 부분이지만, 해당 처리를 지양하기 위한 부수 효과가 매우 크게 발생하기 때문에 현상 유지하는 방향으로 구현하였습니다.

📗 참고 자료 (선택)

📢 리뷰 요구 사항 (선택)

  • 마이페이지 웹에서 사용하는 url은 모바일에서 사용하지 않는데, 이 url로 접근하면 빈 화면이 나옵니다. 해당 페이지에 대한 접근을 디바이스 별로 막아야 할까요?

🚩 후속 작업 (선택)

✅ 셀프 체크리스트

  • PR 제목을 형식에 맞게 작성했나요?
  • 브랜치 전략에 맞는 브랜치에 PR을 올리고 있나요? (master/main이 아닙니다.)
  • 이슈는 close 했나요?
  • Reviewers, Labels, Projects를 등록했나요?
  • 작업 도중 문서 수정이 필요한 경우 잘 수정했나요?
  • 테스트는 잘 통과했나요?
  • 불필요한 코드는 제거했나요?

closes #273

Summary by CodeRabbit

  • New Features

    • 모바일 전용 라우팅이 추가되어, 모바일 기기 사용 시 전용 페이지로 원활하게 전환됩니다.
    • 새로운 모바일 페이지에서 게임 북마크, 투표, 작성글 등 콘텐츠를 날짜별로 그룹화하여 보다 쉽게 확인할 수 있습니다.
  • Style Updates

    • 메뉴와 레이아웃 스타일을 개선하여, 작은 화면에서도 유연한 콘텐츠 표시와 적절한 패딩이 유지됩니다.
  • Asset Enhancements

    • 추가된 이미지와 SVG 자산으로 시각적 표현이 강화되었습니다.

@WonJuneKim WonJuneKim requested review from alwubin and areumH March 13, 2025 22:44
@WonJuneKim WonJuneKim self-assigned this Mar 13, 2025
@github-project-automation github-project-automation bot moved this to Todo in PICK-O Mar 13, 2025
@coderabbitai
Copy link
Contributor

coderabbitai bot commented Mar 13, 2025

Walkthrough

이번 PR은 모바일 환경에 특화된 라우팅 로직과 UI 개선을 도입합니다. App 컴포넌트에서 모바일 기기 여부를 확인하여 MyMobilePage를 렌더링하며, 데스크탑에서는 기존의 MyPage와 하위 라우트를 유지합니다. 또한, 신규 자산 추가, 여러 컴포넌트의 타입 및 스타일 업데이트, 스토리북 예제 보강, 그리고 API 훅 함수 시그니처 개선을 포함하여 기존 코드베이스의 구조적 안전성과 유연성을 향상시켰습니다.

Changes

파일 경로 변경 요약
src/App.tsx 모바일 기기 확인 후 MyMobilePage를 렌더링하도록 라우팅 로직 변경 (데스크탑에서는 기존 MyPage 유지)
src/assets/index.ts MobileCardSampleFirst, MobileCardSampleSecond, SmileEmoji 자산 추가
src/components/atoms/MenuTap/MenuTap.style.ts
src/components/atoms/MenuTap/MenuTap.tsx
MenuTap 스타일 수정 (고정 폭에서 내용 기반 동적 폭과 최소 폭 추가) 및 메뉴 아이템 타입에 필수 id 추가, key prop 업데이트
src/components/mobile/molecules/ProfileListItem/ProfileListItem.tsx
src/components/mobile/molecules/ProfileListItem/ProfileListItem.stories.tsx
랜덤 이미지 선택 기능 도입, imgUrl 선택적 처리, to 프로퍼티 추가로 라우팅 지원 및 스토리북에서 경로 설정 반영
src/components/mobile/organisms/BalanceGameSection/BalanceGameSection.tsx 메뉴 아이템(myGameItem, otherGameItem)에 유니크 id 필드 추가
src/components/mobile/organisms/DateGroupedCard/DateGroupedCard.tsx
src/components/mobile/organisms/DateGroupedCard/DateGroupedCard.stories.tsx
src/components/mobile/organisms/DateGroupedCard/DateGroupedCard.style.ts
새로운 DateGroupedCard 컴포넌트, 스타일 및 스토리북 예제 추가
src/components/mobile/organisms/DateGroupedList/DateGroupedList.tsx imgUrl 프로퍼티를 선택적(imgUrl?: string)로 변경하고, ProfileListItemto 프로퍼티 추가
src/components/mobile/organisms/IconButtonArea/IconButtonArea.tsx 신규 인터페이스 IconButtonConfig 도입 및 IconButtonAreaProps 타입 업데이트로 타입 명시 강화
src/components/mobile/organisms/ProfileInfoCard/ProfileInfoCard.tsx
src/components/mobile/organisms/ProfileInfoCard/ProfileInfoCard.stories.tsx
menuDataid 필드 추가 및 label의 타입을 ReactNode로 변경하여 유연성 향상
src/components/mobile/organisms/TalkPickSection/TalkPickSection.tsx 메뉴 아이템(myTalkPickItem, otherTalkPickItem)에 id 프로퍼티 추가 및 코드 포맷팅 개선
src/components/molecules/CommentItem/CommentItem.tsx
src/components/molecules/ReplyItem/ReplyItem.tsx
댓글 관련 메뉴 아이템들에 유니크 id 추가
src/components/molecules/ContentsButton/ContentsButton.tsx images 프로퍼티를 선택적(images?: string[])으로 변경
src/hooks/api/mypages/useInfiniteScroll.ts
API 훅 관련 파일들:
useMyGameBookmarksQuery.ts, useMyGameVotesQuery.ts, useMyGameWrittensQuery.ts, useMyTalkPickBookmarksQuery.ts, useMyTalkPickCommentsQuery.ts, useMyTalkPickVotesQuery.ts, useMyTalkPickWrittensQuery.ts
useInfiniteScroll 훅의 옵션 파라미터 도입 및 함수 시그니처 개선. 각 API 훅에서 추가 옵션 파라미터를 수용하도록 업데이트
src/layout/layout.tsx 미디어 쿼리를 이용하여 뷰포트 430px 이하에서 main 영역의 paddingTop을 55px로 조정
src/pages/mobile/MyMobilePage/MyMobilePage.style.ts
src/pages/mobile/MyMobilePage/MyMobilePage.tsx
새로운 모바일 페이지 MyMobilePage 컴포넌트 및 관련 스타일 추가 (데이터 페칭, 무한 스크롤, 라우팅 등 포함)
src/stories/atoms/MenuTap.stories.tsx 스토리북 내 메뉴 아이템 배열에 id 프로퍼티 추가
src/types/mypages.ts TalkPickBaseInfoItem, MyContentItem, InfoItem에 선택적 imgUrls 프로퍼티 추가 및 새로운 타입(TabType, ButtonType, AllQueryData) 정의

Sequence Diagram(s)

sequenceDiagram
    participant U as 사용자
    participant A as App 컴포넌트
    participant M as MyMobilePage
    participant D as MyPage
    
    U->>A: 페이지 요청
    A->>A: isMobile 여부 확인
    alt 모바일 기기
        A->>M: MyMobilePage 렌더링 (/MYPAGE 경로)
    else 데스크탑
        A->>D: MyPage 및 하위 라우트 렌더링 (talkpick, balancegame)
    end
Loading

Possibly related PRs

Suggested labels

🎨 markup

Suggested reviewers

  • alwubin
  • areumH

Poem

귀여운 토끼 한 마리,
코드 숲속을 뛰어다니며
모바일 길도 척척 해결해요.
라우팅도 멋지게 변신하고,
자산과 스타일도 반짝반짝,
오늘도 기분 좋은 코드의 날,
토끼는 행복하게 춤춰요!

Tip

⚡🧪 Multi-step agentic review comment chat (experimental)
  • We're introducing multi-step agentic chat in review comments. This experimental feature enhances review discussions with the CodeRabbit agentic chat by enabling advanced interactions, including the ability to create pull requests directly from comments.
    - To enable this feature, set early_access to true under in the settings.
✨ Finishing Touches
  • 📝 Generate Docstrings

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.
    • Generate unit testing code for this file.
    • 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 generate unit testing code for this file.
    • @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 generate unit testing code.
    • @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.

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 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.

Copy link
Contributor

@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

🔭 Outside diff range comments (1)
src/App.tsx (1)

162-164: ⚠️ Potential issue

조건부 연산자 사용 오류가 있습니다.

-{isMobile ?? ( // TODO: 404페이지 생성시 조건부로 수정
+{isMobile && ( // TODO: 404페이지 생성시 조건부로 수정
  <Route path={PATH.NOTIFICATION} element={<NotificationPage />} />
)}

여기서는 ?? 연산자(널 병합 연산자) 대신 && 연산자(논리 AND)를 사용해야 합니다. 널 병합 연산자는 왼쪽 피연산자가 null이나 undefined일 때 오른쪽 피연산자를 반환하는데, 이 경우에는 isMobile이 true일 때만 NotificationPage를 렌더링하는 논리가 필요합니다.

🧹 Nitpick comments (8)
src/hooks/api/mypages/useMyTalkPickCommentsQuery.ts (1)

11-30: 훅 함수의 일관된 개선이 이루어졌습니다!

다른 훅들과 마찬가지로 options 매개변수를 추가하여 쿼리 실행의 유연성을 높였습니다. 이는 특히 모바일 환경에서 조건부 쿼리 실행에 유용할 것입니다.

한 가지 제안: 이러한 옵션의 사용 목적과 가능한 값들에 대한 간단한 문서화(JSDoc 등)를 추가하면 미래의 개발자들이 이 훅을 더 쉽게 이해하고 활용할 수 있을 것입니다.

src/hooks/api/mypages/useMyGameWrittensQuery.ts (1)

12-37: 모든 마이페이지 훅에 일관된 개선이 완료되었습니다!

다른 훅들과 마찬가지로 options 매개변수를 추가하여 무한 스크롤 기능의 유연성을 높였습니다. 이러한 일관된 변경은 PR 목표인 "마이페이지를 위한 무한 스크롤 기능 재설계"를 효과적으로 지원합니다.

추가 제안: 이러한 옵션 처리가 올바르게 작동하는지 확인하는 단위 테스트를 추가하면 좋을 것 같습니다. 특히 enabled 옵션이 모바일 환경에서 조건부 쿼리 실행에 어떻게 영향을 미치는지 테스트하면 유용할 것입니다.

src/components/mobile/organisms/BalanceGameSection/BalanceGameSection.tsx (4)

13-13: 경로 표기 오류가 발견되었습니다.

-import Button from '@/components/mobile//atoms/Button/Button';
+import Button from '@/components/mobile/atoms/Button/Button';

이중 슬래시('//')가 경로에 있습니다. 경로 표기법을 일관되게 유지하려면 수정이 필요합니다.


14-14: 경로 표기 오류가 발견되었습니다.

-import IconButton from '@/components/mobile//atoms/IconButton/IconButton';
+import IconButton from '@/components/mobile/atoms/IconButton/IconButton';

이중 슬래시('//')가 경로에 있습니다. 경로 표기법을 일관되게 유지하려면 수정이 필요합니다.


15-16: 경로 표기 오류가 발견되었습니다.

-import GameTag from '@/components/mobile//atoms/GameTag/GameTag';
-import GameTagChip from '@/components/mobile//atoms/GameTagChip/GameTagChip';
+import GameTag from '@/components/mobile/atoms/GameTag/GameTag';
+import GameTagChip from '@/components/mobile/atoms/GameTagChip/GameTagChip';

이중 슬래시('//')가 경로에 있습니다. 경로 표기법을 일관되게 유지하려면 수정이 필요합니다.


17-17: 경로 표기 오류가 발견되었습니다.

-import GameStageLabel from '@/components/mobile//atoms/GameStageLabel/GameStageLabel';
+import GameStageLabel from '@/components/mobile/atoms/GameStageLabel/GameStageLabel';

이중 슬래시('//')가 경로에 있습니다. 경로 표기법을 일관되게 유지하려면 수정이 필요합니다.

src/components/mobile/organisms/DateGroupedCard/DateGroupedCard.style.ts (1)

5-11: containerStyle 정의가 적절합니다.

컨테이너 스타일이 명확하게 정의되어 있습니다. 다만, 고정 너비(333px)를 사용하고 있어 다양한 모바일 화면 크기에 대응하기 어려울 수 있습니다. 반응형 디자인을 위해 상대적인 단위(%, rem 등)나 min/max-width 속성을 고려해 보세요.

export const containerStyle = css({
  display: 'flex',
  flexDirection: 'column',
-  width: '333px',
+  width: '100%',
+  maxWidth: '333px',
  border: 'none',
  backgroundColor: color.WT,
});
src/components/mobile/organisms/DateGroupedCard/DateGroupedCard.stories.tsx (1)

68-115: All 스토리 구성 및 다양한 상황 테스트

All 스토리에서는 여러 날짜와 콘텐츠 항목을 가진 DateGroupedCard 컴포넌트들을 렌더링하여 다양한 상황을 테스트할 수 있도록 구성되어 있습니다. 각 항목의 onClick 이벤트 핸들러가 console.log를 사용하여 디버깅하기 쉽게 설정되어 있습니다.

다만, 실제 앱에서는 console.log 대신 적절한 이벤트 핸들링 로직으로 대체해야 합니다.

📜 Review details

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

📥 Commits

Reviewing files that changed from the base of the PR and between b51643c and 0023910.

⛔ Files ignored due to path filters (3)
  • src/assets/images/my-card-sample-first.png is excluded by !**/*.png
  • src/assets/images/my-card-sample-second.png is excluded by !**/*.png
  • src/assets/svg/smile-emoji.svg is excluded by !**/*.svg
📒 Files selected for processing (33)
  • src/App.tsx (2 hunks)
  • src/assets/index.ts (1 hunks)
  • src/components/atoms/MenuTap/MenuTap.style.ts (1 hunks)
  • src/components/atoms/MenuTap/MenuTap.tsx (1 hunks)
  • src/components/mobile/molecules/ProfileListItem/ProfileListItem.stories.tsx (3 hunks)
  • src/components/mobile/molecules/ProfileListItem/ProfileListItem.tsx (1 hunks)
  • src/components/mobile/organisms/BalanceGameSection/BalanceGameSection.tsx (1 hunks)
  • src/components/mobile/organisms/DateGroupedCard/DateGroupedCard.stories.tsx (1 hunks)
  • src/components/mobile/organisms/DateGroupedCard/DateGroupedCard.style.ts (1 hunks)
  • src/components/mobile/organisms/DateGroupedCard/DateGroupedCard.tsx (1 hunks)
  • src/components/mobile/organisms/DateGroupedList/DateGroupedList.tsx (2 hunks)
  • src/components/mobile/organisms/IconButtonArea/IconButtonArea.tsx (2 hunks)
  • src/components/mobile/organisms/ProfileInfoCard/ProfileInfoCard.stories.tsx (3 hunks)
  • src/components/mobile/organisms/ProfileInfoCard/ProfileInfoCard.tsx (2 hunks)
  • src/components/mobile/organisms/TalkPickSection/TalkPickSection.tsx (1 hunks)
  • src/components/molecules/CommentItem/CommentItem.tsx (2 hunks)
  • src/components/molecules/ContentsButton/ContentsButton.tsx (1 hunks)
  • src/components/molecules/ReplyItem/ReplyItem.tsx (1 hunks)
  • src/components/organisms/BalanceGameSection/BalanceGameSection.tsx (1 hunks)
  • src/components/organisms/TalkPickSection/TalkPickSection.tsx (1 hunks)
  • src/hooks/api/mypages/useInfiniteScroll.ts (1 hunks)
  • src/hooks/api/mypages/useMyGameBookmarksQuery.ts (1 hunks)
  • src/hooks/api/mypages/useMyGameVotesQuery.ts (1 hunks)
  • src/hooks/api/mypages/useMyGameWrittensQuery.ts (1 hunks)
  • src/hooks/api/mypages/useMyTalkPickBookmarksQuery.ts (1 hunks)
  • src/hooks/api/mypages/useMyTalkPickCommentsQuery.ts (1 hunks)
  • src/hooks/api/mypages/useMyTalkPickVotesQuery.ts (1 hunks)
  • src/hooks/api/mypages/useMyTalkPickWrittensQuery.ts (1 hunks)
  • src/layout/layout.tsx (1 hunks)
  • src/pages/mobile/MyMobilePage/MyMobilePage.style.ts (1 hunks)
  • src/pages/mobile/MyMobilePage/MyMobilePage.tsx (1 hunks)
  • src/stories/atoms/MenuTap.stories.tsx (1 hunks)
  • src/types/mypages.ts (4 hunks)
🔇 Additional comments (73)
src/hooks/api/mypages/useMyGameBookmarksQuery.ts (1)

12-37: 훅 함수의 유연성이 향상되었습니다!

options 매개변수를 추가함으로써 모바일 환경에서의 조건부 쿼리 실행이 가능해졌습니다. useInfiniteScroll의 옵션을 직접 전달할 수 있어 재사용성과 확장성이 크게 향상되었습니다. 특히 TypeScript의 Parameters 유틸리티 타입을 활용하여 타입 안전성을 유지한 점이 좋습니다.

src/hooks/api/mypages/useMyTalkPickBookmarksQuery.ts (1)

11-33: 일관된 패턴으로 훅 함수가 개선되었습니다!

이전 파일과 동일한 패턴으로 options 매개변수를 추가하여 모바일 환경에서의 유연한 쿼리 실행이 가능해졌습니다. 모든 마이페이지 관련 훅에 일관된 패턴을 적용함으로써 코드 베이스의 일관성과 예측 가능성이 향상되었습니다. 직접 반환 방식으로 코드가 더 간결해진 점도 좋은 개선사항입니다.

src/hooks/api/mypages/useMyTalkPickVotesQuery.ts (1)

11-32: 유연성 향상을 위한 훅 수정 👍

이 변경은 useMyTalkPickVotesQuery 훅에 옵션 매개변수를 추가하여 호출 시 더 많은 유연성을 제공합니다. 타입 안전성도 적절히 유지하면서 모바일 페이지에 필요한 조건부 쿼리 실행을 가능하게 해줍니다.

아래와 같은 장점이 있습니다:

  • enabled 같은 옵션을 전달할 수 있어 모바일 특화 로직 구현이 가능해졌습니다
  • 코드 구조 간소화로 가독성이 향상되었습니다
  • 명시적 타입 정의로 타입 안전성이 강화되었습니다

PR 목표에 맞게 잘 구현되었습니다.

src/hooks/api/mypages/useMyGameVotesQuery.ts (1)

11-33: 유연한 옵션 처리를 위한 훅 개선 👍

useMyGameVotesQuery 함수에 옵션 매개변수를 추가하여 모바일 마이페이지에서 필요한 조건부 쿼리 기능을 지원하도록 개선되었습니다.

개선된 부분:

  • as const 어서션을 사용하여 쿼리 키의 타입 안전성 향상
  • 간결해진 코드 구조로 가독성 향상
  • 유연한 옵션 처리로 모바일 환경에서의 쿼리 활성화 조건 지정 가능

이러한 변경사항은 PR 목표인 "모바일 환경을 위한 쿼리 구조 수정"에 잘 부합합니다.

src/hooks/api/mypages/useMyTalkPickWrittensQuery.ts (1)

11-32: 훅 인터페이스 개선 및 유연성 향상 👍

useMyTalkPickWrittensQuery 함수가 옵션 매개변수를 받도록 수정되어 모바일 마이페이지 구현에 필요한 유연성을 제공합니다.

개선된 점:

  • 조건부 쿼리 실행을 위한 enabled 옵션 등을 전달할 수 있는 유연한 인터페이스
  • 타입 안전성 유지
  • 일관된 코드 패턴으로 유지보수성 향상

이 변경사항은 PR 목표인 "모바일 마이페이지를 위한 커스텀 훅 조정 및 무한 스크롤 재설계"에 잘 부합합니다.

src/hooks/api/mypages/useInfiniteScroll.ts (5)

1-6: 필요한 의존성만 가져오도록 import 구문 개선 👍

필요한 타입과 함수들을 명시적으로 import하도록 변경되었습니다. 이는 코드의 의도를 명확히 하고 번들 크기 최적화에도 도움이 됩니다.


14-21: 유연한 옵션 처리를 위한 타입 정의 추가 👍

MyInfiniteUserOptions 타입 정의를 통해 커스텀 옵션 처리가 가능해졌습니다. Omit을 사용하여 내부에서 이미 설정하는 필드들을 제외함으로써 충돌을 방지한 것이 좋습니다.

이 타입 정의는 모바일 마이페이지의 조건부 쿼리 실행에 필요한 enabled 속성을 전달할 수 있는 기반을 마련합니다.


23-29: 명확한 문서화 👍

함수의 매개변수와 반환 값에 대한 자세한 설명을 추가한 것이 좋습니다. 특히 새로 추가된 options 매개변수의 역할과 사용법을 명확히 설명하여 다른 개발자들이 이 함수를 사용할 때 도움이 될 것입니다.


34-38: 함수 매개변수 개선 👍

주요 개선 사항:

  1. queryKeyreadonly string[]로 변경하여 불변성 보장
  2. queryFn의 매개변수 타입을 더 명확하게 정의
  3. 새로운 options 매개변수 추가로 유연성 향상
  4. 반환 타입을 명시적으로 선언하여 타입 안전성 강화

이러한 변경사항은 코드의 안정성과 유연성을 함께 향상시킵니다.


39-51: 구현 로직 개선 👍

함수 구현이 다음과 같이 개선되었습니다:

  1. useInfiniteQuery에 객체 매개변수 패턴 사용
  2. pageParam 타입 체크 로직 추가로 타입 안전성 강화
  3. 사용자 정의 옵션을 스프레드 연산자로 전달하여 유연성 제공

이러한 변경사항은 모바일 마이페이지에서 필요한 조건부 쿼리 실행을 지원하며, PR 목표인 "무한 스크롤 재설계"에 잘 부합합니다.

src/components/molecules/ContentsButton/ContentsButton.tsx (1)

20-20: 속성 변경이 적절하게 처리되었습니다.

images 속성을 선택적으로 변경한 것은 좋은 개선입니다. 컴포넌트가 이미지 없이도 사용할 수 있게 되었고, 이미 58-63번 라인에서 images가 없거나 비어있을 때 memoizedRandomPair로 대체하는 로직이 있어 문제없이 작동할 것입니다.

src/layout/layout.tsx (1)

63-65: 모바일 레이아웃 개선이 잘 적용되었습니다.

모바일 화면(430px 이하)에서 상단 패딩을 55px로 설정하는 미디어 쿼리가 추가되었습니다. 이는 LayoutLayoutNoSearch 컴포넌트에 이미 적용된 것과 일관성을 유지하며, 모바일 기기에서의 사용자 경험을 향상시킵니다.

src/components/molecules/CommentItem/CommentItem.tsx (2)

104-119: 메뉴 아이템에 고유 ID 추가 적용이 잘 되었습니다.

각 메뉴 아이템에 id 속성을 추가한 것은 컴포넌트의 안정성을 높이는 좋은 변경입니다. 이는 React의 렌더링 최적화와 키 관리에 도움이 되며, MenuTap 컴포넌트와의 일관성을 유지합니다.


121-129: reportComment 배열의 메뉴 아이템에도 ID 추가가 잘 적용되었습니다.

신고 메뉴 아이템에도 동일하게 id 속성이 추가되어 일관성 있게 적용되었습니다. 이는 MenuTap 컴포넌트의 요구사항에 맞게 수정된 것으로 보입니다.

src/components/atoms/MenuTap/MenuTap.style.ts (1)

17-28: 메뉴 스타일링 개선이 잘 이루어졌습니다.

메뉴의 너비를 고정값 대신 max-content로 변경하고 최소 너비(minWidth)를 설정한 것은 유연성을 높이는 좋은 개선입니다. 이제 메뉴 항목의 텍스트 길이에 따라 너비가 자동으로 조정되면서도 최소한의 너비를 유지할 수 있게 되었습니다. 이는 특히 다국어 지원이나 다양한 길이의 텍스트를 표시해야 할 때 유용합니다.

src/components/molecules/ReplyItem/ReplyItem.tsx (2)

75-90: MenuTap 구조 개선을 위한 id 속성 추가가 잘 되었습니다.

각 메뉴 아이템에 고유한 id 값을 추가하여 컴포넌트 구조가 더 일관되고 명확해졌습니다. 이는 React 렌더링 최적화에도 도움이 됩니다.


92-100: 신고 메뉴 아이템에도 id 속성이 잘 추가되었습니다.

신고 관련 메뉴 아이템에도 id 속성이 추가되어 일관된 구조를 유지하고 있습니다.

src/assets/index.ts (1)

156-158: 모바일 마이페이지에 필요한 에셋들이 잘 추가되었습니다.

MobileCardSampleFirst, MobileCardSampleSecond, SmileEmoji 등 모바일 마이페이지 구현에 필요한 에셋들이 적절하게 추가되었습니다. 에셋 이름이 용도를 명확하게 나타내고 있어 좋습니다.

src/components/mobile/organisms/DateGroupedCard/DateGroupedCard.tsx (3)

1-6: 적절한 임포트 구성입니다.

필요한 컴포넌트와 스타일을 깔끔하게 임포트하고 있습니다.


7-10: 명확한 인터페이스 정의가 잘 되었습니다.

DateGroupedCardProps 인터페이스가 간결하고 명확하게 정의되어 있습니다. dateitems 속성의 타입이 적절하게 정의되어 있습니다.


12-23: 간결하고 효율적인 컴포넌트 구현입니다.

화살표 함수와 암시적 반환을 활용하여 코드가 간결하며, 컴포넌트 내부에서 items를 map을 사용해 효율적으로 렌더링하고 있습니다. key 값으로 id를 사용한 것도 적절합니다.

src/components/mobile/organisms/ProfileInfoCard/ProfileInfoCard.stories.tsx (2)

38-51: Default 스토리에 id 속성이 잘 추가되었습니다.

메뉴 아이템에 id 속성을 추가하여 MenuTap 컴포넌트의 변경사항에 맞게 적절히 수정되었습니다.


64-87: All 스토리의 메뉴 아이템에도 id 속성이 잘 추가되었습니다.

여러 ProfileInfoCard 컴포넌트의 메뉴 아이템에 고유한 id 값(0, 1)을 부여하여 구조적으로 일관성을 유지하고 있습니다.

src/components/mobile/organisms/ProfileInfoCard/ProfileInfoCard.tsx (1)

1-1: MenuTap 컴포넌트와의 일관성을 유지하기 위한 타입 변경을 확인했습니다.

MenuData 타입에 id 속성을 추가하고 label을 ReactNode로 변경한 것은 모바일 마이페이지에서 더 유연한 메뉴 아이템 표현을 가능하게 합니다.

Also applies to: 13-13

src/components/organisms/BalanceGameSection/BalanceGameSection.tsx (1)

134-140: 메뉴 아이템에 id 속성이 추가되었습니다.

MenuTap 컴포넌트와 일관성을 유지하기 위해 myGameItem 및 otherGameItem에 id 속성을 적절히 추가했습니다. 이는 메뉴 아이템을 구별하는 데 도움이 되며, 컴포넌트 렌더링 시 키(key) 속성으로 활용할 수 있습니다.

src/components/mobile/organisms/BalanceGameSection/BalanceGameSection.tsx (1)

133-157: 모바일용 BalanceGameSection에 메뉴 아이템 id 속성이 적용되었습니다.

마찬가지로 모바일 버전의 MenuItem 배열에도 id 속성이 추가되었습니다. 각 메뉴 아이템에 고유 식별자를 추가하여 컴포넌트의 유지보수성과 일관성이 향상되었습니다.

src/App.tsx (1)

22-22: 모바일 환경에 맞춘 라우팅 처리가 적절히 구현되었습니다.

isMobile 상태에 따라 MyMobilePage와 MyPage 컴포넌트를 조건부로 렌더링하는 구조는 모바일 사용자 경험을 최적화하는 좋은 접근법입니다. 각 환경에 맞는 UI를 제공하면서도 기존 로직을 유지하고 있습니다.

Also applies to: 123-140

src/components/mobile/molecules/ProfileListItem/ProfileListItem.tsx (3)

14-28: 랜덤 이미지 구현이 잘 되었습니다.

프로필 이미지가 없을 때 랜덤 이미지를 표시하는 기능이 잘 구현되었습니다. useMemo를 활용하여 불필요한 재계산을 방지한 점이 좋습니다.


30-35: 인터페이스 수정이 적절하게 이루어졌습니다.

imgUrl을 선택적으로 변경하고 to 속성을 추가한 것은 컴포넌트의 유연성을 향상시키는 좋은 변경사항입니다. 라우팅 기능을 위한 준비가 잘 되어있습니다.


37-54: Link 컴포넌트 활용이 적절합니다.

기존 div에서 Link 컴포넌트로 변경하여 라우팅 기능을 추가한 것은 좋은 접근법입니다. 랜덤 이미지 기능과 함께 사용자 경험을 개선하는 데 도움이 됩니다.

src/components/atoms/MenuTap/MenuTap.tsx (2)

10-14: MenuItem 타입 개선이 적절합니다.

id 속성을 필수로 추가하고 label을 ReactNode 타입으로 변경한 것은 좋은 개선점입니다. 이렇게 하면 메뉴 아이템에 더 다양한 컨텐츠를 표시할 수 있고, 고유한 식별자를 통해 안정적인 렌더링이 가능해집니다.


44-53: key 속성 사용이 개선되었습니다.

메뉴 아이템의 key로 label 대신 id를 사용하는 것은 React의 권장 사항에 맞는 좋은 변경입니다. 고유한 ID를 사용함으로써 리렌더링 시 성능과 안정성이 향상됩니다.

src/components/mobile/organisms/DateGroupedList/DateGroupedList.tsx (2)

5-9: imgUrl 속성을 선택적으로 변경한 것이 적절합니다.

DateGroupedListItem 인터페이스에서 imgUrl을 선택적 속성으로 변경한 것은 ProfileListItem 컴포넌트의 변경사항과 일관성을 유지하는 좋은 접근법입니다.


22-26: ProfileListItem에 to 속성 추가가 적절합니다.

ProfileListItem 컴포넌트에 to 속성을 추가하여 item의 id를 기반으로 TalkPick 페이지로 이동하는 기능을 구현한 것은 좋은 UX 개선입니다.

src/components/mobile/organisms/DateGroupedCard/DateGroupedCard.style.ts (2)

18-25: listStyle의 그리드 레이아웃이 적절합니다.

그리드 레이아웃을 사용하여 항목을 2열로 표시하는 것은 모바일 UI에 적합한 접근법입니다.


27-27: 빈 listItemStyle에 대한 검토가 필요합니다.

listItemStyle이 정의되어 있지만 내용이 비어있습니다. 향후 사용을 위한 것인지, 아니면 불필요한 코드인지 확인해 보세요. 불필요하다면 제거하는 것이 좋습니다.

src/types/mypages.ts (3)

90-90: 새로운 TabType 정의에 대한 의견

TabType'talkPick' | 'balanceGame' 형태로 직관적으로 잘 정의되었습니다. 가독성과 유지보수성 측면에서 적절하며, 추후 탭이 늘어나는 경우에도 확장하기 용이합니다.


92-92: ButtonType 정의에 대한 칭찬

'saved' | 'voted' | 'commented' | 'created'처럼 구체적인 문자열 리터럴 유니온을 사용하여, 상태를 명확하게 표현하였습니다. 상태별 처리가 명확해져서 코드의 의미 전달이 분명합니다.


94-101: AllQueryData 유니온 타입 설계

다수의 인터페이스를 하나의 유니온 타입으로 통합하여, 확장 가능한 구조를 잘 확보하였습니다. 이후 같은 케이스가 추가되거나 제거될 때, 단일 지점(AllQueryData)에서 관리할 수 있어 유지보수에 유리합니다.

src/pages/mobile/MyMobilePage/MyMobilePage.style.ts (6)

1-3: Emotion, 컬러/타이포 임포트 구성

Emotion과 공용 스타일 코드를 임포트하여 모듈화된 형태로 활용하고 있습니다. 프로젝트 전반적으로 색상과 타이포를 통일성 있게 쓰는 것은 매우 바람직합니다.


5-12: pageStyle의 컬럼 레이아웃 설정

컬럼 방향 정렬 및 padding 등을 통해 모바일 환경 레이아웃을 깔끔하게 구성하고 있습니다. width: '100%'로 가로 폭을 화면에 맞춤 처리한 점도 적절합니다.


14-20: selectGroupWrapper의 센터 정렬

alignItemsjustifyContent 모두 'center'로 설정하여, 선택 그룹 요소가 수평·수직으로 중앙에 배치됩니다. 모바일 UI 측면에서 사용자가 집중하기 좋게 배치하는 것으로 보이며, 의도에 충실합니다.


22-30: contentWrapper 사용

내부 컨텐츠를 모두 세로 배열로 정렬하고, gap으로 간격을 부여하였습니다. 여러 컴포넌트가 배치될 때 가독성을 높이는 데 도움이 됩니다.


32-37: menuDataBox 스타일링

flexgap으로 내부 아이콘이나 텍스트 배열을 유연하게 처리한 점이 좋습니다. 색상과 폰트 스타일을 상수로 관리하여 전체 프로젝트에서 일관성을 유지하고 있습니다.


39-42: observerWrapper의 기능적 배치

marginTop을 두어 무한 스크롤용 옵저버를 화면 하단과 약간 띄워 배치하는 구조로 보입니다. 유저가 추가 데이터를 자연스럽게 로드하도록 유도하는 방식으로 무난합니다.

src/pages/mobile/MyMobilePage/MyMobilePage.tsx (8)

1-36: 다양한 타입 및 훅 임포트

다양한 API 훅, 타입을 명확히 분리·임포트하여, 파일 내에서 가독성을 높였습니다. TabType, ButtonType 등으로 뷰 로직을 분기하는 부분도 일관성을 유지해주어 좋습니다.


37-43: InfiniteQueryOrNull 타입 정의

UseInfiniteQueryResult를 옵셔널로 처리해, 실제로 활성화되지 않은 쿼리 호출을 구분할 수 있도록 설계하셨습니다. 코드 가독성과 안전성을 높이는 좋은 방법입니다.


105-113: 무한 스크롤 데이터 결합 로직

data.pages.flatMap(...).content 방식으로 여러 페이지를 깔끔하게 합치고 있어, 무한 스크롤 구현 시 중복 데이터를 줄이는 데 효과적입니다.


191-199: 버튼 클릭 핸들러

handleButtonClick을 통해 activeButton을 갱신하는 흐름이 단순명료합니다. 뷰 로직을 따로 분리해 유지보수하기 수월해 보입니다.


201-205: currentQuery 널 체크 로직

쿼리가 준비되지 않은 경우 빠르게 return하는 구조로 방어 코드를 배치한 점이 좋습니다. 사용자가 의도치 않게 빈 화면을 보는 상황을 최소화할 수 있습니다.


207-211: 에디트 메뉴 라벨으로 ReactNode 활용

editMenuLabel<span>으로 감싸고, 내부에 이모지를 함께 렌더링하여 유연하게 표현해주었습니다. ReactNode를 라벨로 사용하는 패턴이 잘 드러납니다.


214-266: 최종 렌더링

  • 프로필 정보 카드, 탭/버튼 UI, 데이터 그룹 컴포넌트 배치를 통해 모바일용 마이페이지를 간결하게 구성했습니다.
  • 옵저버 ref를 별도의 <div>에 연결해, 스크롤 이벤트를 구조화하고 있어 무한 스크롤 처리로도 적합합니다.

44-100:

❓ Verification inconclusive

쿼리 맵핑 및 상태 관리

  • activeTab, activeButton에 따라 다른 쿼리를 활성화하여, 불필요한 데이터 요청을 방지하는 구조가 합리적입니다.
  • queryMap을 객체로 만들어 버튼/탭 별 쿼리를 한 곳에서 관리하므로 가독성을 높였습니다.
  • member!.id 사용 시, 멤버 값이 undefined가 아닌지 확인할 안전장치가 필요할 수 있습니다.

실제로 member가 아직 로딩 중이 아닐 때 member!.id 접근이 일어날 여지는 없는지 확인해주세요.


🏁 Script executed:

#!/bin/bash
# 파일 내에서 member 사용 시점들을 확인하고, 'undefined' 방어 로직이 있는지 grep으로 확인합니다.
rg --context 5 'member\!' 

Length of output: 108


Member 데이터 접근 관련 안전성 추가 검증 요청

현재 코드는 탭과 버튼에 따라 쿼리를 활성화해 불필요한 데이터 요청을 방지하는 구조로 잘 작성되었습니다. 다만,

  • member!.id를 직접 사용하고 있어, member가 아직 로딩 중이거나 undefined일 경우 발생할 수 있는 잠재적 오류에 대한 안전 체크가 부족해 보입니다.
  • useMyGameVotesQuery(member!.id, {...}) 호출 시, member 값이 확실히 존재하는지 다시 한 번 검토하고, 필요하다면 로딩 상태나 존재 여부를 명시적으로 확인하는 로직을 추가하시길 권장합니다.

추가 검증이 필요한 부분이므로, 관련 사항에 대해 수동 점검 후 안전 장치가 확실히 마련되었는지 확인해주시기 바랍니다.

src/components/mobile/organisms/TalkPickSection/TalkPickSection.tsx (2)

82-97: MenuItem 배열에 id 속성이 추가되었습니다.

각 메뉴 아이템에 고유 식별자(id)를 추가한 것은 좋은 변경입니다. 이는 React에서 리스트 렌더링 시 key 값으로 사용되어 DOM 업데이트 효율성을 향상시킵니다.


99-107: otherTalkPickItem에도 id 속성이 추가되었습니다.

마찬가지로 otherTalkPickItem 배열에도 id 속성을 추가하여 일관성 있게 구현되었습니다.

src/components/mobile/organisms/IconButtonArea/IconButtonArea.tsx (5)

13-13: 타입 안전성 개선을 위한 새로운 타입 임포트

문자열 타입 대신 명확하게 정의된 TabType과 ButtonType을 사용함으로써 타입 안전성이 향상되었습니다.


16-22: IconButtonConfig 인터페이스 추가

버튼 구성을 위한 명확한 인터페이스를 만들어 코드의 가독성과 유지보수성이 향상되었습니다.


24-28: IconButtonAreaProps 인터페이스 업데이트

기존 string 타입 대신 더 구체적인 TabType과 ButtonType을 사용하여 타입 안전성이 향상되었습니다.


30-59: 버튼 구성을 컴포넌트 외부로 이동

allButtons 배열을 컴포넌트 외부로 이동시켜 컴포넌트의 재렌더링 시에도 이 배열이 재생성되지 않도록 최적화되었습니다. 이는 성능 개선에 도움이 됩니다.


72-84: map 함수 내 isActive 변수 추가로 가독성 개선

isActive 상수를 추가하여 코드 가독성이 향상되었습니다. 이전에는 조건식이 직접 JSX 내에 있었을 것으로 추정됩니다.

src/components/mobile/molecules/ProfileListItem/ProfileListItem.stories.tsx (4)

5-5: 라우팅 기능을 위한 MemoryRouter 임포트

ProfileListItem 컴포넌트에 라우팅 기능을 추가하기 위해 MemoryRouter를 임포트했습니다. 이는 스토리북 환경에서 라우팅을 시뮬레이션하기 위한 좋은 접근 방식입니다.


25-29: to 속성 추가

ProfileListItem에 이동할 경로를 지정하는 to 속성이 추가되었습니다. 이는 사용자가 컴포넌트를 클릭했을 때 이동할 경로를 지정할 수 있어 유용합니다.


40-46: Default 스토리에 to 속성 및 MemoryRouter 추가

Default 스토리에 to 속성을 추가하고 MemoryRouter로 컴포넌트를 감싸서 라우팅 기능을 활성화했습니다. 이제 스토리북에서도 라우팅 기능을 테스트할 수 있게 되었습니다.


51-80: All 스토리에 MemoryRouter 및 to 속성 추가

All 스토리에서도 모든 ProfileListItem 컴포넌트에 고유한 to 속성을 추가하고 MemoryRouter로 감싸서 일관된 라우팅 기능을 제공합니다.

src/components/mobile/organisms/DateGroupedCard/DateGroupedCard.stories.tsx (3)

1-34: DateGroupedCard 스토리북 파일 생성 및 샘플 데이터 구성

새로운 DateGroupedCard 컴포넌트를 위한 스토리북 파일이 잘 구성되었습니다. 테스트를 위한 sampleItems 데이터가 적절하게 정의되어 있습니다.


36-56: 메타 데이터 구성

스토리북 메타 데이터가 잘 구성되어 있으며, argTypes에 date와 items에 대한 설명이 명확하게 작성되어 있습니다.


61-66: Default 스토리 구성

기본 스토리가 적절하게 구성되어 있습니다. 기본 date와 items 값이 잘 설정되어 있습니다.

src/components/organisms/TalkPickSection/TalkPickSection.tsx (2)

92-107: MenuItem 객체에 id 속성 추가 적용이 잘 되었습니다.

각 MenuItem 객체에 고유 id를 추가하여 React 렌더링에서 고유 키로 사용할 수 있도록 개선했습니다. 이는 React의 리스트 렌더링 성능과 안정성을 향상시키는 좋은 변경사항입니다.


108-116: otherTalkPickItem에도 id 속성이 잘 구현되었습니다.

otherTalkPickItem도 myTalkPickItem과 동일한 패턴으로 id 속성을 추가하여 일관성 있게 수정했습니다.

src/stories/atoms/MenuTap.stories.tsx (4)

7-11: 메뉴 데이터 구조에 id 속성 추가가 잘 되었습니다.

모든 MenuItem 객체에 일관되게 고유한 id 값을 추가했습니다. 이는 MenuItem 타입 변경에 맞게 스토리북 예제도 적절히 업데이트된 것입니다.


13-21: reportMenu에도 id 속성이 잘 적용되었습니다.

reportMenu 데이터에도 id 값이 추가되어 일관된 MenuItem 인터페이스를 유지하고 있습니다.


23-38: myCommentMenu의 MenuItem 객체들에 id 속성이 잘 구현되었습니다.

여러 항목이 있는 myCommentMenu에 각각 고유한 id 값(0, 1)을 부여하여 적절하게 구현했습니다.


40-55: otherCommentMenu에도 id 속성이 일관되게 적용되었습니다.

otherCommentMenu의 각 MenuItem 객체에도 고유 id 값을 추가하여 MenuTap 컴포넌트의 요구사항에 맞게 잘 수정되었습니다.

commentCount: number;
editedAt: string;
bookmarked: boolean;
imgUrls?: string;
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue

imgUrls 타입 불일치 문제

현재 imgUrlsstring 혹은 undefined로 선언되어 있지만, 실제 사용되는 코드(MyMobilePage.tsx 등)에서 item.imgUrls[0]와 같이 배열 형태로 접근하고 있습니다. 이는 타입 선언과 실제 사용 방식이 어긋나서 런타임 에러를 유발할 수 있습니다.

아래와 같이 string[]로 변경하여, 코드 전체가 일관되도록 맞추기를 권장드립니다:

-  imgUrls?: string;
+  imgUrls?: string[];

Also applies to: 21-21, 32-32

Comment on lines 115 to 189
useEffect(() => {
setActiveButton('saved');
}, [activeTab]);

useEffect(() => {
if (!mergedData || !mergedData.content) {
setDateGroupedData([]);
return;
}

if (activeTab === 'talkPick') {
const talkPickItems = mergedData.content as (
| BookmarkInfoItemResponse
| CommentInfoItemResponse
| VoteInfoItemResponse
| WrittenInfoItemResponse
)[];
const groups: { [date: string]: DateGroupedListItem[] } = {};

talkPickItems.forEach((item) => {
const dateStr = item.editedAt || '날짜없음';
const transformedItem: DateGroupedListItem = {
id: item.id,
title: item.title,
imgUrl:
item.imgUrls && item.imgUrls.length > 0 ? item.imgUrls[0] : '',
};

if (groups[dateStr]) {
groups[dateStr].push(transformedItem);
} else {
groups[dateStr] = [transformedItem];
}
});

const groupedData = Object.keys(groups)
.sort((a, b) => (a < b ? 1 : -1))
.map((date) => ({ date, items: groups[date] }));

setDateGroupedData(groupedData);
} else if (activeTab === 'balanceGame') {
const balanceGameItems = mergedData.content as MyBalanceGameItem[];
const newArr: { date: string; items: ContentsButtonProps[] }[] = [];

balanceGameItems.forEach((item) => {
const dateStr = item.editedAt || '날짜없음';

const transformed: ContentsButtonProps = {
id: String(item.gameId),
title: item.title,
images:
item.optionAImg && item.optionBImg
? [item.optionAImg, item.optionBImg]
: [],
mainTag: item.mainTagName || '',
subTag: item.subTag || '',
onClick: () => navigate(`/balancegame/${item.gameId}`),
onBookmarkClick: () => {
handleBookmarkClick(item);
},
bookmarked: item.bookmarked ?? false,
showBookmark: activeButton === 'saved' || activeButton === 'voted',
size: 'extraSmall',
};

const existingGroup = newArr.find((group) => group.date === dateStr);
if (existingGroup) {
existingGroup.items.push(transformed);
} else {
newArr.push({ date: dateStr, items: [transformed] });
}
});
setDateGroupedData(newArr);
}
}, [mergedData, activeTab, activeButton, navigate, handleBookmarkClick]);
Copy link
Contributor

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

데이터 그룹화 로직 주의점

  • imgUrls?: string; 로 선언된 프로퍼티를 배열처럼 사용하는 부분(item.imgUrls[0])이 있어 타입 불일치로 인한 에러 가능성이 큽니다.
  • 임시로 '날짜없음'을 사용해 날짜를 표시하는 부분은 괜찮지만, 국제화(i18n)를 고려한다면 별도 상수 혹은 번역 키로 뽑아 관리하는 것을 권장합니다.

이미 인터페이스가 배열 형태로 바뀌어야 할 것으로 보이니, 기존에 코멘트한 대로 imgUrls?: string[];로 수정하여 안전하게 처리해주세요.

@sonarqubecloud
Copy link

Copy link
Contributor

@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: 0

🧹 Nitpick comments (2)
src/pages/mobile/MyMobilePage/MyMobilePage.tsx (2)

203-207: 더 나은 로딩/오류 화면 처리 제안

현재 isMemberLoading!currentQuery 시 단순 <div />만 리턴하고 있습니다. 사용자가 로딩 중임을 인지할 수 있는 피드백(스피너, 플레이스홀더, 에러 메시지 등)을 제공하면 UX 개선에 도움이 됩니다.


261-265: 데이터가 없을 때 사용자에게 명확한 안내 필요

dateGroupedData가 비어 있을 경우 아무것도 표시하지 않거나 <p />만 렌더링하고 있습니다. 사용자에게 “저장된 데이터가 없습니다.”와 같은 구체적인 안내 문구나 UI 요소를 제공하면 상황을 더 명확히 전달할 수 있습니다.

📜 Review details

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

📥 Commits

Reviewing files that changed from the base of the PR and between 0023910 and ef01709.

📒 Files selected for processing (2)
  • src/components/mobile/molecules/ProfileListItem/ProfileListItem.tsx (1 hunks)
  • src/pages/mobile/MyMobilePage/MyMobilePage.tsx (1 hunks)
🔇 Additional comments (8)
src/components/mobile/molecules/ProfileListItem/ProfileListItem.tsx (6)

3-11: 새로운 에셋 및 리액트 라우터 링크 임포트가 추가되었습니다.

여러 랜덤 프레임 이미지를 임포트하고 Link 컴포넌트를 추가하여 네비게이션 기능을 확장했습니다. 이로써 컴포넌트의 사용성이 향상되었습니다.


14-21: 랜덤 이미지 배열 정의가 잘 되었습니다.

다양한 프레임 이미지를 배열로 정의하여 랜덤 이미지 선택을 위한 기반을 만들었습니다. 코드 가독성이 좋고 확장성도 고려되었습니다.


23-28: useRandomImage 훅이 효율적으로 구현되었습니다.

useMemo를 활용하여 랜덤 이미지 선택을 최적화한 점이 좋습니다. 빈 의존성 배열을 사용하여 컴포넌트가 마운트될 때만 이미지를 선택하도록 한 점도 적절합니다.


30-35: 인터페이스 변경이 적절히 이루어졌습니다.

ProfileListItemProps 인터페이스에서:

  1. imgUrl을 선택적 속성으로 변경하여 유연성을 높였습니다.
  2. 라우팅을 위한 to 속성을 추가하여 네비게이션 기능을 강화했습니다.
  3. div 대신 a 태그의 속성을 확장하도록 변경하여 링크 기능에 맞게 조정했습니다.

이러한 변경은 컴포넌트의 용도와 잘 부합합니다.


37-44: 랜덤 이미지 폴백 로직이 효과적으로 구현되었습니다.

imgUrl이 제공되지 않을 경우 랜덤 이미지를 사용하는 폴백 메커니즘이 잘 구현되었습니다. 널 병합 연산자(??)를 사용하여 간결하게 처리한 점이 좋습니다.


45-54: Link 컴포넌트로의 전환이 잘 이루어졌습니다.

div에서 Link 컴포넌트로 변경하여 네비게이션 기능을 추가한 것은 좋은 개선입니다. 기존 스타일과 속성을 유지하면서도 새로운 기능을 자연스럽게 통합했습니다.

src/pages/mobile/MyMobilePage/MyMobilePage.tsx (2)

135-143: '날짜없음' 문자열의 i18n 적용 검토

이미 과거 리뷰에서 언급된 부분과 동일합니다. '날짜없음' 대신 국제화(i18n) 처리를 통해 다국어 환경에 대비하거나 상수 파일로 분리하여 재사용성을 높이는 방법을 고려해 보세요.


48-58:

❓ Verification inconclusive

멤버 데이터가 아직 로딩되지 않은 상태에서 member! 사용 주의

member!를 통해 non-null 단언을 사용하고 있으나, 이 로직은 memberundefined일 경우 런타임 오류로 이어질 수 있습니다. isMemberLoading만으로 충분히 방어할 수 있는지 확인하고, 필요하다면 member 존재 여부를 추가로 체크하는 로직을 고려해주세요.

아래 스크립트를 통해 member!가 다른 곳에서도 무방비하게 사용되는지 확인해 볼 수 있습니다:


🏁 Script executed:

#!/bin/bash
# repository 전체에서 member! 사용 위치를 검색
rg -A 2 'member!'

Length of output: 291


주의: member! 사용에 대한 추가 확인 필요

  • 코드 상 src/pages/mobile/MyMobilePage/MyMobilePage.tsx 파일에서 member!useMyGameVotesQuery(member!.id, { … }) 호출 시에만 사용되고 있음이 확인되었습니다.
  • useMemberQuery에서 반환하는 isMemberLoading이 member 값의 안정성을 충분히 보장하는지 재검토해주시기 바랍니다.
  • 만약 로딩 중인 상태에서 member!를 사용하게 되면 런타임 오류가 발생할 수 있으므로, 추가적인 null 체크 또는 조건부 처리가 필요해 보입니다.

Copy link
Collaborator

@areumH areumH 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
Collaborator

Choose a reason for hiding this comment

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

해당 컴포넌트 스토리북 오류로 확인이 안됩니다 수정 부탁드려요!!

Comment on lines +123 to +126
{isMobile ? (
<Route index element={<MyMobilePage />} />
) : (
<Route element={<MyPage />}>
Copy link
Collaborator

Choose a reason for hiding this comment

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

현재 구현된 방식도 괜찮은 것 같습니다!! 👍

Comment on lines +19 to +20

const MenuTap = ({ menuData }: MenuTapProps) => {
Copy link
Collaborator

Choose a reason for hiding this comment

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

스토리북으로 확인해보니 글자 수가 같아도 메뉴가 1개일 때와 2개일 때의 width 길이가 차이가 나는 것 같아요!! 스타일 확인 부탁드립니닷

Comment on lines +26 to +27

export const listItemStyle = css({});
Copy link
Collaborator

Choose a reason for hiding this comment

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

사용되지 않는 스타일은 삭제 부탁드려요!!

Comment on lines +260 to +262
) : (
<p />
)}
Copy link
Collaborator

@areumH areumH Mar 22, 2025

Choose a reason for hiding this comment

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

위 코드는 dateGroupedData가 빈 요소일 때 빈 값을 보여주기 위한 코드인가요??
맞다면 삼항연산자 대신 &&를 사용하는건 어떨까요!??

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

Status: Todo

Development

Successfully merging this pull request may close these issues.

마이페이지 모바일 페이지 데이터 패칭

3 participants