-
Notifications
You must be signed in to change notification settings - Fork 1
Feat/43 로그인 / 회원가입 페이지 구현 #69
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
Conversation
There was a problem hiding this 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
♻️ Duplicate comments (5)
src/app/(non-header)/oauth/kakao/sign-up/page.tsx (2)
86-86: useEffect 의존성 배열이 불완전합니다.
nickname과setUser가 의존성 배열에 누락되어 있습니다.- }, [searchParams, router]); + }, [searchParams, router, nickname, setUser]);
80-82: alert 대신 더 나은 UX를 제공하세요.
alert()는 사용자 경험을 저해합니다. 토스트 알림이나 에러 페이지를 사용하는 것이 좋습니다.src/app/api/auth/refresh/route.ts (1)
58-58: 토큰 만료 시간을 상수로 관리하세요.액세스 토큰 만료 시간이 하드코딩되어 있습니다. 유지보수성 향상을 위해 상수로 관리하는 것이 좋습니다.
파일 상단에 추가:
const ACCESS_TOKEN_MAX_AGE = 60 * 30; // 30분사용:
- maxAge: 60 * 30, // 30분 accessToken 설정 30분으로 되어있음 + maxAge: ACCESS_TOKEN_MAX_AGE,src/app/(non-header)/login/action.ts (1)
70-77: 쿠키 만료 시간을 상수로 관리하세요.액세스 토큰과 리프레시 토큰의 만료 시간이 하드코딩되어 있습니다.
파일 상단에 추가:
const ACCESS_TOKEN_MAX_AGE = 60 * 30; // 30분 const REFRESH_TOKEN_MAX_AGE = 60 * 60 * 24 * 7; // 7일사용:
- maxAge: 60 * 30, + maxAge: ACCESS_TOKEN_MAX_AGE,- maxAge: 60 * 60 * 24 * 7, + maxAge: REFRESH_TOKEN_MAX_AGE,src/apis/privateServerInstance.ts (1)
54-54: 타임아웃 값을 설정 가능하게 만드세요타임아웃이 5초로 하드코딩되어 있습니다. 환경에 따라 조정이 필요할 수 있습니다.
📜 Review details
Configuration used: CodeRabbit UI
Review profile: ASSERTIVE
Plan: Pro
📒 Files selected for processing (6)
src/apis/privateServerInstance.ts(1 hunks)src/app/(non-header)/login/action.ts(1 hunks)src/app/(non-header)/oauth/kakao/sign-up/page.tsx(1 hunks)src/app/api/auth/refresh/route.ts(1 hunks)src/app/test/client/page.tsx(1 hunks)src/app/test/server/page.tsx(1 hunks)
🧰 Additional context used
🧬 Code Graph Analysis (2)
src/app/test/client/page.tsx (2)
src/types/user.ts (1)
User(1-8)src/apis/privateInstance.ts (1)
privateInstance(53-53)
src/app/(non-header)/login/action.ts (2)
src/types/user.ts (1)
User(1-8)src/lib/errors/authErrors.ts (5)
UserNotFoundError(51-55)PasswordValidateError(33-37)PasswordMismatchError(27-31)EmailNotFoundError(21-25)InternalServerError(45-49)
🪛 GitHub Actions: CI
src/app/(non-header)/oauth/kakao/sign-up/page.tsx
[warning] 3-3: Run autofix to sort these imports! (simple-import-sort/imports)
[warning] 86-86: React Hook useEffect has missing dependencies: 'nickname' and 'setUser'. Either include them or remove the dependency array. (react-hooks/exhaustive-deps)
[error] 1-1: useSearchParams() should be wrapped in a suspense boundary at page "/oauth/kakao/sign-up". See https://nextjs.org/docs/messages/missing-suspense-with-csr-bailout
[error] 1-1: Error occurred prerendering page "/oauth/kakao/sign-up". Export encountered an error on /(non-header)/oauth/kakao/sign-up/page, exiting the build.
🔇 Additional comments (5)
src/app/test/client/page.tsx (1)
1-35: 잘 구현되었습니다!이전 리뷰에서 지적된 타입 안전성 문제가 잘 해결되었습니다.
User타입과AxiosError를 적절히 사용하여 타입 안전성이 확보되었습니다.src/app/test/server/page.tsx (1)
1-30: 서버 컴포넌트가 잘 구현되었습니다!비동기 처리와 에러 핸들링이 적절히 구현되었으며, 타입 안전성도 확보되었습니다.
src/app/(non-header)/oauth/kakao/sign-up/page.tsx (1)
49-89: Suspense boundary가 필요합니다.
useSearchParams()는 Next.js App Router에서 Suspense boundary로 감싸야 합니다. 이는 서버 사이드 렌더링 중 발생하는 문제를 방지합니다.페이지를 Suspense로 감싸거나, 상위 layout에서 처리해주세요:
+import { Suspense } from 'react'; + +function KakaoSignupCallbackContent() { + // 현재 컴포넌트의 모든 내용 +} + export default function KakaoSignupCallbackPage() { + return ( + <Suspense fallback={<div>로딩 중...</div>}> + <KakaoSignupCallbackContent /> + </Suspense> + ); }Likely an incorrect or invalid review comment.
src/app/(non-header)/login/action.ts (1)
45-50: 폼 데이터 타입 검증이 잘 구현되었습니다!이전 리뷰에서 제안된 대로
FormDataEntryValue의 타입을 적절히 검증하고 있습니다.src/apis/privateServerInstance.ts (1)
62-90: 인터셉터 구현이 우수합니다401 에러 처리와 토큰 갱신 로직이 잘 구현되어 있습니다.
_retry플래그를 통한 무한 루프 방지도 적절합니다.
| /** | ||
| * 서버 환경에서 쿠키를 문자열로 변환하여 Authorization 요청 시 사용할 수 있도록 반환합니다. | ||
| * | ||
| * @returns {Promise<string>} - `name=value` 형식의 쿠키 문자열 | ||
| */ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🧹 Nitpick (assertive)
JSDoc 설명 수정 필요
JSDoc 설명에서 "Authorization 요청 시"라고 되어 있지만, 실제로는 Cookie 헤더에 사용됩니다.
/**
- * 서버 환경에서 쿠키를 문자열로 변환하여 Authorization 요청 시 사용할 수 있도록 반환합니다.
+ * 서버 환경에서 쿠키를 문자열로 변환하여 Cookie 헤더에 사용할 수 있도록 반환합니다.
*
* @returns {Promise<string>} - `name=value` 형식의 쿠키 문자열
*/📝 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.
| /** | |
| * 서버 환경에서 쿠키를 문자열로 변환하여 Authorization 요청 시 사용할 수 있도록 반환합니다. | |
| * | |
| * @returns {Promise<string>} - `name=value` 형식의 쿠키 문자열 | |
| */ | |
| /** | |
| * 서버 환경에서 쿠키를 문자열로 변환하여 Cookie 헤더에 사용할 수 있도록 반환합니다. | |
| * | |
| * @returns {Promise<string>} - `name=value` 형식의 쿠키 문자열 | |
| */ |
🤖 Prompt for AI Agents
In src/apis/privateServerInstance.ts around lines 4 to 8, update the JSDoc
comment to correctly describe that the returned cookie string is used in the
Cookie header, not specifically for Authorization requests. Modify the
description to clarify that the function returns a cookie string formatted as
"name=value" for use in HTTP Cookie headers.
| const refreshAccessToken = async (): Promise<string | null> => { | ||
| try { | ||
| const res = await axios.post( | ||
| `${process.env.NEXT_PUBLIC_SITE_URL}/api/auth/refresh`, | ||
| {}, | ||
| { headers: { Cookie: await getCookieHeader() } }, | ||
| ); | ||
|
|
||
| return res.data.accessToken; | ||
| } catch { | ||
| return null; | ||
| } | ||
| }; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🧹 Nitpick (assertive)
에러 로깅 추가 고려
토큰 갱신 실패 시 디버깅을 위해 에러 로깅을 추가하는 것이 좋습니다.
const refreshAccessToken = async (): Promise<string | null> => {
try {
const res = await axios.post(
`${process.env.NEXT_PUBLIC_SITE_URL}/api/auth/refresh`,
{},
{ headers: { Cookie: await getCookieHeader() } },
);
return res.data.accessToken;
- } catch {
+ } catch (error) {
+ console.error('[서버] 토큰 갱신 실패:', error);
return null;
}
};📝 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.
| const refreshAccessToken = async (): Promise<string | null> => { | |
| try { | |
| const res = await axios.post( | |
| `${process.env.NEXT_PUBLIC_SITE_URL}/api/auth/refresh`, | |
| {}, | |
| { headers: { Cookie: await getCookieHeader() } }, | |
| ); | |
| return res.data.accessToken; | |
| } catch { | |
| return null; | |
| } | |
| }; | |
| const refreshAccessToken = async (): Promise<string | null> => { | |
| try { | |
| const res = await axios.post( | |
| `${process.env.NEXT_PUBLIC_SITE_URL}/api/auth/refresh`, | |
| {}, | |
| { headers: { Cookie: await getCookieHeader() } }, | |
| ); | |
| return res.data.accessToken; | |
| } catch (error) { | |
| console.error('[서버] 토큰 갱신 실패:', error); | |
| return null; | |
| } | |
| }; |
🤖 Prompt for AI Agents
In src/apis/privateServerInstance.ts around lines 22 to 34, the
refreshAccessToken function catches errors but does not log them, which hinders
debugging. Modify the catch block to capture the error object and log the error
details before returning null, ensuring that any token refresh failures are
recorded for easier troubleshooting.
| 'use client'; | ||
|
|
||
| import useUserStore from '@/stores/authStore'; | ||
| import axios from 'axios'; | ||
| import { useRouter, useSearchParams } from 'next/navigation'; | ||
| import { useEffect } from 'react'; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🧹 Nitpick (assertive)
import 정렬이 필요합니다.
ESLint 규칙에 따라 import를 정렬해주세요.
-import useUserStore from '@/stores/authStore';
-import axios from 'axios';
-import { useRouter, useSearchParams } from 'next/navigation';
-import { useEffect } from 'react';
+import { useEffect } from 'react';
+import { useRouter, useSearchParams } from 'next/navigation';
+import axios from 'axios';
+import useUserStore from '@/stores/authStore';📝 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.
| 'use client'; | |
| import useUserStore from '@/stores/authStore'; | |
| import axios from 'axios'; | |
| import { useRouter, useSearchParams } from 'next/navigation'; | |
| import { useEffect } from 'react'; | |
| 'use client'; | |
| import { useEffect } from 'react'; | |
| import { useRouter, useSearchParams } from 'next/navigation'; | |
| import axios from 'axios'; | |
| import useUserStore from '@/stores/authStore'; |
🧰 Tools
🪛 GitHub Actions: CI
[warning] 3-3: Run autofix to sort these imports! (simple-import-sort/imports)
[error] 1-1: useSearchParams() should be wrapped in a suspense boundary at page "/oauth/kakao/sign-up". See https://nextjs.org/docs/messages/missing-suspense-with-csr-bailout
[error] 1-1: Error occurred prerendering page "/oauth/kakao/sign-up". Export encountered an error on /(non-header)/oauth/kakao/sign-up/page, exiting the build.
🤖 Prompt for AI Agents
In src/app/(non-header)/oauth/kakao/sign-up/page.tsx lines 1 to 6, the import
statements are not sorted according to ESLint rules. Reorder the imports to
follow the project's ESLint import sorting conventions, typically grouping
external modules first, then internal modules, and sorting alphabetically within
groups.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 9
♻️ Duplicate comments (6)
src/app/api/test/route.ts (1)
13-18: 이전 리뷰 코멘트가 적절히 반영되었습니다.액세스 토큰이 없는 경우에 대한 명시적인 에러 처리가 추가되어 이전 리뷰에서 지적된 문제가 해결되었습니다.
src/app/(non-header)/oauth/kakao/sign-up/page.tsx (2)
3-6: import 정렬을 수정하세요.ESLint 규칙에 따라 import문을 정렬해야 합니다.
79-82: 사용자 경험 개선을 위해 alert 대신 다른 방법을 사용하세요.alert()는 사용자 경험이 좋지 않습니다. 토스트 알림이나 전용 에러 페이지를 사용하는 것을 고려해보세요.
src/app/(non-header)/login/components/LoginForm.tsx (1)
84-95: 카카오 로그인 환경 변수 검증이 개선되었습니다.이전 리뷰에서 제안한 환경 변수 검증 로직이 적절히 구현되었습니다. 다만
NEXT_PUBLIC_KAKAO_CLIENT_ID도 함께 검증하는 것이 좋겠습니다.const handleKakaoLogin = () => { const redirectUrl = process.env.NEXT_PUBLIC_KAKAO_SIGNIN_REDIRECT_URL; + const clientId = process.env.NEXT_PUBLIC_KAKAO_CLIENT_ID; - if (!redirectUrl) { + if (!redirectUrl || !clientId) { setErrorMessage('카카오 로그인 설정이 올바르지 않습니다.'); setErrorPopupOpen(true); return; } - const kakaoAuthUrl = `https://kauth.kakao.com/oauth/authorize?client_id=${process.env.NEXT_PUBLIC_KAKAO_CLIENT_ID}&redirect_uri=${encodeURIComponent(redirectUrl)}&response_type=code`; + const kakaoAuthUrl = `https://kauth.kakao.com/oauth/authorize?client_id=${clientId}&redirect_uri=${encodeURIComponent(redirectUrl)}&response_type=code`; window.location.href = kakaoAuthUrl; };src/app/(non-header)/signup/action.ts (1)
65-66: 응답 데이터 구조 검증을 개선하세요.사용자 객체의 구조를 더 엄격하게 검증하면 런타임 오류를 방지할 수 있습니다.
src/lib/errors/authErrors.ts (1)
33-37: 이전 리뷰의 오타 수정이 적용되었습니다.메시지의 한국어 문법이 올바르게 수정되어 "이어야 합니다"로 표기되었습니다.
📜 Review details
Configuration used: CodeRabbit UI
Review profile: ASSERTIVE
Plan: Pro
📒 Files selected for processing (7)
src/app/(non-header)/login/components/LoginForm.tsx(1 hunks)src/app/(non-header)/oauth/kakao/sign-up/page.tsx(1 hunks)src/app/(non-header)/signup/action.ts(1 hunks)src/app/(non-header)/signup/components/SignupForm.tsx(1 hunks)src/app/api/test/route.ts(1 hunks)src/lib/errors/authErrors.ts(1 hunks)src/utils/validateInput.ts(1 hunks)
🧰 Additional context used
🧬 Code Graph Analysis (1)
src/lib/errors/authErrors.ts (1)
src/lib/errors/CustomError.ts (1)
CustomError(10-24)
🪛 GitHub Actions: CI
src/app/(non-header)/login/components/LoginForm.tsx
[warning] 3-3: Run autofix to sort these imports! (simple-import-sort/imports)
[warning] 111-126: Props should be sorted alphabetically and callbacks must be listed after all other props (react/jsx-sort-props)
[warning] 163-163: Curly braces are unnecessary here (react/jsx-curly-brace-presence)
🔇 Additional comments (18)
src/app/api/test/route.ts (2)
1-3: 임포트 구문이 적절합니다.필요한 모든 의존성이 올바르게 임포트되었습니다.
5-7: 타입 정의가 적절합니다.서버 오류 응답을 위한 타입 정의가 올바르게 구현되었습니다.
src/utils/validateInput.ts (2)
3-8: 이메일 검증 함수가 잘 구현되었습니다.이전 리뷰에서 지적된 정규식 개선 사항이 적절히 반영되어 하위 도메인을 포함한 다양한 이메일 형식을 지원합니다.
16-22: 비밀번호 검증 로직이 개선되었습니다.이전 리뷰에서 제안한 대로 특수문자 요구사항이 제거되어 사용자 경험이 개선되었습니다. 영문과 숫자만 요구하는 현재 정책이 적절합니다.
src/app/(non-header)/signup/action.ts (2)
48-54: FormData 검증이 적절히 구현되었습니다.이전 리뷰에서 제안한 FormData 검증 로직이 타입 체크를 통해 구현되어 안전성이 향상되었습니다.
69-87: 에러 처리 로직이 잘 구현되었습니다.커스텀 에러 클래스를 활용한 체계적인 에러 처리가 잘 구현되었습니다. 서버 메시지에 따른 적절한 에러 매핑이 이루어지고 있습니다.
src/app/(non-header)/signup/components/SignupForm.tsx (2)
207-209: 버튼 type 속성이 적절히 추가되었습니다.이전 리뷰에서 제안한
type="button"속성이 추가되어 의도하지 않은 폼 제출을 방지할 수 있습니다.
77-86: useEffect 의존성 배열을 완성하세요.
router와setUser가 의존성 배열에 포함되어야 합니다.- }, [state, setUser]); + }, [state, setUser, router]);Likely an incorrect or invalid review comment.
src/lib/errors/authErrors.ts (10)
1-1: import 구문이 적절합니다.CustomError 클래스의 상대 경로 import가 올바르게 작성되어 있습니다.
3-7: 로그인 에러 처리가 적절합니다.401 상태 코드와 보안을 고려한 일반적인 에러 메시지가 적절하게 구현되어 있습니다.
9-13: 검증 에러 처리가 적절합니다.422 상태 코드는 입력값 검증 실패에 적합한 HTTP 상태 코드입니다.
15-19: 중복 이메일 에러 처리가 적절합니다.중복 이메일 등록에 대한 명확한 메시지와 적절한 상태 코드가 사용되었습니다.
21-25: 이메일 미존재 에러 처리가 적절합니다.404 상태 코드와 명확한 에러 메시지가 적절하게 구현되어 있습니다.
27-31: 비밀번호 불일치 에러 처리가 적절합니다.비밀번호 확인 실패에 대한 명확한 메시지와 적절한 상태 코드가 사용되었습니다.
39-43: 리소스 미발견 에러 처리가 적절합니다.일반적인 리소스 조회 실패에 대한 적절한 상태 코드와 메시지가 구현되어 있습니다.
45-49: 서버 에러 처리가 적절합니다.500 상태 코드와 사용자 친화적인 에러 메시지가 적절하게 구현되어 있습니다.
51-55: 사용자 미발견 에러 처리가 적절합니다.사용자 정보 조회 실패에 대한 적절한 상태 코드와 명확한 메시지가 구현되어 있습니다.
1-56: 인증 에러 클래스들이 체계적으로 잘 구현되었습니다.
- 모든 에러 클래스가 일관된 패턴을 따르고 있습니다
- 각 상황에 적절한 HTTP 상태 코드가 사용되었습니다
- 한국어 메시지가 사용자 친화적이고 명확합니다
- CustomError 기반의 체계적인 에러 처리 구조가 잘 구축되어 있습니다
이러한 구조는 인증 관련 다양한 시나리오에서 일관된 에러 처리를 가능하게 합니다.
| import useUserStore from '@/stores/authStore'; | ||
| import { User } from '@/types/user'; | ||
| import { useRouter } from 'next/navigation'; | ||
| import { useActionState, useEffect, useState } from 'react'; | ||
| import Login from '../action'; | ||
| import Link from 'next/link'; | ||
| import BrandMark from '@assets/svg/brand-mark'; | ||
| import Input from '@/components/Input'; | ||
| import Popup from '@/components/Popup'; | ||
| import { validateEmail, validatePassword } from '@/utils/validateInput'; | ||
| import Button from '@/components/Button'; | ||
| import IconKakao from '@assets/svg/kakao'; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
import 정렬을 수정하세요.
ESLint 규칙에 따라 import문을 정렬해야 합니다.
+'use client';
+
+import { useActionState, useEffect, useState } from 'react';
+import Link from 'next/link';
+import { useRouter } from 'next/navigation';
+
+import Button from '@/components/Button';
+import Input from '@/components/Input';
+import Popup from '@/components/Popup';
+import useUserStore from '@/stores/authStore';
+import { User } from '@/types/user';
+import { validateEmail, validatePassword } from '@/utils/validateInput';
+import BrandMark from '@assets/svg/brand-mark';
+import IconKakao from '@assets/svg/kakao';
+
+import Login from '../action';Committable suggestion skipped: line range outside the PR's diff.
🧰 Tools
🪛 GitHub Actions: CI
[warning] 3-3: Run autofix to sort these imports! (simple-import-sort/imports)
🤖 Prompt for AI Agents
In src/app/(non-header)/login/components/LoginForm.tsx between lines 3 and 14,
the import statements are not sorted according to ESLint rules. Reorder the
imports alphabetically or as per the project's ESLint configuration, grouping
external packages, absolute imports, and relative imports properly to comply
with the linting standards.
| <Input | ||
| required | ||
| name='email' | ||
| error={errors.email} | ||
| label='이메일' | ||
| placeholder='이메일을 입력해 주세요' | ||
| type='email' | ||
| value={email} | ||
| onBlur={() => | ||
| setErrors({ ...errors, email: validateEmail(email) }) | ||
| } | ||
| onChange={(e) => setEmail(e.target.value)} | ||
| className='mb-8' | ||
| /> | ||
| <Input | ||
| required | ||
| name='password' | ||
| error={errors.password} | ||
| label='비밀번호' | ||
| placeholder='비밀번호를 입력해주세요' | ||
| type='password' | ||
| value={password} | ||
| onBlur={() => | ||
| setErrors({ ...errors, password: validatePassword(password) }) | ||
| } | ||
| onChange={(e) => setPassword(e.target.value)} | ||
| className='mb-8' | ||
| /> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Input 컴포넌트 props를 정렬하세요.
ESLint 규칙에 따라 props를 알파벳 순으로 정렬하고 콜백은 마지막에 배치해야 합니다.
<Input
- required
- name='email'
- error={errors.email}
- label='이메일'
- placeholder='이메일을 입력해 주세요'
- type='email'
- value={email}
- onBlur={() =>
- setErrors({ ...errors, email: validateEmail(email) })
- }
- onChange={(e) => setEmail(e.target.value)}
className='mb-8'
+ error={errors.email}
+ label='이메일'
+ name='email'
+ placeholder='이메일을 입력해 주세요'
+ required
+ type='email'
+ value={email}
+ onBlur={() =>
+ setErrors({ ...errors, email: validateEmail(email) })
+ }
+ onChange={(e) => setEmail(e.target.value)}
/>Committable suggestion skipped: line range outside the PR's diff.
🧰 Tools
🪛 GitHub Actions: CI
[warning] 111-126: Props should be sorted alphabetically and callbacks must be listed after all other props (react/jsx-sort-props)
🤖 Prompt for AI Agents
In src/app/(non-header)/login/components/LoginForm.tsx between lines 108 and
135, the props of the Input components are not alphabetically ordered and
callbacks are not placed last. Reorder the props alphabetically by their names
and ensure that callback props like onBlur and onChange are positioned at the
end of the prop list to comply with ESLint rules.
| }; | ||
|
|
||
| handleKakaoSignup(); | ||
| }, [searchParams, router, nickname]); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🛠️ Refactor suggestion
useEffect 의존성 배열에서 nickname을 제거하세요.
닉네임 생성을 useEffect 내부로 이동하면 의존성 배열에서 nickname을 제거해야 합니다.
- }, [searchParams, router, nickname]);
+ }, [searchParams, router, setUser]);📝 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.
| }, [searchParams, router, nickname]); | |
| }, [searchParams, router, setUser]); |
🤖 Prompt for AI Agents
In src/app/(non-header)/oauth/kakao/sign-up/page.tsx at line 86, remove
'nickname' from the useEffect dependency array because the nickname generation
logic has been moved inside the useEffect. This prevents unnecessary re-renders
and ensures the effect only depends on searchParams and router.
| const handleKakaoSignup = () => { | ||
| const redirectUrl = process.env.NEXT_PUBLIC_KAKAO_SIGNUP_REDIRECT_URL ?? ''; | ||
| const kakaoAuthUrl = `https://kauth.kakao.com/oauth/authorize?client_id=${process.env.NEXT_PUBLIC_KAKAO_CLIENT_ID}&redirect_uri=${encodeURIComponent(redirectUrl)}&response_type=code`; | ||
| window.location.href = kakaoAuthUrl; | ||
| }; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🛠️ Refactor suggestion
카카오 회원가입 환경 변수 검증을 추가하세요.
로그인 폼과 마찬가지로 환경 변수 존재 여부와 유효성을 검증하는 것이 좋겠습니다.
const handleKakaoSignup = () => {
- const redirectUrl = process.env.NEXT_PUBLIC_KAKAO_SIGNUP_REDIRECT_URL ?? '';
- const kakaoAuthUrl = `https://kauth.kakao.com/oauth/authorize?client_id=${process.env.NEXT_PUBLIC_KAKAO_CLIENT_ID}&redirect_uri=${encodeURIComponent(redirectUrl)}&response_type=code`;
+ const redirectUrl = process.env.NEXT_PUBLIC_KAKAO_SIGNUP_REDIRECT_URL;
+ const clientId = process.env.NEXT_PUBLIC_KAKAO_CLIENT_ID;
+
+ if (!redirectUrl || !clientId) {
+ setErrorMessage('카카오 회원가입 설정이 올바르지 않습니다.');
+ setErrorPopupOpen(true);
+ return;
+ }
+
+ const kakaoAuthUrl = `https://kauth.kakao.com/oauth/authorize?client_id=${clientId}&redirect_uri=${encodeURIComponent(redirectUrl)}&response_type=code`;
window.location.href = kakaoAuthUrl;
};📝 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.
| const handleKakaoSignup = () => { | |
| const redirectUrl = process.env.NEXT_PUBLIC_KAKAO_SIGNUP_REDIRECT_URL ?? ''; | |
| const kakaoAuthUrl = `https://kauth.kakao.com/oauth/authorize?client_id=${process.env.NEXT_PUBLIC_KAKAO_CLIENT_ID}&redirect_uri=${encodeURIComponent(redirectUrl)}&response_type=code`; | |
| window.location.href = kakaoAuthUrl; | |
| }; | |
| const handleKakaoSignup = () => { | |
| const redirectUrl = process.env.NEXT_PUBLIC_KAKAO_SIGNUP_REDIRECT_URL; | |
| const clientId = process.env.NEXT_PUBLIC_KAKAO_CLIENT_ID; | |
| if (!redirectUrl || !clientId) { | |
| setErrorMessage('카카오 회원가입 설정이 올바르지 않습니다.'); | |
| setErrorPopupOpen(true); | |
| return; | |
| } | |
| const kakaoAuthUrl = `https://kauth.kakao.com/oauth/authorize?client_id=${clientId}&redirect_uri=${encodeURIComponent(redirectUrl)}&response_type=code`; | |
| window.location.href = kakaoAuthUrl; | |
| }; |
🤖 Prompt for AI Agents
In src/app/(non-header)/signup/components/SignupForm.tsx around lines 93 to 97,
the code does not validate the presence and validity of the Kakao signup
environment variables before using them. Add checks to ensure
NEXT_PUBLIC_KAKAO_CLIENT_ID and NEXT_PUBLIC_KAKAO_SIGNUP_REDIRECT_URL are
defined and non-empty. If either is missing or invalid, handle the error
gracefully, such as by showing an error message or preventing the redirect, to
avoid runtime issues.
| onBlur={() => | ||
| setErrors({ | ||
| ...errors, | ||
| passwordConfirmation: validatePasswordConfirmation( | ||
| passwordConfirmation, | ||
| password, | ||
| ), | ||
| }) | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🛠️ Refactor suggestion
비밀번호 확인 검증 로직을 개선하세요.
현재 비밀번호가 변경되어도 비밀번호 확인 필드의 에러 상태가 업데이트되지 않습니다. 비밀번호 상태 변경 시에도 확인 필드를 재검증하세요.
onChange={(e) => setPassword(e.target.value)}
+ onInput={() => {
+ if (passwordConfirmation) {
+ setErrors({
+ ...errors,
+ passwordConfirmation: validatePasswordConfirmation(
+ passwordConfirmation,
+ e.target.value,
+ ),
+ });
+ }
+ }}
className='mb-8'Committable suggestion skipped: line range outside the PR's diff.
🤖 Prompt for AI Agents
In src/app/(non-header)/signup/components/SignupForm.tsx around lines 169 to
177, the password confirmation validation only triggers onBlur and does not
update when the password changes. Modify the code to also re-validate the
password confirmation field whenever the password state changes, ensuring the
error state for password confirmation stays accurate.
| return NextResponse.json(res.data); | ||
| } catch (err) { | ||
| const error = err as AxiosError<ServerErrorResponse>; | ||
| const message = error.response?.data?.error || '유저 정보 업데이트 실패'; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🧹 Nitpick (assertive)
오류 메시지를 실제 작업에 맞게 수정하세요.
현재 오류 메시지가 "유저 정보 업데이트 실패"로 되어 있는데, 실제로는 유저 정보를 조회하는 작업이므로 메시지가 일치하지 않습니다.
다음과 같이 수정하세요:
- const message = error.response?.data?.error || '유저 정보 업데이트 실패';
+ const message = error.response?.data?.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.
| const message = error.response?.data?.error || '유저 정보 업데이트 실패'; | |
| - const message = error.response?.data?.error || '유저 정보 업데이트 실패'; | |
| + const message = error.response?.data?.error || '유저 정보 조회 실패'; |
🤖 Prompt for AI Agents
In src/app/api/test/route.ts at line 33, the error message "유저 정보 업데이트 실패" does
not match the actual operation, which is fetching user information. Update the
message to accurately reflect the action, such as changing it to "유저 정보 조회 실패"
to indicate a failure in retrieving user data.
There was a problem hiding this 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
♻️ Duplicate comments (5)
src/app/(non-header)/oauth/kakao/sign-up/page.tsx (3)
5-8: 임포트 정렬 규칙을 준수하세요.ESLint에서 임포트 정렬 경고가 발생하고 있습니다. 프로젝트의 임포트 정렬 규칙에 따라 정렬해주세요.
88-88: useEffect 의존성 배열에 setUser를 추가하세요.ESLint의 exhaustive-deps 규칙에 따라
setUser를 의존성 배열에 포함시켜야 합니다.- }, [searchParams, router]); + }, [searchParams, router, setUser]);
82-83: 사용자 경험 개선을 위해 alert 대신 토스트 알림을 사용하세요.
alert()사용으로 인한 사용자 경험 저하 문제가 지속되고 있습니다. 토스트 알림이나 에러 페이지 리다이렉션을 고려해보세요.src/app/(non-header)/oauth/kakao/sign-in/page.tsx (2)
81-81: useEffect 의존성 배열에 setUser를 추가하세요.ESLint의 exhaustive-deps 규칙에 따라
setUser를 의존성 배열에 포함시켜야 합니다.- }, [searchParams, router]); + }, [searchParams, router, setUser]);
61-75: 사용자 경험 개선을 위해 alert 대신 토스트 알림을 사용하세요.여러
alert()호출로 인한 사용자 경험 저하 문제가 지속되고 있습니다. 일관된 UI 컴포넌트나 토스트 라이브러리 사용을 고려해보세요.
📜 Review details
Configuration used: CodeRabbit UI
Review profile: ASSERTIVE
Plan: Pro
📒 Files selected for processing (2)
src/app/(non-header)/oauth/kakao/sign-in/page.tsx(1 hunks)src/app/(non-header)/oauth/kakao/sign-up/page.tsx(1 hunks)
🧰 Additional context used
🪛 GitHub Actions: CI
src/app/(non-header)/oauth/kakao/sign-in/page.tsx
[warning] 5-5: Run autofix to sort these imports! (simple-import-sort/imports)
[warning] 81-81: React Hook useEffect has a missing dependency: 'setUser'. Either include it or remove the dependency array. (react-hooks/exhaustive-deps)
[error] 1-1: useSearchParams() should be wrapped in a suspense boundary at page "/oauth/kakao/sign-in". See https://nextjs.org/docs/messages/missing-suspense-with-csr-bailout
[error] 1-1: Error occurred prerendering page "/oauth/kakao/sign-in". Export encountered an error on /(non-header)/oauth/kakao/sign-in/page, exiting the build.
🔇 Additional comments (1)
src/app/(non-header)/oauth/kakao/sign-in/page.tsx (1)
31-32: useSearchParams에 Suspense 경계가 필요합니다.Next.js에서
useSearchParams()는 Suspense 경계로 감싸져야 합니다. 빌드 오류가 발생하고 있습니다.컴포넌트를 Suspense로 감싸도록 수정하세요:
+import { Suspense } from 'react'; + +function KakaoSigninContent() { + const router = useRouter(); + const searchParams = useSearchParams(); + const setUser = useUserStore((state) => state.setUser); + // ... 나머지 로직 +} + export default function KakaoSigninCallbackPage() { - const router = useRouter(); - const searchParams = useSearchParams(); - const setUser = useUserStore((state) => state.setUser); - // ... 나머지 로직 + return ( + <Suspense fallback={<div>로딩 중...</div>}> + <KakaoSigninContent /> + </Suspense> + ); +}Likely an incorrect or invalid review comment.
| import useUserStore from '@/stores/authStore'; | ||
| import axios from 'axios'; | ||
| import { useRouter, useSearchParams } from 'next/navigation'; | ||
| import { useEffect } from 'react'; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
임포트 정렬 규칙을 준수하세요.
ESLint에서 임포트 정렬 경고가 발생하고 있습니다. 프로젝트의 임포트 정렬 규칙에 따라 정렬해주세요.
-import useUserStore from '@/stores/authStore';
-import axios from 'axios';
-import { useRouter, useSearchParams } from 'next/navigation';
-import { useEffect } from 'react';
+import { useEffect } from 'react';
+import { useRouter, useSearchParams } from 'next/navigation';
+import axios from 'axios';
+import useUserStore from '@/stores/authStore';📝 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.
| import useUserStore from '@/stores/authStore'; | |
| import axios from 'axios'; | |
| import { useRouter, useSearchParams } from 'next/navigation'; | |
| import { useEffect } from 'react'; | |
| import { useEffect } from 'react'; | |
| import { useRouter, useSearchParams } from 'next/navigation'; | |
| import axios from 'axios'; | |
| import useUserStore from '@/stores/authStore'; |
🧰 Tools
🪛 GitHub Actions: CI
[warning] 5-5: Run autofix to sort these imports! (simple-import-sort/imports)
🤖 Prompt for AI Agents
In src/app/(non-header)/oauth/kakao/sign-in/page.tsx between lines 5 and 8, the
import statements are not sorted according to the project's ESLint import order
rules. Reorder the imports to follow the project's import sorting convention,
typically grouping external libraries first, then internal modules, and sorting
alphabetically within those groups.
| const router = useRouter(); | ||
| const searchParams = useSearchParams(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
useSearchParams에 Suspense 경계가 필요합니다.
Next.js에서 useSearchParams()는 Suspense 경계로 감싸져야 합니다. 빌드 오류가 발생하고 있습니다.
컴포넌트를 Suspense로 감싸거나 다음과 같이 수정하세요:
+import { Suspense } from 'react';
+
+function KakaoSignupContent() {
+ const router = useRouter();
+ const searchParams = useSearchParams();
+ const setUser = useUserStore((state) => state.setUser);
+ // ... 나머지 로직
+}
+
export default function KakaoSignupCallbackPage() {
- const router = useRouter();
- const searchParams = useSearchParams();
- const setUser = useUserStore((state) => state.setUser);
- // ... 나머지 로직
+ return (
+ <Suspense fallback={<div>로딩 중...</div>}>
+ <KakaoSignupContent />
+ </Suspense>
+ );
+}Committable suggestion skipped: line range outside the PR's diff.
🤖 Prompt for AI Agents
In src/app/(non-header)/oauth/kakao/sign-up/page.tsx around lines 52 to 53, the
useSearchParams hook requires a Suspense boundary to avoid build errors in
Next.js. Wrap the component or the part using useSearchParams with React's
Suspense component to provide the necessary boundary. This will ensure the hook
functions correctly without causing build issues.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
로그인/회원가입 구현 정말 고생 많으셨습니다!
- 주석을 꼼꼼히 달아주시고 잘 구분되어 있어 흐름을 빠르게 파악하고 이해하는 데 큰 도움이 되었네요.
구현 과정에서 발생한 트러블 슈팅 경험, 새롭게 알게 된 점이나 고민했던 선택지 또는 공유하면 좋을 내용들을 PR이나 Discussion에 기록해두시면 향후 회고나 포트폴리오 정리 시 도움이 되실거 같아요! 👍
There was a problem hiding this 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
📜 Review details
Configuration used: CodeRabbit UI
Review profile: ASSERTIVE
Plan: Pro
📒 Files selected for processing (2)
src/app/(non-header)/oauth/kakao/sign-in/page.tsx(1 hunks)src/app/(non-header)/oauth/kakao/sign-up/page.tsx(1 hunks)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
- GitHub Check: Code Quality Check
| export default function KakaoSigninCallbackPage() { | ||
| return <div>카카오 로그인 처리 예정</div>; | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
OAuth 로그인 기능이 완전히 비활성화되어 있습니다.
현재 구현은 카카오 OAuth 로그인 콜백을 처리하지 않고 플레이스홀더만 표시합니다. 사용자가 카카오 로그인 버튼을 클릭하고 인증을 완료한 후 이 페이지로 리다이렉트되지만, 실제 로그인 처리가 이루어지지 않아 사용자가 로그인되지 않는 상태로 남게 됩니다.
이는 사용자 경험을 크게 해치는 중요한 문제입니다. 주석 처리된 구현을 활성화하거나, 임시로 기능 준비 중임을 알리고 일반 로그인으로 안내해야 합니다.
export default function KakaoSigninCallbackPage() {
- return <div>카카오 로그인 처리 예정</div>;
+ return (
+ <div style={{ padding: '20px', textAlign: 'center' }}>
+ <h2>카카오 로그인</h2>
+ <p>현재 카카오 로그인 기능을 준비 중입니다.</p>
+ <p>일반 로그인을 이용해 주세요.</p>
+ <a href="/login">로그인 페이지로 이동</a>
+ </div>
+ );
}📝 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.
| export default function KakaoSigninCallbackPage() { | |
| return <div>카카오 로그인 처리 예정</div>; | |
| } | |
| export default function KakaoSigninCallbackPage() { | |
| return ( | |
| <div style={{ padding: '20px', textAlign: 'center' }}> | |
| <h2>카카오 로그인</h2> | |
| <p>현재 카카오 로그인 기능을 준비 중입니다.</p> | |
| <p>일반 로그인을 이용해 주세요.</p> | |
| <a href="/login">로그인 페이지로 이동</a> | |
| </div> | |
| ); | |
| } |
🤖 Prompt for AI Agents
In src/app/(non-header)/oauth/kakao/sign-in/page.tsx around lines 30 to 32, the
KakaoSigninCallbackPage currently only shows a placeholder and does not handle
the OAuth login callback. To fix this, implement the actual Kakao OAuth login
processing logic here to handle the authentication response and log the user in.
If the full implementation is not ready, replace the placeholder with a message
informing users that the feature is under preparation and provide a link or
guidance to use the regular login method instead.
| export default function KakaoSignupCallbackPage() { | ||
| return <div>회원가입 처리 예정</div>; | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
OAuth 콜백 기능이 작동하지 않습니다.
현재 구현은 카카오 OAuth 콜백을 처리하지 않고 단순한 플레이스홀더만 표시합니다. 사용자가 카카오 인증을 완료한 후 이 페이지로 리다이렉트되면 실제 회원가입 처리가 이루어지지 않아 OAuth 플로우가 중단됩니다.
주석 처리된 구현을 활성화하거나, 임시로 "준비 중" 상태임을 명확히 알리고 적절한 대체 경로를 제공해야 합니다.
export default function KakaoSignupCallbackPage() {
- return <div>회원가입 처리 예정</div>;
+ return (
+ <div style={{ padding: '20px', textAlign: 'center' }}>
+ <h2>카카오 회원가입</h2>
+ <p>현재 카카오 회원가입 기능을 준비 중입니다.</p>
+ <p>일반 회원가입을 이용해 주세요.</p>
+ <a href="/signup">회원가입 페이지로 이동</a>
+ </div>
+ );
}📝 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.
| export default function KakaoSignupCallbackPage() { | |
| return <div>회원가입 처리 예정</div>; | |
| } | |
| export default function KakaoSignupCallbackPage() { | |
| return ( | |
| <div style={{ padding: '20px', textAlign: 'center' }}> | |
| <h2>카카오 회원가입</h2> | |
| <p>현재 카카오 회원가입 기능을 준비 중입니다.</p> | |
| <p>일반 회원가입을 이용해 주세요.</p> | |
| <a href="/signup">회원가입 페이지로 이동</a> | |
| </div> | |
| ); | |
| } |
🤖 Prompt for AI Agents
In src/app/(non-header)/oauth/kakao/sign-up/page.tsx around lines 51 to 53, the
current implementation only renders a placeholder and does not handle the Kakao
OAuth callback, causing the OAuth flow to break. To fix this, either activate
the previously commented-out code that processes the OAuth callback and
completes the signup, or update the component to clearly indicate that the
feature is under preparation and provide a fallback or redirect to guide users
appropriately.
There was a problem hiding this 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
♻️ Duplicate comments (4)
src/app/(non-header)/login/components/LoginForm.tsx (2)
3-14: import 정렬 문제가 여전히 존재합니다.ESLint 규칙에 따른 import 정렬이 필요합니다. 이전 리뷰에서 지적된 사항과 동일한 문제입니다.
108-137: Input 컴포넌트의 props 정렬이 필요합니다.여전히 props가 알파벳 순으로 정렬되지 않았고, 콜백 함수들이 마지막에 위치하지 않습니다. 이전 리뷰에서 지적된 ESLint 규칙을 따라 수정이 필요합니다.
src/app/(non-header)/signup/components/SignupForm.tsx (2)
156-169: 비밀번호 변경 시 확인 필드 재검증이 누락되었습니다.비밀번호가 변경될 때 비밀번호 확인 필드의 에러 상태가 자동으로 업데이트되지 않는 문제가 여전히 존재합니다. 이전 리뷰에서 지적된 사항과 동일합니다.
비밀번호 Input 컴포넌트에 다음과 같은 추가 검증 로직이 필요합니다:
onChange={(e) => setPassword(e.target.value)} + onInput={(e) => { + if (passwordConfirmation) { + setErrors({ + ...errors, + passwordConfirmation: validatePasswordConfirmation( + passwordConfirmation, + e.target.value, + ), + }); + } + }}
93-104: 카카오 클라이언트 ID 검증을 추가하세요.로그인 폼과 마찬가지로
NEXT_PUBLIC_KAKAO_CLIENT_ID환경 변수에 대한 검증이 누락되어 있습니다.다음과 같이 수정하여 완전한 환경 변수 검증을 구현하세요:
const handleKakaoSignup = () => { const redirectUrl = process.env.NEXT_PUBLIC_KAKAO_SIGNUP_REDIRECT_URL; + const clientId = process.env.NEXT_PUBLIC_KAKAO_CLIENT_ID; - if (!redirectUrl) { + if (!redirectUrl || !clientId) { setErrorMessage('카카오 회원가입 설정이 올바르지 않습니다.'); setErrorPopupOpen(true); return; } - const kakaoAuthUrl = `https://kauth.kakao.com/oauth/authorize?client_id=${process.env.NEXT_PUBLIC_KAKAO_CLIENT_ID}&redirect_uri=${encodeURIComponent(redirectUrl)}&response_type=code`; + const kakaoAuthUrl = `https://kauth.kakao.com/oauth/authorize?client_id=${clientId}&redirect_uri=${encodeURIComponent(redirectUrl)}&response_type=code`; window.location.href = kakaoAuthUrl; };
📜 Review details
Configuration used: CodeRabbit UI
Review profile: ASSERTIVE
Plan: Pro
📒 Files selected for processing (4)
src/app/(non-header)/login/components/LoginForm.tsx(1 hunks)src/app/(non-header)/signup/components/SignupForm.tsx(1 hunks)src/components/Input.tsx(2 hunks)src/types/inputTypes.ts(1 hunks)
🧰 Additional context used
🧬 Code Graph Analysis (2)
src/app/(non-header)/login/components/LoginForm.tsx (6)
src/types/user.ts (1)
User(1-8)src/app/(non-header)/login/action.ts (1)
Login(41-100)src/components/Input.tsx (1)
Input(17-63)src/utils/validateInput.ts (2)
validateEmail(33-33)validatePassword(35-35)src/components/Button.tsx (1)
Button(18-49)src/components/Popup.tsx (1)
Popup(36-107)
src/app/(non-header)/signup/components/SignupForm.tsx (6)
src/types/user.ts (1)
User(1-8)src/app/(non-header)/signup/action.ts (1)
Signup(40-88)src/components/Input.tsx (1)
Input(17-63)src/utils/validateInput.ts (4)
validateEmail(33-33)validateNickname(34-34)validatePassword(35-35)validatePasswordConfirmation(36-36)src/components/Button.tsx (1)
Button(18-49)src/components/Popup.tsx (1)
Popup(36-107)
🔇 Additional comments (8)
src/types/inputTypes.ts (1)
12-14: 잘 구현된 인터페이스 확장입니다.
focusColor속성이 적절하게 추가되었으며, 선택적 속성으로 설정되어 기존 코드와의 호환성을 유지합니다. JSDoc 주석도 명확하게 작성되었습니다.src/components/Input.tsx (2)
21-21: 매개변수 추가가 올바르게 구현되었습니다.
focusColor매개변수가 인터페이스 정의와 일관되게 추가되었습니다.
46-47: className 구성이 잘 개선되었습니다.패딩 조정(
px-20→pr-50 pl-20)과 커스텀 포커스 스타일을 위한focus:outline-none추가, 그리고 동적focusColor적용이 올바르게 구현되었습니다.src/app/(non-header)/login/components/LoginForm.tsx (3)
112-112: focusColor 속성이 올바르게 활용되었습니다.새로 추가된
focusColor속성을 적절한 Tailwind CSS 클래스와 함께 사용하여 일관된 포커스 스타일을 구현했습니다.Also applies to: 127-127
67-82: 상태 관리와 사이드 이펙트 처리가 잘 구현되었습니다.
useActionState를 활용한 서버 액션 처리와 성공/실패 케이스에 대한 적절한 상태 업데이트 및 네비게이션 로직이 올바르게 구현되었습니다.
60-62: 폼 유효성 검사 로직이 적절하게 구현되었습니다.에러 상태와 입력 완성도를 모두 고려한 버튼 활성화 로직이 사용자 경험을 향상시킵니다.
src/app/(non-header)/signup/components/SignupForm.tsx (2)
131-131: focusColor 속성이 일관되게 잘 적용되었습니다.모든 입력 필드에서
focusColor='focus:border-nomad'를 일관되게 사용하여 통일된 사용자 경험을 제공합니다.Also applies to: 146-146, 161-161, 176-176
47-86: 전체적인 컴포넌트 구조가 잘 설계되었습니다.서버 액션을 활용한 비동기 처리, 적절한 상태 관리, 사용자 피드백을 위한 팝업 처리 등이 모두 잘 구현되어 있어 견고한 회원가입 기능을 제공합니다.
Also applies to: 115-241
| const handleKakaoLogin = () => { | ||
| const redirectUrl = process.env.NEXT_PUBLIC_KAKAO_SIGNIN_REDIRECT_URL; | ||
|
|
||
| if (!redirectUrl) { | ||
| setErrorMessage('카카오 로그인 설정이 올바르지 않습니다.'); | ||
| setErrorPopupOpen(true); | ||
| return; | ||
| } | ||
|
|
||
| const kakaoAuthUrl = `https://kauth.kakao.com/oauth/authorize?client_id=${process.env.NEXT_PUBLIC_KAKAO_CLIENT_ID}&redirect_uri=${encodeURIComponent(redirectUrl)}&response_type=code`; | ||
| window.location.href = kakaoAuthUrl; | ||
| }; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
카카오 클라이언트 ID 검증이 누락되었습니다.
NEXT_PUBLIC_KAKAO_SIGNIN_REDIRECT_URL 검증은 추가되었으나, NEXT_PUBLIC_KAKAO_CLIENT_ID에 대한 검증이 여전히 없습니다.
다음과 같이 수정하여 완전한 검증을 구현하세요:
const handleKakaoLogin = () => {
const redirectUrl = process.env.NEXT_PUBLIC_KAKAO_SIGNIN_REDIRECT_URL;
+ const clientId = process.env.NEXT_PUBLIC_KAKAO_CLIENT_ID;
- if (!redirectUrl) {
+ if (!redirectUrl || !clientId) {
setErrorMessage('카카오 로그인 설정이 올바르지 않습니다.');
setErrorPopupOpen(true);
return;
}
- const kakaoAuthUrl = `https://kauth.kakao.com/oauth/authorize?client_id=${process.env.NEXT_PUBLIC_KAKAO_CLIENT_ID}&redirect_uri=${encodeURIComponent(redirectUrl)}&response_type=code`;
+ const kakaoAuthUrl = `https://kauth.kakao.com/oauth/authorize?client_id=${clientId}&redirect_uri=${encodeURIComponent(redirectUrl)}&response_type=code`;
window.location.href = kakaoAuthUrl;
};📝 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.
| const handleKakaoLogin = () => { | |
| const redirectUrl = process.env.NEXT_PUBLIC_KAKAO_SIGNIN_REDIRECT_URL; | |
| if (!redirectUrl) { | |
| setErrorMessage('카카오 로그인 설정이 올바르지 않습니다.'); | |
| setErrorPopupOpen(true); | |
| return; | |
| } | |
| const kakaoAuthUrl = `https://kauth.kakao.com/oauth/authorize?client_id=${process.env.NEXT_PUBLIC_KAKAO_CLIENT_ID}&redirect_uri=${encodeURIComponent(redirectUrl)}&response_type=code`; | |
| window.location.href = kakaoAuthUrl; | |
| }; | |
| const handleKakaoLogin = () => { | |
| const redirectUrl = process.env.NEXT_PUBLIC_KAKAO_SIGNIN_REDIRECT_URL; | |
| const clientId = process.env.NEXT_PUBLIC_KAKAO_CLIENT_ID; | |
| if (!redirectUrl || !clientId) { | |
| setErrorMessage('카카오 로그인 설정이 올바르지 않습니다.'); | |
| setErrorPopupOpen(true); | |
| return; | |
| } | |
| const kakaoAuthUrl = `https://kauth.kakao.com/oauth/authorize?client_id=${clientId}&redirect_uri=${encodeURIComponent(redirectUrl)}&response_type=code`; | |
| window.location.href = kakaoAuthUrl; | |
| }; |
🤖 Prompt for AI Agents
In src/app/(non-header)/login/components/LoginForm.tsx around lines 84 to 95,
the code checks for the presence of NEXT_PUBLIC_KAKAO_SIGNIN_REDIRECT_URL but
does not verify if NEXT_PUBLIC_KAKAO_CLIENT_ID is set. To fix this, add a
validation step to check if NEXT_PUBLIC_KAKAO_CLIENT_ID exists before
constructing the kakaoAuthUrl. If it is missing, set an appropriate error
message and open the error popup, then return early to prevent further
execution.
📌 변경 사항 개요
로그인 / 회원가입 페이지 구현
📝 상세 내용
로그인 / 회원가입 페이지를 구현했습니다.
Axios instance 설정으로 자동 재시도 / 에러 메세지 처리 로직을 만들었습니다.
카카오 간편 로그인 / 회원가입 기능을 구현 했습니다. 가입이 안되어 있으면 회원 가입 후 로그인 됩니다.
카카오는 회원가입 시 닉네임을 가져오지 못해 랜덤으로 설정되게 했습니다.
쿠키에 토큰을 저장하고 로그아웃 시 삭제할 수 있습니다.
🔗 관련 이슈
🖼️ 스크린샷(선택사항)
💡 참고 사항
Summary by CodeRabbit
신규 기능
버그 수정
개선 및 기타