Skip to content

Conversation

@Insung-Jo
Copy link

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

📌 변경 사항 개요

  • 로그인 페이지과 동시에 관련된 로직을 개선 했습니다!
  • 해당 PR은 다른 PR 머지 이후 머지 할 예정입니다.

✨ 요약

  • 로그인 페이지 구현
  • 로그인 로직 axios + try/catch -> react-qurey 로 변경
  • useAuth 로직 변경

📝 상세 내용

  • 글로벌 스타일 Text-violet이 추가 되었습니다!

useAuth

  • useAuthreact-qurey를 사용하게 되면서 상태만 관리하도록 변경하였습니다. (기존에는 api 호출도 useAuth에 포함되어 있었습니다.)
// 변경된 부분
  function updateAuthState(response: {
    accessToken: string
    user: User
  }) {
    const { accessToken, user } = response

    if (!accessToken || !user) {
      throw new Error('유효하지 않은 응답입니다.')
    }

    setAccessToken(accessToken)
    setUser(user)
  }

// 회원 가입 페이지 작성 시 변경 예정
  async function signup(data: SignupRequest) { 
    await signupApi(data)
  }

useLoginSubmit -> useLoginMutaion

  • 기존 axios + try/catch를 사용한 부분을 react-qurey를 사용하면서 파일명도 변경 되었습니다.
옵션명 설명
mutationFn 비동기 작업을 실행하는 함수 (Promise를 반환, 내부에서 자동으로 await 처리)
onSuccess 성공 시 실행할 콜백
onError 실패 시 실행할 콜백
export function useLoginMutaion() {
  const router = useRouter()
  const { updateAuthState } = useAuth()

  return useMutation({
    mutationFn: login,
    onSuccess: async (response) => {
      updateAuthState(response)
      toast.success('로그인 성공')
      await new Promise((resolve) => setTimeout(resolve, 400)) 
      router.push('/mydashboard')
    },
    onError: (error: unknown) => {
      if (axios.isAxiosError(error)) {
        const message = error.response?.data?.message
        toast.error(message ?? '로그인 실패')
      } else {
        toast.error('알 수 없는 에러 발생')
      }
    },
  })
  • await new Promise((resolve) => setTimeout(resolve, 400)) 이 부분은 테스트로 토스트를 사용 했을 때 보이기도 전에 페이지 이동으로 인해 보이지 않았던 현상이 있었기 때문에 약간의 딜레이를 추가했습니다.

🔗 관련 이슈

#58

🖼️ 스크린샷

White

image

Dark

image

로그인 시

image

✅ 체크리스트

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

💡 참고 사항

  • 어제 브랜치를 생성하다가 브랜치 소스를 잘못 지정하여 브랜치를 삭제해보았지만... 유령 브랜치.. 이러한 이유로 브랜치명을 login_v2로 만들어서 작업했습니다 흑흑

Summary by CodeRabbit

  • 신규 기능

    • 로그인 처리를 위한 커스텀 훅(useLoginMutation)이 추가되었습니다.
    • 로그인 레이아웃(DashboardLayout)이 도입되어 인증 페이지의 UI가 개선되었습니다.
    • 로그인 페이지 상단에 로고와 환영 메시지가 추가되고, 하단에 회원가입 링크가 포함되었습니다.
    • 새로운 텍스트 색상 유틸리티 클래스(.Text-violet)가 추가되었습니다.
  • 버그 수정

    • 로그인 폼의 에러 표시 및 버튼 상태 관리가 개선되었습니다.
  • 리팩터링

    • 인증 상태 갱신 로직이 개선되어 내부 훅 구조가 변경되었습니다.
    • 불필요한 훅(useLoginSubmit)이 제거되었습니다.
    • 일부 import 순서가 정리되었습니다.

@Insung-Jo Insung-Jo added this to the 2차 구현 기간 milestone Jun 17, 2025
@Insung-Jo Insung-Jo self-assigned this Jun 17, 2025
@Insung-Jo Insung-Jo added ✨Feat 기능 개발 🎨Style UI, 스타일 관련 수정 🗑️Remove 불필요한 코드/파일 제거 ♻️Refactor 리팩토링 labels Jun 17, 2025
@coderabbitai
Copy link

coderabbitai bot commented Jun 17, 2025

"""

Walkthrough

로그인 플로우와 레이아웃 구조가 전면적으로 리팩토링되었습니다. 로그인 관련 커스텀 훅이 삭제되고, React Query 기반의 useLoginMutation 훅이 도입되었습니다. 로그인 폼과 레이아웃이 개선되었으며, 인증 상태 관리 방식이 변경되고, 새로운 스타일 유틸리티 클래스가 추가되었습니다.

Changes

파일/경로 요약 변경 내용 요약
src/app/(auth)/layout.tsx DashboardLayout 컴포넌트 신설, 중앙 정렬 및 고정 폭 레이아웃 구현
src/app/(auth)/login/page.tsx 마운트 체크 추가, AuthLogo 및 회원가입 링크 추가, UI 개선
src/app/features/auth/components/LoginForm.tsx useLoginSubmituseLoginMutation 훅 교체, 상태/에러 처리 단순화, 버튼 상태 개선
src/app/features/auth/hooks/useLoginMutation.ts React Query 기반의 로그인용 커스텀 훅 신규 추가
src/app/features/auth/hooks/useLoginSubmit.ts 로그인 제출용 커스텀 훅 파일 삭제
src/app/features/auth/hooks/useAuth.ts login 함수 삭제, updateAuthState 함수 도입, 인증 상태 갱신 방식 변경
src/app/features/auth/api/authApi.ts import 순서만 변경, 로직 변화 없음
src/app/globals.css .Text-violet 텍스트 색상 유틸리티 클래스 추가

Sequence Diagram(s)

sequenceDiagram
    participant User
    participant LoginForm
    participant useLoginMutation
    participant login API
    participant useAuth
    participant Router

    User->>LoginForm: 로그인 폼 제출
    LoginForm->>useLoginMutation: loginMutate(form data)
    useLoginMutation->>login API: 로그인 요청
    login API-->>useLoginMutation: 응답 (accessToken, user)
    useLoginMutation->>useAuth: updateAuthState(response)
    useLoginMutation->>LoginForm: 성공 토스트 표시
    useLoginMutation->>Router: /mydashboard로 이동
Loading

Possibly related PRs

  • CoPlay-FE/coplan#46: DashboardLayoutAuthLogo 컴포넌트 도입, 본 PR의 레이아웃/브랜딩 개선과 직접 연관됨.
  • CoPlay-FE/coplan#29: 기존 useAuth 훅 초기 구현, 본 PR에서 해당 훅의 로그인 함수 제거 및 상태 갱신 함수 도입으로 직접 연관됨.
  • CoPlay-FE/coplan#52: 기존 로그인 폼 및 useLoginSubmit 훅 구현, 본 PR에서 해당 훅이 삭제되고 대체됨.

Suggested reviewers

  • dkslel1225
  • yuj2n

Poem

🐇
로그인 흐름이 새로워졌네,
토스트 알림에 기쁨이 번져가네.
보라빛 텍스트 살랑살랑,
대시보드로 hop-hop 달려가네.
중앙 레이아웃에 토끼도 미소,
새 훅과 함께 시작하는 새 아침!

"""

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-17T08_33_43_615Z-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 fdbd6c9 and f4bdea9.

📒 Files selected for processing (1)
  • src/app/features/auth/hooks/useLoginMutation.ts (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • src/app/features/auth/hooks/useLoginMutation.ts
✨ 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: 6

🧹 Nitpick comments (7)
src/app/globals.css (1)

70-72: 다크 모드 대비 색상 지정 누락

.Text-violet 클래스는 라이트 모드(#228DFF)만 지정되어 있어 다크 모드에서 동일한 색상을 유지하지 못합니다. 다른 텍스트 유틸리티(Text-black, Text-gray 등)는 dark: 변수를 함께 사용하니 일관성을 맞춰 주세요.

 .Text-violet {
-  @apply text-[#228DFF];
+  @apply text-[#228DFF] dark:text-[#228DFF];
 }
src/app/(auth)/layout.tsx (1)

1-5: 컴포넌트 명칭 혼동 가능성

(auth)/layout.tsx에 위치하지만 컴포넌트명이 DashboardLayout입니다. 인증 레이아웃이라는 의도가 드러나지 않으니 AuthLayout과 같이 폴더 구조와 맞춰주면 가독성이 높아집니다.

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

9-13: 마운트 체크 필요성 재검토

SSR → CSR hydration 불일치(FOUC) 방지 목적이라면 OK입니다. 다만 본 컴포넌트 내부에서는 window 접근이 없으므로, AuthLogo 내부 useTheme로 인한 깜빡임만 해결하려는 것이라면 AuthLogo에서 mounted 처리하거나 suppressHydrationWarning 속성을 사용하는 방법도 고려해 보세요.

src/app/features/auth/hooks/useLoginMutaion.ts (2)

18-20: 토스트 표시 지연 로직 개선

setTimeout으로 임의 지연을 두면 테스트 코드나 사용자 네트워크 환경에 따라 UX 가 달라집니다. toast.success의 Promise 반환값 또는 react-query onSettled 에서 라우팅하는 방식이 더 의도에 맞습니다.


22-27: Axios 에러 메시지 경로 불안정

error.response?.data?.message 경로가 백엔드 구조 변경 시 깨질 수 있습니다. 스키마가 보장되지 않으면 fallback 을 조금 더 구체화하거나 i18n 키를 사용하세요.

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

51-58: 클래스 토글 로직 간결화 가능

isValid && !isSubmitting && !isPending 조건을 두 곳에서 각각 사용하고 있어 중복됩니다. const disabled = !isValid || isSubmitting || isPending 처럼 변수로 뽑아 재사용하면 가독성과 유지보수성이 좋아집니다.

src/app/features/auth/hooks/useAuth.ts (1)

10-19: updateAuthState 메모이제이션 고려

updateAuthState 가 컴포넌트마다 새로 정의되어 전달되면, 이를 의존성으로 갖는 훅/컴포넌트들이 불필요하게 리렌더링될 수 있습니다. useCallback 으로 감싸거나 store 쪽에 메서드를 옮기는 방안을 검토해 주세요.

📜 Review details

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

📥 Commits

Reviewing files that changed from the base of the PR and between f7e0d13 and adbba55.

📒 Files selected for processing (8)
  • src/app/(auth)/layout.tsx (1 hunks)
  • src/app/(auth)/login/page.tsx (1 hunks)
  • src/app/features/auth/api/authApi.ts (1 hunks)
  • src/app/features/auth/components/LoginForm.tsx (3 hunks)
  • src/app/features/auth/hooks/useAuth.ts (2 hunks)
  • src/app/features/auth/hooks/useLoginMutaion.ts (1 hunks)
  • src/app/features/auth/hooks/useLoginSubmit.ts (0 hunks)
  • src/app/globals.css (1 hunks)
💤 Files with no reviewable changes (1)
  • src/app/features/auth/hooks/useLoginSubmit.ts
🧰 Additional context used
🧬 Code Graph Analysis (4)
src/app/(auth)/login/page.tsx (2)
src/app/features/auth/components/AuthLogo.tsx (1)
  • AuthLogo (11-30)
src/app/features/auth/components/LoginForm.tsx (1)
  • LoginForm (11-63)
src/app/features/auth/hooks/useLoginMutaion.ts (2)
src/app/features/auth/hooks/useAuth.ts (1)
  • useAuth (7-35)
src/app/features/auth/api/authApi.ts (1)
  • login (7-10)
src/app/features/auth/components/LoginForm.tsx (3)
src/app/features/auth/hooks/useLoginMutaion.ts (1)
  • useLoginMutaion (9-30)
src/app/features/auth/schemas/loginValidation.ts (1)
  • loginValidation (1-16)
src/app/shared/lib/cn.ts (1)
  • cn (4-6)
src/app/features/auth/hooks/useAuth.ts (2)
src/app/features/auth/store/useAuthStore.ts (1)
  • useAuthStore (5-20)
src/app/shared/types/user.type.ts (1)
  • User (1-8)
🔇 Additional comments (3)
src/app/features/auth/api/authApi.ts (1)

4-5: 변경 사항 이상 없음

타입 import 순서만 조정되었습니다. 기능적 문제 없습니다.

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

24-25: react-query 버전에 따른 상태 플래그 확인 필요

useMutation 이 반환하는 상태 값은 v4 기준 isLoading, v5 기준 isPending 입니다. 프로젝트에서 사용하는 react-query 버전을 확인해 맞지 않으면 런타임 오류가 발생합니다.

const { mutate: loginMutate, isLoading } = useLoginMutation()

처럼 수정하거나 패키지 버전을 v5 이상으로 명시해 주세요.

src/app/features/auth/hooks/useAuth.ts (1)

25-28: 스토리지 초기화 비동기 여부 확인

useAuthStore.persist.clearStorage() 가 Promise 를 반환할 경우 await 없이 호출하면 제거 순서 보장이 안 됩니다. 반환 타입을 확인해 필요하면 await 처리 후 후속 로직(예: redirect) 을 수행하세요.

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

@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 (1)
src/app/features/auth/hooks/useLoginMutation.ts (1)

16-21: setTimeout-기반 대기는 컴포넌트 언마운트 시 메모리 누수를 유발할 수 있습니다
await new Promise 로 400 ms 대기하는 동안 해당 컴포넌트가 언마운트되면 불필요한 라우팅 시도가 발생할 수 있습니다. 토스트 기본 지속 시간을 활용하거나 router.push 직후 toast.successduration 옵션을 조정하는 방식이 더 안전합니다.

-      toast.success('로그인 성공')
-      await new Promise((resolve) => setTimeout(resolve, 400))
-      router.push('/mydashboard')
+      toast.success('로그인 성공', { duration: 400 })
+      router.push('/mydashboard')
📜 Review details

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

📥 Commits

Reviewing files that changed from the base of the PR and between adbba55 and fdbd6c9.

📒 Files selected for processing (2)
  • src/app/features/auth/components/LoginForm.tsx (3 hunks)
  • src/app/features/auth/hooks/useLoginMutation.ts (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • src/app/features/auth/components/LoginForm.tsx
🧰 Additional context used
🧬 Code Graph Analysis (1)
src/app/features/auth/hooks/useLoginMutation.ts (3)
src/app/features/auth/hooks/useAuth.ts (1)
  • useAuth (7-35)
src/app/features/auth/types/auth.type.ts (2)
  • LoginResponse (8-11)
  • LoginRequest (3-6)
src/app/features/auth/api/authApi.ts (1)
  • login (7-10)

@LeeCh0129 LeeCh0129 requested review from LeeCh0129 June 17, 2025 08:58
Copy link

@LeeCh0129 LeeCh0129 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 Insung-Jo merged commit bd4eac1 into develop Jun 17, 2025
2 checks passed
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.

react-query 사용하여 로직 변경해주셨네용 👍
인성님 로그인 페이지 구현 수고많으셨습니다~

Comment on lines +1 to +35
import { showError, showSuccess } from '@lib/toast'
import { useMutation } from '@tanstack/react-query'
import type { AxiosError } from 'axios'
import axios from 'axios'
import { useRouter } from 'next/navigation'

import { login } from '../api/authApi'
import { LoginRequest, LoginResponse } from '../types/auth.type'
import { useAuth } from './useAuth'

export function useLoginMutation() {
const router = useRouter()
const { updateAuthState } = useAuth()

return useMutation<LoginResponse, AxiosError | Error, LoginRequest>({
mutationFn: login,
onSuccess: async (response) => {
updateAuthState(response)
showSuccess('로그인에 성공하셨습니다!')
await new Promise((resolve) => setTimeout(resolve, 400))
router.push('/mydashboard')
},
onError: (error) => {
if (axios.isAxiosError(error)) {
const severMessage = (
error.response?.data as { message?: string } | undefined
)?.message
const fallback = error.message || '로그인 실패'
showError(severMessage ?? fallback)
} else {
showError('알 수 없는 에러 발생')
}
},
})
}
Copy link
Contributor

Choose a reason for hiding this comment

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

react-query 사용하여 함수 작성해주셨군용!!
이전 코드 대비 어떤 장점이 있는 지 알 수 있을까용

Copy link
Author

Choose a reason for hiding this comment

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

우선 일관성의 목적으로 기존 try-catch에서 바꾸게 되었습니다! 현재 적용 해봤을 때 느낄 수 있는 장점은 우선 가독성 측면에서도 분리가 되어있어서 코드를 이해할 때 수월하고 react-qurey에서 쿼리의 실행 여부를 알 수 있는 isPending이 존재 하는데 그것을 이용해서 조건부 UI를 다룰 때 장점이 있었던 거 같습니다!

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

Labels

✨Feat 기능 개발 ♻️Refactor 리팩토링 🗑️Remove 불필요한 코드/파일 제거 🎨Style UI, 스타일 관련 수정

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants