Skip to content

Conversation

@yoorli
Copy link
Member

@yoorli yoorli commented Dec 23, 2025

📝 변경 사항

src/app/login/page.tsx

src/app/signup/page.tsx

  • import 경로를 components/pages/auth로 정리

src/components/pages/auth/auth-button/index.tsx

  • 로그인/회원가입 제출 버튼 컴포넌트 분리

src/components/pages/auth/fields/email-field/index.tsx

src/components/pages/auth/fields/nickname-field/index.tsx

src/components/pages/auth/fields/password-field/index.tsx

src/components/pages/auth/fields/termsAgreement-field/index.tsx

  • 입력 필드를 전용 컴포넌트로 분리
    • 힌트/에러 표시 로직을 getHintMessage 기반으로 통일

src/components/pages/auth/login/login-form/index.tsx

  • 로그인 실패 시 에러 메시지를 폼 하단에 노출하도록 UI 추가
    • useLogin()에서 반환하는 loginError를 표시

src/components/pages/auth/login/login-toast-effect/index.tsx

  • 로그인 진입 시 안내 토스트(쿼리 기반 등) 표시 흐름 유지

src/components/pages/auth/signup/signup-agreement-modal/index.tsx

  • 약관 동의 UI/모달 책임 분리

src/components/pages/login/index.ts

src/components/pages/signup/index.ts

  • 기존 login/signup pages export를 auth 구조로 정리(호환/정리 목적)

src/components/shared/form-input/index.tsx

  • FormInput 역할을 유지하면서 auth 필드 분리 구조에 맞게 연결부를 정리
    • 중복 확인 버튼/상태 UI가 붙는 경우를 고려한 컴포넌트 구조 개선

src/lib/auth/utils.ts

  • 입력 힌트/에러 노출 기준을 개선
    • isTouched 외에 isDirty도 반영하여 에러 표시 타이밍 보강

src/lib/schema/auth.ts

  • auth 스키마/유효성 검증 로직 정리

src/hooks/use-auth/use-auth-login/index.ts

  • 로그인 훅에서 에러 핸들링을 강화
    • loginError 상태를 관리하고, 에러 코드/메시지를 매핑하여 반환

src/components/pages/user/mypage/mypage-setting/index.tsx

  • 마이페이지 설정 화면에서 로그아웃/회원탈퇴 훅을 연결

src/hooks/use-auth/use-auth-refresh/index.ts

  • 임시 refresh 훅/액션 제거 및 export 정리
    • _temp 액션에서 refresh 제거
    • use-auth/index.ts에서 refresh export 제거
    • use-auth-refresh 파일 삭제

🔗 관련 이슈

#160


🧪 테스트 방법

  • 수동 테스트 검증(로컬 환경)
  • 유닛 테스트 검증
  • 통합 테스트 검증

📸 스크린샷 (선택)


📋 체크리스트

  • 관련 문서를 업데이트했습니다 (필요한 경우)
  • 테스트를 추가/수정했습니다 (필요한 경우)
  • Breaking change가 있다면 명시했습니다

💬 추가 코멘트


CodeRabbit Review는 자동으로 실행되지 않습니다.

Review를 실행하려면 comment에 아래와 같이 작성해주세요

@coderabbitai review

Summary by CodeRabbit

릴리스 노트

  • 새로운 기능

    • 회원가입 시 이메일과 닉네임 중복 확인 기능 추가
    • 비밀번호 입력 필드에 보기/숨기기 토글 버튼 추가
    • 로그인 시 더욱 명확한 오류 메시지 제공
  • 개선 사항

    • 로그아웃 후 홈페이지로 이동 (로그인 페이지 → 홈페이지)
    • 폼 유효성 검사 및 사용자 입력 처리 개선

✏️ Tip: You can customize this high-level summary in your review settings.

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Dec 23, 2025

Important

Review skipped

Auto reviews are disabled on this repository.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Walkthrough

인증 컴포넌트를 로그인/회원가입 모듈에서 통합 auth 모듈로 재구성하고, useRefresh 훅을 제거하며, 새로운 필드 컴포넌트 및 폼 로직을 추가하고, 바렐 파일을 통해 내보내기를 통합합니다.

Changes

Cohort / File(s) 변경 내용
인증 모듈 재구성
src/app/login/page.tsx, src/app/signup/page.tsx
LoginForm과 LoginToastEffect 임포트 경로를 @/components/pages/login에서 @/components/pages/auth로 변경; SignupForm 임포트 경로도 마찬가지로 업데이트
새로운 인증 필드 컴포넌트
src/components/pages/auth/fields/email-field/index.tsx, src/components/pages/auth/fields/nickname-field/index.tsx, src/components/pages/auth/fields/password-field/index.tsx, src/components/pages/auth/fields/termsAgreement-field/index.tsx, src/components/pages/auth/fields/index.ts
이메일 가용성 확인, 닉네임 가용성 확인, 비밀번호 표시/숨김 토글, 약관 동의 체크박스를 지원하는 새로운 필드 컴포넌트들 추가; 바렐 파일에서 모두 재내보내기
인증 제출 버튼 및 폼
src/components/pages/auth/auth-button/index.tsx, src/components/pages/auth/login/login-form/index.tsx, src/components/pages/auth/signup/signup-form/index.tsx, src/components/pages/auth/index.ts
AuthSubmitButton 컴포넌트 추가 (비활성화 상태: !canSubmit || isSubmitting || isPristine || !canSubmitAll); 로그인/회원가입 폼을 auth 모듈 아래로 이동하고 새로운 필드 컴포넌트 통합; 바렐 파일에서 재내보내기
기존 로그인/회원가입 컴포넌트 제거
src/components/pages/login/login-form/index.tsx, src/components/pages/login/index.ts, src/components/pages/signup/signup-form/index.tsx, src/components/pages/signup/index.ts
기존 로그인 폼, 회원가입 폼, 그리고 관련 바렐 파일에서 해당 내보내기 제거
인증 훅 변경
src/hooks/use-auth/use-auth-login/index.ts, src/hooks/use-auth/use-auth-logout/index.ts, src/hooks/use-auth/use-auth-refresh/index.ts, src/hooks/use-auth/index.ts
useLogin이 {handleLogin, loginError, clearLoginError} 객체 반환으로 변경 (이전: 함수만 반환); 로그인 오류 상태 관리 추가; 로그아웃 후 리다이렉션 경로를 '/login'에서 '/'로 변경; useRefresh 훅 제거
유틸리티 및 스키마 업데이트
src/lib/auth/utils.ts, src/lib/schema/auth.ts
getHintMessage 유틸 함수 추가; loginSchema의 password에 min(1) 검증 추가; signupSchema의 confirmPassword, termsAgreement 검증 개선
FormInput 리팩토링
src/components/shared/form-input/index.tsx
비밀번호 가시성 및 가용성 하위 컴포넌트 제거; inputProps에 iconButton 필드 지원 추가; InputPropsWithIcon 타입 정의
MyPage 설정
src/components/pages/user/mypage/mypage-setting/index.tsx
useLogout, useWithdraw 훅 추가 및 관련 버튼 onClick 핸들러를 직접 호출로 변경
임시 로그인 액션 제거
src/app/login/_temp/login-temp-actions.tsx
useRefresh 임포트 및 관련 MyPageActionButton 제거

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Possibly related PRs

Suggested reviewers

  • wooktori

Poem

🐰 인증의 나뭇가지 정리하네,
필드들 모아 한곳에 담고,
폼도 갈아입은 새 옷 입고,
useRefresh는 안녕, 새로운 길로!
바렐 통에 쏙 담아내니,
모듈의 정원이 더 예뻐졌네 🌿✨

Pre-merge checks and finishing touches

✅ Passed checks (3 passed)
Check name Status Explanation
Title check ✅ Passed PR 제목이 변경 사항의 주요 내용을 명확하게 요약하고 있습니다. 'form 구조 변경'과 '로그인 오류 처리 추가'는 원시 요약에 명시된 핵심 변경 사항들과 일치합니다.
Description check ✅ Passed PR 설명이 제공된 템플릿의 주요 섹션을 충분히 포함하고 있습니다. 변경 사항, 관련 이슈, 테스트 방법 및 체크리스트가 모두 작성되어 있습니다.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@github-actions
Copy link

github-actions bot commented Dec 23, 2025

🎭 Playwright Report

E2E Test가 성공적으로 완료되었습니다.

Test 요약 내용을 확인해주세요.

Status Build Log Updated (UTC)
✅ Ready View Build 2025-12-24 00:29:44

📊 Test Summary

  • ✅ Passed: 3
  • ❌ Failed: 0
  • ⏱️ Duration: 33.1s

📜 Test Details

✅ Passed Tests (3)
  • profile.test.ts (3)
    • [chromium] 존재하지 않는 프로필 페이지로 접속 시 404 redirect 되는 지 테스트
    • [firefox] 존재하지 않는 프로필 페이지로 접속 시 404 redirect 되는 지 테스트
    • [webkit] 존재하지 않는 프로필 페이지로 접속 시 404 redirect 되는 지 테스트

@github-actions
Copy link

github-actions bot commented Dec 23, 2025

🎨 Storybook Report

Story가 변경되었습니다

Chromatic에서 비주얼 변경사항을 확인하세요.

Status Storybook Build Log Updated (UTC)
✅ Ready View Storybook View Build 2025-12-24 00:29:44

@github-actions
Copy link

github-actions bot commented Dec 23, 2025

📊 Coverage Report

Status Build Log Updated (UTC)
✅ Ready View Build 2025-12-24 00:28:38

📉 #233main에 병합하면 coverage가 0.56% 감소합니다.

Coverage 요약

@@             Coverage Diff             @@
##             main     #233       +/-   ##
===========================================
- Coverage   38.80%   38.24%    -0.56%     
===========================================
  Files         170      175        +5     
  Lines        7496     7574       +78     
  Branches      325      330        +5     
===========================================
- Hits         2909     2897       -12     
+ Misses       4587     4677       +90     

영향받은 파일

파일 Coverage 변화
/home/runner/work/WeGo_FrontEnd/WeGo_FrontEnd/src/components/shared/form-input/index.tsx 35.63% (+7.71%) ⬆️

@github-actions
Copy link

github-actions bot commented Dec 23, 2025

🚀 PR Preview Report

Build가 성공적으로 완료되었습니다.

Preview에서 변경사항을 확인하세요.

Status Preview Build Log Updated (UTC)
✅ Ready Visit Preview View Logs 2025-12-24 00:30:05

@yoorli yoorli added the Ready For Review! 리뷰 받을 준비가 되었습니다. label Dec 23, 2025
Copy link
Member

@Chiman2937 Chiman2937 left a comment

Choose a reason for hiding this comment

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

수고하셨습니다~

Comment on lines +36 to +46
const isCommonErrorResponse = (e: unknown): e is CommonErrorResponse => {
if (!e || typeof e !== 'object') return false;

const obj = e as Record<string, unknown>;
return (
typeof obj.status === 'number' &&
typeof obj.detail === 'string' &&
typeof obj.errorCode === 'string' &&
typeof obj.instance === 'string'
);
};
Copy link
Member

Choose a reason for hiding this comment

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

아마 타입가드 때문에 만드신거같은데,
이부분은 제가 proxy 설정하면서 instanceof CommonErrorResponse 형태로 쓸 수 있게 만들어드릴게요!

console.error(error);
setLoginError('서버와 연결할 수 없습니다.');
}
return;
Copy link
Member

Choose a reason for hiding this comment

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

이 부분은 axios interceptor 설정에서 항상 CommonErrorResponse type으로 return 해주고 있어서 없어도 될 것 같네요~

@claudia99503
Copy link
Member

@coderabbitai review

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Dec 24, 2025

✅ Actions performed

Review triggered.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

Copy link
Contributor

@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 (3)
src/components/pages/auth/fields/email-field/index.tsx (1)

28-44: 중복 확인 버튼에서 중복된 속성을 제거하세요.

Line 35의 aria-disabled 속성은 이미 disabled 속성이 있을 때 중복됩니다. disabled 속성이 이미 버튼을 비활성화하고 스크린 리더에도 올바르게 전달되므로 aria-disabled는 제거해도 됩니다.

🔎 제안하는 수정
     <button
       className={cn(
         'text-text-xs-semibold absolute top-4 right-5 rounded-lg bg-gray-100 px-3 py-1 text-gray-800',
         disabled && '!cursor-not-allowed',
       )}
-      aria-disabled={disabled}
       aria-label='이메일 중복 확인'
       disabled={disabled}
       type='button'
       onClick={onClick}
     >
       중복 확인
     </button>
src/components/pages/auth/fields/password-field/index.tsx (1)

21-33: 비밀번호 표시/숨김 버튼의 접근성을 개선하세요.

Line 26의 tabIndex={-1}은 키보드 네비게이션에서 이 버튼을 제외합니다. 키보드만 사용하는 사용자는 비밀번호 표시/숨김 기능에 접근할 수 없게 됩니다. 접근성 향상을 위해 tabIndex={-1}을 제거하는 것을 권장합니다.

🔎 제안하는 수정
     <button
       className='absolute top-4 right-5 h-6 w-6'
       aria-label={isVisible ? '비밀번호 숨기기' : '비밀번호 보기'}
-      tabIndex={-1}
       type='button'
       onClick={onToggle}
     >
       <Icon id={isVisible ? 'visibility-true' : 'visibility-false'} className='text-gray-600' />
     </button>
src/components/pages/auth/fields/nickname-field/index.tsx (1)

27-43: aria-disableddisabled의 중복 사용에 대한 고려

현재 disabledaria-disabled가 동일한 값으로 설정되어 있습니다. 네이티브 disabled 속성이 적용되면 버튼이 이미 비활성화되어 aria-disabled가 중복됩니다.

만약 비활성화 상태에서도 버튼이 포커스 가능하게 하려면 disabled 대신 aria-disabled만 사용하고 onClick 핸들러에서 조건부로 동작을 막는 방식이 더 접근성에 좋습니다. 현재 구현도 기능적으로 문제는 없습니다.

📜 Review details

Configuration used: Path: .coderabbit.yml

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between c47b196 and 3ac2c80.

📒 Files selected for processing (26)
  • src/app/login/_temp/login-temp-actions.tsx
  • src/app/login/page.tsx
  • src/app/signup/page.tsx
  • src/components/pages/auth/auth-button/index.tsx
  • src/components/pages/auth/fields/email-field/index.tsx
  • src/components/pages/auth/fields/index.ts
  • src/components/pages/auth/fields/nickname-field/index.tsx
  • src/components/pages/auth/fields/password-field/index.tsx
  • src/components/pages/auth/fields/termsAgreement-field/index.tsx
  • src/components/pages/auth/index.ts
  • src/components/pages/auth/login/login-form/index.tsx
  • src/components/pages/auth/login/login-toast-effect/index.tsx
  • src/components/pages/auth/signup/signup-agreement-modal/index.tsx
  • src/components/pages/auth/signup/signup-form/index.tsx
  • src/components/pages/login/index.ts
  • src/components/pages/login/login-form/index.tsx
  • src/components/pages/signup/index.ts
  • src/components/pages/signup/signup-form/index.tsx
  • src/components/pages/user/mypage/mypage-setting/index.tsx
  • src/components/shared/form-input/index.tsx
  • src/hooks/use-auth/index.ts
  • src/hooks/use-auth/use-auth-login/index.ts
  • src/hooks/use-auth/use-auth-logout/index.ts
  • src/hooks/use-auth/use-auth-refresh/index.ts
  • src/lib/auth/utils.ts
  • src/lib/schema/auth.ts
💤 Files with no reviewable changes (6)
  • src/hooks/use-auth/use-auth-refresh/index.ts
  • src/components/pages/login/index.ts
  • src/components/pages/signup/signup-form/index.tsx
  • src/hooks/use-auth/index.ts
  • src/components/pages/signup/index.ts
  • src/components/pages/login/login-form/index.tsx
🧰 Additional context used
🧠 Learnings (2)
📚 Learning: 2025-12-17T09:40:44.719Z
Learnt from: HopeFullee
Repo: WeGo-Together/WeGo_FrontEnd PR: 205
File: src/components/pages/post-meetup/fields/cap-field/index.tsx:47-47
Timestamp: 2025-12-17T09:40:44.719Z
Learning: In TanStack Form with Zod validation, when `field.state.meta.isValid` is false, the `field.state.meta.errors` array is guaranteed to contain at least one error. Therefore, accessing `field.state.meta.errors[0]` within an `isInvalid` check (where isInvalid = field.state.meta.isTouched && !field.state.meta.isValid) is safe and doesn't require additional null/empty checks.

Applied to files:

  • src/lib/auth/utils.ts
📚 Learning: 2025-12-17T09:40:37.733Z
Learnt from: HopeFullee
Repo: WeGo-Together/WeGo_FrontEnd PR: 205
File: src/components/pages/post-meetup/fields/cap-field/index.tsx:47-47
Timestamp: 2025-12-17T09:40:37.733Z
Learning: In TanStack Form with Zod validation, when field.state.meta.isValid is false, field.state.meta.errors is guaranteed to have at least one entry. Therefore, in an isInvalid check defined as field.state.meta.isTouched && !field.state.meta.isValid, safely access field.state.meta.errors[0] without extra null/empty checks. This guideline applies to TSX form fields under src/components/pages (and similar forms using the same pattern).

Applied to files:

  • src/components/pages/auth/signup/signup-form/index.tsx
  • src/components/pages/auth/login/login-form/index.tsx
  • src/components/pages/auth/auth-button/index.tsx
  • src/components/pages/auth/fields/email-field/index.tsx
  • src/components/pages/user/mypage/mypage-setting/index.tsx
  • src/components/pages/auth/fields/password-field/index.tsx
  • src/components/pages/auth/fields/nickname-field/index.tsx
  • src/components/pages/auth/fields/termsAgreement-field/index.tsx
🧬 Code graph analysis (8)
src/components/pages/auth/signup/signup-form/index.tsx (6)
src/components/pages/auth/index.ts (1)
  • SignupForm (3-3)
src/hooks/use-auth/use-auth-availabilityCheck/index.ts (1)
  • useAvailabilityCheck (21-68)
src/api/index.ts (1)
  • API (22-22)
src/components/pages/auth/fields/email-field/index.tsx (1)
  • EmailField (46-98)
src/components/pages/auth/fields/index.ts (4)
  • EmailField (1-1)
  • NicknameField (2-2)
  • PasswordField (3-3)
  • TermsAgreementField (4-4)
src/components/pages/auth/auth-button/index.tsx (1)
  • AuthSubmitButton (11-23)
src/components/pages/auth/login/login-form/index.tsx (5)
src/hooks/use-auth/use-auth-login/index.ts (1)
  • useLogin (48-99)
src/lib/schema/auth.ts (1)
  • loginSchema (3-8)
src/components/pages/auth/fields/email-field/index.tsx (1)
  • EmailField (46-98)
src/components/pages/auth/fields/password-field/index.tsx (1)
  • PasswordField (35-66)
src/components/pages/auth/auth-button/index.tsx (1)
  • AuthSubmitButton (11-23)
src/components/pages/auth/fields/email-field/index.tsx (3)
src/lib/utils.ts (1)
  • cn (74-76)
src/lib/auth/utils.ts (1)
  • getHintMessage (3-13)
src/components/shared/form-input/index.tsx (1)
  • FormInput (31-87)
src/components/pages/user/mypage/mypage-setting/index.tsx (1)
src/components/pages/user/mypage/mypage-setting-button/index.tsx (1)
  • MyPageActionButton (23-25)
src/hooks/use-auth/use-auth-login/index.ts (3)
src/types/service/common.ts (1)
  • CommonErrorResponse (1-8)
src/hooks/use-auth/index.ts (1)
  • useLogin (1-1)
src/types/service/auth.ts (1)
  • LoginRequest (14-17)
src/components/pages/auth/fields/password-field/index.tsx (4)
src/components/icon/index.tsx (1)
  • Icon (53-59)
src/components/pages/auth/fields/index.ts (1)
  • PasswordField (3-3)
src/lib/auth/utils.ts (1)
  • getHintMessage (3-13)
src/components/shared/form-input/index.tsx (1)
  • FormInput (31-87)
src/components/pages/auth/fields/nickname-field/index.tsx (4)
src/lib/utils.ts (1)
  • cn (74-76)
src/components/pages/auth/fields/index.ts (1)
  • NicknameField (2-2)
src/lib/auth/utils.ts (1)
  • getHintMessage (3-13)
src/components/shared/form-input/index.tsx (1)
  • FormInput (31-87)
src/components/pages/auth/fields/termsAgreement-field/index.tsx (4)
src/components/pages/auth/fields/index.ts (1)
  • TermsAgreementField (4-4)
src/components/icon/index.tsx (1)
  • Icon (53-59)
src/lib/utils.ts (1)
  • cn (74-76)
src/components/pages/auth/signup/signup-agreement-modal/index.tsx (1)
  • SignupAgreementModal (13-81)
🪛 Biome (2.1.2)
src/components/pages/auth/signup/signup-form/index.tsx

[error] 79-79: Avoid passing children using a prop

The canonical way to pass children in React is to use JSX elements

(lint/correctness/noChildrenProp)


[error] 84-84: Avoid passing children using a prop

The canonical way to pass children in React is to use JSX elements

(lint/correctness/noChildrenProp)


[error] 88-88: Avoid passing children using a prop

The canonical way to pass children in React is to use JSX elements

(lint/correctness/noChildrenProp)


[error] 94-94: Avoid passing children using a prop

The canonical way to pass children in React is to use JSX elements

(lint/correctness/noChildrenProp)


[error] 101-101: Avoid passing children using a prop

The canonical way to pass children in React is to use JSX elements

(lint/correctness/noChildrenProp)

src/components/pages/auth/login/login-form/index.tsx

[error] 50-50: Avoid passing children using a prop

The canonical way to pass children in React is to use JSX elements

(lint/correctness/noChildrenProp)


[error] 52-52: Avoid passing children using a prop

The canonical way to pass children in React is to use JSX elements

(lint/correctness/noChildrenProp)


[error] 59-59: Avoid passing children using a prop

The canonical way to pass children in React is to use JSX elements

(lint/correctness/noChildrenProp)

🔇 Additional comments (24)
src/hooks/use-auth/use-auth-logout/index.ts (1)

27-27: 로그아웃 후 홈으로 리디렉션 - 변경 승인

로그아웃 후 로그인 페이지가 아닌 홈페이지('/')로 이동하도록 변경되었습니다. 이는 일반적인 UX 패턴과 일치하며, 사용자가 로그아웃 후 다시 로그인할 필요 없이 공개 콘텐츠를 탐색할 수 있도록 합니다.

src/components/pages/user/mypage/mypage-setting/index.tsx (1)

2-2: 실제 로그아웃/회원탈퇴 기능 연결 완료

임시 구현(console.log)에서 실제 훅 기능으로 올바르게 전환되었습니다. useLogoutuseWithdraw 훅이 적절히 import되고 사용되었으며, MyPageActionButton이 onClick을 정상적으로 전달하는 것이 확인되었습니다.

Also applies to: 14-15, 25-26

src/app/login/_temp/login-temp-actions.tsx (1)

4-4: 임시 refresh 기능 제거 완료

PR 목표에 따라 useRefresh 관련 코드가 정상적으로 제거되었습니다. 이 파일이 _temp 디렉토리에 위치한 점을 고려하면, 향후 완전히 제거될 예정인 것으로 보입니다.

src/components/shared/form-input/index.tsx (1)

8-10: iconButton prop 패턴으로 리팩터링 완료

내부 하위 컴포넌트를 제거하고 iconButton prop을 통해 필드별 아이콘 액션을 지원하도록 개선되었습니다. 이는 더 유연하고 재사용 가능한 구조를 제공하며, EmailField 및 NicknameField 등의 인증 폼 필드에서 활용됩니다.

Also applies to: 20-20, 40-40, 68-72

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

4-4: import 경로를 auth 배럴로 통합

인증 관련 컴포넌트들이 새로운 @/components/pages/auth 배럴을 통해 import되도록 경로가 업데이트되었습니다. 기능적 변경 없이 구조만 개선되었으며, 인증 관련 컴포넌트의 일관된 import 경로를 제공합니다.

src/app/signup/page.tsx (1)

2-2: import 경로를 auth 배럴로 통합

회원가입 폼 컴포넌트가 새로운 auth 배럴을 통해 import되도록 업데이트되었습니다. 로그인 페이지와 일관된 패턴을 유지합니다.

src/components/pages/auth/index.ts (1)

1-3: 인증 컴포넌트 배럴 파일 생성

인증 관련 컴포넌트들(LoginForm, LoginToastEffect, SignupForm)을 단일 import 경로로 제공하는 배럴 파일이 추가되었습니다. 이는 import 경로를 단순화하고 인증 모듈의 public API를 명확히 정의합니다.

src/lib/auth/utils.ts (1)

3-13: 힌트 메시지 유틸리티 함수 추가

필드의 상태를 기반으로 힌트 메시지를 결정하는 유틸리티 함수가 적절히 구현되었습니다. showError 조건(isTouched || isDirty || submissionAttempts > 0)은 사용자 경험을 고려한 합리적인 에러 표시 로직이며, errors[0]에 대한 접근은 선택적 체이닝(firstError?.message)으로 안전하게 처리되어 있습니다.

errors 배열이 비어있을 수 있는 경우도 올바르게 처리되고 있습니다(undefined 반환).

src/components/pages/auth/login/login-form/index.tsx (2)

50-60: 정적 분석 경고는 무시해도 됩니다.

Biome가 children prop 사용에 대해 경고하고 있지만, 이는 TanStack Form의 FieldSubscribe API에서 권장하는 정확한 패턴입니다. 이 경고는 무시해도 안전합니다.


37-39: 로그인 에러 초기화 로직이 적절합니다.

이메일이나 비밀번호가 변경될 때 로그인 에러를 자동으로 초기화하는 것은 좋은 UX 패턴입니다. clearLoginErroruseCallback으로 안정화되어 있어 의존성 배열도 올바릅니다.

src/components/pages/auth/fields/index.ts (1)

1-4: 배럴 내보내기 구조가 깔끔합니다.

인증 필드 컴포넌트들을 하나의 진입점으로 통합하여 import 경로를 단순화했습니다.

src/components/pages/auth/fields/termsAgreement-field/index.tsx (1)

15-42: 약관 동의 필드 구현이 올바릅니다.

체크박스 상태 관리와 모달 트리거가 잘 분리되어 있으며, 접근성을 고려한 label 구조를 사용하고 있습니다.

src/components/pages/auth/auth-button/index.tsx (1)

11-22: 제출 버튼 컴포넌트가 명확합니다.

폼 상태와 추가 검증 조건(canSubmitAll)을 결합하여 버튼 활성화 여부를 결정하는 로직이 적절합니다.

src/components/pages/auth/fields/email-field/index.tsx (1)

46-98: 이메일 필드 구현이 잘 되어 있습니다.

가용성 검사의 조건부 렌더링과 값 트리밍 처리가 적절하며, 입력 변경 시 검사 상태를 초기화하는 로직도 올바릅니다.

src/components/pages/auth/fields/password-field/index.tsx (1)

35-66: 비밀번호 필드 구현이 적절합니다.

비밀번호 타입에 따른 autoComplete 속성 설정과 플레이스홀더/레이블 텍스트 조정이 올바르게 구현되어 있습니다.

src/components/pages/auth/signup/signup-form/index.tsx (2)

72-104: 정적 분석 경고는 무시해도 됩니다.

Biome가 여러 곳에서 children prop 사용에 대해 경고하고 있지만, 이는 TanStack Form의 FieldSubscribe API에서 사용하는 정확한 패턴입니다.


39-61: 가용성 검사 통합이 잘 구현되었습니다.

이메일과 닉네임의 중복 확인을 별도로 관리하고, 두 검사가 모두 성공해야만 제출 가능하도록 canSubmitAll을 설정한 것이 적절합니다.

src/hooks/use-auth/use-auth-login/index.ts (1)

52-98: 로그인 에러 상태 관리가 잘 구현되었습니다.

loginError 상태를 추가하고 clearLoginError로 초기화할 수 있도록 한 것이 좋습니다. 이전의 alert 기반 UI 대신 상태 기반 에러 표시로 변경하여 더 나은 사용자 경험을 제공합니다.

src/components/pages/auth/fields/nickname-field/index.tsx (3)

9-25: 타입 정의가 명확하고 잘 구성되어 있습니다.

NicknameCheck 타입이 상태 관리에 필요한 모든 속성을 포함하고 있으며, state.status의 유니온 타입이 가능한 모든 상태를 명확하게 정의하고 있습니다.


63-81: FormInput 연동 및 전체 구현이 잘 되어 있습니다.

FormInput에 전달되는 props가 적절하게 구성되어 있으며, availabilityHintavailabilityStatus를 통해 중복 확인 상태를 UI에 반영합니다. onChange 핸들러에서 nicknameCheck.reset()을 호출하여 사용자가 값을 변경할 때 이전 중복 확인 결과를 초기화하는 것이 좋습니다.


48-49: No action needed. The nickname field is properly initialized with an empty string '' in the form's defaultValues (src/components/pages/auth/signup/signup-form/index.tsx, line 19), and TanStack Form guarantees that field.state.value will always be a string. Calling .trim() on a string is safe and will not cause a runtime error.

Likely an incorrect or invalid review comment.

src/lib/schema/auth.ts (3)

7-7: 로그인 비밀번호 유효성 검사 개선

min(1)으로 빈 값 체크를 추가한 것이 좋습니다. 로그인 시에는 복잡한 비밀번호 규칙을 검증할 필요가 없으므로 적절한 변경입니다.


21-24: confirmPasswordtermsAgreement 유효성 검사가 적절합니다.

  • confirmPasswordmin(1) 추가로 빈 값 체크
  • termsAgreementboolean().refine()으로 변경하여 true인 경우만 통과하도록 설정

.refine((v) => v === true, ...)는 의도를 명확히 하지만, z.literal(true)를 사용하는 것이 더 간결할 수 있습니다. 단, 현재 방식도 에러 메시지 커스터마이징에 유리하므로 유지해도 좋습니다.


4-6: 프로젝트에서 사용 중인 Zod는 4.1.13 버전으로, z.email() 구문은 Zod 4의 올바른 문법이며 완전히 호환됩니다. 이 코드는 수정이 필요하지 않습니다.

Comment on lines +36 to +46
const isCommonErrorResponse = (e: unknown): e is CommonErrorResponse => {
if (!e || typeof e !== 'object') return false;

const obj = e as Record<string, unknown>;
return (
typeof obj.status === 'number' &&
typeof obj.detail === 'string' &&
typeof obj.errorCode === 'string' &&
typeof obj.instance === 'string'
);
};
Copy link
Contributor

@coderabbitai coderabbitai bot Dec 24, 2025

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

타입 가드에서 선택적 필드 처리 오류를 수정하세요.

Line 43에서 errorCode를 필수 문자열로 확인하고 있지만, CommonErrorResponse 인터페이스에서는 errorCode?: string으로 선택적 속성입니다. errorCodeundefined인 유효한 에러 응답이 이 타입 가드를 통과하지 못해 일반 에러 메시지로 처리될 수 있습니다.

🔎 제안하는 수정
 const isCommonErrorResponse = (e: unknown): e is CommonErrorResponse => {
   if (!e || typeof e !== 'object') return false;
 
   const obj = e as Record<string, unknown>;
   return (
     typeof obj.status === 'number' &&
     typeof obj.detail === 'string' &&
-    typeof obj.errorCode === 'string' &&
+    (obj.errorCode === undefined || typeof obj.errorCode === 'string') &&
     typeof obj.instance === 'string'
   );
 };
📝 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 isCommonErrorResponse = (e: unknown): e is CommonErrorResponse => {
if (!e || typeof e !== 'object') return false;
const obj = e as Record<string, unknown>;
return (
typeof obj.status === 'number' &&
typeof obj.detail === 'string' &&
typeof obj.errorCode === 'string' &&
typeof obj.instance === 'string'
);
};
const isCommonErrorResponse = (e: unknown): e is CommonErrorResponse => {
if (!e || typeof e !== 'object') return false;
const obj = e as Record<string, unknown>;
return (
typeof obj.status === 'number' &&
typeof obj.detail === 'string' &&
(obj.errorCode === undefined || typeof obj.errorCode === 'string') &&
typeof obj.instance === 'string'
);
};
🤖 Prompt for AI Agents
In src/hooks/use-auth/use-auth-login/index.ts around lines 36 to 46, the type
guard currently requires errorCode to be a string but the CommonErrorResponse
defines errorCode as optional; adjust the condition so the guard accepts either
a string or undefined for errorCode (e.g. check that typeof obj.errorCode ===
'string' || typeof obj.errorCode === 'undefined'), then keep the other property
checks unchanged so valid responses with no errorCode still pass the guard.

Copy link
Member Author

Choose a reason for hiding this comment

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

proxy 추가 후 삭제 예정

Copy link
Contributor

Choose a reason for hiding this comment

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

@yoorli 이해했습니다! Proxy 설정이 완료되면 isCommonErrorResponse 타입 가드가 삭제될 예정이시군요. 임시 코드이므로 현재 상태로 진행하셔도 괜찮습니다. 👍

Proxy 구성 후 해당 코드가 제거되면 타입 가드 관련 이슈도 함께 해결될 것으로 보입니다.

Comment on lines 73 to 91
if (isCommonErrorResponse(error)) {
console.error('[LOGIN ERROR]', error.errorCode, error.detail);
setLoginError(getLoginErrorMessage(error));
return;
}

if (axios.isAxiosError(error)) {
const axiosError = error as AxiosError<CommonErrorResponse>;
const problem = axiosError.response?.data;

if (problem) {
console.error('[LOGIN ERROR]', problem.errorCode, problem.detail);
setLoginError(getLoginErrorMessage(problem));
} else {
console.error(error);
setLoginError('서버와 연결할 수 없습니다.');
}
return;
}
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Find axios/interceptor configuration files
echo "=== Looking for axios interceptor setup ==="
fd -type f \( -name "*intercept*" -o -name "*api*" -o -name "*axios*" \) -e ts -e tsx

echo ""
echo "=== Searching for interceptor.response configuration ==="
rg -n "interceptors\." --type ts -A 15 | head -100

echo ""
echo "=== Searching for CommonErrorResponse handling in interceptors ==="
rg -n "CommonErrorResponse" --type ts -B 3 -A 3

Repository: WeGo-Together/WeGo_FrontEnd

Length of output: 7559


🏁 Script executed:

#!/bin/bash
# Read complete interceptor implementation
echo "=== Complete interceptor response handler ==="
cat -n src/api/core/index.ts | sed -n '35,80p'

echo ""
echo "=== Complete isCommonErrorResponse type guard ==="
cat -n src/hooks/use-auth/use-auth-login/index.ts | sed -n '36,50p'

Repository: WeGo-Together/WeGo_FrontEnd

Length of output: 2425


인터셉터가 모든 에러를 CommonErrorResponse로 정규화하므로, Lines 79-91의 axios.isAxiosError 검사는 불필요합니다.

src/api/core/index.ts의 응답 인터셉터는 모든 에러를 CommonErrorResponse 타입으로 정규화한 후 throws하므로, API.login() 호출에서 발생하는 에러는 항상 Line 73의 isCommonErrorResponse 검사에서 처리됩니다. 따라서 Lines 79-91의 axios.isAxiosError 블록은 도달할 수 없는 코드입니다. 불필요한 검사를 제거하거나, 특정 목적이 있다면 주석으로 그 의도를 명확히 하세요.

🤖 Prompt for AI Agents
In src/hooks/use-auth/use-auth-login/index.ts around lines 73 to 91, the
axios.isAxiosError block is unreachable because the API response interceptor in
src/api/core/index.ts normalizes and throws all errors as CommonErrorResponse
which is already handled by the isCommonErrorResponse check at line 73; remove
the entire axios.isAxiosError block (lines 79–91) and any now-unused
axios/AxiosError imports, or if you intended to keep it for a specific edge
case, replace it with a clear comment explaining that intent and why the
interceptor won’t cover that case.

@yoorli yoorli merged commit 09d336f into main Dec 24, 2025
7 of 8 checks passed
@yoorli yoorli deleted the yoolri-refactor/input-ui branch December 24, 2025 00:30
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Ready For Review! 리뷰 받을 준비가 되었습니다.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants