8000 Refactor: 리팩토링 by guesung · Pull Request #152 · guesung/Web-Memo · GitHub
[go: up one dir, main page]
More Web Proxy on the site http://driver.im/
Skip to content

Refactor: 리팩토링 #152

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

Merged
merged 46 commits into from
Jan 29, 2025
Merged

Refactor: 리팩토링 #152

merged 46 commits into from
Jan 29, 2025

Conversation

guesung
Copy link
Owner
@guesung guesung commented Jan 27, 2025

Summary by CodeRabbit

다음은 릴리즈 노트의 주요 변경 사항입니다:

  • 새로운 기능

    • 키보드 바인딩 후크 추가
    • 확장 프로그램 설치 확인 대화 상자 도입
    • Google Tag Manager 통합
  • 버그 수정

    • ESLint 구성 개선
    • 번역 후크 경로 최적화
    • 타입 가져오기 정리
  • 리팩토링

    • 후크 및 구성 요소 구조 재구성
    • 인증 및 세션 관리 로직 간소화
    • 불필요한 구성 요소 제거
  • 성능 개선

    • 쿼리 및 돌연변이 기본 옵션 최적화
    • 의존성 배열 관리 개선
  • 문서화

    • 코드 타입 안전성 향상
    • 가져오기 구조 명확화

주요 변경 사항은 애플리케이션의 구조와 개발 워크플로우를 개선하는 데 중점을 두었습니다.

Copy link
coderabbitai bot commented Jan 27, 2025

Caution

Review failed

The pull request is closed.

개요

이 풀 리퀘스트는 다양한 모듈과 컴포넌트에 걸쳐 광범위한 리팩토링과 구조 개선을 포함하고 있습니다. 주요 변경 사항은 다음과 같습니다:

주요 변경 사항

  1. 훅과 컴포넌트 구조 재구성
  2. ESLint 구성 업데이트
  3. 타입스크립트 타입 가져오기 최적화
  4. 번역 및 국제화 모듈 개선
  5. 컴포넌트 및 유틸리티 정리

상세 분석

1. 훅 및 컴포넌트 변경

  • useSupabaseUseruseSupabaseUserQuery로 대체
  • 여러 공통 훅들이 재구성되고 일부 제거됨
  • 다이나믹 임포트와 코드 스플리팅 개선

2. ESLint 구성

  • unused-imports 플러그인 추가
  • TypeScript 타입 가져오기 일관성 강화
  • 사용하지 않는 임포트 제거 규칙 추가

3. 타입스크립트 개선

  • 대부분의 타입을 import type으로 변경
  • 타입 가져오기 최적화
  • 타입 안전성 향상

4. 국제화 모듈

  • 번역 훅 경로 변경 (clientutil.client)
  • 언어 관련 유틸리티 개선

5. 컴포넌트 정리

  • 사용되지 않는 컴포넌트 제거
  • 컴포넌트 이름 및 구조 개선
  • 피드백 및 오류 처리 컴포넌트 리팩토링

결론

이 풀 리퀘스트는 코드 품질, 성능, 그리고 개발자 경험을 개선하기 위한 광범위하고 체계적인 리팩토링을 나타냅니다. 주요 초점은 코드 일관성, 타입 안전성, 그리고 모듈 구조의 최적화에 맞춰져 있습니다.

🐰 코드 리팩토링, 깔끔하고 멋져!
타입은 안전하게, 훅은 깔끔하게
리팩토링의 춤을 추네 🎉


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.

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.

@guesung guesung changed the base branch from master to develop January 27, 2025 07:44
Copy link

리팩토링

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)
packages/web/src/app/[lng]/(auth)/memos/_components/InitSentryUserInfo/index.tsx (1)

Line range hint 15-22: useEffect의 의존성 배열을 수정해주세요.

useEffect 내에서 사용되는 userlng 변수가 의존성 배열에 포함되어 있지 않습니다. 이로 인해 이 값들이 변경되어도 Sentry 정보가 업데이트되지 않을 수 있습니다.

  useEffect(() => {
    Sentry.setUser({
      username: user?.data?.data?.user?.identities?.[0]?.identity_data?.name,
      email: user?.data?.data?.user?.email,
      id: user?.data?.data?.user?.id,
      ip_address: '{{auto}}',
    });
    Sentry.setTag('lng', lng ?? '');
-  }, []);
+  }, [user?.data?.data?.user, lng]);
packages/shared/src/hooks/supabase/mutations/useMemosUpsertMutation.ts (1)

Line range hint 17-41: 뮤테이션 에러 케이스 처리 강화 필요

현재 NoMemosError만 처리하고 있지만, 다른 잠재적인 에러 케이스(네트워크 오류, 데이터 유효성 등)에 대한 처리가 필요합니다.

// 추가할 에러 타입 정의
type NetworkError = Error & { code: 'NETWORK_ERROR' };
type ValidationError = Error & { code: 'VALIDATION_ERROR' };

// 에러 처리 개선
if (!previousMemosData) {
  const error = new Error('데이터 검증 실패') as ValidationError;
  error.code = 'VALIDATION_ERROR';
  throw error;
}
🧹 Nitpick comments (14)
packages/web/src/app/[lng]/(auth)/memos/_components/MemoSidebar/index.tsx (1)

Line range hint 28-39: items 배열에 타입 안전성 개선이 필요합니다.

현재 items 배열의 타입이 암시적으로 추론되고 있습니다. 명시적인 타입 정의를 추가하면 유지보수성이 향상될 것 같습니다.

다음과 같이 타입을 추가하는 것을 제안드립니다:

+type MenuItem = {
+  i18n: string;
+  url: string;
+  icon: LucideIcon;
+};

-const items = [
+const items: MenuItem[] = [
  {
    i18n: 'sideBar.memo',
    url: PATHS.memos,
    icon: Home,
  },
  {
    i18n: 'sideBar.wishList',
    url: PATHS.memosWish,
    icon: Heart,
  },
];
packages/shared/src/hooks/supabase/index.ts (1)

1-2: 내보내기 순서를 정렬해주세요.

일관성을 위해 내보내기 문을 알파벳 순서로 정렬하는 것이 좋습니다.

-export * from './queries';
-export * from './mutations';
+export * from './mutations';
+export * from './queries';
🧰 Tools
🪛 ESLint

[error] 1-2: Run autofix to sort these exports!

(simple-import-sort/exports)

packages/shared/src/hooks/index.ts (1)

1-3: 내보내기 순서를 정렬해주세요.

일관성을 위해 내보내기 문을 알파벳 순서로 정렬하는 것이 좋습니다.

-export * from './supabase';
-export * from './common';
-export * from './extension';
+export * from './common';
+export * from './extension';
+export * from './supabase';
🧰 Tools
🪛 ESLint

[error] 1-3: Run autofix to sort these exports!

(simple-import-sort/exports)

packages/web/src/instrumentation.ts (1)

1-13: 중복 조건을 리팩토링하면 좋을 것 같습니다.

'nodejs'와 'server' 런타임에서 동일한 설정 파일을 가져오고 있습니다. 조건문을 통합하여 코드를 더 간결하게 만들 수 있습니다.

 export async function register() {
-  if (process.env.NEXT_RUNTIME === 'nodejs') {
+  if (process.env.NEXT_RUNTIME === 'nodejs' || process.env.NEXT_RUNTIME === 'server') {
     await import('./sentry.server.config');
   }

   if (process.env.NEXT_RUNTIME === 'edge') {
     await import('./sentry.edge.config');
   }
-
-  if (process.env.NEXT_RUNTIME === 'server') {
-    await import('./sentry.server.config');
-  }
 }
packages/web/src/app/[lng]/(auth)/memos/_components/index.ts (1)

1-8: 내보내기 구문을 정렬해주세요.

ESLint 규칙에 따라 내보내기 구문을 알파벳 순으로 정렬하는 것이 좋습니다.

+export { default as ExtensionInstallCheckDialog } from './ExtensionInstallCheckDialog';
+export { default as InitSentryUserInfo } from './InitSentryUserInfo';
 export { default as MemoDialog } from './MemoDialog';
+export { default as MemoSearchForm } from './MemoSearchForm';
+export { default as MemoSearchFormProvider } from './MemoSearchFormProvider';
 export { default as MemoSidebar } from './MemoSidebar';
 export { default as MemoSidebarTrigger } from './MemoSidebarTrigger';
 export { default as MemoView } from './MemoView';
-export { default as MemoSearchFormProvider } from './MemoSearchFormProvider';
-export { default as MemoSearchForm } from './MemoSearchForm';
-export { default as InitSentryUserInfo } from './InitSentryUserInfo';
-export { default as ExtensionInstallCheckDialog } from './ExtensionInstallCheckDialog';
🧰 Tools
🪛 ESLint

[error] 1-8: Run autofix to sort these exports!

(simple-import-sort/exports)

packages/web/src/app/[lng]/(auth)/memos/_components/InitSentryUserInfo/index.tsx (1)

Line range hint 2-6: 임포트 구문을 정렬해주세요.

ESLint 규칙에 따라 임포트 구문을 알파벳 순으로 정렬하는 것이 좋습니다.

'use client';

-import { useSupabaseUserQuery } from '@extension/shared/hooks';
-import * as Sentry from '@sentry/nextjs';
-
-import { Language } from '@src/modules/i18n';
-import { useEffect } from 'react';
+import * as Sentry from '@sentry/nextjs';
+import { useSupabaseUserQuery } from '@extension/shared/hooks';
+import { useEffect } from 'react';
+
+import { Language } from '@src/modules/i18n';
packages/shared/src/hooks/supabase/mutations/index.ts (1)

1-10: 내보내기 문을 정렬해주세요

일관성과 가독성을 위해 내보내기 문을 알파벳 순으로 정렬하는 것이 좋습니다.

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

 export { default as useCategoryDeleteMutation } from './useCategoryDeleteMutation';
 export { default as useCategoryPatchMutation } from './useCategoryPatchMutation';
 export { default as useCategoryPostMutation } from './useCategoryPostMutation';
 export { default as useCategoryUpsertMutation } from './useCategoryUpsertMutation';
+export { default as useFeedbackMutation } from './useFeedbackMutation';
 export { default as useDeleteMemosMutation } from './useDeleteMemosMutation';
 export { default as useMemoPatchMutation } from './useMemoPatchMutation';
 export { default as useMemoPostMutation } from './useMemoPostMutation';
-export { default as useMemosUpsertMutation } from './useMemosUpsertMutation';
 export { default as useSignoutMutation } from './useSignoutMutation';
-export { default as useFeedbackMutation } from './useFeedbackMutation';
+export { default as useMemosUpsertMutation } from './useMemosUpsertMutation';
🧰 Tools
🪛 ESLint

[error] 1-10: Run autofix to sort these exports!

(simple-import-sort/exports)

packages/shared/src/hooks/common/useKeyboardBind.ts (1)

3-3: 키보드 이벤트 타입을 확장하는 것을 고려해보세요

현재 'Backspace', 'Escape', 's' 키만 지원하고 있습니다. 향후 확장성을 고려하여 더 많은 키를 지원하도록 타입을 확장하는 것이 좋을 것 같습니다.

packages/shared/src/hooks/supabase/mutations/useDeleteMemosMutation.ts (1)

Line range hint 12-29: 뮤테이션 응답 타입의 안전성을 개선해주세요

뮤테이션의 응답 타입이 MemoSupabaseResponse로 정의되어 있지만, 실제 에러 케이스에서 더 구체적인 타입 정보를 제공할 수 있습니다.

다음과 같이 수정하는 것을 추천드립니다:

-  return useMutation<MemoSupabaseResponse, Error, number[]>({
+  return useMutation<MemoSupabaseResponse, NoMemosError | Error, number[]>({
packages/web/src/app/[lng]/(auth)/memos/layout.tsx (1)

Line range hint 18-38: 에러 바운더리 추가 권장

Suspense를 사용하여 로딩 상태를 적절히 처리하고 있지만, 에러 처리를 위한 ErrorBoundary 컴포넌트가 없습니다. 사용자 경험 향상을 위해 에러 바운더리 추가를 고려해보세요.

import { ErrorBoundary } from '@src/components/ErrorBoundary';

// Suspense 감싸기
<ErrorBoundary fallback={<ErrorFallback />}>
  <Suspense fallback={<Loading />}>
    <MemoSidebar lng={lng} />
  </Suspense>
</ErrorBoundary>
packages/web/src/app/[lng]/(auth)/memos/page.tsx (1)

16-18: 다이나믹 임포트 최적화 제안

ExtensionInstallCheckDialog의 다이나믹 임포트에 loading 컴포넌트를 추가하면 사용자 경험을 개선할 수 있습니다.

const ExtensionInstallCheckDialog = dynamic(() => import('./_components/ExtensionInstallCheckDialog'), {
  ssr: false,
+ loading: () => <Loading />,
});
packages/web/src/app/[lng]/(auth)/memos/_components/MemoView/MemoGrid.tsx (1)

81-144: 드래그 앤 드롭 구현이 개선되었으나 추가 개선이 가능합니다.

RAF를 사용한 성능 최적화와 스크롤 동기화는 잘 구현되었습니다. 하지만 다음과 같은 개선사항을 제안드립니다:

  1. 매직 넘버(예: 50)를 상수로 분리
  2. 스크롤 관련 로직을 별도 함수로 분리
  3. 한글 주석을 영문으로 변경하여 일관성 유지
+ const SCROLL_UPDATE_INTERVAL = 50;
+ const SCROLL_DETECTION_THRESHOLD = 50;

+ const handleScroll = (container: HTMLElement, isNear: boolean, isAtEdge: boolean, timeoutRef: MutableRefObject<NodeJS.Timeout | null>, scrollDirection: 1 | -1) => {
+   if (isNear && !isAtEdge && !timeoutRef.current) {
+     timeoutRef.current = setInterval(() => {
+       if (isAtEdge) {
+         clearInterval(timeoutRef.current!);
+         timeoutRef.current = null;
+         return;
+       }
+       container.scrollBy({ top: SCROLL_UNIT * scrollDirection, behavior: 'auto' });
+     }, SCROLL_UPDATE_INTERVAL);
+   } else if (!isNear && timeoutRef.current) {
+     clearInterval(timeoutRef.current);
+     timeoutRef.current = null;
+   }
+ };
packages/web/src/app/[lng]/(auth)/memos/_components/ExtensionInstallCheckDialog/index.tsx (1)

41-43: 로컬 스토리지 키 상수화 제안

handleCancelClick 함수에서 문자열 리터럴로 직접 키를 사용하는 것보다 상수로 관리하는 것이 더 안전합니다.

다음과 같이 수정하는 것을 제안합니다:

+ const INSTALL_CHECK_KEY = 'install' as const;

  const handleCancelClick = () => {
-   setLocalStorageTrue('install');
+   setLocalStorageTrue(INSTALL_CHECK_KEY);
  };
packages/shared/src/hooks/common/index.ts (1)

1-7: export 구문 정렬 필요

가독성 향상을 위해 export 구문들을 알파벳 순으로 정렬하는 것이 좋겠습니다.

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

+ export { default as useDebounce } from './useDebounce';
+ export { default as useDidMount } from './useDidMount';
+ export { default as useError } from './useError';
+ export { default as useFetch } from './useFetch';
+ export { default as useKeyboardBind } from './useKeyboardBind';
+ export { default as useThrottle } from './useThrottle';
+ export { default as useUserPreferDarkMode } from './useUserPreferDarkMode';
- export { default as useDidMount } from './useDidMount';
- export { default as useError } from './useError';
- export { default as useFetch } from './useFetch';
- export { default as useKeyboardBind } from './useKeyboardBind';
- export { default as useThrottle } from './useThrottle';
- export { default as useUserPreferDarkMode } from './useUserPreferDarkMode';
- export { default as useDebounce } from './useDebounce';
🧰 Tools
🪛 ESLint

[error] 1-7: Run autofix to sort these exports!

(simple-import-sort/exports)

📜 Review details

Configuration used: .coderabbit.yaml
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between a7dd914 and 6e4f530.

⛔ Files ignored due to path filters (1)
  • pnpm-lock.yaml is excluded by !**/pnpm-lock.yaml
📒 Files selected for processing (66)
  • .eslintrc (2 hunks)
  • package.json (1 hunks)
  • packages/shared/src/hooks/common/index.ts (1 hunks)
  • packages/shared/src/hooks/common/useKeyboardBind.ts (1 hunks)
  • packages/shared/src/hooks/index.ts (1 hunks)
  • packages/shared/src/hooks/supabase/index.ts (1 hunks)
  • packages/shared/src/hooks/supabase/mutations/index.ts (1 hunks)
  • packages/shared/src/hooks/supabase/mutations/useCategoryDeleteMutation.ts (1 hunks)
  • packages/shared/src/hooks/supabase/mutations/useCategoryPatchMutation.ts (1 hunks)
  • packages/shared/src/hooks/supabase/mutations/useCategoryPostMutation.ts (1 hunks)
  • packages/shared/src/hooks/supabase/mutations/useCategoryUpsertMutation.ts (1 hunks)
  • packages/shared/src/hooks/supabase/mutations/useDeleteMemosMutation.ts (1 hunks)
  • packages/shared/src/hooks/supabase/mutations/useFeedbackMutation.ts (1 hunks)
  • packages/shared/src/hooks/supabase/mutations/useMemoPatchMutation.ts (1 hunks)
  • packages/shared/src/hooks/supabase/mutations/useMemoPostMutation.ts (1 hunks)
  • packages/shared/src/hooks/supabase/mutations/useMemosUpsertMutation.ts (1 hunks)
  • packages/shared/src/hooks/supabase/mutations/useSignoutMutation.ts (1 hunks)
  • packages/shared/src/hooks/supabase/queries/index.ts (1 hunks)
  • packages/shared/src/hooks/supabase/queries/useSupabaseUserQuery.ts (1 hunks)
  • packages/shared/src/hooks/useKeyboardBind.ts (0 hunks)
  • packages/shared/src/hooks/useRAF.ts (0 hunks)
  • packages/shared/src/modules/chrome-storage/ChromeSyncStorage.ts (1 hunks)
  • packages/shared/src/modules/extension-bridge/ExtensionBridge.ts (0 hunks)
  • packages/shared/src/modules/extension-bridge/index.ts (1 hunks)
  • packages/shared/src/modules/local-storage/index.ts (1 hunks)
  • packages/web/next.config.mjs (0 hunks)
  • packages/web/src/app/[lng]/(auth)/memos/_components/ExtensionInstallCheckDialog/index.tsx (1 hunks)
  • packages/web/src/app/[lng]/(auth)/memos/_components/InitSentryUserInfo/index.tsx (2 hunks)
  • packages/web/src/app/[lng]/(auth)/memos/_components/MemoCardHeader/index.tsx (2 hunks)
  • packages/web/src/app/[lng]/(auth)/memos/_components/MemoDialog/index.tsx (3 hunks)
  • packages/web/src/app/[lng]/(auth)/memos/_components/MemoSearchForm/index.tsx (1 hunks)
  • packages/web/src/app/[lng]/(auth)/memos/_components/MemoSearchFormProvider/index.tsx (1 hunks)
  • packages/web/src/app/[lng]/(auth)/memos/_components/MemoSidebar/index.tsx (1 hunks)
  • packages/web/src/app/[lng]/(auth)/memos/_components/MemoView/MemoGrid.tsx (8 hunks)
  • packages/web/src/app/[lng]/(auth)/memos/_components/MemoView/MemoItem.tsx (4 hunks)
  • packages/web/src/app/[lng]/(auth)/memos/_components/MemoView/MemoRefreshButton.tsx (1 hunks)
  • packages/web/src/app/[lng]/(auth)/memos/_components/MemoView/index.tsx (2 hunks)
  • packages/web/src/app/[lng]/(auth)/memos/_components/index.ts (1 hunks)
  • packages/web/src/app/[lng]/(auth)/memos/_utils/index.ts (1 hunks)
  • packages/web/src/app/[lng]/(auth)/memos/layout.tsx (1 hunks)
  • packages/web/src/app/[lng]/(auth)/memos/page.tsx (2 hunks)
  • packages/web/src/app/[lng]/(auth)/memos/setting/page.tsx (1 hunks)
  • packages/web/src/app/[lng]/(no-auth)/introduce/page.tsx (1 hunks)
  • packages/web/src/app/[lng]/(no-auth)/update/page.tsx (1 hunks)
  • packages/web/src/app/[lng]/_components/Header/HeaderRight.tsx (3 hunks)
  • packages/web/src/app/[lng]/_components/index.ts (1 hunks)
  • packages/web/src/app/[lng]/layout.tsx (3 hunks)
  • packages/web/src/app/[lng]/page.tsx (0 hunks)
  • packages/web/src/app/_components/ExtensionDialog/index.tsx (0 hunks)
  • packages/web/src/app/_components/ExtensionDialog/useExtensionDialog.ts (0 hunks)
  • packages/web/src/app/_components/ExtensionDialog/useExtensionDialogInfo.ts (0 hunks)
  • packages/web/src/app/_components/index.ts (0 hunks)
  • packages/web/src/app/layout.tsx (2 hunks)
  • packages/web/src/components/AuthProvider.tsx (0 hunks)
  • packages/web/src/components/feedback/FeedbackContainer.tsx (2 hunks)
  • packages/web/src/components/index.ts (0 hunks)
  • packages/web/src/constants/Config.ts (1 hunks)
  • packages/web/src/hooks/useGetExtensionManifest.ts (1 hunks)
  • packages/web/src/instrumentation.ts (1 hunks)
  • packages/web/src/middleware.ts (1 hunks)
  • packages/web/src/modules/guide/useGuide.ts (1 hunks)
  • packages/web/src/modules/supabase/util.ts (1 hunks)
  • pages/options/src/components/Header.tsx (0 hunks)
  • pages/side-panel/src/components/MemoForm.tsx (1 hunks)
  • pages/side-panel/src/components/MemoHeader.tsx (1 hunks)
  • pages/side-panel/src/hoc/withAuthentication.tsx (1 hunks)
💤 Files with no reviewable changes (12)
  • packages/web/src/app/_components/index.ts
  • packages/web/src/components/index.ts
  • pages/options/src/components/Header.tsx
  • packages/web/src/app/[lng]/page.tsx
  • packages/shared/src/hooks/useRAF.ts
  • packages/web/next.config.mjs
  • packages/web/src/components/AuthProvider.tsx
  • packages/web/src/app/_components/ExtensionDialog/useExtensionDialogInfo.ts
  • packages/web/src/app/_components/ExtensionDialog/useExtensionDialog.ts
  • packages/shared/src/modules/extension-bridge/ExtensionBridge.ts
  • packages/shared/src/hooks/useKeyboardBind.ts
  • packages/web/src/app/_components/ExtensionDialog/index.tsx
✅ Files skipped from review due to trivial changes (15)
  • packages/web/src/app/[lng]/_components/index.ts
  • packages/web/src/app/[lng]/(no-auth)/introduce/page.tsx
  • packages/web/src/app/[lng]/(auth)/memos/_utils/index.ts
  • packages/web/src/hooks/useGetExtensionManifest.ts
  • packages/shared/src/modules/chrome-storage/ChromeSyncStorage.ts
  • packages/shared/src/modules/extension-bridge/index.ts
  • packages/web/src/app/[lng]/(auth)/memos/setting/page.tsx
  • packages/web/src/app/[lng]/(no-auth)/update/page.tsx
  • packages/shared/src/hooks/supabase/mutations/useCategoryUpsertMutation.ts
  • packages/web/src/app/[lng]/(auth)/memos/_components/MemoSearchFormProvider/index.tsx
  • pages/side-panel/src/components/MemoHeader.tsx
  • packages/shared/src/hooks/supabase/queries/useSupabaseUserQuery.ts
  • packages/shared/src/hooks/supabase/mutations/useCategoryDeleteMutation.ts
  • packages/shared/src/hooks/supabase/mutations/useMemoPatchMutation.ts
  • packages/shared/src/modules/local-storage/index.ts
🧰 Additional context used
🪛 ESLint
packages/web/src/app/[lng]/(auth)/memos/_components/MemoDialog/index.tsx

[error] 2-16: Run autofix to sort these imports!

(simple-import-sort/imports)

packages/shared/src/hooks/supabase/mutations/useFeedbackMutation.ts

[error] 1-3: Run autofix to sort these imports!

(simple-import-sort/imports)

packages/web/src/app/[lng]/(auth)/memos/layout.tsx

[error] 3-13: Run autofix to sort these imports!

(simple-import-sort/imports)

packages/web/src/app/layout.tsx

[error] 33-33: elements must have the lang prop.

(jsx-a11y/html-has-lang)

packages/web/src/app/[lng]/(auth)/memos/_components/InitSentryUserInfo/index.tsx

[error] 2-6: Run autofix to sort these imports!

(simple-import-sort/imports)

packages/web/src/app/[lng]/(auth)/memos/_components/index.ts

[error] 1-8: Run autofix to sort these exports!

(simple-import-sort/exports)

packages/web/src/app/[lng]/(auth)/memos/_components/ExtensionInstallCheckDialog/index.tsx

[error] 3-23: Run autofix to sort these imports!

(simple-import-sort/imports)


[error] 15-15: 'checkLocalStorageKey' is defined but never used.

(unused-imports/no-unused-imports)


[error] 15-15: 'checkLocalStorageKey' is defined but never used.

(@typescript-eslint/no-unused-vars)


[error] 17-17: 'LocalStorageKeyType' is defined but never used.

(unused-imports/no-unused-imports)


[error] 17-17: 'LocalStorageKeyType' is defined but never used.

(@typescript-eslint/no-unused-vars)

packages/web/src/app/[lng]/layout.tsx

[error] 1-7: Run autofix to sort these imports!

(simple-import-sort/imports)

packages/shared/src/hooks/index.ts

[error] 1-3: Run autofix to sort these exports!

(simple-import-sort/exports)

packages/shared/src/hooks/supabase/queries/index.ts

[error] 1-6: Run autofix to sort these exports!

(simple-import-sort/exports)

packages/shared/src/hooks/supabase/mutations/index.ts

[error] 1-10: Run autofix to sort these exports!

(simple-import-sort/exports)

packages/shared/src/hooks/supabase/index.ts

[error] 1-2: Run autofix to sort these exports!

(simple-import-sort/exports)

packages/shared/src/hooks/common/index.ts

[error] 1-7: Run autofix to sort these exports!

(simple-import-sort/exports)

🔇 Additional comments (37)
packages/web/src/app/[lng]/(auth)/memos/_components/MemoSidebar/index.tsx (1)

24-24: HeaderMargin 컴포넌트의 import 경로 변경이 적절합니다.

공통 컴포넌트를 _components 디렉토리로 중앙 집중화하는 것은 좋은 리팩토링 방향입니다.

packages/web/src/middleware.ts (4)

5-5: 함수 이름이 의미론적으로 개선되었습니다.

updateSession에서 updateAuthorization으로의 이름 변경은 함수의 실제 목적을 더 명확하게 표현합니다.


10-12: 루트 경로 처리 로직이 명확합니다.

루트 경로 접근 시 메모 페이지로 리다이렉션하는 로직이 간단하고 명확하게 구현되었습니다.


25-26: 주석이 명확하게 개선되었습니다.

'토큰 업데이트'라는 주석이 함수의 목적을 간단명료하게 설명합니다.


22-22: URL 구성 방식 검토 필요

language 변수가 이미 '/'로 시작하는지 확인이 필요합니다. 현재 구현에서는 중복된 '/'가 발생할 수 있습니다.

다음 스크립트로 getLanguage 함수의 반환값 형식을 확인해보세요:

packages/web/src/modules/supabase/util.ts (2)

Line range hint 7-35: 인증 로직이 견고하게 구현되어 있습니다.

함수의 전반적인 구현이 다음과 같은 장점을 가지고 있습니다:

  • 쿠키 처리가 안전하게 구현됨
  • 사용자 로그인 상태 확인이 명확함
  • 인증이 필요한 페이지에 대한 처리가 적절함

7-7: 함수 이름 변경의 영향도 확인 필요

updateSession에서 updateAuthorization으로의 이름 변경이 적절합니다. 다만, 다른 파일에서의 참조도 모두 업데이트되었는지 확인이 필요합니다.

다음 스크립트로 이전 함수명 사용 여부를 확인해보세요:

✅ Verification successful

함수 이름 변경이 올바르게 적용되었습니다

updateSession에서 updateAuthorization으로의 이름 변경이 코드베이스 전체에 걸쳐 일관되게 적용되었습니다. 이전 함수명의 참조가 남아있지 않으며, 새로운 함수명이 필요한 곳에서 올바르게 사용되고 있습니다.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# updateSession 함수 호출 검색
rg "updateSession\(" --type ts

Length of output: 32


Script:

#!/bin/bash
# 더 유연한 패턴으로 이전 함수명 검색
rg "updateSession" --type ts

# 새로운 함수명 사용 확인
rg "updateAuthorization" --type ts

# git 히스토리에서 이전 함수명 확인
git log -p | rg "updateSession"

Length of output: 336

packages/shared/src/hooks/supabase/mutations/useSignoutMutation.ts (1)

Line range hint 1-11: 구현이 깔끔해 보입니다!

import 경로 변경이 새로운 폴더 구조와 잘 맞습니다.

🧰 Tools
🪛 ESLint

[error] 1-3: Run autofix to sort these imports!

(simple-import-sort/imports)

packages/shared/src/hooks/supabase/mutations/useFeedbackMutation.ts (1)

3-3: 상대 경로에서 모듈 경로로의 변경이 잘 이루어졌습니다

../queries로의 import 경로 변경은 코드의 구조화와 유지보수성을 향상시킵니다.

🧰 Tools
🪛 ESLint

[error] 1-3: Run autofix to sort these imports!

(simple-import-sort/imports)

pages/side-panel/src/hoc/withAuthentication.tsx (1)

1-1: 훅 이름 변경이 일관성 있게 적용되었습니다

useSupabaseUser에서 useSupabaseUserQuery로의 이름 변경이 잘 이루어졌습니다. 이는 쿼리 관련 훅의 네이밍 컨벤션을 더 명확하게 만듭니다.

Also applies to: 6-6

packages/web/src/constants/Config.ts (1)

8-8: Google Tag Manager ID 설정이 적절하게 추가되었습니다

기존 설정 패턴을 따라 gtmId가 잘 추가되었습니다. getSafeConfig를 사용하여 환경 변수를 안전하게 처리하는 것도 좋습니다.

packages/web/src/app/[lng]/(auth)/memos/_components/index.ts (1)

5-8: 컴포넌트 이름이 더 명확해졌습니다!

SearchForm에서 MemoSearchForm으로의 이름 변경은 컴포넌트의 목적을 더 잘 나타냅니다. 이는 코드의 가독성과 유지보수성을 향상시킵니다.

🧰 Tools
🪛 ESLint

[error] 1-8: Run autofix to sort these exports!

(simple-import-sort/exports)

packages/shared/src/hooks/supabase/mutations/useCategoryPostMutation.ts (1)

5-5: 임포트 구조가 개선되었습니다!

상대 경로에서 모듈 경로로의 변경은 코드의 구조를 더 명확하게 만들어줍니다. 이는 향후 파일 구조 변경 시 유지보수를 더 쉽게 만들어줄 것입니다.

packages/shared/src/hooks/supabase/mutations/useCategoryPatchMutation.ts (1)

5-5: 일관된 리팩토링이 적용되었습니다!

useSupabaseClientQuery 임포트 경로의 변경이 다른 파일들과 일관되게 적용되었습니다. 이러한 일관성은 코드베이스의 품질을 향상시킵니다.

packages/web/src/app/[lng]/(auth)/memos/_components/MemoView/MemoRefreshButton.tsx (1)

14-14: 컴포넌트 이름이 적절하게 변경되었습니다!

RefreshButton에서 MemoRefreshButton으로의 이름 변경은 컴포넌트의 목적을 더 명확하게 표현하며, 네이밍 일관성을 개선합니다.

packages/web/src/app/layout.tsx (1)

3-3: Google Tag Manager가 성공적으로 통합되었습니다!

Google Analytics와 함께 GTM을 추가함으로써 웹사이트 분석 기능이 향상되었습니다.

Also applies to: 39-39

packages/shared/src/hooks/supabase/mutations/useMemoPostMutation.ts (1)

6-6: 모듈 구조가 개선되었습니다!

useSupabaseClientQuery 임포트 경로의 변경으로 관련 쿼리들이 더 논리적으로 구성되었습니다.

packages/web/src/app/[lng]/layout.tsx (2)

33-33: 시맨틱 HTML 구조를 검토해주세요

<main> 태그에서 <div>로의 변경은 웹페이지의 시맨틱 구조를 약화시킬 수 있습니다. 이는 접근성과 SEO에 영향을 미칠 수 있습니다.

다음 스크립트를 실행하여 다른 시맨틱 태그의 사용을 확인해주세요:

✅ Verification successful

레이아웃의 <div> 사용이 적절합니다

페이지 컴포넌트들이 이미 <main> 태그를 적절히 사용하고 있어, 레이아웃에서 <div>를 사용하는 것이 더 적합합니다. 이는 HTML 시맨틱 구조를 해치지 않으며, 오히려 중복된 <main> 태그 사용을 방지합니다.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Check semantic HTML usage in layout files
rg -l '<(header|main|footer|nav|article|section|aside)' 'packages/web/src/app'

Length of output: 692


Script:

#!/bin/bash
# Check the content of layout files and their semantic structure
rg -B 2 -A 2 '<(header|main|footer|nav|article|section|aside)' 'packages/web/src/app/[lng]'

Length of output: 4655


1-1: 인증 흐름 변경을 확인해주세요

AuthProvider가 제거되었습니다. 인증이 필요한 컴포넌트들이 여전히 올바르게 보호되고 있는지 확인이 필요합니다.

다음 스크립트를 실행하여 인증 관련 변경사항을 확인해주세요:

Also applies to: 36-37

✅ Verification successful

인증 시스템이 안전하게 구현되어 있음을 확인했습니다

AuthProvider 제거는 의도된 변경으로, 인증 시스템이 다음과 같이 더 견고하게 구현되어 있습니다:

  • Next.js 미들웨어에서 전역적으로 인증 처리
  • Route groups을 통한 보호된 경로 관리 ((auth)/(no-auth))
  • 서버 사이드 인증 검증으로 무단 접근 차단
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Check authentication implementation
rg -A 5 'auth|protected|private|isAuthenticated' 'packages/web/src/app'

Length of output: 1138


Script:

#!/bin/bash
# Search for auth-related implementations
echo "=== Checking components ==="
rg -g '!*.test.*' -g '!*.spec.*' 'auth|isAuthenticated|protected|private' packages/web/src/components

echo -e "\n=== Checking middleware ==="
fd middleware packages/web/src --exec cat {}

echo -e "\n=== Checking hooks and utils ==="
rg -g '!*.test.*' -g '!*.spec.*' 'auth|isAuthenticated|protected|private' packages/web/src/hooks packages/web/src/utils

echo -e "\n=== Checking route protection patterns ==="
rg -g '!*.test.*' -g '!*.spec.*' 'redirect|unauthorized|forbidden' packages/web/src

Length of output: 3166

🧰 Tools
🪛 ESLint

[error] 1-7: Run autofix to sort these imports!

(simple-import-sort/imports)

packages/web/src/app/[lng]/(auth)/memos/layout.tsx (1)

Line range hint 3-13: import 문 정렬 필요

ESLint 규칙에 따라 import 문을 정렬해야 합니다. 자동 수정을 실행하여 이 문제를 해결할 수 있습니다.

✅ Verification successful

import 문 정렬 규칙이 확인되었습니다

프로젝트의 ESLint 설정에 simple-import-sort 플러그인이 구성되어 있으며, import 문 정렬 규칙이 활성화되어 있습니다. 다음 명령어로 자동 정렬이 가능합니다:

npx eslint --fix packages/web/src/app/[lng]/(auth)/memos/layout.tsx
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# ESLint 자동 수정 실행 여부 확인
eslint --fix packages/web/src/app/[lng]/(auth)/memos/layout.tsx --print-config .eslintrc

Length of output: 271


Script:

#!/bin/bash
# Check for ESLint configuration files
echo "=== ESLint Config Files ==="
fd -H "\.eslintrc" --type f

# Check import statements
echo -e "\n=== Import Statements ==="
ast-grep --pattern 'import { $$ } from "$_";'

# Check package.json for ESLint related dependencies
echo -e "\n=== ESLint Dependencies ==="
fd "package.json" --type f --exec cat {} \; | jq '.dependencies,.devDependencies | select(. != null) | with_entries(select(.key | contains("eslint")))'

Length of output: 1132


Script:

#!/bin/bash
# Check ESLint configuration content
echo "=== ESLint Configuration ==="
cat .eslintrc

# Check if there are any import sorting related rules
echo -e "\n=== Import Sort Rules ==="
cat .eslintrc | grep -A 5 "simple-import-sort\|import/order"

Length of output: 1591

packages/web/src/app/[lng]/(auth)/memos/_components/MemoView/index.tsx (2)

14-14: 컴포넌트 이름 변경이 일관성 있게 적용되었습니다.

SearchFormProvider에서 MemoSearchFormProvider로의 변경과 RefreshButton에서 MemoRefreshButton으로의 변경이 잘 이루어졌습니다. 이는 메모 관련 컴포넌트들의 네이밍 일관성을 향상시킵니다.

Also applies to: 17-17


52-52: 불필요한 gridKey prop이 제거되었습니다.

MemoGrid 컴포넌트에서 불필요한 gridKey prop을 제거하고, 필수적인 memos와 lng prop만 남긴 것이 좋은 변경입니다.

Also applies to: 58-59

packages/web/src/app/[lng]/(auth)/memos/_components/MemoCardHeader/index.tsx (2)

12-13: prop 이름이 더 명확하게 변경되었습니다.

isHovered와 isSelected에서 isMemoHovering과 isMemoSelected로의 변경은 prop의 목적을 더 명확하게 표현합니다.


16-21: 기본값 설정과 조건부 렌더링이 개선되었습니다.

  • isMemoHovering의 기본값을 false로 설정한 것이 적절합니다.
  • isShowingSelectButton 변수명이 의도를 잘 표현합니다.

Also applies to: 31-31

packages/web/src/modules/guide/useGuide.ts (1)

64-64: 가이드 표시 조건이 더 안전하게 개선되었습니다.

manifest가 falsy한 경우(null, undefined 등)에 대한 체크가 추가되어 더 안전한 조건 처리가 가능해졌습니다.

packages/web/src/app/[lng]/(auth)/memos/_components/MemoSearchForm/index.tsx (1)

8-9: 컴포넌트와 인터페이스 이름이 일관성 있게 변경되었습니다.

  • SearchFormProps에서 MemoSearchFormProps로의 변경
  • SearchForm에서 MemoSearchForm으로의 변경
  • SearchFormProvider에서 MemoSearchFormProvider로의 import 경로 변경

이러한 변경들은 메모 관련 컴포넌트들의 네이밍 컨벤션을 일관되게 유지합니다.

Also applies to: 11-11, 13-13

🧰 Tools
🪛 ESLint

[error] 3-9: Run autofix to sort these imports!

(simple-import-sort/imports)

packages/web/src/app/[lng]/(auth)/memos/_components/MemoView/MemoItem.tsx (3)

15-15: Props 이름이 더 명확해졌습니다!

isSelectingisSelectingMode로, isSelectedisMemoSelected로 변경한 것이 좋습니다. 이는 각 prop의 목적을 더 명확하게 전달합니다.

Also applies to: 17-17


32-32: 상태 변수 이름이 일관성 있게 변경되었습니다.

isHoveredisMemoHovering으로 변경하여 다른 prop 이름들과 일관성을 유지하고 있습니다.


68-68: 컴포넌트 전체적으로 일관성 있게 변경되었습니다.

prop 이름 변경이 컴포넌트의 모든 부분(조건부 렌더링, 자식 컴포넌트 props, memo 비교 함수 등)에 일관되게 적용되었습니다.

Also applies to: 73-74, 82-82, 91-94

pages/side-panel/src/components/MemoForm.tsx (1)

7-7: 탭 데이터 처리가 개선되었습니다.

useTabQuery 훅을 추가하여 탭 데이터를 더 효과적으로 관리하고 있습니다. 또한 메모 추가 로직의 타이밍이 1ms로 최적화되었습니다.

하지만 한 가지 주의할 점이 있습니다:

1ms의 타이밍이 너무 짧아 브라우저에 따라 안정적으로 동작하지 않을 수 있습니다. 최소 16ms (1프레임)를 권장드립니다.

-    }, 1);
+    }, 16);

Also applies to: 187-207

packages/web/src/app/[lng]/(auth)/memos/_components/MemoDialog/index.tsx (2)

2-2: 키보드 이벤트 처리가 개선되었습니다.

useKeyboardBind 훅을 사용하여 키보드 이벤트 처리를 단순화했습니다. 이는 코드의 가독성과 재사용성을 향상시킵니다.

Also applies to: 53-54

🧰 Tools
🪛 ESLint

[error] 2-16: Run autofix to sort these imports!

(simple-import-sort/imports)


31-31: 폼 처리 로직이 단순화되었습니다.

불필요한 useWatch 훅을 제거하고 watch를 직접 사용하여 폼 처리 로직을 단순화했습니다.

packages/web/src/app/[lng]/(auth)/memos/_components/MemoView/MemoGrid.tsx (3)

235-235: 키보드 바인딩이 일관되게 구현되었습니다.

useKeyboardBind 훅을 사용하여 ESC 키 처리를 구현한 것이 좋습니다. 이는 MemoDialog와 동일한 패턴을 따르고 있습니다.


256-262: 그리드 구성이 최적화되었습니다.

성능 향상을 위한 변경사항들이 잘 적용되었습니다:

  • useRecycle={false}로 설정하여 DOM 재사용을 비활성화
  • gapalign 속성으로 레이아웃 개선
  • placeholder 컴포넌트 추가로 로딩 상태 표시

288-290: 스켈레톤 컴포넌트가 적절히 구현되었습니다.

MemoItem의 크기와 동일한 dimensions를 가진 스켈레톤 컴포넌트가 잘 구현되었습니다.

.eslintrc (1)

24-24: 사용하지 않는 import 제거 규칙 추가에 대한 승인

ESLint 설정에 unused-imports 플러그인과 규칙을 추가한 것은 코드 품질 향상에 도움이 될 것입니다. 사용하지 않는 import문을 자동으로 감지하고 제거함으로써 코드베이스를 더 깔끔하게 유지할 수 있습니다.

Also applies to: 45-45

package.json (1)

94-94: ESLint 플러그인 의존성 추가 승인

eslint-plugin-unused-imports 의존성 추가는 앞서 설정된 ESLint 규칙을 지원하기 위한 적절한 변경사항입니다.

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

🔭 Outside diff range comments (4)
packages/web/src/app/[lng]/(auth)/memos/_components/MemoView/MemoOptionHeader.tsx (1)

Line range hint 28-32: 접근성 개선이 필요합니다.

닫기 버튼에 aria-label이 누락되어 있습니다. 스크린 리더 사용자를 위해 추가해주세요.

 <Button variant="ghost" size="icon" 
+  aria-label={t('common.close')}
 >
   <XIcon className="h-6 w-6" />
 </Button>
packages/web/src/app/[lng]/(no-auth)/login/_components/LoginSection/index.tsx (1)

Line range hint 31-35: 사용하지 않는 코드를 제거해야 합니다.

주석 처리된 이메일 로그인 코드는 더 이상 사용되지 않는다면 완전히 제거하는 것이 좋습니다.

-  {/* <Button
-    formAction={signInWithEmail.bind(null, SUPABASE.testEmail, SUPABASE.testPassword)}
-    className="h-12 bg-green-300 text-black hover:bg-green-300">
-    테스트 계정으로 로그인
-  </Button> */}
packages/web/src/app/[lng]/(no-auth)/introduce/_components/AdditionalFeatures/index.tsx (1)

동적 Tailwind 클래스 사용 문제 확인됨

코드 검토 결과, 리뷰 의견이 정확합니다. 현재 구현에서는 'yellow'와 'pink' 두 가지 색상만 사용되고 있으나, 템플릿 리터럴을 통한 동적 클래스 생성 방식은 Tailwind의 정적 분석을 방해할 수 있습니다. 제안된 해결책처럼 colorClasses 객체를 사용하는 것이 안전하고 명시적인 방법이 될 것입니다.

🔗 Analysis chain

Line range hint 82-84: 동적 Tailwind 클래스 사용에 대한 주의가 필요합니다!

className={`mb-4 flex h-12 w-12 items-center justify-center rounded-lg bg-${feature.color}-100`}

템플릿 리터럴을 사용한 동적 Tailwind 클래스는 제대로 작동하지 않을 수 있습니다. Tailwind는 빌드 시점에 사용된 클래스들을 정적으로 분석하기 때문입니다.

대안으로 다음과 같은 방법을 고려해보세요:

  1. 색상별 클래스를 객체로 미리 정의
  2. className을 조건부로 결합
- className={`mb-4 flex h-12 w-12 items-center justify-center rounded-lg bg-${feature.color}-100`}
+ const colorClasses = {
+   yellow: 'bg-yellow-100',
+   pink: 'bg-pink-100'
+ };
+ className={`mb-4 flex h-12 w-12 items-center justify-center rounded-lg ${colorClasses[feature.color]}`}
🏁 Scripts executed

The following scripts were executed for the analysis:

Error: No shell scripts found


Script:

#!/bin/bash
# First, let's look at the component implementation
cat "packages/web/src/app/[lng]/(no-auth)/introduce/_components/AdditionalFeatures/index.tsx"

# Then, let's look for any type definitions related to feature
rg "type.*feature" -t typescript

# Finally, check Tailwind config
fd "tailwind.config" --type f

Length of output: 3062

packages/web/src/app/[lng]/(auth)/memos/_components/MemoCardFooter/MemoOption.tsx (1)

Line range hint 64-64: 디버깅 코드를 제거해주세요.

console.log(1) 구문은 디버깅 목적으로 추가된 것으로 보입니다. 프로덕션 코드에서는 제거하는 것이 좋습니다.

-    console.log(1);
🧹 Nitpick comments (15)
packages/web/src/components/YoutubeEmbed.tsx (1)

Line range hint 11-19: iframe 보안 강화를 위한 제안

YouTube 임베드 시 보안을 강화하기 위해 sandbox 속성 추가를 고려해보세요. 필요한 기능만 허용하는 것이 좋습니다.

다음과 같이 수정하는 것을 추천드립니다:

      <iframe
        width="853"
        height="480"
        src={cn(`https://www.youtube.com/embed/${embedId}`, { '?autoplay=1': isAutoPlay })}
        allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture"
        allowFullScreen
        title="Embedded youtube"
+       sandbox="allow-same-origin allow-scripts allow-popups allow-presentation"
        className={`absolute inset-x-0 h-full w-full ${className}`}
        {...props}
      />
packages/web/src/hooks/useDrag.ts (1)

Line range hint 8-13: 이벤트 리스너 메모리 누수 방지를 위한 제안

컴포넌트가 마운트 해제되기 전에 clean-up 함수가 호출되지 않을 수 있는 edge case를 방지하기 위해, abort controller 사용을 고려해보세요.

 export default function useDrag({ onMouseDown }: UseDragProps) {
   useEffect(() => {
+    const controller = new AbortController();
-    document.body.addEventListener('mousedown', onMouseDown);
+    document.body.addEventListener('mousedown', onMouseDown, {
+      signal: controller.signal,
+    });
 
     return () => {
-      document.body.removeEventListener('mousedown', onMouseDown);
+      controller.abort();
     };
   }, [onMouseDown]);
 }
packages/web/src/app/_components/NotFoundContainer/index.tsx (1)

Line range hint 39-39: 이미지 대체 텍스트의 현지화가 필요합니다.

"Lost in Space" 대체 텍스트를 i18n을 통해 현지화하는 것이 좋겠습니다.

다음과 같이 변경하는 것을 제안드립니다:

-<img src="/images/error/lost-astronaut.svg" alt="Lost in Space" className="h-full w-full" />
+<img src="/images/error/lost-astronaut.svg" alt={t('error.404.astronautAlt')} className="h-full w-full" />
packages/web/src/app/[lng]/_components/QueryProvider.tsx (1)

Line range hint 13-47: 컴포넌트 구조가 견고합니다.

다음과 같은 장점들이 있습니다:

  • React Query 설정이 체계적으로 구성되어 있습니다
  • 에러 처리와 국제화(i18n)가 적절히 구현되어 있습니다
  • 메모 데이터 갱신 로직이 잘 통합되어 있습니다

하나의 제안사항이 있습니다:

defaultOptions를 별도의 상수로 분리하여 관리하면 설정값의 재사용성과 유지보수성을 더욱 향상시킬 수 있습니다. 다음과 같이 리팩토링하는 것을 고려해보세요:

+const DEFAULT_QUERY_OPTIONS = {
+  queries: { refetchOnWindowFocus: true, staleTime: 1000 * 60 * 5 },
+  mutations: {
+    onSuccess: async () => {
+      await ExtensionBridge.requestRefetchTheMemos();
+    },
+    onError: error => {
+      toast({ title: t('toastTitle.errorSave') });
+      Sentry.captureException(error, {
+        level: 'fatal',
+      });
+    },
+  },
+};

export default function QueryProvider({ children, lng }: QueryProviderProps) {
  const { t } = useTranslation(lng);

  const [queryClient] = useState(
    () =>
      new QueryClient({
-        defaultOptions: {
-          queries: { refetchOnWindowFocus: true, staleTime: 1000 * 60 * 5 },
-          mutations: {
-            onSuccess: async () => {
-              await ExtensionBridge.requestRefetchTheMemos();
-            },
-            onError: error => {
-              toast({ title: t('toastTitle.errorSave') });
-              Sentry.captureException(error, {
-                level: 'fatal',
-              });
-            },
-          },
-        },
+        defaultOptions: DEFAULT_QUERY_OPTIONS,
      }),
  );
packages/web/src/app/[lng]/layout.tsx (1)

35-44: 시맨틱 HTML 태그 사용 권장

레이아웃의 주요 콘텐츠 영역을 나타내는 <main> 태그 대신 <div>를 사용하고 있습니다. 웹 접근성과 SEO를 위해 시맨틱 태그 사용을 권장드립니다.

다음과 같이 수정하는 것을 고려해보세요:

-    <div lang={lng} dir={dir(lng)} className="h-screen">
+    <main lang={lng} dir={dir(lng)} className="h-screen">
       <ThemeProvider>
         <QueryProvider lng={lng}>
           <Header lng={lng} />
           {children}
         </QueryProvider>
       </ThemeProvider>

       <InitDayjs lng={lng} />
-    </div>
+    </main>
packages/web/src/app/_components/ErrorSection/index.tsx (1)

Line range hint 13-29: 에러 메시지 표시 기능 추가를 제안드립니다.

현재 구현에서는 일반적인 에러 메시지만 표시되고 있습니다. 개발 모드나 특정 조건에서 실제 에러 메시지를 표시하면 디버깅에 도움이 될 것 같습니다.

다음과 같은 변경을 제안드립니다:

  return (
    <div className="flex min-h-screen flex-col items-center justify-center gap-6 p-4 text-center">
      <h1 className="text-4xl font-bold text-gray-800 dark:text-gray-100">{t('error.500.title')}</h1>
+     {process.env.NODE_ENV === 'development' && (
+       <p className="text-red-600 dark:text-red-400">
+         {error.message || error.digest}
+       </p>
+     )}
      <Button  className="mt-4 px-6 py-3 text-lg shadow-lg transition-all duration-300 hover:shadow-xl">
        {t('error.500.retry')}
      </Button>
    </div>
  );
packages/web/src/components/index.ts (1)

1-1: DragBox 컴포넌트 추가 관련 문서화 요청

새로 추가된 DragBox 컴포넌트의 사용 방법과 목적에 대한 문서화가 필요합니다.

packages/web/src/components/Header/FeedbackSection.tsx (1)

8-10: SSR이 비활성화된 이유를 문서화해주세요.

FeedbackDialog 컴포넌트의 SSR 비활성화 이유를 주석으로 설명하면 좋을 것 같습니다.

 const FeedbackDialog = dynamic(() => import('./FeedbackDialog'), {
+  // FeedbackDialog는 클라이언트 사이드에서만 필요하며,
+  // window 객체에 의존성이 있어 SSR을 비활성화합니다.
   ssr: false,
 });
packages/web/src/app/[lng]/_components/QueryProvider/index.tsx (1)

21-23: 쿼리 설정을 최적화해주세요.

재시도 로직과 캐시 무효화 전략을 추가하면 좋을 것 같습니다.

 defaultOptions: {
   queries: {
     refetchOnWindowFocus: true,
     staleTime: 1000 * 60 * 5,
+    retry: (failureCount, error) => {
+      if (error instanceof NetworkError) return failureCount < 3;
+      return false;
+    },
   },
packages/web/src/app/[lng]/(auth)/memos/_components/MemoSidebar/SidebarGroupCategory.tsx (1)

Line range hint 27-31: 카테고리 클릭 핸들러를 최적화할 수 있습니다.

handleCategoryClick 함수에서 URL 파라미터 조작을 별도의 유틸리티 함수로 분리하면 재사용성이 향상될 것 같습니다.

+ const updateSearchParams = (params: URLSearchParams, category: string) => {
+   params.removeAll('isWish');
+   params.set('category', category);
+   return params;
+ };

  const handleCategoryClick = (category: string) => {
-   searchParams.removeAll('isWish');
-   searchParams.set('category', category);
+   const updatedParams = updateSearchParams(searchParams, category);
-   router.push(searchParams.getUrl(), { scroll: true });
+   router.push(updatedParams.getUrl(), { scroll: true });
  };
packages/web/src/app/[lng]/(auth)/memos/_components/MemoCardFooter/index.tsx (1)

5-5: 타입 임포트 변환이 일관되게 적용되었습니다.

타입 관련 임포트들을 모두 type 키워드를 사용하도록 변경한 것이 좋습니다.

import 구문 순서를 개선할 수 있습니다.

dayjs 임포트를 다른 서드파티 라이브러리와 함께 그룹화하면 코드 구조가 더 명확해질 것 같습니다.

 import type { LanguageType } from '@src/modules/i18n';
 import useTranslation from '@src/modules/i18n/util.client';
-import dayjs from 'dayjs';
 import { HeartIcon } from 'lucide-react';
+import dayjs from 'dayjs';
 import { useRouter } from 'next/navigation';

Also applies to: 8-8, 9-9, 13-13

packages/web/src/app/[lng]/(auth)/memos/_components/index.ts (1)

1-7: 컴포넌트 구조 개선이 잘 이루어졌습니다.

기존 컴포넌트들을 새로운 구조로 리팩토링한 것이 적절해 보입니다.

export 구문 순서를 알파벳 순으로 정렬하면 좋을 것 같습니다.

가독성 향상을 위해 export 구문들을 알파벳 순으로 정렬하는 것을 제안드립니다.

 export { default as ExtensionInstallCheckDialog } from './ExtensionInstallCheckDialog';
 export { default as InitSentryUserInfo } from './InitSentryUserInfo';
 export { default as MemoDialog } from './MemoDialog';
-export { default as MemoSearchForm } from './MemoSearchForm';
-export { default as MemoSearchFormProvider } from './MemoSearchFormProvider';
-export { default as MemoSidebar } from './MemoSidebar';
-export { default as MemoView } from './MemoView';
+export { default as MemoSearchForm } from './MemoSearchForm';
+export { default as MemoSearchFormProvider } from './MemoSearchFormProvider';
+export { default as MemoSidebar } from './MemoSidebar';
+export { default as MemoView } from './MemoView';
packages/web/src/app/[lng]/(auth)/memos/_components/ExtensionInstallCheckDialog/index.tsx (1)

46-59: Dialog 컴포넌트의 접근성 개선 필요

Dialog 컴포넌트에 aria-label이나 aria-describedby와 같은 접근성 속성이 누락되어 있습니다. 스크린 리더 사용자를 위해 이러한 속성들을 추가하는 것이 좋습니다.

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

- <Dialog open={open} >
+ <Dialog 
+   open={open} 
+   >
+   aria-label={t('dialogInstall.title')}
+ >
packages/web/src/app/[lng]/(auth)/memos/_components/MemoSearchForm/index.tsx (2)

Line range hint 33-45: Input 컴포넌트의 접근성 개선 필요

검색 입력창에 aria-label이 누락되어 있습니다. 또한 현재 placeholder만으로는 충분한 접근성을 제공하지 못합니다.

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

  <Input
    type="text"
    placeholder={t('memos.searchPlaceholder')}
    className="w-full select-none pr-8"
+   aria-label={t('memos.searchInputLabel')}
    {...field}
  />

Line range hint 46-60: Select 컴포넌트의 접근성 및 사용성 개선 필요

Select 컴포넌트에 aria-label이 누락되어 있으며, 현재 선택된 값이 변경될 때 사용자에게 알림이 제공되지 않습니다.

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

  <Select 
     
    value={field.value}
+   aria-label={t('memos.searchTargetLabel')}
  >
    <SelectTrigger className="w-[180px] select-none">
      <SelectValue placeholder={t('memos.searchTarget.all')} />
    </SelectTrigger>
📜 Review details

Configuration used: .coderabbit.yaml
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 6e4f530 and e947836.

⛔ Files ignored due to path filters (1)
  • pnpm-lock.yaml is excluded by !**/pnpm-lock.yaml
📒 Files selected for processing (82)
  • .eslintrc (1 hunks)
  • package.json (1 hunks)
  • packages/web/package.json (1 hunks)
  • packages/web/src/app/[lng]/(auth)/memos/_components/ExtensionInstallCheckDialog/index.tsx (1 hunks)
  • packages/web/src/app/[lng]/(auth)/memos/_components/InitSentryUserInfo/index.tsx (2 hunks)
  • packages/web/src/app/[lng]/(auth)/memos/_components/MemoCardFooter/MemoOption.tsx (1 hunks)
  • packages/web/src/app/[lng]/(auth)/memos/_components/MemoCardFooter/index.tsx (1 hunks)
  • packages/web/src/app/[lng]/(auth)/memos/_components/MemoCardHeader/index.tsx (2 hunks)
  • packages/web/src/app/[lng]/(auth)/memos/_components/MemoDialog/UnsavedChangesAlert.tsx (1 hunks)
  • packages/web/src/app/[lng]/(auth)/memos/_components/MemoDialog/index.tsx (3 hunks)
  • packages/web/src/app/[lng]/(auth)/memos/_components/MemoSearchForm/index.tsx (1 hunks)
  • packages/web/src/app/[lng]/(auth)/memos/_components/MemoSearchFormProvider/index.tsx (2 hunks)
  • packages/web/src/app/[lng]/(auth)/memos/_components/MemoSidebar/SidebarGroupCategory.tsx (2 hunks)
  • packages/web/src/app/[lng]/(auth)/memos/_components/MemoSidebar/SidebarMenuItemAddCategory.tsx (1 hunks)
  • packages/web/src/app/[lng]/(auth)/memos/_components/MemoSidebar/index.tsx (2 hunks)
  • packages/web/src/app/[lng]/(auth)/memos/_components/MemoSidebarTrigger/index.tsx (0 hunks)
  • packages/web/src/app/[lng]/(auth)/memos/_components/MemoView/MemoCalendar.tsx (1 hunks)
  • packages/web/src/app/[lng]/(auth)/memos/_components/MemoView/MemoGrid.tsx (8 hunks)
  • packages/web/src/app/[lng]/(auth)/memos/_components/MemoView/MemoItem.tsx (2 hunks)
  • packages/web/src/app/[lng]/(auth)/memos/_components/MemoView/MemoOptionHeader.tsx (1 hunks)
  • packages/web/src/app/[lng]/(auth)/memos/_components/MemoView/MemoRefreshButton.tsx (1 hunks)
  • packages/web/src/app/[lng]/(auth)/memos/_components/MemoView/ToggleView.tsx (1 hunks)
  • packages/web/src/app/[lng]/(auth)/memos/_components/MemoView/index.tsx (3 hunks)
  • packages/web/src/app/[lng]/(auth)/memos/_components/index.ts (1 hunks)
  • packages/web/src/app/[lng]/(auth)/memos/_utils/Sentry.ts (1 hunks)
  • packages/web/src/app/[lng]/(auth)/memos/layout.tsx (1 hunks)
  • packages/web/src/app/[lng]/(auth)/memos/page.tsx (2 hunks)
  • packages/web/src/app/[lng]/(auth)/memos/setting/_components/Setting/SettingCategoryForm.tsx (1 hunks)
  • packages/web/src/app/[lng]/(auth)/memos/setting/_components/Setting/SettingGuide.tsx (1 hunks)
  • packages/web/src/app/[lng]/(auth)/memos/setting/_components/Setting/SettingLanguage.tsx (1 hunks)
  • packages/web/src/app/[lng]/(auth)/memos/setting/_components/Setting/index.tsx (1 hunks)
  • packages/web/src/app/[lng]/(auth)/memos/setting/_components/SettingHeader/index.tsx (1 hunks)
  • packages/web/src/app/[lng]/(auth)/memos/setting/_hooks/index.ts (1 hunks)
  • packages/web/src/app/[lng]/(auth)/memos/setting/_hooks/useLanguage.ts (1 hunks)
  • packages/web/src/app/[lng]/(auth)/memos/setting/page.tsx (1 hunks)
  • packages/web/src/app/[lng]/(no-auth)/introduce/_components/AdditionalFeatures/index.tsx (1 hunks)
  • packages/web/src/app/[lng]/(no-auth)/introduce/_components/Features/index.tsx (1 hunks)
  • packages/web/src/app/[lng]/(no-auth)/introduce/_components/Footer/index.tsx (1 hunks)
  • packages/web/src/app/[lng]/(no-auth)/introduce/_components/Hero/index.tsx (1 hunks)
  • packages/web/src/app/[lng]/(no-auth)/introduce/_components/ImageSlider/index.tsx (1 hunks)
  • packages/web/src/app/[lng]/(no-auth)/introduce/_components/QuestionAndAnswer/index.tsx (1 hunks)
  • packages/web/src/app/[lng]/(no-auth)/introduce/page.tsx (1 hunks)
  • packages/web/src/app/[lng]/(no-auth)/login/_components/LoginSection/index.tsx (1 hunks)
  • packages/web/src/app/[lng]/(no-auth)/login/_components/PersonalInformationInfo/index.tsx (1 hunks)
  • packages/web/src/app/[lng]/(no-auth)/login/page.tsx (1 hunks)
  • packages/web/src/app/[lng]/(no-auth)/update/_components/UpdateList/index.tsx (1 hunks)
  • packages/web/src/app/[lng]/(no-auth)/update/_components/UpdateTitle/index.tsx (1 hunks)
  • packages/web/src/app/[lng]/(no-auth)/update/page.tsx (2 hunks)
  • packages/web/src/app/[lng]/_components/QueryProvider.tsx (1 hunks)
  • packages/web/src/app/[lng]/_components/QueryProvider/index.tsx (1 hunks)
  • packages/web/src/app/[lng]/_components/index.ts (1 hunks)
  • packages/web/src/app/[lng]/layout.tsx (3 hunks)
  • packages/web/src/app/_components/ErrorSection/index.tsx (1 hunks)
  • packages/web/src/app/_components/InitDayjs/index.tsx (2 hunks)
  • packages/web/src/app/_components/Introduction.tsx (0 hunks)
  • packages/web/src/app/_components/NotFoundContainer.tsx (0 hunks)
  • packages/web/src/app/_components/NotFoundContainer/index.tsx (2 hunks)
  • packages/web/src/app/_components/index.ts (1 hunks)
  • packages/web/src/app/_constants/Metadata.ts (1 hunks)
  • packages/web/src/app/_constants/index.ts (1 hunks)
  • packages/web/src/app/error.tsx (2 hunks)
  • packages/web/src/app/global-error.tsx (2 hunks)
  • packages/web/src/app/layout.tsx (2 hunks)
  • packages/web/src/app/not-found.tsx (1 hunks)
  • packages/web/src/app/sitemap.ts (1 hunks)
  • packages/web/src/components/DebugCache.tsx (1 hunks)
  • packages/web/src/components/DragBox.tsx (1 hunks)
  • packages/web/src/components/Header/FeedbackDialog.tsx (1 hunks)
  • packages/web/src/components/Header/FeedbackSection.tsx (1 hunks)
  • packages/web/src/components/Header/HeaderLeft.tsx (2 hunks)
  • packages/web/src/components/Header/HeaderRight.tsx (2 hunks)
  • packages/web/src/components/Header/index.tsx (1 hunks)
  • packages/web/src/components/HydrationBoundaryWrapper.tsx (1 hunks)
  • packages/web/src/components/RevalidateButton.tsx (0 hunks)
  • packages/web/src/components/YoutubeEmbed.tsx (1 hunks)
  • packages/web/src/components/feedback/FeedbackButton.tsx (0 hunks)
  • packages/web/src/components/index.ts (1 hunks)
  • packages/web/src/constants/index.ts (0 hunks)
  • packages/web/src/hooks/index.ts (1 hunks)
  • packages/web/src/hooks/useDrag.ts (1 hunks)
  • packages/web/src/hooks/usePropagateEvent.ts (0 hunks)
  • packages/web/src/hooks/useScrollSync.ts (0 hunks)
⛔ Files not processed due to max files limit (9)
  • packages/web/src/middleware.ts
  • packages/web/src/modules/guide/useGuide.ts
  • packages/web/src/modules/i18n/type.ts
  • packages/web/src/modules/i18n/util.client.ts
  • packages/web/src/modules/i18n/util.server.ts
  • packages/web/src/modules/i18n/util.ts
  • packages/web/src/modules/supabase/util.server.ts
  • packages/web/src/modules/supabase/util.ts
  • packages/web/src/types/feedback.ts
💤 Files with no reviewable changes (8)
  • packages/web/src/constants/index.ts
  • packages/web/src/components/feedback/FeedbackButton.tsx
  • packages/web/src/app/_components/Introduction.tsx
  • packages/web/src/app/[lng]/(auth)/memos/_components/MemoSidebarTrigger/index.tsx
  • packages/web/src/hooks/useScrollSync.ts
  • packages/web/src/app/_components/NotFoundContainer.tsx
  • packages/web/src/hooks/usePropagateEvent.ts
  • packages/web/src/components/RevalidateButton.tsx
✅ Files skipped from review due to trivial changes (13)
  • packages/web/src/components/DragBox.tsx
  • packages/web/src/app/_constants/index.ts
  • packages/web/src/app/[lng]/(auth)/memos/setting/_hooks/index.ts
  • packages/web/src/app/[lng]/(auth)/memos/_utils/Sentry.ts
  • packages/web/src/app/_constants/Metadata.ts
  • packages/web/src/app/[lng]/(auth)/memos/_components/MemoSidebar/SidebarMenuItemAddCategory.tsx
  • packages/web/src/app/[lng]/(no-auth)/introduce/_components/ImageSlider/index.tsx
  • packages/web/src/app/[lng]/(no-auth)/update/_components/UpdateList/index.tsx
  • packages/web/src/app/sitemap.ts
  • packages/web/src/components/HydrationBoundaryWrapper.tsx
  • packages/web/src/app/[lng]/(no-auth)/login/_components/PersonalInformationInfo/index.tsx
  • packages/web/src/app/[lng]/(no-auth)/login/page.tsx
  • packages/web/src/app/[lng]/(auth)/memos/setting/_hooks/useLanguage.ts
🚧 Files skipped from review as they are similar to previous changes (19)
  • packages/web/src/app/[lng]/(no-auth)/introduce/page.tsx
  • packages/web/src/app/[lng]/_components/index.ts
  • packages/web/src/app/layout.tsx
  • packages/web/src/app/[lng]/(auth)/memos/page.tsx
  • packages/web/src/app/[lng]/(auth)/memos/layout.tsx
  • packages/web/src/app/[lng]/(auth)/memos/_components/InitSentryUserInfo/index.tsx
  • packages/web/src/app/[lng]/(auth)/memos/_components/MemoDialog/index.tsx
  • packages/web/src/app/_components/index.ts
  • packages/web/src/app/[lng]/(auth)/memos/_components/MemoSearchFormProvider/index.tsx
  • packages/web/src/app/[lng]/(auth)/memos/setting/page.tsx
  • packages/web/src/app/[lng]/(no-auth)/update/page.tsx
  • packages/web/src/app/[lng]/(auth)/memos/_components/MemoView/MemoRefreshButton.tsx
  • package.json
  • packages/web/src/app/[lng]/(auth)/memos/_components/MemoView/MemoItem.tsx
  • packages/web/src/app/[lng]/(auth)/memos/_components/MemoView/MemoGrid.tsx
  • packages/web/src/app/[lng]/(auth)/memos/_components/MemoView/index.tsx
  • .eslintrc
  • packages/web/src/app/[lng]/(auth)/memos/_components/MemoSidebar/index.tsx
  • packages/web/src/app/[lng]/(auth)/memos/_components/MemoCardHeader/index.tsx
🔇 Additional comments (48)
packages/web/src/components/YoutubeEmbed.tsx (1)

2-2: 타입 임포트 변경이 잘 되었습니다!

IframeHTMLAttributes를 타입 임포트로 변경한 것은 TypeScript의 모범 사례를 잘 따르고 있습니다. 이는 번들 크기를 최적화하는 데도 도움이 됩니다.

packages/web/src/hooks/useDrag.ts (1)

14-14: 의존성 배열에 onMouseDown 추가는 적절합니다.

useEffect의 의존성 배열에 onMouseDown을 추가한 것은 React의 훅 규칙을 잘 준수하고 있습니다. 이는 onMouseDown 함수가 변경될 때마다 이벤트 리스너가 적절히 업데이트되도록 보장합니다.

packages/web/src/app/_components/NotFoundContainer/index.tsx (2)

3-7: 코드 구조가 개선되었습니다!

함수 선언 방식을 화살표 함수에서 일반 함수로 변경하고, export default를 직접 사용한 것이 React의 권장 패턴에 더 잘 부합합니다.


11-11: 시맨틱 마크업으로의 개선을 환영합니다!

div에서 section 요소로의 변경은 HTML 시맨틱을 개선하는 좋은 변화입니다.

packages/web/src/app/[lng]/_components/QueryProvider.tsx (1)

3-3: 타입 임포트 리팩토링이 잘 되었습니다.

타입 임포트를 명시적으로 구분하여 코드의 가독성과 유지보수성이 향상되었습니다. ESLint 규칙 @typescript-eslint/consistent-type-imports를 잘 준수하고 있습니다.

Also applies to: 5-7, 10-10

packages/web/src/app/[lng]/(auth)/memos/_components/MemoView/ToggleView.tsx (2)

4-4: 타입 임포트 선언이 개선되었습니다!

type 키워드를 사용하여 타입 임포트를 명시적으로 선언한 것은 좋은 변경사항입니다. 이는 번들 크기 최적화에 도움이 되며 코드의 의도를 더 명확하게 만듭니다.


5-5: 모듈 경로 변경이 일관되게 적용되었는지 확인이 필요합니다.

useTranslation 임포트 경로가 client에서 util.client로 변경되었습니다. 이 변경이 다른 컴포넌트에서도 일관되게 적용되었는지 확인해주세요.

✅ Verification successful

모든 파일에서 일관되게 새로운 import 경로를 사용하고 있습니다.

검증 결과, 기존 @src/modules/i18n/client 경로를 사용하는 파일이 없으며, 모든 관련 파일들이 새로운 @src/modules/i18n/util.client 경로로 올바르게 변경되어 있습니다.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: useTranslation 임포트 경로의 일관성 검사

echo "기존 client 경로 사용 중인 파일 검색:"
rg "from ['|\"]@src/modules/i18n/client['|\"]" -l

echo "\n새로운 util.client 경로 사용 중인 파일 검색:"
rg "from ['|\"]@src/modules/i18n/util\.client['|\"]" -l

Length of output: 2419

packages/web/package.json (1)

11-12: 새로운 lint 스크립트가 추가되었습니다.

자동 수정 기능(--fix)이 포함된 ESLint 스크립트가 추가되어 코드 품질 관리가 향상될 것으로 보입니다.

packages/web/src/app/[lng]/(no-auth)/introduce/_components/QuestionAndAnswer/index.tsx (2)

4-5: 타입 임포트와 유틸리티 경로 변경이 적절해 보입니다.

LanguageType을 타입 임포트로 변경하고 useTranslation의 경로를 util.client로 변경한 것은 좋은 리팩토링입니다. 타입 임포트를 사용하면 번들 크기를 줄일 수 있습니다.


8-8: 상수 파일 위치 변경이 적절해 보입니다.

FAQ_ITEMS를 컴포넌트와 더 가까운 위치로 이동한 것은 관련 코드를 더 응집력 있게 만듭니다. 다만, 다른 페이지에서도 이 상수를 사용하는지 확인이 필요합니다.

✅ Verification successful

FAQ_ITEMS 상수 위치 변경이 적절합니다

ripgrep 검색 결과, FAQ_ITEMS는 QuestionAndAnswer 컴포넌트에서만 사용되고 있어 상수 파일의 위치 변경이 적절했음을 확인했습니다.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# FAQ_ITEMS 상수가 다른 곳에서 사용되는지 확인
rg "FAQ_ITEMS" --type ts --type tsx

Length of output: 63


Script:

#!/bin/bash
# Search for FAQ_ITEMS usage in TypeScript and TSX files
rg -C 2 "FAQ_ITEMS" --glob "*.{ts,tsx}"

Length of output: 1596

packages/web/src/components/DebugCache.tsx (1)

1-2: 코드가 단순화되어 좋습니다만, 문서화가 필요해 보입니다.

코드베이스 최적화 측면에서 dayjs 의존성을 제거하고 네이티브 Date API를 사용한 것은 좋은 변경입니다. 하지만 다음 사항들을 고려해주시기 바랍니다:

  1. 컴포넌트의 목적과 사용 사례에 대한 주석이나 문서화가 필요합니다.
  2. RevalidateButton 제거로 인한 캐시 관리 기능의 영향을 확인해야 합니다.

캐시 관리 기능에 미치는 영향을 확인하기 위해 다음 스크립트를 실행하겠습니다:

✅ Verification successful

RevalidateButton 제거는 안전하며 더 나은 디버깅 도구가 있습니다.

캐시 관련 코드베이스 분석 결과:

  • 핵심 캐시 관리는 QueryClient와 Next.js 캐시 시스템으로 처리됩니다.
  • ReactQueryDevtools가 더 강력한 캐시 디버깅 기능을 제공합니다.

제안사항:

  • 컴포넌트의 목적과 ReactQueryDevtools 사용법에 대한 간단한 주석 추가를 권장드립니다.
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: RevalidateButton 사용처 및 관련 캐시 관리 코드 확인

# RevalidateButton 컴포넌트의 이전 사용처 검색
rg -l "RevalidateButton"

# 캐시 관련 로직 검색
rg -l "revalidate|cache|stale"

Length of output: 472


Script:

#!/bin/bash
# Check implementation of cache-related utilities and debug functionality

# Check revalidateFullRouteCache implementation
echo "=== revalidateFullRouteCache.ts ==="
cat packages/web/src/utils/revalidateFullRouteCache.ts

# Check QueryProvider implementation
echo -e "\n=== QueryProvider.tsx ==="
cat packages/web/src/app/[lng]/_components/QueryProvider.tsx

# Search for debug-related cache patterns
echo -e "\n=== Debug cache patterns ==="
rg -l "debug.*cache|cache.*debug" --type ts --type tsx

Length of output: 2023

packages/web/src/app/[lng]/layout.tsx (2)

18-18: 메타데이터 제목에서 불필요한 공백 제거 👍

한글 메타데이터 제목의 끝부분 공백을 제거한 것은 좋은 개선입니다.


1-9: 인증 관련 변경사항 확인 필요

AuthProvider가 제거되었습니다. 이로 인한 인증 관련 기능이 다른 곳으로 이전되었는지 확인이 필요합니다.

다음 스크립트를 실행하여 인증 관련 코드의 위치를 확인하겠습니다:

✅ Verification successful

AuthProvider 제거는 적절한 변경사항입니다

인증 로직이 미들웨어 레벨에서 Supabase SSR을 통해 더 안전하게 처리되고 있습니다. 서버 사이드 검증과 미들웨어를 통한 라우트 보호가 잘 구현되어 있어 클라이언트 측 AuthProvider가 더 이상 필요하지 않습니다.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: AuthProvider 관련 변경사항 확인

# AuthProvider 사용 여부 확인
rg -l "AuthProvider"

# 인증 관련 로직 확인
rg -l "auth|login|session"

Length of output: 1652


Script:

#!/bin/bash
# Description: 인증 구현 상세 확인

# 미들웨어 구현 확인
echo "=== Middleware Implementation ==="
cat packages/web/src/middleware.ts

# Supabase 인증 구현 확인
echo -e "\n=== Supabase Auth Implementation ==="
cat packages/web/src/modules/supabase/util.ts

# auth 라우트 레이아웃 확인
echo -e "\n=== Auth Route Layout ==="
cat "packages/web/src/app/[lng]/(auth)/memos/layout.tsx"

Length of output: 4196

packages/web/src/app/global-error.tsx (1)

3-3: 컴포넌트 이름 변경이 일관성 있게 적용되었습니다!

ErrorContainer에서 ErrorSection으로의 변경이 잘 이루어졌습니다. 컴포넌트의 기능은 동일하게 유지되면서 이름만 더 명확하게 변경되었습니다.

Also applies to: 14-14

packages/web/src/app/not-found.tsx (1)

3-3: 404 페이지 컴포넌트 이름이 일관성 있게 변경되었습니다!

NotFoundContainer에서 NotFoundSection으로의 변경이 적절하게 이루어졌습니다. 에러 처리 관련 컴포넌트들의 네이밍 컨벤션이 일관되게 유지되고 있습니다.

Also applies to: 10-10

packages/web/src/app/error.tsx (1)

4-4: 에러 페이지 컴포넌트 변경이 올바르게 적용되었습니다!

ErrorContainer에서 ErrorSection으로의 변경이 적절하게 이루어졌으며, Suspense와 ErrorBoundary 구조 내에서도 올바르게 적용되었습니다.

Also applies to: 16-16

packages/web/src/app/_components/ErrorSection/index.tsx (1)

8-13: 인터페이스와 컴포넌트 이름이 일관성 있게 변경되었습니다!

ErrorContainerProps에서 ErrorSectionProps로, ErrorContainer에서 ErrorSection으로의 변경이 일관되게 이루어졌습니다.

packages/web/src/app/[lng]/(auth)/memos/_components/MemoView/MemoCalendar.tsx (4)

7-7: 타입 임포트 변경이 적절하게 이루어졌습니다.

GetMemoResponse를 타입으로만 사용하므로 타입 임포트로 변경한 것이 적절합니다. 이는 번들 크기를 최적화하는 데 도움이 됩니다.


10-10: 타입 임포트 변경이 적절하게 이루어졌습니다.

LanguageType을 타입으로만 사용하므로 타입 임포트로 변경한 것이 적절합니다. 이는 번들 크기를 최적화하는 데 도움이 됩니다.


11-11: i18n 유틸리티 경로 변경이 일관성 있게 적용되었습니다.

useTranslation 임포트 경로를 @src/modules/i18n/util.client로 변경한 것이 적절합니다. 이는 클라이언트 사이드 유틸리티의 명확한 구분을 제공합니다.


Line range hint 93-93: 타입 에러에 대한 해결이 필요합니다.

@ts-expect-error 주석이 있는 TODO 항목이 있습니다. 이는 기술 부채가 될 수 있으므로 가능한 빨리 해결하는 것이 좋습니다.

타입 에러를 해결하기 위한 작업을 도와드릴까요? 먼저 react-big-calendar의 타입 정의를 확인하고 적절한 해결책을 제안해드리겠습니다.

packages/web/src/hooks/index.ts (1)

Line range hint 1-3: 후크 내보내기 변경사항 검증 필요

여러 후크들이 제거되었습니다. 이러한 변경이 다른 컴포넌트에 영향을 미치지 않는지 확인이 필요합니다.

다음 스크립트를 실행하여 제거된 후크들의 사용처를 확인해주세요:

✅ Verification successful

후크 제거가 안전하게 확인됨

  • useLanguagememos/setting/_hooks로 적절히 이동되었으며 모든 임포트가 업데이트되었습니다.
  • useScrollSyncusePropagateEvent는 코드베이스 어디에서도 사용되지 않아 안전하게 제거된 것으로 확인됩니다.
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Check for any remaining usage of removed hooks

echo "Checking for useLanguage usage..."
rg "useLanguage"

echo "Checking for useScrollSync usage..."
rg "useScrollSync"

echo "Checking for usePropagateEvent usage..."
rg "usePropagateEvent"

Length of output: 812


Script:

#!/bin/bash
# Check if hooks exist in shared package
echo "Checking shared package for moved hooks..."
fd -t f "useScrollSync|usePropagateEvent" "packages/shared"

echo "Checking imports from shared hooks..."
rg "from ['|\"]@common/hooks" -A 1
rg "from ['|\"]@shared/hooks" -A 1

Length of output: 317

packages/web/src/components/index.ts (1)

Line range hint 1-4: 프로바이더 컴포넌트 제거에 대한 검증 필요

QueryProvider, AuthProvider 등 중요한 프로바이더 컴포넌트들이 제거되었습니다. 이는 애플리케이션의 핵심 기능에 영향을 미칠 수 있습니다.

다음 스크립트를 실행하여 제거된 프로바이더들의 새로운 위치를 확인해주세요:

packages/web/src/app/[lng]/(auth)/memos/setting/_components/SettingHeader/index.tsx (1)

4-5: 타입 임포트와 유틸리티 경로 변경이 적절히 이루어졌습니다.

타입 전용 임포트로의 전환과 번역 유틸리티의 경로 변경이 일관성 있게 적용되었습니다.

packages/web/src/app/[lng]/(no-auth)/update/_components/UpdateTitle/index.tsx (1)

2-3: 클라이언트 컴포넌트의 임포트 구조가 개선되었습니다.

타입 임포트와 클라이언트 유틸리티 경로 변경이 적절하게 이루어졌습니다.

packages/web/src/app/_components/InitDayjs/index.tsx (2)

6-7: 타입 임포트 변경이 적절합니다.

LanguageType을 타입 전용 임포트로 변경한 것이 타입스크립트 모범 사례를 따르고 있습니다.


21-21: useEffect의 의존성 배열 수정이 올바르게 이루어졌습니다.

lng 값이 변경될 때 로케일을 업데이트하도록 의존성 배열에 추가한 것이 적절합니다. 이전에는 컴포넌트 마운트 시에만 실행되어 언어 변경이 제대로 반영되지 않을 수 있었습니다.

packages/web/src/components/Header/index.tsx (1)

4-4: 타입 임포트 변경이 일관성 있게 적용되었습니다.

LanguageType을 타입 전용 임포트로 변경하여 전체 코드베이스의 일관성을 유지하고 있습니다.

packages/web/src/app/[lng]/(auth)/memos/setting/_components/Setting/index.tsx (1)

5-5: 타입 임포트로의 변경이 적절합니다!

LanguageType를 타입 전용 임포트로 변경한 것은 런타임 번들 크기를 최적화하고 타입 안전성을 향상시키는 좋은 방법입니다.

packages/web/src/app/[lng]/(auth)/memos/setting/_components/Setting/SettingGuide.tsx (1)

4-5: 모듈 구조 개선이 잘 이루어졌습니다!

  1. LanguageType를 타입 전용 임포트로 변경
  2. useTranslation 임포트 경로를 util.client로 업데이트

두 변경 사항 모두 코드베이스의 구조를 개선하고 타입 안전성을 강화하는데 도움이 됩니다.

packages/web/src/app/[lng]/(auth)/memos/_components/MemoDialog/UnsavedChangesAlert.tsx (1)

9-10: 일관된 리팩토링이 잘 적용되었습니다!

다른 컴포넌트들과 동일한 패턴으로:

  1. LanguageType 타입 임포트 변경
  2. useTranslation 경로 업데이트

이러한 일관성은 코드베이스의 유지보수성을 향상시킵니다.

packages/web/src/components/Header/HeaderLeft.tsx (2)

4-5: 임포트 구조가 개선되었습니다!

타입 시스템 활용과 모듈 구조가 개선되었습니다.


9-9: FeedbackSection 컴포넌트 교체에 대한 검증이 필요합니다.

FeedbackContainer에서 FeedbackSection으로의 변경이 있었습니다. 기존 기능이 모두 올바르게 마이그레이션 되었는지 확인이 필요합니다.

다음 스크립트를 실행하여 컴포넌트 변경의 영향을 확인해주세요:

Also applies to: 28-28

packages/web/src/app/[lng]/(auth)/memos/setting/_components/Setting/SettingLanguage.tsx (1)

2-3: 모듈 임포트 구조가 개선되었습니다!

타입 임포트와 훅 임포트 경로가 더 명확하게 정리되었습니다:

  • 타입 전용 임포트 사용으로 번들 크기 최적화
  • 상대 경로를 통한 명확한 모듈 의존성

Also applies to: 6-6

packages/web/src/components/Header/HeaderRight.tsx (2)

4-4: 임포트 구문이 개선되었습니다.

타입 임포트와 훅 임포트가 더 명확하게 구성되었습니다.

Also applies to: 6-7


15-16: 로그아웃 로직 검증이 필요합니다.

로그아웃 후 즉시 로그인 페이지로 이동하는 것은 사용자 세션이 완전히 정리되기 전에 발생할 수 있습니다.

다음과 같이 수정하는 것이 좋습니다:

  const handleSignoutClick = () => {
-   mutateSignout();
-   router.push(PATHS.login);
+   mutateSignout({
+     onSuccess: () => {
+       router.push(PATHS.login);
+     }
+   });
  };

Also applies to: 25-26

packages/web/src/components/Header/FeedbackDialog.tsx (2)

1-3: 임포트 구문이 잘 정리되었습니다.

UI 컴포넌트들의 임포트가 한 줄로 통합되어 가독성이 향상되었습니다.


6-6: 컴포넌트 이름이 더 명확해졌습니다.

Modal에서 Dialog로의 이름 변경이 컴포넌트의 실제 역할을 더 잘 반영합니다.

Also applies to: 12-12

packages/web/src/app/[lng]/(no-auth)/login/_components/LoginSection/index.tsx (1)

4-6: 임포트 경로가 개선되었습니다.

타입 임포트와 유틸리티 함수의 경로가 더 명확하게 구성되었습니다.

packages/web/src/app/[lng]/(auth)/memos/_components/MemoSidebar/SidebarGroupCategory.tsx (1)

4-4: 임포트 구문이 개선되었습니다.

검색 파라미터와 타입 임포트가 더 명확하게 구성되었습니다.

Also applies to: 13-14

packages/web/src/app/[lng]/(no-auth)/introduce/_components/Footer/index.tsx (1)

4-5: 타입 안전성이 향상된 import 구문 변경을 승인합니다!

LanguageType을 명시적인 타입 import로 변경하고 useTranslation의 경로를 수정한 것은 타입 안전성과 모듈 구조를 개선하는 좋은 변경사항입니다.

packages/web/src/app/[lng]/(no-auth)/introduce/_components/Hero/index.tsx (1)

4-5: 일관된 import 구문 변경을 확인했습니다!

Footer 컴포넌트와 동일한 패턴으로 import 구문이 개선되었습니다. 이러한 일관성은 코드베이스의 유지보수성을 향상시킵니다.

packages/web/src/app/[lng]/(no-auth)/introduce/_components/AdditionalFeatures/index.tsx (1)

3-4: 일관된 import 구문 리팩토링을 승인합니다!

다른 컴포넌트들과 동일한 패턴으로 import 구문이 개선되었습니다.

packages/web/src/app/[lng]/(auth)/memos/setting/_components/Setting/SettingCategoryForm.tsx (1)

8-9: 일관된 import 구문 개선을 승인합니다!

다른 컴포넌트들과 마찬가지로 LanguageType을 타입 import로 변경하고 useTranslation의 경로를 수정한 변경사항이 일관성 있게 적용되었습니다.

packages/web/src/app/[lng]/(no-auth)/introduce/_components/Features/index.tsx (1)

3-4: 타입 임포트 및 경로 변경이 적절히 이루어졌습니다!

타입 전용 임포트를 사용하고 유틸리티 경로를 업데이트한 것이 타입스크립트 모범 사례를 잘 따르고 있습니다.

packages/web/src/app/[lng]/(auth)/memos/_components/MemoCardFooter/MemoOption.tsx (1)

26-26: 타입 임포트 변환이 잘 이루어졌습니다.

타입 관련 임포트들을 type 키워드를 사용하도록 변경한 것이 적절합니다.

Also applies to: 27-27, 31-31, 32-32

packages/web/src/app/[lng]/(auth)/memos/_components/ExtensionInstallCheckDialog/index.tsx (1)

39-43: useEffect 의존성 배열에 checkLocalStorageTrue 추가 필요

현재 useEffect는 manifest 변경시에만 실행되도록 설정되어 있습니다. 하지만 checkLocalStorageTrue('install')의 결과도 effect에 영향을 미치므로 의존성 배열에 포함되어야 합니다.

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

  useEffect(() => {
    const isInstalled = typeof manifest === 'object';

    if (!isInstalled && !checkLocalStorageTrue('install')) setOpen(true);
-  }, [manifest]);
+  }, [manifest, checkLocalStorageTrue]);
packages/web/src/app/[lng]/(auth)/memos/_components/MemoSearchForm/index.tsx (1)

Line range hint 23-41: form 제출 이벤트 핸들러 개선 필요

현재 form의 onSubmit 핸들러가 단순히 기본 동작만 막고 있습니다. 검색 기능의 실제 구현이 누락된 것으로 보입니다.

검색 기능이 의도적으로 구현되지 않은 것인지 확인이 필요합니다. 만약 검색 기능이 필요하다면 적절한 핸들러를 구현해야 합니다.

Comment on lines +19 to +26
const handleSubmit = (content: string) => {
setIsOpen(false);
mutateFeedback({ content });
toast({
title: t('feedback.success'),
description: t('feedback.successDescription'),
});
};
Copy link

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

피드백 제출 로직 개선이 필요합니다.

현재 구현에서 다음 사항들을 개선하면 좋을 것 같습니다:

  1. 뮤테이션 완료 전에 성공 토스트가 표시됩니다
  2. 오류 처리가 누락되어 있습니다
  3. 제출 중 로딩 상태가 표시되지 않습니다

다음과 같이 수정하는 것을 제안드립니다:

  const handleSubmit = (content: string) => {
    setIsOpen(false);
-   mutateFeedback({ content });
-   toast({
-     title: t('feedback.success'),
-     description: t('feedback.successDescription'),
-   });
+   mutateFeedback(
+     { content },
+     {
+       onSuccess: () => {
+         toast({
+           title: t('feedback.success'),
+           description: t('feedback.successDescription'),
+         });
+       },
+       onError: () => {
+         toast({
+           title: t('feedback.error'),
+           description: t('feedback.errorDescription'),
+           variant: 'destructive',
+         });
+       },
+     },
+   );
  };
📝 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 handleSubmit = (content: string) => {
setIsOpen(false);
mutateFeedback({ content });
toast({
title: t('feedback.success'),
description: t('feedback.successDescription'),
});
};
const handleSubmit = (content: string) => {
setIsOpen(false);
mutateFeedback(
{ content },
{
onSuccess: () => {
toast({
title: t('feedback.success'),
description: t('feedback.successDescription'),
});
},
onError: () => {
toast({
title: t('feedback.error'),
description: t('feedback.errorDescription'),
variant: 'destructive',
});
},
},
);
};

Comment on lines +27 to +32
onError: error => {
toast({ title: t('toastTitle.errorSave') });
Sentry.captureException(error, {
level: 'fatal',
});
},
Copy link

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

에러 처리 전략을 개선해주세요.

현재 구현의 개선 포인트입니다:

  1. 일반적인 뮤테이션 에러에 'fatal' 레벨은 과도할 수 있습니다
  2. 에러 메시지가 너무 일반적입니다
  3. 재시도 설정이 누락되어 있습니다
 onError: error => {
-  toast({ title: t('toastTitle.errorSave') });
+  toast({
+    title: t('toastTitle.errorSave'),
+    description: error instanceof Error ? error.message : undefined,
+  });
   Sentry.captureException(error, {
-    level: 'fatal',
+    level: 'error',
   });
 },
📝 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
onError: error => {
toast({ title: t('toastTitle.errorSave') });
Sentry.captureException(error, {
level: 'fatal',
});
},
onError: error => {
toast({
title: t('toastTitle.errorSave'),
description: error instanceof Error ? error.message : undefined,
});
Sentry.captureException(error, {
level: 'error',
});
},

Comment on lines +35 to +37
const handleCancelClick = () => {
setLocalStorageTrue('install');
};
Copy link

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

handleCancelClick 함수에서 dialog 닫기 로직 누락

handleCancelClick 함수에서 로컬 스토리지 값만 설정하고 dialog를 닫지 않고 있습니다. 사용자 경험 향상을 위해 closeDialog() 함수도 호출해야 합니다.

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

  const handleCancelClick = () => {
    setLocalStorageTrue('install');
+   closeDialog();
  };
📝 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 handleCancelClick = () => {
setLocalStorageTrue('install');
};
const handleCancelClick = () => {
setLocalStorageTrue('install');
closeDialog();
};

@guesung guesung merged commit 47b99e9 into develop Jan 29, 2025
4 of 7 checks passed
@guesung guesung deleted the refactor/2025-01-27 branch January 29, 2025 03:51
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.

1 participant
0