Skip to content

Create Week7 Mission1, 2#98

Merged
wantkdd merged 4 commits intomainfrom
wantkdd/week07
Nov 22, 2025
Merged

Create Week7 Mission1, 2#98
wantkdd merged 4 commits intomainfrom
wantkdd/week07

Conversation

@wantkdd
Copy link
Copy Markdown
Member

@wantkdd wantkdd commented Nov 15, 2025

📝 미션 번호

7주차 Misson 1, 2

📋 구현 사항

  • lp post 기능 추가
  • 댓글 기능 추가
  • 좋아요 기능 추가
  • 마이페이지 추가
  • 낙관적 업데이트 적용 및 로그인 로직 useMutation으로 변경

📎 스크린샷

image image

✅ 체크리스트

  • Merge 하려는 브랜치가 올바르게 설정되어 있나요?
  • 로컬에서 실행했을 때 에러가 발생하지 않나요?
  • 불필요한 주석이 제거되었나요?
  • 코드 스타일이 일관적인가요?

🤔 질문 사항

@wantkdd wantkdd requested a review from woojo230 November 15, 2025 07:04
@wantkdd wantkdd self-assigned this Nov 15, 2025
},
onSuccess: () => {
alert('프로필이 성공적으로 수정되었습니다.');
queryClient.invalidateQueries({ queryKey: ['user'] });
Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

onSettled에서와 쿼리키 무효화 동작이 중복되니 onSuccess에서는 제거하는 것이 나아보이네요.

@github-actions
Copy link
Copy Markdown

github-actions bot commented Nov 15, 2025

🤖 Gemini 코드리뷰 결과

코드 리뷰 통합 결과

안녕하세요, 시니어 프론트엔드 개발자로서 제출해주신 Pull Request 변경 사항을 면밀히 검토했습니다.

전반적으로 코드 품질이 높고, React Query, Zustand, Zod, React Hook Form, Framer Motion 등 최신 라이브러리 및 기술 스택을 적절히 활용하여 관심사 분리 및 타입 안전성을 확보하려는 노력이 돋보입니다. 특히 무한 스크롤, 폼 관리, 이미지 업로드, Axios 인터셉터를 통한 데이터 관리, 그리고 컴포넌트 분리 등 여러 복잡한 기능들이 잘 구현되어 있으며, 아키텍처 측면에서 높은 이해도를 보여주고 계십니다.

다만, 몇 가지 개선점을 통해 코드의 견고성, 사용자 경험, 보안, 그리고 장기적인 유지보수성을 더욱 높일 수 있습니다. 아래는 프로젝트 설정, 의존성 관리, 그리고 핵심 src 코드에 대한 상세 리뷰 및 구체적인 개선 제안입니다.


1. 프로젝트 설정 및 의존성 관리

현재 PR은 src 디렉토리 내의 TypeScript/TSX 파일뿐만 아니라, package.json, pnpm-lock.yaml, eslint.config.js, README.md 등 프로젝트 초기 설정 파일 변경 내용도 포함하고 있습니다. 이러한 설정은 향후 src 코드의 품질과 개발 경험에 큰 영향을 미치므로, 관련 개선 제안을 드립니다.

1.1. ESLint 및 TypeScript 설정 개선

  • Type-Aware Linting 활성화 및 parserOptions.project 추가 (eslint.config.js)
    • tseslint.configs.recommendedTypeChecked로 변경하고, languageOptions.parserOptionsproject: ['./tsconfig.json', './tsconfig.node.json'] 설정을 추가하여 타입 기반 ESLint 규칙이 제대로 작동하도록 합니다. README.md에서 권장하는 tseslint.configs.strictTypeChecked로의 업그레이드 여부도 팀과 논의하여 결정하는 것을 고려해볼 수 있습니다.
  • ecmaVersion'latest'로 업데이트 (eslint.config.js)
    • languageOptions.ecmaVersion: 2020ecmaVersion: 'latest'로 변경하여 최신 JavaScript 문법을 지원하도록 합니다.
  • languageOptionssourceType: 'module' 명시적 추가 (eslint.config.js)
    • TypeScript 및 React 프로젝트는 대부분 ES Modules를 사용하므로, languageOptionssourceType: 'module'을 명시적으로 추가하여 파싱 문제를 방지합니다.
  • settings.react.version 설정 추가 (eslint.config.js)
    • eslint-plugin-react가 최신 React 버전(예: React 19)에 맞는 규칙을 적용하도록 settings 블록에 react: { version: 'detect' }를 추가합니다.
  • eslint-plugin-react-xeslint-plugin-react-dom 통합 고려 (eslint.config.js, README.md)
    • README.md에서 권장하는 eslint-plugin-react-xeslint-plugin-react-dompackage.jsondevDependencies에 추가하고 eslint.config.jsextends 배열에 포함하여 React 관련 린팅 규칙을 확장합니다.

1.2. package.json 및 의존성 관리

  • package.jsonname 필드 일관성 유지
    • package-lock.json의 최상위 name 필드와 프로젝트 경로(week07/wantkdd/mission1)의 불일치를 해소하기 위해 package.jsonname 필드를 "mission1"으로 변경합니다.
  • 프로젝트 engines 필드를 package.json에 명시하여 Node.js 버전 제어
    • package-lock.json에 명시된 의존성들이 특정 Node.js 버전을 요구하고 있으므로, package.jsonengines 필드 ("node": ">=20.19.0")를 추가하여 개발 환경 간의 일관성을 유지합니다.
  • Vite 버전 업데이트 검토 필요
    • package.jsonvite: ^7.1.7 (lockfile에는 7.1.8)로 명시되어 있으나, 현재 Vite의 안정적인 최신 버전은 5.x.x대입니다. 빌드 성능, 개발 서버 속도, 최신 웹 기술 지원, 보안 취약점 등을 위해 Vite를 최신 안정 버전으로 업데이트하는 것을 강력히 권장합니다.
  • 의존성 업데이트 후 테스트 강화
    • Rollup, Tailwind CSS, TanStack Query, ESLint, Framer Motion 등 다수의 핵심 라이브러리 및 개발 도구들이 메이저 버전으로 업데이트되었습니다. 이러한 업데이트는 잠재적인 Breaking Change를 내포하므로, 충분한 단위/통합/E2E 테스트를 통해 기존 기능의 정상 작동 여부를 확인해야 합니다.

1.3. 선택된 기술 스택 기반 src 코드 작성 권고 사항 (미래 대비)

  • React 19 기능 활용 및 타입 안전성 확보
    • React 19의 use 훅, React Actions 등 새로운 비동기 데이터 처리 기능을 활용하고, 관련 타입 정의를 정확히 사용하며 Suspense와 Error Boundary 패턴을 적절히 적용하여 타입 안전성과 사용자 경험을 향상시키십시오.
  • react-hook-form + zod 스키마 재사용 및 분리
    • Zod 스키마 정의를 src/schemas와 같은 별도의 디렉토리로 분리하고, z.infer<typeof yourSchema>를 활용하여 폼 데이터 타입을 추론하여 코드의 응집도를 높이고 타입 정의 중복을 피하십시오.
  • @tanstack/react-query 쿼리 키 중앙 관리 및 커스텀 훅 추상화
    • 쿼리 키를 src/constants/queryKeys.ts와 같이 중앙 집중식으로 관리하고, useQueryuseMutation 로직을 src/hooks/use[Feature]Data.ts 형태의 커스텀 훅으로 추상화하여 중복 코드를 제거하고 src 컴포넌트에서 데이터 페칭 로직을 깔끔하게 분리합니다.
  • zustand 스토어 구조화 및 최적화된 셀렉터 사용
    • 각 스토어를 독립적인 파일로 분리하고, 컴포넌트에서는 필요한 상태만 shallow 셀렉터(useShallow 훅 등)를 사용하여 구독하도록 하여 불필요한 컴포넌트 리렌더링을 방지합니다.
  • Tailwind CSS 유틸리티 및 clsx/tailwind-merge 활용
    • clsx는 조건부 클래스를 깔끔하게 관리하며, tailwind-merge는 Tailwind 클래스 충돌을 자동으로 해결하여 최종 CSS 번들을 최적화하고 코드의 가독성을 높입니다. 이를 적극적으로 활용하십시오.
  • 애니메이션 라이브러리(framer-motion)의 성능 최적화
    • 복잡한 애니메이션이 성능에 영향을 주지 않도록 react-intersection-observer로 뷰포트 진입 시 애니메이션을 활성화하거나, will-change CSS 속성을 사용하여 브라우저가 애니메이션 요소를 최적화하도록 유도합니다.
  • Vite 번들 최적화 전략 적용
    • React.lazySuspense를 활용한 코드 스플리팅, rollup-plugin-visualizer를 이용한 번들 크기 분석 및 최적화, 이미지 및 정적 자산의 지연 로딩/최적화 등을 도입하여 초기 로딩 시간을 단축하십시오.

2. 핵심 src 코드 리뷰 (성능, 타입스크립트, 코드 품질, 리팩토링)

제공된 diff 중 src 디렉토리 내 .ts.tsx 파일을 중심으로 다음과 같은 구체적인 개선 제안을 드립니다.

2.1. API 통신 및 데이터 관리

  1. API 응답 반환 값 일관성 확보 (src/apis/axios.ts, src/apis/*.ts)

    • 문제점: src/apis/lp.tscreateLp, deleteLp, updateLp 함수와 src/apis/comment.tscreateComment, updateComment, deleteComment 함수는 response.data (전체 응답 객체)를 반환하는 반면, 다른 API 함수들은 response.data.data (실제 페이로드)를 반환하는 등 일관성이 부족합니다. src/apis/axios.tsnormalizeResponse 인터셉터도 normalizedData 속성을 추가하지만 실제 사용되지 않아 혼란을 줄 수 있습니다.
    • 개선 제안: normalizeResponse 인터셉터가 response.data 자체를 response.data.data로 대체하도록 수정하여, 모든 API 함수들이 항상 실제 데이터 페이로드인 response.data를 최종 반환하도록 통일합니다.
      // src/apis/axios.ts (normalizeResponse 함수 수정)
      const normalizeResponse = (response: any) => {
        if (response.data && typeof response.data === 'object' && 'data' in response.data) {
          return {
            ...response,
            data: response.data.data, // response.data를 직접 교체
          };
        }
        return response;
      };
      // 이제 각 API 함수들은 `response.data`로 실제 페이로드를 받을 수 있습니다.
    • 기대 효과: API 함수들의 데이터 접근 방식 통일, 타입 안정성 향상, 코드 가독성 증대.
  2. Axios refreshToken 로직의 견고성 강화 (src/apis/axios.ts)

    • 문제점: refreshAccessToken 함수 내 JSON.parse(refreshToken) 시도 시, localStorage에 저장된 refreshTokennull이거나 유효하지 않은 JSON 문자열일 경우 런타임 오류가 발생할 수 있습니다.
    • 개선 제안: try-catch 블록으로 JSON.parse를 감싸서 파싱 실패 시 오류를 방지하고, 유효하지 않은 토큰으로 간주하여 강제로 로그아웃 처리하도록 합니다.
      // src/apis/axios.ts (refreshAccessToken 함수 내부 수정)
      const refreshAccessToken = async (): Promise<string | null> => {
        const refreshToken = localStorage.getItem(LOCAL_STORAGE_KEY.refreshToken);
        // ... (기존 null 체크)
      
        let parsedRefreshToken: string;
        try {
          parsedRefreshToken = JSON.parse(refreshToken);
        } catch (e) {
          console.error('Invalid refresh token in localStorage, logging out:', e);
          useAuthStore.getState().logout();
          window.location.href = '/login';
          return null;
        }
        // ... (나머지 refreshAccessToken 로직)
      };
    • 기대 효과: 애플리케이션의 안정성 향상, 잘못된 토큰 처리 시 일관된 사용자 경험 제공.
  3. useAuth Hook의 초기 로딩 및 데이터 상태 최적화 (src/hooks/auth/useAuth.ts)

    • 문제점: useAuth 훅이 getUserMe 쿼리를 실행하기 전까지 usernull이고 isLoggedInfalse 상태를 유지하여, 로그인 상태임에도 잠시 "로그아웃된" UI가 보이거나 데이터 깜빡임이 발생할 수 있습니다. isFetching 전역 변수도 중복 요청 문제를 일으킬 수 있습니다.
    • 개선 제안: useAuth 훅에서 전역 isFetching 변수를 제거하고, useQueryinitialData 또는 placeholderData 옵션을 활용하여 useAuthStore의 현재 userisLoggedIn 상태를 쿼리의 초기 데이터로 제공합니다. enabled: hasTokenInStorage() 조건도 추가하여 토큰이 있을 때만 쿼리가 실행되도록 합니다.
    • 기대 효과: 초기 로딩 시 깜빡임 현상 감소, 사용자에게 더 부드러운 전환 경험 제공, react-query의 강력한 캐싱 및 중복 요청 방지 기능 활용.
  4. useLpDetail Hook 활성화 조건 추가 (src/hooks/lp/useLpDetail.ts)

    • 문제점: useParams로부터 lpIdstring | undefined로 넘어오며, Number(lpId)lpIdundefined일 때 NaN을 생성하여 불필요한 API 호출을 시도할 수 있습니다.
    • 개선 제안: useQuery 옵션에 enabled: !!lpId && Number(lpId) > 0와 같은 조건을 추가하여 lpId가 유효한 숫자일 때만 쿼리가 실행되도록 수정합니다.
  5. useLps 훅의 initialPageParam 타입 추론 개선 (src/hooks/lp/useLps.ts)

    • 문제점: initialPageParam: undefined as number | undefined와 같이 as 키워드를 사용하여 타입 단언을 하고 있습니다. 이는 실제 타입과 다를 경우 런타임 오류로 이어질 수 있습니다.
    • 개선 제안: getLps 함수의 cursor 타입이 number | undefined를 허용한다면, initialPageParam: undefined,로 명시적으로 작성하는 것이 더 간결하고 안전합니다.
  6. useLikeLp 훅의 낙관적 업데이트 임시 id 생성 로직 개선 (src/hooks/lp/useLikeLp.ts)

    • 문제점: 낙관적 업데이트 시 새로운 Like 객체에 id: -1을 부여하는데, 여러 개의 낙관적 Like 객체가 생성될 경우 key 중복 경고를 유발하거나 예상치 못한 동작을 할 수 있습니다.
    • 개선 제안: 임시 ID를 생성할 때 Date.now() * -1 또는 uuid 라이브러리를 사용하여 고유한 음수 ID를 생성하는 것을 고려합니다.

2.2. 타입스크립트 및 코드 견고성

  1. useLocalStorage getItem 함수 타입 개선 (src/hooks/auth/useLocalStorage.ts)

    • 문제점: getItem 함수의 반환 타입이 명시되어 있지 않아 any로 추론됩니다.
    • 개선 제안: getItem<T = unknown>(): T | undefined와 같이 제네릭을 사용하여 타입 안정성을 높입니다.
  2. SignUpRequestBodyavatar 타입 개선 (src/types/auth/signup.ts)

    • 문제점: SignUpRequestBody 인터페이스에서 avatar?: File | null;로 정의되어 있지만, 실제 백엔드에는 업로드 후 반환된 이미지 URL 문자열이 전송될 가능성이 높습니다.
    • 개선 제안: avatar?: string | null;로 변경하여 API 호출 시 전달될 데이터 형태에 대한 정확한 타입을 정의합니다.
  3. Lp 인터페이스의 author 필드 필수 여부 명확화 (src/types/lp.ts)

    • 문제점: Lp 인터페이스에서 author?: Author;로 선택적 필드로 정의되어 있어, LP 상세 페이지와 같이 author 정보가 필수적인 컨텍스트에서 런타임 오류 가능성이 있습니다.
    • 개선 제안: LP 상세 조회 시 사용될 LpDetail 타입을 별도로 정의하고 author: Author;로 필수로 명시하여 특정 컨텍스트에서의 데이터 존재를 보장합니다.
      // src/types/lp.ts
      export interface Lp { /* ... */ }
      export interface LpDetail extends Lp {
        author: Author; // LpDetail에서는 author가 필수
      }
      export type LpDetailResponse = ApiResponse<LpDetail>;
  4. signUpSchema에 비밀번호 확인 로직 추가 (src/utils/validate.ts)

    • 문제점: 현재 signUpSchemapasswordpasswordConfirm이 일치하는지 검증하는 로직이 누락되어 있습니다.
    • 개선 제안: zod.refine() 메서드를 추가하여 클라이언트 측에서 비밀번호 일치 유효성 검사를 강화합니다.
      // src/utils/validate.ts
      export const signUpSchema = z
        .object({
          // ...
          password: passwordSchema,
          passwordConfirm: z.string().min(1, { message: '비밀번호를 다시 입력해주세요.' }),
          // ...
        })
        .refine((data) => data.password === data.passwordConfirm, {
          message: '비밀번호가 일치하지 않습니다.',
          path: ['passwordConfirm'],
        });

2.3. UI/UX 및 접근성 (Accessibility)

  1. alert() 대신 토스트/스낵바 알림 시스템 도입 (src/hooks/*.ts, src/pages/*.tsx 전반)

    • 문제점: 현재 alert() 함수가 사용자에게 피드백(성공, 실패 알림 등)을 주기 위해 광범위하게 사용되고 있습니다. alert()는 브라우저 기본 UI로 커스터마이징이 불가능하고, 사용자 경험을 저해하며, 비동기 작업 흐름을 끊을 수 있습니다.
    • 개선 제안: react-hot-toast 또는 유사한 비간섭적 토스트/스낵바 라이브러리를 도입하여 사용자에게 비동기 작업의 결과를 더 부드럽고 일관된 방식으로 알립니다. (예: src/App.tsx<Toaster /> 추가, 각 훅의 onSuccess/onError 및 컴포넌트에서 toast.success/toast.error 사용)
    • 적용 파일 예시: useUpdateUserMutation.ts, useDeleteLpMutation.ts, useUpdateLpMutation.ts, PostLpModal.tsx, GoogleLoginRedirectPage.tsx, LpDetailPage.tsx, CommentMenu.tsx, SignUpPage.tsxalert를 사용하는 모든 곳.
  2. vw/vh 단위 사용 재검토 및 대체 고려 (src/components/*.tsx, src/layout/*.tsx, src/pages/*.tsx 전반)

    • 문제점: Button, Input, Brand, LpImageDisplay, SidebarItem 등 많은 UI 컴포넌트에서 vw/vh 단위를 직접 사용하고 있습니다. 이는 매우 작은 화면이나 매우 큰 화면에서 UI 요소의 크기가 예상치 못하게 작아지거나 커져 사용자 경험과 접근성을 해칠 수 있습니다.
    • 개선 제안: 가능한 경우 rem 또는 em 단위를 사용하거나, Tailwind CSS의 반응형 접두사 (예: sm:text-sm, md:text-base)를 활용하여 각 브레이크포인트에 맞는 디자인을 적용합니다. min-w, min-h, max-w, max-h 등을 적극적으로 활용하여 요소의 최소/최대 크기를 제어합니다.
    • 기대 효과: 다양한 디바이스 및 화면 크기에서 일관되고 예측 가능한 UI를 제공하여 사용자 경험을 향상시키고, 디자인 시스템의 유연성을 높입니다.
  3. 클릭 가능한 div 요소의 접근성 강화 (src/components/avatarUpload/AvatarUpload.tsx, src/components/modal/Modal.tsx 등)

    • 문제점: AvatarUploadLpImageDisplay에서 div 요소에 onClick 핸들러를 사용하여 클릭 가능한 인터랙티브 요소를 구현했지만, 스크린 리더 사용자나 키보드 내비게이션 사용자에게는 접근성 문제가 발생할 수 있습니다. 닫기 버튼 (<X /> 아이콘)에도 aria-label이 없습니다.
    • 개선 제안: onClick이 있는 divrole="button" 속성을 추가하고, 키보드로도 활성화할 수 있도록 onKeyDown 이벤트 핸들러(Enter 및 Space 키)를 구현합니다. tabIndex={0}를 사용하여 포커스 가능하게 하고, aria-label 속성을 통해 스크린 리더에 기능을 명시적으로 알립니다.
      // src/components/avatarUpload/AvatarUpload.tsx (div onClick 수정 예시)
      <div
        onClick={handleClick}
        onKeyDown={(e) => { if (e.key === 'Enter' || e.key === ' ') handleClick(); }}
        role="button"
        tabIndex={isEditing ? 0 : -1}
        aria-label="아바타 변경"
        // ...
      >
        {/* ... */}
      </div>
      // src/components/modal/Modal.tsx (닫기 버튼)
      <X size={24} className="cursor-pointer" onClick={onClose} aria-label="모달 닫기" />
    • 기대 효과: 키보드 사용자 및 스크린 리더 사용자에게 향상된 접근성을 제공하여 애플리케이션의 사용성을 높입니다.
  4. NotFound 페이지 메시지 표준화 (src/pages/NotFound.tsx)

    • 문제점: <h1>너는 찾을 수 없는 페이지 야호~!</h1> 메시지는 비표준적이며, 사용자에게 혼란을 줄 수 있습니다.
    • 개선 제안: "페이지를 찾을 수 없습니다." 또는 "요청하신 페이지를 찾을 수 없습니다. 다른 페이지로 이동하거나 메인 페이지로 돌아가세요."와 같이 사용자에게 더 명확하고 전문적인 정보를 제공하는 메시지로 변경합니다.

2.4. 코드 유지보수성 및 리팩토링

  1. 인증 토큰 저장 방식 보안 강화 (핵심 보안 개선)

    • 문제점: accessTokenrefreshTokenlocalStorage에 저장하는 방식은 XSS(Cross-Site Scripting) 공격에 취약하여 공격자가 토큰을 탈취할 가능성이 높습니다. src/pages/auth/GoogleLoginRedirectPage.tsxsrc/store/authStore.ts에서 직접 localStorage를 사용하고 있습니다.
    • 개선 제안:
      • refreshTokenHttpOnlySecure 플래그가 설정된 쿠키에 저장하여 클라이언트 측 JavaScript에서 접근할 수 없도록 보호해야 합니다.
      • accessToken은 웹 애플리케이션의 **메모리(in-memory)**에 저장하고, 페이지 새로고침 시에는 refreshToken을 사용하여 새 accessToken을 발급받는 방식으로 구현하는 것이 가장 안전합니다.
    • 중요성: 이는 프로덕션 환경에서 반드시 고려해야 할 보안상 매우 중요한 개선점입니다.
  2. 전역 localStorage 키 관리 중앙화 (src/apis/axios.ts, src/hooks/auth/useLocalStorage.ts 등)

    • 문제점: localStorage 키 ('accessToken', 'refreshToken')가 axios.ts에서는 LOCAL_STORAGE_KEY 객체로 정의되어 있지만, useLoginMutation.ts에서는 useLocalStorage 훅을 호출할 때 하드코딩된 문자열 리터럴로 사용되고 있습니다.
    • 개선 제안: LOCAL_STORAGE_KEY 객체를 별도의 상수 파일 (예: src/constants/localStorageKeys.ts)로 분리하고, 필요한 모든 곳에서 해당 상수를 임포트하여 사용합니다. 또한 GoogleLoginRedirectPage.tsx에서도 useLocalStorage 훅을 사용하여 토큰을 저장하도록 변경하여 로직의 일관성을 높입니다.
    • 기대 효과: 코드의 유지보수성 향상, 키 이름 변경에 따른 오류 방지.
  3. UserAvatar 컴포넌트 추출 (src/pages/lpDetail/components/LpHeader.tsx, src/pages/lpDetail/components/comments/CommentItem.tsx)

    • 문제점: LpHeader.tsxCommentItem.tsx에서 사용자 아바타를 렌더링하는 로직(comment.author.avatar ? <img /> : <div className="..."><User /></div>)이 동일하게 반복됩니다.
    • 개선 제안: 이 로직을 src/components/UserAvatar.tsx와 같은 별도의 재사용 가능한 컴포넌트로 추출하여 코드 중복을 제거하고 유지보수성을 높입니다.
  4. 날짜 형식화 헬퍼 함수 (formatDate) 사용 (src/pages/lpDetail/components/LpHeader.tsx, src/pages/lpDetail/components/comments/CommentHeader.tsx)

    • 문제점: new Date(createdAt).toLocaleDateString() 호출이 여러 곳에서 직접 반복됩니다.
    • 개선 제안: src/utils/date.ts와 같은 헬퍼 모듈에 formatDate 함수를 만들어 캐싱/재사용성을 높이고 날짜 형식의 일관성을 유지합니다.
      // src/utils/date.ts
      export const formatDate = (dateString: string): string => {
        if (!dateString) return '';
        return new Date(dateString).toLocaleDateString('ko-KR', { year: 'numeric', month: 'long', day: 'numeric' });
      };
  5. LpLikeSectionisLiked prop 활용 (src/pages/lpDetail/components/LpLikeSection.tsx)

    • 문제점: isLiked prop이 정의되어 있지만 주석 처리되어 실제 코드에서 사용되지 않습니다.
    • 개선 제안: Heart 아이콘의 fill 속성을 isLiked prop에 따라 조건부로 적용하여 좋아요 상태에 따른 명확한 시각적 피드백을 제공합니다.
      <Heart size={32} fill={isLiked ? 'currentColor' : 'none'} />
  6. PostLpModal에서 URL.revokeObjectURL 적용 (src/pages/post/PostLpModal.tsx)

    • 문제점: URL.createObjectURL(file)로 생성된 이미지 미리보기 URL은 사용이 끝났을 때 URL.revokeObjectURL()을 통해 명시적으로 해제하지 않으면 메모리 누수를 유발할 수 있습니다.
    • 개선 제안: useEffect의 cleanup 함수를 활용하여 컴포넌트 언마운트 시 또는 selectedFile이 변경되어 새로운 URL이 생성될 때 이전 URL을 해제하도록 구현합니다.
  7. memo 컴포넌트의 onClick 프롭 안정화 (src/components/navbar/NavBar.tsx, src/components/navbar/Brand.tsx, src/components/navbar/MenuButton.tsx)

    • 문제점: BrandMenuButton 컴포넌트가 React.memo로 최적화되어 있지만, NavBar 컴포넌트에서 이들에게 전달하는 onClick 프롭이 매 렌더링마다 새로운 함수 인스턴스를 생성하여 memo의 최적화 효과를 무력화할 수 있습니다.
    • 개선 제안: NavBar 컴포넌트 내에서 onClick 프롭으로 전달되는 함수들을 useCallback 훅으로 감싸서 메모이제이션합니다.
  8. AnimatedTag 컴포넌트 스타일 유연성 확보 (src/components/animation/Animation.tsx)

    • 문제점: AnimatedTag 컴포넌트 내부에서 w-full max-w-sm이라는 고정된 레이아웃 스타일을 적용하고 있습니다.
    • 개선 제안: 특정 레이아웃 스타일을 제거하고, 필요하면 className prop을 통해 상위 컴포넌트에서 전달받도록 하여 컴포넌트의 재사용성을 높입니다.
  9. useLoginForm 훅의 반환 값 최소화 (src/pages/auth/login/hooks/useLoginForm.ts)

    • 문제점: useLoginForm 훅에서 react-hook-form이 제공하는 많은 메서드를 반환하지만, 사용하는 컴포넌트에서는 일부만 사용하고 있습니다.
    • 개선 제안: 훅은 해당 훅을 사용하는 컴포넌트에 필요한 최소한의 값만 반환하도록 하여 훅의 API를 명확히 하고, 코드의 가독성을 높입니다.

2.5. 기타 개선/수정 사항

  • API 주석 통일: API 함수들의 주석을 좀 더 전문적이고 일관된 표현으로 통일하는 것을 고려합니다. (예: //lp 목록 조회 -> // Get LP List)
  • LpHeader.tsx 스타일 수정: className="w-[3vw] h-[3v와 같이 잘려 있는 부분을 h-[3vw]로 수정합니다.
  • console.log 대신 console.error: 에러 발생 시 catch 블록에서 console.error(error)를 사용하는 것이 에러 로깅의 시맨틱을 더 잘 나타냅니다.
  • LpCard.tsx alt 속성: <img> 태그의 alt="LP Thumbnail"을 동적으로 설정할 수 있도록 alt prop을 부모 컴포넌트로부터 받아서 적용하는 것이 좋습니다.

총평

전반적으로 매우 깔끔하고 체계적인 코드베이스입니다. 특히 react-query의 효과적인 활용과 타입스크립트 적용 방식은 매우 인상 깊습니다. 위에서 언급한 개선 제안들은 대부분 UX 개선, 보안 강화, 그리고 코드의 견고함을 더욱 높이는 방향에 초점을 맞추고 있으며, 현재 코드의 높은 품질을 더욱 발전시키는 데 기여할 것입니다.

수고 많으셨습니다!

Copy link
Copy Markdown
Collaborator

@woojo230 woojo230 left a comment

Choose a reason for hiding this comment

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

7주차도 고생하셨습니다!
쉽지 않은 내용이지만 반복해서 숙달하면 금방 익숙해 질 수 있을겁니다!

@wantkdd wantkdd merged commit dc4084c into main Nov 22, 2025
1 check passed
@wantkdd wantkdd deleted the wantkdd/week07 branch November 22, 2025 15:34
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.

2 participants