Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[24.12.31/ TASK-65] 그래프 페이지 완성 #6

Merged
merged 52 commits into from
Dec 31, 2024
Merged

Conversation

six-standard
Copy link
Member

@six-standard six-standard commented Dec 30, 2024

사실 리퀘스트를 꾸준히 분리했어야 하지만, 타이밍을 놓쳐서 이렇게 한 브랜치로 통합하게 되었습니다..

스크린샷 2024-12-31 오전 2 20 41
어찌 됬든 그래프 페이지를 완전히 완성했습니다!

Summary by CodeRabbit

릴리즈 노트

  • 새로운 기능

    • 대시보드 페이지에 포스트 통계 및 상세 그래프 추가
    • 사용자 인증 및 로그인 프로세스 개선
    • 새로운 드롭다운, 체크박스, 입력 컴포넌트 도입
    • 새로운 이미지 처리 설정 추가
    • 새로운 쿠키 관리 함수 도입
    • 사용자 이벤트 추적 기능 개선
    • 새로운 검색 파라미터 관리 훅 추가
    • 새로운 색상 및 폰트 상수 추가
  • 버그 수정

    • 이미지 로딩 및 원격 이미지 처리 안정성 향상
    • 쿠키 및 인증 토큰 관리 최적화
  • 개선 사항

    • 성능 및 코드 구조 리팩토링
    • 타입스크립트 및 ESLint 설정 업데이트
    • 반응형 디자인 및 스타일링 개선
    • 새로운 색상 및 폰트 상수 추가

Copy link

Copy link

coderabbitai bot commented Dec 30, 2024

Walkthrough

이 풀 리퀘스트는 Next.js 기반 웹 애플리케이션의 광범위한 리팩토링과 기능 개선을 포함합니다. 주요 변경 사항은 ESLint 구성 업데이트, 새로운 API 요청 및 타입 정의, 컴포넌트 구조 재구성, 상수 및 유틸리티 함수 개선 등을 포함합니다. 프로젝트의 모듈성, 타입 안전성, 개발자 경험을 향상시키는 데 중점을 두고 있습니다.

Changes

파일 변경 요약
.eslintrc.json Next.js 및 TypeScript를 위한 ESLint 구성 추가
eslint.config.mjs React 및 NodeJS를 위한 글로벌 변수 추가
next.config.mjs 원격 이미지 소스 구성 추가
package.json 의존성 업데이트 및 새로운 라이브러리 추가
src/apis/* 대시보드, 사용자 API 요청 및 인스턴스 요청 로직 개선
src/components/* 새로운 컴포넌트 추가 및 기존 컴포넌트 리팩토링
src/constants/* 색상, 폰트, 경로 상수 추가 및 구조화
src/types/* 대시보드 및 사용자 관련 타입 정의 추가
src/utils/* 유틸리티 함수 개선 및 새로운 함수 추가
src/hooks/* 새로운 커스텀 훅 추가 및 기존 훅 수정
src/errors/* 오류 처리 모듈 수정
src/layout.tsx 레이아웃 구성 수정
src/global-error.tsx 글로벌 오류 처리 수정
src/index.ts 로그인 관련 기능의 접근성 변경

Sequence Diagram

sequenceDiagram
    participant Client
    participant QueryProvider
    participant API
    participant AuthLayout
    participant MainPage

    Client->>QueryProvider: 애플리케이션 초기화
    QueryProvider->>API: 사용자 프로필 요청
    API-->>QueryProvider: 프로필 데이터 응답
    QueryProvider->>AuthLayout: 인증된 레이아웃 렌더링
    AuthLayout->>MainPage: 메인 페이지 로드
    MainPage->>API: 게시물 목록 및 요약 요청
    API-->>MainPage: 게시물 데이터 응답
Loading

Poem

🐰 코드의 숲을 거니는 토끼의 노래 🌿

리팩토링의 바람 살랑살랑
타입과 훅이 춤을 추네
상수들은 반짝이는 보석처럼
새로운 기능 무지개를 그리네
개발의 즐거움 깃든 코드여! 🚀

Tip

CodeRabbit's docstrings feature is now available as part of our Early Access Program! Simply use the command @coderabbitai generate docstrings to have CodeRabbit automatically generate docstrings for your pull request. We would love to hear your feedback on Discord.


Thank you for using CodeRabbit. We offer it for free to the OSS community and would appreciate your support in helping us grow. If you find it useful, would you consider giving us a shout-out on your favorite social media?

❤️ 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. (Beta)
  • @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

@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

🧹 Nitpick comments (38)
src/apis/instance.request.ts (2)

25-27: 유연한 Request Init 타입 도입
InitType<I>를 통해 init.body가 객체 또는 제네릭 타입 I로 처리되도록 유연성을 확보한 점이 좋습니다. 추가로 FormData 등 다른 타입의 가능성도 고려해야 한다면, 런타임에서 타입 검사를 추가할 수 있습니다.


54-78: SSR 환경에서 location 접근 여부 확인
401 또는 403 에러 시 location.replace('/')로 리다이렉트하는 로직이 클라이언트 사이드 환경만 전제하고 있습니다. Next.js의 서버 사이드 렌더링 환경에서 location 객체를 사용할 수 없으므로, 필요한 경우 조건 분기를 추가하거나 다른 리다이렉트 방법을 고려해 보세요.

src/utils/numberUtil.ts (1)

2-2: 0 처리 로직 간결화
item이 falsy일 경우 '0'을 반환하도록 변경되어, 0도 정상적으로 처리됩니다. 다만, 소수점이나 국제화 포맷 등 추가 요구사항이 있을 경우에는 또 다른 로직을 고려해야 할 수 있습니다.

src/constants/sizes.constant.ts (1)

2-2: Tailwind 클래스 표현 방법 검토
FULL: 'w-[100%]' 방식으로 폭을 100% 지정하는 것은 문제 없지만, w-full과 같은 Tailwind 기본 클래스를 사용하는 편이 유지보수에 조금 더 직관적일 수 있습니다.

src/components/common/index.ts (1)

2-3: 추가 컴포넌트 Export로 재사용성 확보
ArriveSoon, Dropdown, Check 컴포넌트들을 함께 Export하여 손쉽게 재활용할 수 있게 되었습니다. 혹시 스토리북이나 문서화를 고려하고 있다면, 각 컴포넌트별 사용 예시를 제공하면 팀 협업에 도움이 될 것입니다.

Also applies to: 6-6

src/utils/cookieUtil.tsx (1)

8-8: [ko-KR] 대입문의 위치 재검토 필요
keys.forEach((i) => (cookie.headers[i] = cookies().get(i)?.value || '')); 와 같이 식 내부에서 바로 대입하는 구문은 가독성이 떨어질 수 있고, static analysis에서는 ‘부적절한 표현식 내 대입’으로 인식합니다. 다음과 같이 표현을 분리하는 방식으로 가독성과 유지보수성을 높일 수 있습니다.

- keys.forEach((i) => (cookie.headers[i] = cookies().get(i)?.value || ''));
+ keys.forEach((i) => {
+   cookie.headers[i] = cookies().get(i)?.value || '';
+ });
🧰 Tools
🪛 Biome (1.9.4)

[error] 8-8: The assignment should not be in an expression.

The use of assignments in expressions is confusing.
Expressions are often considered as side-effect free.

(lint/suspicious/noAssignInExpressions)

src/components/common/Button.tsx (2)

9-10: CSS 클래스 중복 정의 주의
LARGE 키에 rounded-sm이 두 번 선언되어 있습니다. 중복 작성으로 인해 혼돈이 발생할 수 있으니 하나로 정리해 주세요.

-  LARGE: 'h-fit rounded-sm py-4 rounded-sm max-TBL:py-[14px]',
+  LARGE: 'h-fit rounded-sm py-4 max-TBL:py-[14px]',

16-16: 유연한 클래스병합 처리
${rest.className}를 이용해 추가 스타일을 병합하는 로직이 깔끔합니다. 다만, 추후 CSS-in-JS 라이브러리나 Class Merge(예: clsx 등)를 사용할 계획이 있다면 함께 고려해 보셔도 좋겠습니다.

src/apis/user.request.ts (1)

6-16: 로그인 요청 및 에러 처리 로직 확인
NotFoundError를 HTTP 404에 매핑하여 적절한 에러 메시지를 표시하는 방식이 깔끔합니다. 하지만 로그인 이외에도 404가 발생할 수 있으므로, 에러 처리를 좀 더 범용적으로 확장할 계획이라면 공통 에러 헨들링 구조를 고려해보세요.

src/hooks/useResponsive.ts (1)

11-19: 타이머 해제 및 지연 처리
리사이즈 이벤트 시 즉각적으로 상태를 업데이트하지 않고, setTimeout을 통해 지연 후에 처리하는 방식은 성능상 이점이 있습니다. 다만, timeruseEffect 전역에 정의되어 있기 때문에 여러 효과가 중첩되진 않는지 살펴보면 좋겠습니다. 필요 시 useRef를 사용해 timer를 관리하는 방법도 고려하십시오.

src/components/common/Input.tsx (1)

23-24: [권장] data-placeholder는 사용자 접근성 향상을 위해 유용할 수 있지만, 실제로 사용되는지 확인이 필요합니다.
Tailwind나 기타 스타일에서 ::before::after와 결합하여 시각적으로 안내하는 용도로 사용된다면 좋습니다. 그렇지 않다면 오히려 혼란을 줄 수도 있으니 목적을 명확히 해주세요.

src/apis/dashboard.request.ts (2)

10-21: [설명] postList 함수에서 cursor가 있을 때와 없을 때의 분기 처리가 깔끔합니다.
template literal로 쿼리 파라미터를 직관적으로 구분하고 있어서, 유지보수가 수월해 보입니다. 다만, 페이지네이션을 구현할 때 사용자가 cursor 값을 임의로 크게 설정하는 부분에 대한 예외 처리도 필요할 수 있으니 주의 바랍니다.


22-24: [위험도 낮음] postSummary 함수의 작동 방식이 간단하고 직관적입니다.
API 호출 시 반환되는 PostSummaryDto에 대한 에러 처리는 별도로 하는지 확인하시고, 필요하다면 try-catch 구문 등으로 예외를 다루면 좋겠습니다.

src/components/auth-required/main/Summary/SidebarContent.tsx (2)

11-11: [안내] after:content-[attr(data-increasement)_"↑"]을 통한 동적 텍스트 표시가 잘 구현되었습니다.
Tailwind CSS의 기능을 잘 활용하고 있어, 값에 따라 자동으로 표시되는 부분이 인상적입니다. 단, 접근성 측면에서 스크린 리더가 이 내용을 제대로 읽을 수 있는지 여부를 확인해보시길 권장드립니다.


20-26: [의견] SidebarContent 컴포넌트의 레이아웃 설정이 직관적이나, 폭 고정 값(375px, 280px)이 반응형 측면에서 적절한지 재검토가 필요합니다.
해상도별 UI를 세밀하게 제어하기 위해서는 ThemeBreakPoint 또는 Tailwind 플러그인을 적극적으로 활용하는 것도 방법입니다.

src/app/(with-tracker)/(auth-required)/layout.tsx (1)

13-20: 사용자 정보 사전 로드시 에러 핸들링 로직을 고려해 주세요.
prefetchQuery를 통해 me API를 사전에 호출하는 로직은 적절해 보이지만, 서버 응답 에러 발생 시 처리 방안이 보이지 않습니다. 에러 동작을 명확히 정의하거나, 임시 화면/알림 등으로 사용자에게 안내할 수 있도록 보완을 권장합니다.

src/constants/fonts.constant.ts (1)

5-20: 각 폰트 설정의 통일성과 가독성을 확인해 주세요.
폰트 크기, 줄 높이, 폰트 무게가 일관성 있게 정의되어 있으나, 유사한 폰트 크기가 너무 자주 반복되면 실제 UI에서 구분이 어려울 수 있습니다. 필요하다면 사용 빈도에 따라 범위를 조정해 볼 수도 있습니다.

src/components/common/QueryProvider.tsx (1)

7-24: 서버-클라이언트 분기 처리로 QueryClient를 재활용하는 접근이 효율적입니다.
typeof window를 분기점으로 하여 서버 사이드 렌더링 시 새로운 QueryClient를 생성하고, 클라이언트 렌더링 시 전역 변수에 보관하여 재활용하는 로직은 성능 면에서 유리합니다. 다만, 클라이언트 환경에서 더 이상 사용되지 않는 QueryClient가 있는지 모니터링할 필요가 있습니다.

src/app/(with-tracker)/(auth-required)/main/page.tsx (1)

18-35: prefetchInfiniteQuery와 prefetchQuery를 적절히 활용해 서버에서 데이터를 미리 로드하고 있습니다.
게시글 목록과 요약 정보를 사전에 불러오는 로직은 성능과 사용자 경험 측면에서 크게 이점이 있습니다. 에러 발생 시 처리 방안을 명시하거나, 로딩 상태를 간단히 시각화해 주면 더욱 견고한 UX를 제공할 수 있습니다.

src/components/common/Dropdown.tsx (3)

1-2: OptionType 정의에 대한 유연성을 다시 검토해보세요.
OptionType이 문자열, 배열 등을 모두 허용하도록 설계되어 있어 재사용성은 좋지만, 향후 복잡한 타입(예: 다차원 배열)으로 확장될 경우 유지보수가 어려울 수 있습니다.


3-13: IProp 인터페이스에 대한 주석 보강을 제안합니다.
인터페이스 내의 onChangedefaultValue 등 각 필드의 의미가 명확히 드러나도록 추가 설명을 부탁드립니다. 추후 협업이나 유지보수 시 이해를 높이는 데 도움이 됩니다.


15-47: 드롭다운 로직 검증이 필요합니다.
typeof i === 'object'로 분기 처리 후 i[2] 여부에 따라 다른 값을 반환하는 로직이 다소 복잡합니다. 타입가드를 활용하거나 별도 함수로 추출해 읽기 쉽게 만들면 좋겠습니다.

src/components/auth-required/main/Summary/index.tsx (1)

9-49: 증가량 계산 로직을 범용적으로 사용하도록 모듈화해보세요.
stats.totalViews - stats.yesterdayViews 같은 증가량 계산은 다른 곳에서도 반복될 수 있습니다. 별도 함수나 유틸로 분리하면 재사용성이 높아집니다.

next.config.mjs (1)

17-23: 원격 이미지 도메인 추가 시 보안과 트래픽을 고려해주세요.
velog.velcdn.com, images.velog.io 외에도 필요한 호스트가 있는지, 그리고 무분별하게 이미지를 불러오는 상황을 방지하기 위해 제한을 둘 필요가 있는지 재검토해보시면 좋겠습니다.

src/components/auth-required/main/Section/index.tsx (1)

10-11: [코멘트] 컴포넌트 Section 타입 지정
파라미터 p: PostType이 명확하게 선언되어 있어 가독성이 좋습니다. 다만, 추후 props 구조분해 할당을 통해 코드 읽기 편의성을 높일 수 있음을 제안합니다.

-export const Section = (p: PostType) => {
+export const Section = ({ id, title, views, yesterdayViews, likes, releasedAt }: PostType) => {
  // 내부에서 p 대신 각 변수 직접 활용
}
src/app/(with-tracker)/(login)/Content.tsx (1)

14-30: [코멘트] 로그인 로직과 반응처리
onSuccess 콜백에서 client.setQueryData(['profile'], res)를 통해 프로필 캐싱 후 리다이렉트하는 로직은 효율적입니다. 단, 로그인 성공 시 /main?asc=false&sort=로 이동하는 로직이 하드코딩되어 있어, 장차 경로가 변경될 때 코드를 수정해야 할 수 있습니다.

src/app/(with-tracker)/(auth-required)/main/Content.tsx (3)

1-2: [코멘트] Next.js 클라이언트 컴포넌트 사용
Auth-required 페이지로 사용되지만 클라이언트 전용 컴포넌트가 적절한지 다시 확인해주세요. 필요 시 서버 컴포넌트로 활용하여 보안을 강화하는 방안을 고려할 수도 있습니다.


28-39: [코멘트] getNextPageParamgetPreviousPageParam 설정
무한 스크롤에 필요한 페이지네이션 로직 구성은 적절합니다. 다만, 이전 페이지가 필요한 경우가 없다면 getPreviousPageParam은 생략 가능할 수도 있으니 검토 부탁드립니다.


46-55: [코멘트] inView 값 변경 시 자동 로드
스크롤 최하단에 도달했을 때 fetchNextPage가 자동 호출되어 UX가 좋습니다. 더 구체적인 로딩 상태 처리(예: 로딩 스피너 표시)도 고려하시면 좋습니다.

src/components/auth-required/Header.tsx (2)

37-41: [프로필 데이터 핸들링 주의]
profiles?.user?.profile.thumbnailprofiles?.user?.usernameundefined일 경우 예기치 않은 UI 깨짐이 발생할 수 있으므로 개별 null/undefined 체크 로직이 필요합니다.

- src={profiles?.user?.profile.thumbnail || '/profile.jpg'}
+ src={profiles?.user?.profile?.thumbnail ?? '/profile.jpg'}

76-79: [드롭다운 토글 가시성 제어 논의]
드롭다운 요소가 열릴 때, 화면 오른쪽에서 요소가 가려지지 않는지 및 스크롤 가능 영역과 충돌이 없는지 UI 관점에서 한번 검토해주세요.

src/components/auth-required/main/Section/Graph.tsx (2)

70-80: [데이터 가공 로직 분리 제안]
select 옵션 내에서 라벨 및 data 배열 가공 로직이 단순하지만, 규모가 확장될 경우를 대비해 가공 로직을 별도의 함수나 util로 추출하는 방안을 고려해볼 수 있습니다.


117-123: [미선택 상태 안내 UI]
!datas일 때 표시되는 “날짜를 선택해서 데이터를 확인하세요!” 문구가 적절합니다. 추가적으로 접속 환경(일자 입력이 어렵거나, 정해진 범위를 벗어난 경우)에서도 직관적인 에러 또는 안내 메시지를 고려하면 사용자 경험이 향상될 수 있습니다.

src/app/globals.css (2)

7-7: [User-select 비활성화 확인]
user-select: none;으로 인해 모든 텍스트가 드래그 및 복사가 불가능합니다. 의도된 UX라면 괜찮으나, 일부 텍스트가 선택되어야 하는 경우가 있다면 필요 범위를 제한하는 것이 좋습니다.


28-36: [스크롤바 UI 커스터마이징 점검]
스크롤바가 매우 얇아지는(5px) 경우 사용자 경험이 떨어질 수 있으며, 투명 배경으로 인해 구분이 어려울 수 있습니다. 디자인 컨셉과 접근성을 함께 고려해주세요.

src/app/layout.tsx (1)

26-26: ToastContainer 국제화 설정 제안

현재 ToastContainerautoClose 설정만 되어있습니다. 한국어 사용자를 위한 추가 설정을 고려해보세요.

-<ToastContainer autoClose={2000} />
+<ToastContainer
+  autoClose={2000}
+  position="top-right"
+  hideProgressBar={false}
+  closeOnClick
+  pauseOnHover
+  draggable
+  theme="light"
+/>
src/utils/trackUtil.tsx (2)

11-11: 타입 이름의 명확성 개선 필요

MessageType이라는 이름이 이벤트 타입을 나타내는데 충분히 명확하지 않습니다. 더 구체적인 이름을 사용하는 것이 좋습니다.

-type MessageType = '01' | '02' | '03' | '04' | '99';
+type EventTrackingCode = '01' | '02' | '03' | '04' | '99';

또한 매직 넘버 대신 의미 있는 상수를 사용하는 것을 추천드립니다:

export const EventType = {
  PAGE_VIEW: '01',
  USER_ACTION: '02',
  ERROR: '03',
  PERFORMANCE: '04',
  CUSTOM: '99'
} as const;

type EventTrackingCode = typeof EventType[keyof typeof EventType];

35-43: 환경 분기 처리 개선 필요

현재 프로덕션 환경 체크가 중복되어 있습니다. 상수나 유틸리티 함수로 분리하는 것이 좋습니다.

+const isProduction = process.env.NODE_ENV === 'production';

 useEffect(() => {
   data.current.loadDate = new Date().toISOString();
-  if (process.env.NODE_ENV === 'production') {
+  if (isProduction) {
     window.addEventListener('unload', setUnloadData);
   }

   return () => {
-    if (process.env.NODE_ENV === 'production') {
+    if (isProduction) {
       window.removeEventListener('unload', setUnloadData);
     }
   };
 }, []);
📜 Review details

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

📥 Commits

Reviewing files that changed from the base of the PR and between 179dbd5 and 25ef09b.

⛔ Files ignored due to path filters (2)
  • pnpm-lock.yaml is excluded by !**/pnpm-lock.yaml
  • public/favicon.jpg is excluded by !**/*.jpg
📒 Files selected for processing (66)
  • .eslintrc.json (1 hunks)
  • eslint.config.mjs (1 hunks)
  • next.config.mjs (1 hunks)
  • package.json (1 hunks)
  • readme.md (1 hunks)
  • src/__test__/login.test.tsx (1 hunks)
  • src/apis/dashboard.request.ts (1 hunks)
  • src/apis/index.ts (1 hunks)
  • src/apis/instance.request.ts (2 hunks)
  • src/apis/user.request.ts (1 hunks)
  • src/app/(auth-required)/compare/page.tsx (0 hunks)
  • src/app/(auth-required)/layout.tsx (0 hunks)
  • src/app/(auth-required)/leaderboards/page.tsx (0 hunks)
  • src/app/(auth-required)/main/page.tsx (0 hunks)
  • src/app/(login)/Content.tsx (0 hunks)
  • src/app/(login)/index.ts (0 hunks)
  • src/app/(with-tracker)/(auth-required)/compare/page.tsx (1 hunks)
  • src/app/(with-tracker)/(auth-required)/layout.tsx (1 hunks)
  • src/app/(with-tracker)/(auth-required)/leaderboards/page.tsx (1 hunks)
  • src/app/(with-tracker)/(auth-required)/main/Content.tsx (1 hunks)
  • src/app/(with-tracker)/(auth-required)/main/page.tsx (1 hunks)
  • src/app/(with-tracker)/(login)/Content.tsx (1 hunks)
  • src/app/(with-tracker)/layout.tsx (1 hunks)
  • src/app/global-error.tsx (0 hunks)
  • src/app/globals.css (1 hunks)
  • src/app/index.ts (0 hunks)
  • src/app/layout.tsx (1 hunks)
  • src/components/QueryProvider.tsx (0 hunks)
  • src/components/auth-required/Header.tsx (2 hunks)
  • src/components/auth-required/main/Section.tsx (0 hunks)
  • src/components/auth-required/main/Section/Graph.tsx (1 hunks)
  • src/components/auth-required/main/Section/index.tsx (1 hunks)
  • src/components/auth-required/main/Summary/BarContent.tsx (3 hunks)
  • src/components/auth-required/main/Summary/SidebarContent.tsx (2 hunks)
  • src/components/auth-required/main/Summary/index.tsx (1 hunks)
  • src/components/common/ArriveSoon.tsx (1 hunks)
  • src/components/common/Button.tsx (1 hunks)
  • src/components/common/Check.tsx (1 hunks)
  • src/components/common/Dropdown.tsx (1 hunks)
  • src/components/common/Icon/index.tsx (3 hunks)
  • src/components/common/Input.tsx (2 hunks)
  • src/components/common/QueryProvider.tsx (1 hunks)
  • src/components/common/index.ts (1 hunks)
  • src/components/index.ts (1 hunks)
  • src/constants/colors.constant.ts (1 hunks)
  • src/constants/colors.ts (0 hunks)
  • src/constants/fonts.constant.ts (1 hunks)
  • src/constants/index.ts (1 hunks)
  • src/constants/paths.constant.ts (1 hunks)
  • src/constants/sizes.constant.ts (1 hunks)
  • src/errors/fetch.error.ts (1 hunks)
  • src/errors/index.ts (1 hunks)
  • src/hooks/index.ts (1 hunks)
  • src/hooks/useResponsive.ts (1 hunks)
  • src/hooks/useSearchParam.ts (1 hunks)
  • src/types/apis/dashboard.type.ts (1 hunks)
  • src/types/apis/index.ts (1 hunks)
  • src/types/apis/user.type.ts (1 hunks)
  • src/types/index.ts (1 hunks)
  • src/utils/componentUtil.tsx (1 hunks)
  • src/utils/cookieUtil.tsx (1 hunks)
  • src/utils/index.tsx (1 hunks)
  • src/utils/numberUtil.ts (1 hunks)
  • src/utils/trackUtil.tsx (2 hunks)
  • tailwind.config.ts (2 hunks)
  • tsconfig.json (0 hunks)
💤 Files with no reviewable changes (12)
  • src/app/index.ts
  • src/app/global-error.tsx
  • tsconfig.json
  • src/app/(auth-required)/leaderboards/page.tsx
  • src/app/(auth-required)/layout.tsx
  • src/app/(auth-required)/compare/page.tsx
  • src/constants/colors.ts
  • src/app/(login)/index.ts
  • src/components/QueryProvider.tsx
  • src/app/(auth-required)/main/page.tsx
  • src/components/auth-required/main/Section.tsx
  • src/app/(login)/Content.tsx
✅ Files skipped from review due to trivial changes (13)
  • src/components/index.ts
  • src/app/(with-tracker)/(auth-required)/leaderboards/page.tsx
  • src/types/index.ts
  • src/app/(with-tracker)/(auth-required)/compare/page.tsx
  • src/types/apis/index.ts
  • src/apis/index.ts
  • src/components/common/ArriveSoon.tsx
  • .eslintrc.json
  • src/utils/componentUtil.tsx
  • src/constants/paths.constant.ts
  • src/errors/index.ts
  • src/errors/fetch.error.ts
  • src/constants/index.ts
🧰 Additional context used
🪛 Biome (1.9.4)
src/utils/cookieUtil.tsx

[error] 8-8: The assignment should not be in an expression.

The use of assignments in expressions is confusing.
Expressions are often considered as side-effect free.

(lint/suspicious/noAssignInExpressions)

🔇 Additional comments (75)
src/utils/index.tsx (2)

2-2: numberUtil 익스포트 유지에 대한 확인

이 라인은 기존 로직 그대로 유지되어 있어 보입니다. 별도의 문제 없이 numberUtil이 정상적으로 동작하고 있는지 다시 한번 확인해 주세요.


3-3: 새로운 trackUtil 익스포트 추가 확인

trackUtil 모듈이 새롭게 익스포트되어 있으므로, 해당 모듈을 사용하는 코드가 정상적으로 동작하는지와 이전에 사용하던 eventTracker와의 의존 관계가 해소되었는지 확인하시기 바랍니다.

src/apis/instance.request.ts (2)

18-23: 타입 구조 일관성 확인 필요
SuccessType<T>는 성공 응답 구조를 명확히 정의하여 API 일관성을 높이는 데 도움이 됩니다. 다만, 백엔드에서 모든 성공 응답이 해당 구조를 준수하는지 확인이 필요합니다.


36-40: 엔드포인트 Prefix 처리 주의
baseUrl이 설정되어 있음에도, 실제 요청에는 '/api' + input이 사용되고 있습니다. URL path가 중복으로 합쳐지거나 슬래시(//)가 중복되는 문제가 발생하지 않는지 확인해야 합니다.

src/hooks/index.ts (1)

1-1: 새로운 훅 재활용성 상승
useSearchParam 훅을 re-export하여 다른 모듈에서도 쉽게 활용 가능한 구조가 되었습니다. 전역에서 사용 시 코드 유지보수가 용이해질 것으로 보입니다.

src/constants/sizes.constant.ts (1)

8-8: 타입 네이밍 컨벤션 반영
sizeType에서 SizeType으로 변경하여 가독성을 향상했습니다. 대문자로 시작하는 타입명을 사용하면 더욱 일관성 있는 코드 스타일을 유지할 수 있습니다.

src/app/(with-tracker)/layout.tsx (2)

1-2: [ko-KR] import문의 정상 사용 확인
해당 import 구문은 올바르게 작성되어 있으며, 추적 기능을 위한 컴포넌트가 정상적으로 로드됩니다.


3-10: [ko-KR] Layout 컴포넌트 구조 점검
TrackVisitEvent를 통해 페이지 방문 트래킹을 수행한 후 children을 표시함으로써, 원하는 콘텐츠의 렌더링 흐름이 명확합니다. 유지보수성 또한 양호하며 문제 사항이 없어 보입니다.

src/types/apis/user.type.ts (2)

1-4: [ko-KR] LoginVo 타입 검토
accessTokenrefreshToken을 필드로 두어 인증 관련 정보를 구조화한 점이 좋아 보입니다. 추가로, 로그인 관련 요청/응답에서의 밸리데이션 테스트도 함께 고려하면 안전성 향상에 도움이 됩니다.


6-15: [ko-KR] UserDto 타입의 계층적 정의
중첩된 profile 객체가 사용자 데이터를 확장성 있게 다룰 수 있도록 설계되었습니다. 역할과 책임 구분이 잘 드러나며, 협업 시 혼동을 줄여줄 것으로 보입니다.

src/constants/colors.constant.ts (2)

1-26: [ko-KR] COLORS 상수 구조가 명확하여 유지보수성과 확장성 확보
각 색상 그룹을 카테고리화하여 시각적인 일관성을 유지하기에 용이합니다. 추가로, 색상 값들이 정확한지와 실제 UI/UX에서 의도된 색상과 일치하는지 시각 테스트가 필요해 보입니다.


28-28: [ko-KR] ColorType 정의
COLORS의 키를 기반으로 'MAIN' | 'SUB' | 'ALT'를 사용하도록 타입을 구성함으로써, 색상 속성의 오타나 누락을 방지할 수 있습니다. 이 방식은 타입 안정성을 보장하면서도 불필요한 반복 정의를 최소화합니다.

tailwind.config.ts (2)

2-7: Tailwind 구성에 FONTS 상수 추가 확인
해당 import 구문을 통해 FONTS 상수를 정상적으로 불러오고 있습니다. 폰트 사이즈를 Tailwind 설정에 반영하는 의도가 명확해 보입니다.


19-23: 커스텀 폰트 사이즈 설정 사용 제안
fontSize 속성에 FONTS 상수를 직접 지정함으로써 폰트 크기를 일원화하고 유지보수를 용이하게 만들었습니다. Tailwind 플러그인이나 추가적인 프리셋과 충돌이 없는지 확인해 주세요.

src/components/common/Button.tsx (2)

1-1: 상수 및 타입 불러오는 위치 확인
SIZESSizeType@/constants로부터 불러오는 것은 프로젝트 구조상 합리적으로 보입니다.


3-5: IProp 인터페이스 개선
React.ButtonHTMLAttributes<HTMLButtonElement>를 상속받아 확장하는 방식으로 변경되어, 불필요한 제네릭 중첩이 제거되고 가독성이 좋아졌습니다.

src/apis/user.request.ts (2)

18-19: 사용자 정보 요청 (me) 함수
me 함수는 instance 호출로 사용자 정보를 받아오며, 반환 타입을 명시하여 타입 안전성을 보장하는 점이 좋습니다.


21-22: 로그아웃 처리
로그아웃 요청에 별도의 바디가 필요 없는 경우, { method: 'POST', body: undefined } 방식은 단순 명료합니다. 추가적으로 실패 응답 코드 처리(401, 500 등)도 고려해 주세요.

src/hooks/useResponsive.ts (1)

8-10: 클라이언트 환경 확인 로직 반전
if (typeof window === 'undefined') 체크를 통해 SSR 환경에서 아무 동작도 하지 않도록 처리한 점이 좋습니다. 단, 반환된 cleanup 함수가 SSR에서 불필요하게 호출되지 않도록 주의하십시오.

src/components/auth-required/main/Summary/BarContent.tsx (4)

1-1: [임포트 경로 변경이 잘 반영되었습니다]

이전 @/utils 경로에서 @/utils/numberUtil로 이동하여 parseNumber를 불러오는 변경 사항은 의도대로 동작해 보이므로 문제 없어 보입니다.


11-11: [CSS 클래스 변경 확인 필요]

before:text-primary-sub에서 before:text-PRIMARY-SUB로 바뀌었고, before:text-[18px]에서 before:text-T5로 수정되었습니다. 새로운 스타일 토큰(T5)이 정의되어 있는지, 다른 컴포넌트와 일관성을 유지하는지 확인이 필요합니다.


21-21: [텍스트 스타일 토큰 적용]

text-[15px] font-medium text-text-alt에서 text-ST5 text-TEXT-ALT로 변경되었습니다. 기존 폰트 사이즈, 볼드 여부와 시각적 일관성을 확인해 보세요.


23-23: [폰트 스타일 변경 주의]

flex items-center font-bold text-text-main text-[25px]에서 flex items-center text-TEXT-MAIN text-T4로 바뀌어 폰트 두께가 달라졌습니다. 디자인 가이드에 맞다면 문제 없으나, 의도된 변경인지 다시 확인해 주세요.

src/types/apis/dashboard.type.ts (5)

1-10: [PostType 정의]

게시물 속성(id, title, views 등)이 직관적이고 명확하게 타입으로 선언되어 있습니다. 문제될 부분 없어 보입니다.


12-16: [PostListDto 설계]

nextCursornull일 가능성을 열어 두어 페이징 처리에 유연성을 주었습니다. 안정적인 설계로 보입니다.


18-27: [PostSummaryDto의 날짜 문자열 처리 확인]

lastUpdatedDate가 문자열 형태로 정의되어 있는데, 문자열 파싱 혹은 포매팅이 필요한 경우 호출부에서 적절히 처리하는지 점검해 보세요.


29-33: [snake_case 속성 주의]

daily_view_count, daily_like_count 등 snake_case가 백엔드 API 사양과 일치하는지, 혹은 이후에 camelCase로 변환해 주는 로직이 필요한지 확인이 필요합니다.


35-37: [PostDetailDto 구조]

PostDetailValue 항목을 배열로 갖도록 설계해, 상세 조회에 일관성을 주는 구조입니다. 명확하고 직관적으로 보입니다.

src/components/common/Icon/index.tsx (5)

3-3: [타입 네이밍 개선]

nameType에서 NameType으로 변경되어 가독성이 좋아졌습니다.


5-6: [iconType 레코드 키 업데이트]

NameType을 키로 사용하는 iconType 정의가 보다 명확해졌습니다. 잘 반영되었습니다.


9-10: [컴포넌트 Prop 타입 정의]

name: NameType으로 변경하여 더 엄격하고 명료한 타입 지정이 되었습니다. 문제 없어 보입니다.


25-25: [디폴트값으로 size, color, rotate 설정]

size = 30, color = '#ACACAC', rotate = 'up' 등으로 기본값을 명확하게 설정해, 사용 시 편리함을 제공합니다.


36-38: [클래스 및 width/height 설정]

widthheightsize 값을 직접 할당해 로직이 단순해졌습니다. rotates[rotate] 클래스로 회전도 손쉽게 적용하도록 설계되어 좋습니다.

src/hooks/useSearchParam.ts (4)

1-7: [Next.js Navigation 훅 사용]

useSearchParams, useRouter, usePathname를 조합하여 검색 파라미터를 관리하는 로직의 시작 부분입니다. 의도대로 동작할 것으로 보입니다.


9-15: [setNewParams 함수 동작 확인]

newParams 객체를 순회하며 value가 없으면 delete하는 로직이 있어 유연해 보이지만, 파라미터로 null 혹은 undefined가 올 수 있는 경우를 한 번 더 점검해 보세요.


17-19: [router.push 활용 주의]

router.push로 쿼리 파라미터를 갱신할 때, 페이지 리로드나 라우팅 충돌이 발생하지 않는지 확인해 보세요.


21-25: [searchParams 오브젝트 반환]

Object.fromEntries(searchParams)로 현재 쿼리 파라미터 상태를 쉽게 활용할 수 있도록 해 두었습니다. 충분히 이해하기 쉬운 훅 API 설계입니다.

src/components/common/Input.tsx (3)

1-2: [주의] import 구조를 단순화한 점은 좋지만, React 관련 타입 사용을 명확히 합시다.
현재 React.InputHTMLAttributes를 직접 사용하도록 변경했는데, 이 방식은 문제없어 보입니다. 다만, 프로젝트 전반에서 사용하는 import 패턴과 일관성을 유지하는지 확인이 필요합니다.


5-7: [의견] IProp 인터페이스에서 'size'가 필수 필드인 점을 재확인해주세요.
만약 size가 필수일 필요가 없다면, 옵셔널로 변경하는 것을 고려해볼 수 있습니다. 현재 구조상 size는 필수로 사용되는 것으로 보이며, 이를 유지하려면 호출 측에서 빼먹지 않도록 주의가 필요합니다.


11-12: [확인] FORMS에 정의된 클래스명 변경이 다른 컴포넌트들과 호환되는지 점검해주세요.
ClassName을 전역적으로 일관되게 적용하고 있는지 확인이 필요합니다. 기존에 사용하던 스타일링에 영향이 있을 수 있으니, 다른 컴포넌트와 동작을 비교해보면 좋겠습니다.

src/apis/dashboard.request.ts (3)

1-4: [의견] 타입 및 상수 import 구조가 깔끔합니다.
PostDetailDto, PostListDto, PostSummaryDto 등 필요한 타입만 명확히 가져와 사용하신 점이 좋아 보입니다. PATHS 같은 상수 값도 한눈에 들어와서, 유지보수가 용이할 것 같습니다.


5-9: [확인] SortType 정의 시, ascsort 모두 필수인지 검토해주세요.
클라이언트에서 정렬 옵션을 다양하게 전달할 때, sort가 실제로 어떤 프로퍼티를 가리키는지 명확하면 좋겠습니다. 또한 asc/desc 구분 필요성이 명확한지 다시 한 번 확인 부탁드립니다.


25-28: [검토] postDetail 함수에서 path, start, end로 필터링할 때 형식 검증이 필요한지 확인해 보세요.
URL 파라미터로 들어오는 값이 예상 형태가 아닐 경우 서버나 클라이언트에서 에러가 발생할 수 있으므로, 안전한 처리를 위해 추가 검증 로직을 고려해볼 수 있습니다.

src/components/common/Check.tsx (2)

1-6: [설명] IProp 인터페이스를 통해 체크박스의 필수 속성과 선택 속성을 명확히 구분한 점이 좋습니다.
checked에 boolean을 할당하여 제어하는 구조, direction으로 레이아웃 방향을 설정하는 방식 모두 직관적입니다.


8-35: [안내] Check 컴포넌트에서 label과 checkbox를 분리해 시각적으로 배치하는 방법이 잘 설계되었습니다.
Tailwind CSS 클래스도 간결하며, onChange 이벤트를 input 대신 부모 div에서 처리하려고 시도한 점이 이색적이나, 이벤트 전파와 접근성 측면에서 문제가 없는지 한 번 더 확인해보시면 좋겠습니다.

src/app/(with-tracker)/(auth-required)/layout.tsx (1)

22-30: HydrationBoundary와 Header를 통한 레이아웃 구성이 명확하고 일관성이 있습니다.
부모 컴포넌트에서 데이터를 사전에 불러온 뒤 HydrationBoundary로 감싸는 패턴은 React Query 활용에 있어 바람직한 구조로 보입니다. 현재 로직은 가독성이 뛰어나고, 재사용성도 높아 보이므로 유지해도 좋습니다.

src/constants/fonts.constant.ts (1)

1-4: 타입 정보를 Record 형태로 선언하여 유연성을 확보했습니다.
Record<string, [string, { lineHeight: string; fontWeight: number }]>를 통해 다양한 폰트 설정을 구조적으로 관리할 수 있습니다. 유지 보수 시에도 용이해 보입니다.

src/components/common/QueryProvider.tsx (2)

4-5: ReactQueryDevtools를 통한 디버깅 환경 강화가 좋습니다.
개발 중에 쿼리 상태를 쉽게 확인할 수 있으므로 유지보수 시 도움이 큽니다. 운영 환경에서 비활성화가 필요한 경우도 있으니, 빌드 환경에 따라 조건부로 노출하도록 고려해 보세요.


31-38: QueryClientProvider 내부에서 Devtools와 자식 컴포넌트를 함께 관리해 구조가 깔끔합니다.
ReactQueryDevtools가 동일 계층에서 정의되어 있어 디버깅이 한층 수월합니다. 실제 운영 시 Devtools가 불필요하다면 빌드 환경 분기에 따라 제거하는 방법도 검토해 보세요.

src/app/(with-tracker)/(auth-required)/main/page.tsx (2)

13-16: 페이지 메타데이터가 페이지 목적과 부합합니다.
페이지의 제목과 설명이 실제 대시보드 기능을 표현하고 있어 사용자 이해에 도움이 됩니다.


45-50: HydrationBoundary를 통해 서버에서 사전 로딩한 상태를 안전하게 전달하고 있습니다.
SSR 렌더링 후 클라이언트에서 동일한 상태를 이어받을 수 있어, 중복 요청을 방지하고 UI 깜박임이 최소화됩니다. 이 패턴은 React Query 활용의 모범 사례입니다.

eslint.config.mjs (1)

15-24: React와 NodeJS를 글로벌로 선언할 때 충돌 여부를 확인해주세요.
React, NodeJS 두 글로벌 환경에서 동작하는 프로젝트가 아닐 경우, 의도치 않은 전역 변수가 생길 수 있으니 실제로 필요한 전역만 열어 둘 것을 권장합니다.

src/components/auth-required/main/Summary/index.tsx (1)

5-5: PostSummaryDto 임포트 확인
PostSummaryDto가 실제로 필요한 필드를 모두 제공하는지, 다른 컴포넌트나 API 스펙과 일관성이 있는지 점검을 권장드립니다.

src/components/auth-required/main/Section/index.tsx (3)

1-2: [코멘트] Next.js 클라이언트 컴포넌트를 올바르게 선언했는지 확인해주세요.
이 파일 전체가 클라이언트 사이드에서만 동작해야 한다면 'use client' 지시자는 적절합니다.


3-9: [코멘트] 불필요한 import 존재 여부와 의존성 확인
현재 코드에서는 useState, parseNumber, COLORS, Icon, PostType, Graph 군이 모두 실제로 사용되고 있습니다. import가 적절하며 불필요한 의존성은 없어 보입니다.


13-55: [코멘트] 토글 로직과 UI 구조
open 상태에 따라 UI가 동적으로 변경되어, 사용자에게 직관적인 인터랙션을 제공해줍니다. 다만, releasedAt.split('T') 호출 전 releasedAt이 항상 기대하는 형태의 문자열인지 유효성 검토가 필요합니다.

src/app/(with-tracker)/(login)/Content.tsx (3)

1-2: [코멘트] Next.js 클라이언트 컴포넌트 사용 확인
이 페이지가 실제로 클라이언트 사이드에서만 구동되어야 한다면 'use client' 옵션은 적절합니다.


3-10: [코멘트] 라우팅 및 폼 관리 라이브러리 의존성
useRouter, react-hook-form, useMutation 등 필요한 라이브러리들을 적절히 import하였습니다. v상태 관리와 폼 검증이 명확하게 분리되어 있어 유지보수가 용이합니다.


32-76: [코멘트] UI 구현 및 입력폼 유효성 검증

  • isValid를 통해 Submit 버튼의 활성화를 제어하는 방식이 간단하고 직관적입니다.
  • type="password"로 설정하여 보안 향상에 신경 쓴 점이 좋습니다.
    추가로, 향후 보안 이슈(토큰 노출 방지)를 고려하여 애플리케이션 전반에서 이 토큰들이 로그 등 외부 저장소에 노출되지 않도록 주의해주세요.
src/__test__/login.test.tsx (2)

6-6: [코멘트] renderWithQueryClient 경로 변경
테스트 유틸 함수를 @/utils/componentUtil로 이동한 점이 확인됩니다. 이전 참조 코드와의 충돌이 없는지 한번 더 확인해주세요.


8-8: [코멘트] Login 컴포넌트 경로 변경
import { default as Login } from '@/app/(with-tracker)/(login)/page'; 형태의 변경은 논리적으로 맞으며, 테스트에서 정상 동작하는지 CI 환경에서 확인 권장드립니다.

src/app/(with-tracker)/(auth-required)/main/Content.tsx (4)

3-17: [코멘트] React Query 훅과 intersection observer 활용
useInfiniteQuery, useQuery, useInView를 혼합 사용하여 무한 스크롤을 구현하는 구조가 잘 갖추어져 있습니다. 유지보수가 용이해 보이므로 동일 패턴을 다른 곳에서도 일관성 있게 적용하는 것을 권장합니다.


18-22: [코멘트] 정렬 옵션 배열 구현
sorts 배열 구조가 한글 라벨과 정렬 기준값을 구분 짓고 있어 명확합니다. 향후 정렬 기준이 늘어날 경우 동일한 형태로 손쉽게 확장 가능해 보입니다.


41-44: [코멘트] 개별 요약 데이터 Fetch
postSummary로부터 가져오는 요약 데이터가 게시글 리스트와 별개로 잘 분리되어 있습니다. 쿼리 키가 단순 [PATHS.SUMMARY]인데, 향후 여러 요약 데이터가 더 필요해진다면 키를 세분화하는 방안도 검토해주세요.


57-112: [코멘트] 컨테이너 구조 및 정렬 기능

  • 정렬 드롭다운, 오름차순 옵션, 요약 섹션 및 게시글 리스트를 한 화면에서 직관적으로 구성했습니다.
  • 마지막 게시글을 렌더링할 때 ref를 배치하여 무한 스크롤을 작동시키는 방법이 적절합니다.
    추가 로딩 시 사용자에게 로딩 상태를 안내해 주는 방안(스피너, 로딩 메시지 등)을 고민해보시면 좋겠습니다.
src/components/auth-required/Header.tsx (3)

32-35: [로그아웃 처리 시 리다이렉션 확인 권장]
로그아웃 이후 router.replace('/')가 정상적으로 메인 페이지(또는 원하는 경로)로 이동하는지 실제 시나리오에서 한 번 더 확인해보면 좋겠습니다.


66-70: [링크 UI 표시 개선 제안]
LinkIcon만 보이는 모바일 뷰(max-MBI:hidden)와 달리, 데스크톱 뷰에서도 텍스트가 가능하도록 논리 분리가 명확한지 확인이 필요합니다.


42-51: [외부 클릭에 의한 메뉴 닫힘 로직 검토]
document.addEventListener('mousedown', handleClickOutside); 후 정리 작업(removeEventListener)이 적절히 수행되므로 메모리 누수 방지는 괜찮아 보입니다. 단, menu가 존재하지 않는 상황이 있을 경우를 대비해 방어 코드를 추가할 수 있습니다.

src/components/auth-required/main/Section/Graph.tsx (2)

66-82: [조건부 쿼리 사용 검토]
enabled: !!type.start && !!type.end 설정으로 쿼리 실행을 제어하는 로직은 적절합니다. 다만, start, end가 무조건 valid date인지(사용자가 미래 날짜를 입력하는 등)를 추가 확인할 필요가 있을 수 있습니다.


125-150: [차트 옵션 적절성 확인]
responsive: true, animation: false, legend: { display: false } 등 Chart.js 옵션이 제대로 적용되었는지, 그리고 UX 시나리오상 필요한 에니메이션이나 범례가 있는지 확인해주세요.

readme.md (1)

10-10: [중복된 패키지 설치 여부 확인]
NODE_ENV=development pnpm install과 뒤이어 pnpm install을 모두 실행하는 경우, 의도치 않게 동일 라이브러리가 두 번 설치되거나 환경이 꼬일 수 있습니다. 실제 설치 과정에서 문제가 없는지 확인을 권장합니다.

src/app/globals.css (2)

12-15: [input/textarea 스타일 주의]
appearance: none 주석 처리 시 브라우저 기본 스타일이 제거됩니다. 특정 사용자 접근성 기능(예: iOS용 확대 제스처)이 제대로 동작하는지 점검이 필요할 수 있습니다.


38-50: [fadeIn 애니메이션 사용 시점 검토]
display: none;display: flex; 전환이 필요한 실제 UI 요소에서만 적용해야 부자연스러운 화면 전환을 방지할 수 있습니다. 추후 자동 테스트나 E2E 테스트에서 이 애니메이션으로 인한 포커스 타이밍이 문제되지 않을지도 확인해보세요.

src/app/layout.tsx (1)

23-23: 클래스명 컨벤션 변경 확인 필요

bg-bg-main에서 bg-BG-MAIN로의 변경이 확인되었습니다. 이는 스타일링 네이밍 컨벤션의 변경을 의미할 수 있습니다. 전체 프로젝트에서 일관된 네이밍 컨벤션이 적용되었는지 확인이 필요합니다.

✅ Verification successful

대문자 네이밍 컨벤션이 일관되게 적용되어 있음을 확인

검색 결과를 통해 프로젝트 전체에서 bg-BG-MAIN, bg-BG-SUB, bg-BG-ALT 등과 같이 대문자 네이밍 컨벤션이 일관되게 사용되고 있음을 확인했습니다. 소문자 패턴(bg-bg-main)은 발견되지 않았으며, 이는 이번 변경이 기존 컨벤션을 따르고 있음을 의미합니다.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# 프로젝트 전체에서 기존 네이밍 패턴 검색
rg 'bg-[a-z]-[a-z]' -t css -t tsx
# 새로운 네이밍 패턴 검색
rg 'bg-[A-Z]-[A-Z]' -t css -t tsx

Length of output: 127


Script:

#!/bin/bash
# Search for both old and new naming patterns in all files
rg 'bg-[a-z]+-[a-z]+' --type-add 'tsx:*.tsx' --type-add 'css:*.css'
rg 'bg-[A-Z]+-[A-Z]+' --type-add 'tsx:*.tsx' --type-add 'css:*.css'

# Also check tailwind config for color definitions
fd -e js -e cjs -e ts -X rg 'BG-MAIN|bg-main'

Length of output: 2642

package.json (1)

17-17: Chart.js 버전 호환성 확인 필요

chart.js 버전이 4.4.7로 설정되어 있는데, 이는 현재 안정 버전보다 높습니다. 호환성 문제가 발생할 수 있습니다.

✅ Verification successful

Chart.js 버전이 최신 안정 버전과 일치합니다

패키지의 [email protected] 버전이 npm 레지스트리의 최신 안정 버전과 정확히 일치하므로 호환성 문제가 발생하지 않을 것입니다.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Chart.js의 현재 안정 버전 확인
curl -s https://registry.npmjs.org/chart.js/latest | jq '.version'

Length of output: 74

src/utils/trackUtil.tsx Show resolved Hide resolved
package.json Show resolved Hide resolved
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

🧹 Nitpick comments (2)
src/types/apis/dashboard.type.ts (2)

1-10: 날짜 필드의 타입 개선이 필요합니다

createdAtreleasedAt 필드가 문자열 대신 더 명확한 타입을 사용할 수 있습니다.

다음과 같이 변경을 제안합니다:

 export type PostType = {
   id: string;
   title: string;
-  createdAt: string;
-  releasedAt: string;
+  createdAt: Date;
+  releasedAt: Date;
   views: number;
   likes: number;
   yesterdayViews: number;
   yesterdayLikes: number;
 };

17-26: 통계 데이터의 시간 정보 개선이 필요합니다

통계 정보에 대한 시간 관련 필드의 개선사항:

  1. lastUpdatedDate 필드를 Date 타입으로 변경
  2. 통계 데이터의 기준 시간대 명시 필요

다음과 같이 변경을 제안합니다:

 export type PostSummaryDto = {
   totalPostCount: number;
   stats: {
     totalViews: number;
     totalLikes: number;
     yesterdayViews: number;
     yesterdayLikes: number;
-    lastUpdatedDate: string;
+    lastUpdatedDate: Date;
+    timezone: string; // e.g. 'Asia/Seoul'
   };
 };
📜 Review details

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

📥 Commits

Reviewing files that changed from the base of the PR and between 25ef09b and 9ef2690.

📒 Files selected for processing (1)
  • src/types/apis/dashboard.type.ts (1 hunks)
🔇 Additional comments (1)
src/types/apis/dashboard.type.ts (1)

12-15: 구현이 적절합니다!

페이지네이션을 위한 커서 기반 구조가 잘 설계되어 있습니다.

src/types/apis/dashboard.type.ts Show resolved Hide resolved
src/types/apis/dashboard.type.ts Show resolved Hide resolved
Copy link

@HA0N1 HA0N1 left a comment

Choose a reason for hiding this comment

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

상수 처리가 인상 깊었습니다!
빠르게 승인 하겠습니다!

Comment on lines +30 to +31
daily_view_count: number;
daily_like_count: number;
Copy link
Member

Choose a reason for hiding this comment

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

@HA0N1 얘 근데 왜 스네이크케이스?

Copy link
Member Author

Choose a reason for hiding this comment

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

클라 쪽에선 우선 서버에서 넘어오는 형태로 반환하긴 했습니다..
사실 케이스가 다르다고 하온님께 말씀을 드려야 했는데 자연스러워서 눈치도 못 챘네요;;

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

♻️ Duplicate comments (2)
src/types/apis/dashboard.type.ts (2)

28-32: 🛠️ Refactor suggestion

명명 규칙의 일관성 개선이 필요합니다

서버에서 snake_case로 데이터가 전달된다고 해도, 프론트엔드에서는 TypeScript/JavaScript 컨벤션에 맞춰 camelCase를 사용하고 타입 변환 계층에서 처리하는 것이 좋습니다.

다음과 같이 변경을 제안합니다:

 export type PostDetailValue = {
   date: string;
-  daily_view_count: number;
-  daily_like_count: number;
+  dailyViewCount: number;
+  dailyLikeCount: number;
 };

34-36: 🛠️ Refactor suggestion

배열을 나타내는 필드 이름의 복수형 사용이 필요합니다

post 필드가 배열임에도 단수형으로 되어있어 혼란을 줄 수 있습니다.

다음과 같이 변경을 제안합니다:

 export type PostDetailDto = {
-  post: PostDetailValue[];
+  posts: PostDetailValue[];
 };
🧹 Nitpick comments (6)
src/types/apis/dashboard.type.ts (3)

1-10: 날짜 필드의 타입 개선이 필요합니다

createdAtreleasedAt 필드가 현재 string 타입으로 정의되어 있습니다. 날짜 관련 연산과 유효성 검사를 위해 Date 타입을 사용하는 것이 더 안전합니다.

다음과 같이 변경을 제안합니다:

 export type PostType = {
   id: string;
   title: string;
-  createdAt: string;
-  releasedAt: string;
+  createdAt: Date;
+  releasedAt: Date;
   views: number;
   likes: number;
   yesterdayViews: number;
   yesterdayLikes: number;
 };

12-15: 커서 필드에 대한 문서화가 필요합니다

nextCursor 필드가 콤마로 구분된 복합 문자열 값을 사용한다는 점을 JSDoc으로 문서화하면 좋을 것 같습니다.

다음과 같이 문서화를 추가하는 것을 제안합니다:

 export type PostListDto = {
+  /** 콤마(,)로 구분된 복합 커서 값 */
   nextCursor: string;
   posts: PostType[];
 };

17-26: 날짜 타입의 일관성 유지가 필요합니다

lastUpdatedDate 필드도 다른 날짜 필드들과 마찬가지로 Date 타입을 사용하는 것이 좋습니다.

다음과 같이 변경을 제안합니다:

   stats: {
     totalViews: number;
     totalLikes: number;
     yesterdayViews: number;
     yesterdayLikes: number;
-    lastUpdatedDate: string;
+    lastUpdatedDate: Date;
   };
src/apis/dashboard.request.ts (3)

5-20: 타입과 함수 매개변수에 대한 문서화가 필요합니다

SortTypepostList 함수의 매개변수에 대한 설명이 없어 사용하기 어려울 수 있습니다.

다음과 같이 JSDoc을 추가하는 것을 제안합니다:

+/** 정렬 옵션 타입 */
 type SortType = {
+  /** 오름차순 여부 */
   asc: boolean;
+  /** 정렬 기준 필드 */
   sort: string;
 };

+/**
+ * 게시물 목록을 조회합니다.
+ * @param props - 초기화 옵션
+ * @param sort - 정렬 옵션
+ * @param cursor - 페이지네이션 커서 (콤마로 구분된 복합 값)
+ */
 export const postList = async (
   props: InitType<PostListDto>,
   sort: SortType,
   cursor?: number | string,
 ) => ...

22-23: 함수 설명 문서화가 필요합니다

postSummary 함수의 용도와 매개변수에 대한 설명이 필요합니다.

다음과 같이 JSDoc을 추가하는 것을 제안합니다:

+/**
+ * 게시물 통계 요약을 조회합니다.
+ * @param props - 초기화 옵션
+ */
 export const postSummary = async (props: InitType<PostSummaryDto>) =>
   await instance<null, PostSummaryDto>(PATHS.SUMMARY, props);

25-28: 날짜 매개변수의 타입 안전성 개선이 필요합니다

startend 매개변수가 string 타입으로 되어 있어 잘못된 형식의 날짜가 전달될 수 있습니다.

다음과 같이 개선을 제안합니다:

+/**
+ * 특정 게시물의 상세 통계를 조회합니다.
+ * @param path - 게시물 경로
+ * @param start - 시작 날짜 (YYYY-MM-DD 형식)
+ * @param end - 종료 날짜 (YYYY-MM-DD 형식)
+ */
-export const postDetail = async (path: string, start: string, end: string) =>
+export const postDetail = async (
+  path: string,
+  start: `${number}-${number}-${number}`,
+  end: `${number}-${number}-${number}`,
+) =>
   await instance<null, PostDetailDto>(
     `${PATHS.DETAIL}/${path}?start=${start}&end=${end}`,
   );
📜 Review details

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

📥 Commits

Reviewing files that changed from the base of the PR and between 9ef2690 and 3c4bb83.

📒 Files selected for processing (2)
  • src/apis/dashboard.request.ts (1 hunks)
  • src/types/apis/dashboard.type.ts (1 hunks)

@six-standard six-standard merged commit 0fd3816 into main Dec 31, 2024
1 check passed
@six-standard six-standard deleted the feature/graph branch January 1, 2025 09:10
@six-standard six-standard restored the feature/graph branch January 1, 2025 09:10
@six-standard six-standard deleted the feature/graph branch January 1, 2025 09:10
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants