Skip to content

Conversation

@Insung-Jo
Copy link

@Insung-Jo Insung-Jo commented Jun 14, 2025

📌 변경 사항 개요

  • 로그인 폼 구현 했습니다.

✨ 요약

  • 로그인 폼 구현 했습니다.

📝 상세 내용

  • 핵심 코드에 대한 설명과 react-hook-form과 관련된 설명을 정리 했습니다.
  • BG-blue-disabled 커스텀 클래스 추가

loginValidation

검증 규칙 설명
required 필수 입력 여부를 검사합니다.
pattern 특정 정규식 패턴과 일치하는지 검사합니다.
minLength 입력된 문자열의 최소 길이를 제한합니다.
  email: {
    required: '이메일을 입력해 주세요.', // 필수 입력 여부
    pattern: { // 정규식 검증
      value: /^[^\s@]+@[^\s@]+\.[^\s@]+$/,
      message: '유효한 이메일 주소를 입력해주세요',
    },
  },
  password: {
    required: '비밀번호를 입력해 주세요.',
    minLength: { // 최소 길이 제한
      value: 8,
      message: '비밀번호는 최소 8자 이상이어야 합니다.',
    },
  },
}
  • input에 유효성 검사를 바로 집어넣지 않고 별도의 파일로 분리 했습니다.

useLoginSubmit

export function useLoginSubmit() {
  const { login } = useAuth()
  const router = useRouter()

  async function handleSubmit(data: LoginRequest) {
    try {
      await login(data)
      toast.success('로그인 성공')
      router.push('/mydashboard')
    } catch (e: unknown) {
      if (axios.isAxiosError(e)) {
        const message = e.response?.data?.message
        toast.error(message ?? '로그인 실패')
      } else {
        toast.error('알 수 없는 에러 발생')
      }
    }
  }

  return { handleSubmit }
}
  • 로그인 API 호출 및 예외 처리를 훅으로 분리 했습니다.
  • 에러 메세지의 경우는 서버에서 보내주는 에러 메세지를 토스트로 처리하고 메세지가 없을 경우에는 별도의 문구를 출력했습니다. (토스트는 세팅만 되어 있습니다 구현은 X)

LoginForm

부분 설명
useForm<LoginRequest>() 폼 전체를 관리하는 훅 (폼 상태, 값, 검증 등 모든 기능 시작점)
mode: 'onChange' 검증 시점 설정 (onChange, onBlur, onSubmit 등).
defaultValues 폼을 초기값 지정
handleSubmit 검증 후 제출 콜백 실행.
formState 폼의 상태를 담고 있는 객체 (에러, 제출 중 여부 등 포함)
errors 각 필드의 검증 에러 정보.
isSubmitting 제출 중 여부.
control 고급 기능에서 폼을 세밀하게 제어할 때 사용 (ex: useWatch, Controller 등)
 const {
    register,
    handleSubmit,
    formState: { errors, isSubmitting },
    control,
  } = useForm<LoginRequest>({
    mode: 'onChange',
    defaultValues: {
      email: '',
      password: '',
    },
  })

  const { submit } = useLoginSubmit()
  const watch = useWatch({ control }) // 실시간으로 폼 필드 값을 감시 하는 훅
  const allFilled = watch.email?.trim() !== '' && watch.password?.trim() !== '' 
  const showEmailError = !!errors.email
  const showPasswordError = !!errors.password
  • react-hook-form에 있는 속성을 이용하여 구현을 진행했습니다.
  • 궁금한 사항이 있을 경우 코드 리뷰 부탁드립니다!

🔗 관련 이슈

#47

🖼️ 스크린샷

image
image

✅ 체크리스트

  • 브랜치 네이밍 컨벤션을 준수했습니다
  • 커밋 컨벤션을 준수했습니다
  • 코드가 프로젝트의 스타일 가이드라인을 준수합니다

💡 참고 사항

  • 중복 제출을 최대한 막아보려고 했지만... 실패
  • 추후 리펙토링 작업 때 다시 시도 해보려고 합니다.
  • 페이지에 해당 폼을 적용했습니다! 머지 되고 나면 API 잘 동작하는 지 테스트 해보시고 안되면 말씀해주세요!

Summary by CodeRabbit

  • 신규 기능

    • 로그인 페이지와 로그인 폼이 추가되었습니다.
    • 이메일과 비밀번호 입력 필드가 포함된 로그인 폼이 제공되며, 입력값 유효성 검사가 적용됩니다.
    • 로그인 성공 시 대시보드로 이동하고, 알림 토스트가 표시됩니다.
  • 버그 수정

    • 로그아웃 시 저장된 인증 정보가 완전히 삭제되도록 개선되었습니다.
  • 스타일

    • 비활성화 상태의 버튼에 사용할 수 있는 .BG-blue-disabled CSS 클래스가 추가되었습니다.
  • 기타

    • 로그인 폼에 새로운 입력 필드(라벨: "안녕")가 추가되었습니다.

@Insung-Jo Insung-Jo added this to the 2차 구현 기간 milestone Jun 14, 2025
@Insung-Jo Insung-Jo self-assigned this Jun 14, 2025
@Insung-Jo Insung-Jo added ✨Feat 기능 개발 🎨Style UI, 스타일 관련 수정 labels Jun 14, 2025
@coderabbitai
Copy link

coderabbitai bot commented Jun 14, 2025

Walkthrough

로그인 페이지와 관련된 새로운 컴포넌트 및 훅이 도입되었습니다. 로그인 폼의 입력값 검증을 위한 스키마와 제출 로직이 추가되었으며, 로그아웃 시 인증 상태의 영구 저장소도 함께 초기화됩니다. 또한, 비활성화된 버튼 스타일을 위한 CSS 클래스가 추가되었습니다.

Changes

파일/경로 요약 변경 내용 요약
src/app/(auth)/login/page.tsx Login 컴포넌트 신설, LoginForm 렌더링
src/app/features/auth/components/LoginForm.tsx LoginForm 컴포넌트 신설, 입력값 제어 및 검증, 제출 버튼 상태 관리
src/app/features/auth/hooks/useLoginSubmit.ts useLoginSubmit 커스텀 훅 신설, 로그인 제출 로직 및 예외 처리
src/app/features/auth/schemas/loginValidation.ts loginValidation 검증 스키마 신설, 이메일/비밀번호 규칙 정의
src/app/features/auth/hooks/useAuth.ts 로그아웃 시 useAuthStore.persist.clearStorage() 호출 추가
src/app/(auth)/signin/page.tsx 폼에 "안녕" 입력 필드 추가
src/app/globals.css .BG-blue-disabled 비활성화 버튼용 CSS 클래스 추가

Sequence Diagram(s)

sequenceDiagram
    participant User
    participant LoginForm
    participant useLoginSubmit
    participant useAuth
    participant Router
    participant Toast

    User->>LoginForm: 이메일/비밀번호 입력 후 제출
    LoginForm->>useLoginSubmit: submit({ email, password })
    useLoginSubmit->>useAuth: login(data)
    alt 로그인 성공
        useLoginSubmit->>Toast: 성공 메시지 표시
        useLoginSubmit->>Router: /mydashboard로 이동
    else 로그인 실패
        useLoginSubmit->>Toast: 에러 메시지 표시
    end
Loading

Possibly related PRs

  • CoPlay-FE/coplan#29: 인증 로직과 상태 관리(useAuth, useAuthStore)를 도입하며, 본 PR의 로그인 폼 및 제출 훅이 이 구조를 기반으로 구현됨.
  • CoPlay-FE/coplan#44: 재사용 가능한 Input 컴포넌트 및 에러 스타일링을 도입, 본 PR의 LoginForm에서 해당 컴포넌트 활용 가능성이 높음.

Suggested reviewers

  • dkslel1225
  • LeeCh0129

Poem

로그인 폼이 토끼처럼 깡총 등장,
검증 스키마로 입력값을 단단히 무장!
제출 버튼은 비활성화도 멋지게,
성공하면 대시보드로 폴짝 뛰네.
🐇 로그인 여정, 이제 한층 더 안전하게!

Warning

There were issues while running some tools. Please review the errors and either fix the tool's configuration or disable the tool if it's a critical failure.

🔧 ESLint

If the error stems from missing dependencies, add them to the package.json file. For unrecoverable errors (e.g., due to private dependencies), disable the tool in the CodeRabbit configuration.

npm error Exit handler never called!
npm error This is an error with npm itself. Please report this error at:
npm error https://github.com/npm/cli/issues
npm error A complete log of this run can be found in: /.npm/_logs/2025-06-15T08_31_37_799Z-debug-0.log


📜 Recent review details

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

📥 Commits

Reviewing files that changed from the base of the PR and between b227c2a and b10a37a.

📒 Files selected for processing (1)
  • src/app/features/auth/components/LoginForm.tsx (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • src/app/features/auth/components/LoginForm.tsx
✨ Finishing Touches
  • 📝 Generate Docstrings

🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

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

Support

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

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

CodeRabbit Commands (Invoked using PR comments)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai full review to do a full review from scratch and review all the files again.
  • @coderabbitai summary to regenerate the summary of the PR.
  • @coderabbitai generate docstrings to generate docstrings for this PR.
  • @coderabbitai generate sequence diagram to generate a sequence diagram of the changes in this PR.
  • @coderabbitai 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.

@coderabbitai
Copy link

coderabbitai bot commented Jun 14, 2025

Walkthrough

로그인 페이지와 관련된 주요 컴포넌트 및 훅이 새롭게 추가되었습니다. 로그인 폼의 유효성 검사, 제출 처리, 상태 관리, 스타일링 등이 구현되었으며, 로그아웃 시 영속 저장소도 초기화하도록 수정되었습니다. 로그인 폼의 입력 필드와 제출 버튼의 상태가 동적으로 반영됩니다.

Changes

파일/경로 변경 요약
src/app/(auth)/login/page.tsx Login 컴포넌트 추가: LoginForm 렌더링, 로그인 페이지 UI 진입점
src/app/features/auth/components/LoginForm.tsx LoginForm 컴포넌트 추가: 이메일/비밀번호 입력, 유효성 검사, 제출 버튼 상태 관리
src/app/features/auth/hooks/useLoginSubmit.ts useLoginSubmit 훅 추가: 로그인 제출 처리, 성공/실패 토스트, 라우팅
src/app/features/auth/schemas/loginValidation.ts loginValidation 스키마 추가: 이메일/비밀번호 유효성 검사 규칙 정의
src/app/features/auth/hooks/useAuth.ts 로그아웃 시 persist.clearStorage() 호출 추가로 영속 저장소도 초기화
src/app/globals.css .BG-blue-disabled 클래스 추가: 비활성화 버튼 스타일링
src/app/(auth)/signin/page.tsx 폼에 "안녕" 레이블의 텍스트 입력 필드 추가

Sequence Diagram(s)

sequenceDiagram
    participant User
    participant LoginForm
    participant useLoginSubmit
    participant useAuth
    participant Router
    participant Toast

    User->>LoginForm: 이메일/비밀번호 입력
    LoginForm->>useLoginSubmit: submit({email, password})
    useLoginSubmit->>useAuth: login({email, password})
    useAuth-->>useLoginSubmit: 로그인 결과 반환
    alt 로그인 성공
        useLoginSubmit->>Toast: 성공 메시지 표시
        useLoginSubmit->>Router: /mydashboard로 이동
    else 로그인 실패
        useLoginSubmit->>Toast: 에러 메시지 표시
    end
Loading

Possibly related PRs

  • CoPlay-FE/coplan#44: Input 컴포넌트 구현 PR로, 본 PR의 LoginForm에서 사용되는 입력 필드와 직접적으로 연결됩니다.
  • CoPlay-FE/coplan#29: 인증 상태 관리 및 useAuth 훅 구현 PR로, 본 PR의 로그인 제출 및 상태 관리 로직과 밀접하게 관련되어 있습니다.

Suggested reviewers

  • dkslel1225
  • LeeCh0129

Poem

🐇
로그인 폼이 새로 왔어요,
이메일, 비번 꼭 넣어요!
버튼이 파랗게, 때론 흐리게,
성공하면 대시보드로 슝—
오늘도 코드는 깔끔하게,
로그인 여정, 함께해요!
🥕

Warning

There were issues while running some tools. Please review the errors and either fix the tool's configuration or disable the tool if it's a critical failure.

🔧 ESLint

If the error stems from missing dependencies, add them to the package.json file. For unrecoverable errors (e.g., due to private dependencies), disable the tool in the CodeRabbit configuration.

npm error Exit handler never called!
npm error This is an error with npm itself. Please report this error at:
npm error https://github.com/npm/cli/issues
npm error A complete log of this run can be found in: /.npm/_logs/2025-06-14T08_15_28_561Z-debug-0.log

✨ Finishing Touches
  • 📝 Generate Docstrings

🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

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

Support

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

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

CodeRabbit Commands (Invoked using PR comments)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai full review to do a full review from scratch and review all the files again.
  • @coderabbitai summary to regenerate the summary of the PR.
  • @coderabbitai generate docstrings to generate docstrings for this PR.
  • @coderabbitai generate sequence diagram to generate a sequence diagram of the changes in this PR.
  • @coderabbitai 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: 1

🧹 Nitpick comments (6)
src/app/features/auth/hooks/useAuth.ts (1)

24-27: logout을 비동기화하고 스토리지 초기화 오류 처리 권장

persist.clearStorage()는 내부적으로 localStorage.removeItem 등을 호출하므로 I/O 오류가 발생할 여지가 있습니다. 함수 자체를 async로 선언해 예외를 캐치하면 안정성이 증가합니다.

-  function logout() {
-    clearAuthState()
-    useAuthStore.persist.clearStorage()
-  }
+  async function logout() {
+    try {
+      clearAuthState()
+      await useAuthStore.persist.clearStorage()
+    } catch (e) {
+      // TODO: toast 또는 Sentry 로깅
+      console.error('로그아웃 중 스토리지 제거 실패', e)
+    }
+  }
src/app/features/auth/schemas/loginValidation.ts (1)

1-16: 검증 스키마 세분화 및 상수화 제안

현재 스키마로도 동작에는 문제가 없지만, 아래와 같이 가독성과 재사용성을 높일 수 있습니다.

 export const loginValidation = {
   email: {
     required: '이메일을 입력해 주세요.',
     pattern: {
       value: /^[^\s@]+@[^\s@]+\.[^\s@]+$/,
       message: '유효한 이메일 주소를 입력해주세요',
     },
+    maxLength: {
+      value: 50,
+      message: '이메일은 50자 이하로 입력해주세요.',
+    },
   },
   password: {
     required: '비밀번호를 입력해 주세요.',
     minLength: {
       value: 8,
       message: '비밀번호는 최소 8자 이상이어야 합니다.',
     },
+    maxLength: {
+      value: 30,
+      message: '비밀번호는 30자 이하로 입력해주세요.',
+    },
   },
 }
  • 상수(e.g., EMAIL_MAX_LENGTH)로 분리하면 여러 스키마에서 재사용 가능
  • 패스워드에 추가적인 정규식(영문·숫자 혼합 등)을 적용할지 검토해 보세요.
src/app/(auth)/login/page.tsx (1)

5-10: 불필요한 Fragment 제거로 간결화 가능

단일 컴포넌트만 반환하므로 React Fragment(<>...</>) 없이 바로 반환해도 됩니다.

 export default function Login() {
-  return (
-    <>
-      <LoginForm />
-    </>
-  )
+  return <LoginForm />
 }
src/app/features/auth/hooks/useLoginSubmit.ts (2)

12-24: 예외 로깅 및 메시지 보강을 권장합니다.

catch 블록에서 토스트만 띄우고 예외를 별도로 기록하지 않아 디버깅이 어려울 수 있습니다. 콘솔 출력 또는 Sentry·LogRocket 같은 모니터링 툴로 예외를 전달하는 로직을 추가하면 운영 중 문제 추적이 한결 수월합니다.

 } catch (e: unknown) {
   if (axios.isAxiosError(e)) {
     const message = e.response?.data?.message
     toast.error(message ?? '로그인 실패')
+    console.error('Login failed:', e) // 혹은 모니터링 서비스 전송
   } else {
     toast.error('알 수 없는 에러 발생')
+    console.error('Unknown login error:', e)
   }
 }

8-11: submit 함수를 useCallback으로 메모이제이션하면 재렌더 최적화에 도움이 됩니다.

훅을 사용하는 컴포넌트가 빈번히 재렌더될 때마다 submit 참조가 바뀌면, 이를 의존성으로 갖는 하위 컴포넌트에서 불필요한 렌더가 발생할 수 있습니다. 의존성이 고정이라면 한 번만 생성되도록 메모이제이션을 고려해 보세요.

 import { useAuth } from './useAuth'
+import { useCallback } from 'react'

 export function useLoginSubmit() {
   const { login } = useAuth()
   const router = useRouter()

-  async function submit(data: LoginRequest) {
+  const submit = useCallback(async (data: LoginRequest) => {
     ...
-  }
+  }, [login, router])
 
   return { submit }
 }

Also applies to: 27-28

src/app/features/auth/components/LoginForm.tsx (1)

26-29: allFilled 계산식을 간단·견고하게 개선할 수 있습니다.

현재 구현은 잘 동작하지만, 불리언 변환을 명시적으로 해 주면 가독성과 안정성이 향상됩니다.

-const allFilled = watch.email?.trim() !== '' && watch.password?.trim() !== ''
+const allFilled = !!watch.email?.trim() && !!watch.password?.trim()
📜 Review details

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

📥 Commits

Reviewing files that changed from the base of the PR and between 74597e5 and b227c2a.

📒 Files selected for processing (7)
  • src/app/(auth)/login/page.tsx (1 hunks)
  • src/app/(auth)/signin/page.tsx (1 hunks)
  • src/app/features/auth/components/LoginForm.tsx (1 hunks)
  • src/app/features/auth/hooks/useAuth.ts (2 hunks)
  • src/app/features/auth/hooks/useLoginSubmit.ts (1 hunks)
  • src/app/features/auth/schemas/loginValidation.ts (1 hunks)
  • src/app/globals.css (1 hunks)
🧰 Additional context used
🧬 Code Graph Analysis (3)
src/app/features/auth/hooks/useAuth.ts (1)
src/app/features/auth/store/useAuthStore.ts (1)
  • useAuthStore (5-20)
src/app/(auth)/login/page.tsx (1)
src/app/features/auth/components/LoginForm.tsx (1)
  • LoginForm (11-63)
src/app/features/auth/components/LoginForm.tsx (4)
src/app/features/auth/types/auth.type.ts (1)
  • LoginRequest (3-6)
src/app/features/auth/hooks/useLoginSubmit.ts (1)
  • useLoginSubmit (8-28)
src/app/features/auth/schemas/loginValidation.ts (1)
  • loginValidation (1-16)
src/app/shared/lib/cn.ts (1)
  • cn (4-6)
🔇 Additional comments (1)
src/app/globals.css (1)

25-27: 버튼 비활성 색상 대비 비율 확인 필요

#9FA6B2 배경에 text-white(≈ #FFFFFF) 조합은 WCAG AA 기준(4.5 : 1)을 충족하지 못할 가능성이 큽니다. 작은 글씨(※ 버튼 라벨 text-lg)에 적용될 때 접근성 경고가 발생할 수 있으니 실제 대비 비율을 확인하고 필요 시 더 어두운 색상으로 조정해 주세요.

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 (8)
src/app/globals.css (1)

25-27: 비활성화 색상에 다크 모드 대응이 없습니다

.BG-blue, .BG-gray 등 기존 유틸리티는 다크 모드를 함께 정의하고 있는데, .BG-blue-disabled 는 라이트 모드 색상만 지정되어 있습니다. 다크 모드일 때 버튼이 어두운 배경에서 충분한 대비를 갖지 못할 수 있으므로 아래처럼 다크 변형을 포함하는 것이 좋겠습니다.

-.BG-blue-disabled {
-  @apply cursor-not-allowed bg-[#9FA6B2];
-}
+.BG-blue-disabled {
+  @apply cursor-not-allowed bg-[#9FA6B2] dark:bg-[#4B5563];
+}
src/app/features/auth/schemas/loginValidation.ts (2)

1-8: 이메일 정규식 범위‧가독성 개선 제안

현 정규식은 간단하지만 RFC5322 를 충분히 커버하지 못하고, 유지보수 관점에서도 한눈에 해석하기 어렵습니다. zod · yup 같은 검증 라이브러리를 사용하거나, 최소한 정규식을 상수로 분리해 의도를 명확히 하면 좋겠습니다.

-      value: /^[^\s@]+@[^\s@]+\.[^\s@]+$/,
+      // RFC5322 간략 버전
+      value: /^[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Za-z]{2,}$/,

9-15: 패스워드 정책 상수화 및 재사용 고려

minLength: 8 이 하드코딩되어 있어 향후 정책 변경 시 여러 곳을 수정해야 할 수 있습니다. const PASSWORD_MIN = 8 형태로 상수화하거나 공통 validation util 로 분리하면 재사용성이 높아집니다.

src/app/(auth)/login/page.tsx (1)

5-10: 불필요한 Fragment 제거로 코드 간소화

루트가 단일 컴포넌트이므로 빈 fragment (<>...</>) 는 필요 없습니다.

-export default function Login() {
-  return (
-    <>
-      <LoginForm />
-    </>
-  )
-}
+export default function Login() {
+  return <LoginForm />
+}
src/app/features/auth/components/LoginForm.tsx (2)

25-30: useWatch 사용 방식 최적화 필요
useWatch로 전체 폼 값을 감시하면서 매 렌더마다 객체가 새로 생성됩니다. 이는 다른 상태가 변해도 로그인 폼이 불필요하게 재렌더링되는 원인이 될 수 있습니다.
필요한 필드만 감시하거나 useMemo로 계산값을 캐싱해 성능을 개선해 보세요.

- const watch = useWatch({ control })
- const allFilled = watch.email?.trim() !== '' && watch.password?.trim() !== ''
+ const { email = '', password = '' } = useWatch({
+   control,
+   name: ['email', 'password'],
+ }) ?? {}
+ const allFilled = email.trim() !== '' && password.trim() !== ''

43-47: autoComplete="off"current-password 권장
브라우저·패스워드 매니저가 비밀번호 저장/자동완성을 차단하지 않도록 표준 값인 current-password를 사용해 주세요.

- autoComplete="off"
+ autoComplete="current-password"
src/app/features/auth/hooks/useLoginSubmit.ts (2)

14-17: 성공 후 라우팅 시 replace 사용 고려
router.push는 히스토리에 로그인 페이지를 남겨 ‘뒤로가기’ 시 다시 로그인 페이지로 돌아가는 UX 를 유발합니다. 로그인은 단발성 페이지이므로 replace로 교체하는 편이 일반적입니다.

- router.push('/mydashboard')
+ router.replace('/mydashboard')

18-24: 에러 메시지 파싱 로직 안전성 강화
e.response?.data 구조가 API 스펙 변경으로 문자열·배열 등이 될 경우 data.message 접근에서 런타임 오류가 발생할 수 있습니다. 타입 가드 후 메시지를 문자열로 강제 변환하거나 기본 메시지로 대체하는 방어 코드가 필요합니다.

- const message = e.response?.data?.message
+ const message =
+   typeof e.response?.data === 'object' && 'message' in (e.response?.data ?? {})
+     ? String((e.response?.data as Record<string, unknown>).message)
+     : undefined
📜 Review details

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

📥 Commits

Reviewing files that changed from the base of the PR and between 74597e5 and b227c2a.

📒 Files selected for processing (7)
  • src/app/(auth)/login/page.tsx (1 hunks)
  • src/app/(auth)/signin/page.tsx (1 hunks)
  • src/app/features/auth/components/LoginForm.tsx (1 hunks)
  • src/app/features/auth/hooks/useAuth.ts (2 hunks)
  • src/app/features/auth/hooks/useLoginSubmit.ts (1 hunks)
  • src/app/features/auth/schemas/loginValidation.ts (1 hunks)
  • src/app/globals.css (1 hunks)
🧰 Additional context used
🧬 Code Graph Analysis (2)
src/app/(auth)/login/page.tsx (1)
src/app/features/auth/components/LoginForm.tsx (1)
  • LoginForm (11-63)
src/app/features/auth/hooks/useAuth.ts (1)
src/app/features/auth/store/useAuthStore.ts (1)
  • useAuthStore (5-20)
🔇 Additional comments (1)
src/app/features/auth/hooks/useAuth.ts (1)

24-27: persist 객체 존재 여부 확인 필요

useAuthStore.persistzustand/middleware 가 정상 적용돼야만 존재합니다. 미들웨어가 제거되거나 이름이 변경되면 런타임 오류가 발생합니다. 안전하게 optional chaining 을 사용하거나 예외 처리를 권장드립니다.

-    useAuthStore.persist.clearStorage()
+    useAuthStore.persist?.clearStorage()

Copy link
Contributor

@dkslel1225 dkslel1225 left a comment

Choose a reason for hiding this comment

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

폼 구현 고생하셨습니다! 설명 덕분에 수월하게 읽을수 있었습니당⛄️

Copy link
Contributor

@yuj2n yuj2n left a comment

Choose a reason for hiding this comment

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

인성님 로그인 폼 구현 수고하셨습니다~
이제 로그인으로 사용자 정보 받아오면 되는 걸까용?!

@Insung-Jo
Copy link
Author

네네 해당 PR 머지 완료되면 가능합니다! api 동작이랑 사용자 정보가 zustand에 저장되는 거 확인 했고 만약 문제 있으면 편하게 말씀해주시면 될 거 같습니다!

@Insung-Jo Insung-Jo merged commit 0554e17 into develop Jun 15, 2025
2 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

✨Feat 기능 개발 🎨Style UI, 스타일 관련 수정

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants