-
Notifications
You must be signed in to change notification settings - Fork 1
Fix/75 빌드 오류 수정 및 알림창 변경 #85
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
Walkthrough카카오 OAuth 로그인 및 회원가입 콜백 처리를 위한 새로운 React 컴포넌트들이 도입되었습니다. 기존의 콜백 페이지 구현은 별도의 컴포넌트로 분리되어 Suspense로 감싸졌으며, 전역 사용자 상태 관리와 에러 처리, 로딩 UI 컴포넌트, 인증 미들웨어 및 팝업 타입 정의가 추가되었습니다. globals.css 파일에는 줄바꿈이 추가되었습니다. Changes
Sequence Diagram(s)sequenceDiagram
participant User
participant KakaoSigninCallbackPage
participant BackendAPI
participant ZustandStore
participant Router
User->>KakaoSigninCallbackPage: OAuth 콜백 URL 접속 (code 포함)
KakaoSigninCallbackPage->>BackendAPI: code로 POST /api/auth/kakao/sign-in
BackendAPI-->>KakaoSigninCallbackPage: 사용자 데이터 or 에러 반환
alt 성공
KakaoSigninCallbackPage->>ZustandStore: 사용자 정보 저장
KakaoSigninCallbackPage->>Router: 메인 페이지로 이동
else 404 에러
KakaoSigninCallbackPage->>User: 회원가입 안내 팝업
KakaoSigninCallbackPage->>Router: /signup 이동
else 500 에러
KakaoSigninCallbackPage->>User: 서버 에러 팝업
KakaoSigninCallbackPage->>Router: /login 이동
else 기타 에러
KakaoSigninCallbackPage->>User: 로그인 실패 팝업
KakaoSigninCallbackPage->>Router: /login 이동
end
sequenceDiagram
participant User
participant KakaoSignupCallbackPage
participant BackendAPI
participant ZustandStore
participant Router
User->>KakaoSignupCallbackPage: OAuth 콜백 URL 접속 (code 포함)
KakaoSignupCallbackPage->>KakaoSignupCallbackPage: 랜덤 닉네임 생성
KakaoSignupCallbackPage->>BackendAPI: code, nickname으로 POST /api/auth/kakao/sign-up
BackendAPI-->>KakaoSignupCallbackPage: 사용자 데이터 or 에러 반환
alt 성공
KakaoSignupCallbackPage->>ZustandStore: 사용자 정보 저장
KakaoSignupCallbackPage->>Router: /login 이동
else 400 에러
KakaoSignupCallbackPage->>User: 이미 가입된 사용자 팝업
KakaoSignupCallbackPage->>Router: /login 이동
else 500 에러
KakaoSignupCallbackPage->>User: 서버 에러 팝업
KakaoSignupCallbackPage->>Router: /signup 이동
else 기타 에러
KakaoSignupCallbackPage->>User: 회원가입 실패 팝업
KakaoSignupCallbackPage->>Router: /signup 이동
end
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~20 minutes Suggested labels
Suggested reviewers
Poem
Note ⚡️ Unit Test Generation is now available in beta!Learn more here, or try it out under "Finishing Touches" below. 📜 Recent review detailsConfiguration used: CodeRabbit UI 📒 Files selected for processing (1)
✨ Finishing Touches
🧪 Generate unit tests
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. 🪧 TipsChatThere are 3 ways to chat with CodeRabbit:
SupportNeed 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)
Other keywords and placeholders
CodeRabbit Configuration File (
|
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: 8
📜 Review details
Configuration used: CodeRabbit UI
Review profile: ASSERTIVE
Plan: Pro
📒 Files selected for processing (9)
src/app/(non-header)/oauth/kakao/components/KakaoLoading.tsx(1 hunks)src/app/(non-header)/oauth/kakao/sign-in/kakaoSigninCallbackPage.tsx(1 hunks)src/app/(non-header)/oauth/kakao/sign-in/page.tsx(1 hunks)src/app/(non-header)/oauth/kakao/sign-up/kakaoSignupCallbackPage.tsx(1 hunks)src/app/(non-header)/oauth/kakao/sign-up/page.tsx(1 hunks)src/app/globals.css(1 hunks)src/components/Loading.tsx(1 hunks)src/middleware.ts(1 hunks)src/types/popupTypes.ts(1 hunks)
🧰 Additional context used
🧬 Code Graph Analysis (3)
src/app/(non-header)/oauth/kakao/sign-in/kakaoSigninCallbackPage.tsx (3)
src/types/popupTypes.ts (1)
PopupState(27-31)src/app/(non-header)/oauth/kakao/components/KakaoLoading.tsx (1)
KakaoLoading(7-16)src/components/Popup.tsx (1)
Popup(36-107)
src/middleware.ts (1)
src/components/Header.tsx (1)
Header(9-64)
src/app/(non-header)/oauth/kakao/sign-in/page.tsx (2)
src/components/Loading.tsx (1)
Loading(3-29)src/app/(non-header)/oauth/kakao/sign-in/kakaoSigninCallbackPage.tsx (1)
KakaoSigninCallbackPage(31-116)
🪛 Biome (2.1.2)
src/app/(non-header)/oauth/kakao/sign-in/kakaoSigninCallbackPage.tsx
[error] 90-105: This case is falling through to the next case.
Add a break or return statement to the end of this case to prevent fallthrough.
(lint/suspicious/noFallthroughSwitchClause)
🔇 Additional comments (13)
src/types/popupTypes.ts (1)
27-31: 새로운 PopupState 인터페이스가 잘 정의되었습니다.OAuth 콜백 처리를 위한 팝업 상태 관리에 필요한 속성들이 적절히 포함되어 있습니다. 타입 정의가 명확하고 사용 목적에 부합합니다.
src/app/globals.css (1)
142-143: 파일 끝 개행 문자 추가가 적절합니다.파일 끝에 개행 문자를 추가하는 것은 표준 관례이며, 일부 도구에서 발생할 수 있는 문제를 방지합니다.
src/middleware.ts (2)
9-14: 인증된 사용자 리디렉션 로직이 적절합니다.로그인/회원가입 페이지에서 이미 인증된 사용자를 홈으로 리디렉션하는 로직이 올바르게 구현되어 있습니다.
26-28: 매처 설정이 올바르게 구성되어 있습니다.미들웨어가 실행될 경로가 적절히 지정되어 있어 불필요한 실행을 방지합니다.
src/app/(non-header)/oauth/kakao/components/KakaoLoading.tsx (2)
3-5: Props 인터페이스가 명확하게 정의되었습니다.TypeScript 인터페이스가 적절히 정의되어 컴포넌트의 예상 동작을 명확히 합니다.
7-16: 카카오 브랜딩에 맞는 로딩 컴포넌트가 잘 구현되었습니다.노란색 스피너와 깔끔한 레이아웃으로 카카오 OAuth 플로우에 적합한 로딩 UI를 제공합니다. Tailwind 클래스 사용도 일관성 있게 적용되었습니다.
src/app/(non-header)/oauth/kakao/sign-up/kakaoSignupCallbackPage.tsx (3)
34-50: 훌륭한 문서화입니다!컴포넌트의 목적과 주요 흐름이 명확하게 문서화되어 있으며, 한국어로 작성되어 프로젝트의 언어 일관성을 유지하고 있습니다.
51-60: 컴포넌트 구조가 잘 설계되었습니다.적절한 Next.js 훅과 Zustand 스토어를 사용하고 있으며, PopupState 인터페이스를 통해 타입 안전성을 보장하고 있습니다.
127-143: 렌더링 구조가 깔끔합니다.로딩 컴포넌트와 팝업이 적절히 구성되어 있으며, 팝업 닫기 핸들러가 상태 관리와 네비게이션을 올바르게 처리하고 있습니다.
src/app/(non-header)/oauth/kakao/sign-in/kakaoSigninCallbackPage.tsx (3)
13-30: 문서화가 매우 잘 되어 있습니다.컴포넌트의 목적, 주요 흐름, 그리고 오류 처리 방식이 명확하게 설명되어 있습니다. 한국어로 작성되어 프로젝트의 일관성을 유지하고 있습니다.
31-40: 컴포넌트 설정이 일관성 있게 구성되었습니다.회원가입 콜백 컴포넌트와 동일한 패턴을 사용하여 일관성을 유지하고 있으며, 적절한 상태 관리를 하고 있습니다.
100-116: 렌더링 구조가 적절합니다.회원가입 콜백과 일관된 구조를 사용하고 있으며, 로딩과 팝업 처리가 올바르게 구현되어 있습니다.
src/app/(non-header)/oauth/kakao/sign-in/page.tsx (1)
1-11: Suspense 패턴이 적절히 구현되었습니다.로그인 콜백 컴포넌트를 Suspense로 감싸고 적절한 로딩 폴백을 제공하고 있습니다. 관심사의 분리가 잘 이루어져 있습니다.
| const adjectives = [ | ||
| '상냥한', | ||
| '용감한', | ||
| '조용한', | ||
| '귀여운', | ||
| '멋진', | ||
| '차분한', | ||
| '빠른', | ||
| '신비한', | ||
| ]; | ||
| const animals = [ | ||
| '고양이', | ||
| '호랑이', | ||
| '강아지', | ||
| '여우', | ||
| '곰', | ||
| '사자', | ||
| '토끼', | ||
| '다람쥐', | ||
| ]; |
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)
상수를 별도 파일로 분리하는 것을 고려해보세요.
형용사와 동물 배열이 컴포넌트 내부에 하드코딩되어 있습니다. 코드 재사용성과 유지보수성을 위해 별도의 상수 파일로 분리하는 것을 권장합니다.
예시로 src/constants/nickname.ts 파일을 생성할 수 있습니다:
export const ADJECTIVES = [
'상냥한',
'용감한',
'조용한',
// ... 나머지 형용사들
];
export const ANIMALS = [
'고양이',
'호랑이',
'강아지',
// ... 나머지 동물들
];🤖 Prompt for AI Agents
In src/app/(non-header)/oauth/kakao/sign-up/kakaoSignupCallbackPage.tsx around
lines 13 to 32, the adjective and animal arrays are hardcoded inside the
component file. To improve code reuse and maintainability, move these arrays
into a separate constants file, for example, create src/constants/nickname.ts
exporting ADJECTIVES and ANIMALS arrays. Then import these constants into the
component file and replace the hardcoded arrays with the imported constants.
|
|
||
| if (!code) return; | ||
|
|
||
| const nickname = `${adjectives[Math.floor(Math.random() * adjectives.length)]}${animals[Math.floor(Math.random() * animals.length)]}`; |
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)
닉네임 중복 가능성을 고려해보세요.
현재 Math.random()을 사용한 닉네임 생성은 중복될 가능성이 있습니다. 서버에서 중복 체크를 하거나, 타임스탬프를 추가하는 등의 방법을 고려해보세요.
예시 개선안:
const nickname = `${adjectives[Math.floor(Math.random() * adjectives.length)]}${animals[Math.floor(Math.random() * animals.length)]}${Date.now().toString().slice(-4)}`;🤖 Prompt for AI Agents
In src/app/(non-header)/oauth/kakao/sign-up/kakaoSignupCallbackPage.tsx at line
67, the current nickname generation using Math.random() can produce duplicates.
To fix this, append a unique element such as a timestamp substring to the
generated nickname to reduce collision risk. For example, concatenate the last
few digits of Date.now() to the nickname string after the adjective and animal
parts.
| return ( | ||
| <div className='flex min-h-screen items-center justify-center'> | ||
| <div | ||
| className='animate-loader-spin aspect-square w-80 rounded-full bg-green-300 p-2' |
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)
스피너 크기가 과도할 수 있습니다.
현재 w-80 (20rem, 320px)로 설정되어 있어 화면에서 매우 큰 공간을 차지합니다. 사용자 경험을 위해 더 적절한 크기를 고려해보세요.
- className='animate-loader-spin aspect-square w-80 rounded-full bg-green-300 p-2'
+ className='animate-loader-spin aspect-square w-16 rounded-full bg-green-300 p-2'📝 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.
| className='animate-loader-spin aspect-square w-80 rounded-full bg-green-300 p-2' | |
| className='animate-loader-spin aspect-square w-16 rounded-full bg-green-300 p-2' |
🤖 Prompt for AI Agents
In src/components/Loading.tsx at line 7, the spinner's width is set to w-80
(20rem, 320px), which is excessively large and may negatively impact user
experience. Reduce the width class to a smaller size such as w-16 or w-24 to
make the spinner more appropriately sized for typical screen layouts.
| <style jsx>{` | ||
| @keyframes loader-spin { | ||
| to { | ||
| transform: rotate(1turn); | ||
| } | ||
| } | ||
| .animate-loader-spin { | ||
| animation: loader-spin 1s linear infinite; | ||
| } | ||
| `}</style> |
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)
인라인 JSX 스타일을 전역 CSS로 이동하는 것을 고려해보세요.
현재 컴포넌트 내부에 keyframe 애니메이션을 정의하고 있는데, 이는 다음과 같은 문제가 있을 수 있습니다:
- 컴포넌트가 렌더링될 때마다 스타일이 재정의됨
- 다른 컴포넌트에서 같은 애니메이션을 재사용하기 어려움
globals.css에 애니메이션을 추가하는 것을 권장합니다:
+@keyframes loader-spin {
+ to {
+ transform: rotate(1turn);
+ }
+}
+
+.animate-loader-spin {
+ animation: loader-spin 1s linear infinite;
+}그리고 컴포넌트에서는 인라인 스타일을 제거하세요:
- <style jsx>{`
- @keyframes loader-spin {
- to {
- transform: rotate(1turn);
- }
- }
-
- .animate-loader-spin {
- animation: loader-spin 1s linear infinite;
- }
- `}</style>📝 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.
| <style jsx>{` | |
| @keyframes loader-spin { | |
| to { | |
| transform: rotate(1turn); | |
| } | |
| } | |
| .animate-loader-spin { | |
| animation: loader-spin 1s linear infinite; | |
| } | |
| `}</style> |
🤖 Prompt for AI Agents
In src/components/Loading.tsx around lines 16 to 26, the keyframe animation and
related CSS are defined inline within the component, causing styles to be
redefined on every render and making reuse difficult. Move the @keyframes
loader-spin and the .animate-loader-spin animation class to the global CSS file
(e.g., globals.css). Then, remove the inline <style jsx> block from the
component and apply the animation class via className in the component JSX.
| const accessToken = request.cookies.get('accessToken')?.value; | ||
| const refreshToken = request.cookies.get('refreshToken')?.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.
🛠️ Refactor suggestion
토큰 유효성 검증을 고려해보세요.
현재는 토큰의 존재 여부만 확인하고 있습니다. 토큰이 만료되었거나 손상된 경우에 대한 처리를 추가하는 것을 권장합니다.
토큰 검증 로직을 별도 함수로 분리하여 재사용성을 높이세요:
+function isAuthenticated(accessToken?: string, refreshToken?: string): boolean {
+ // 토큰 존재 여부와 기본적인 형식 검증
+ return Boolean(accessToken || refreshToken);
+}
+
export async function middleware(request: NextRequest) {
const accessToken = request.cookies.get('accessToken')?.value;
const refreshToken = request.cookies.get('refreshToken')?.value;
+ const authenticated = isAuthenticated(accessToken, refreshToken);
const { pathname } = request.nextUrl;
if (
(pathname === '/login' || pathname === '/signup') &&
- (accessToken || refreshToken)
+ authenticated
) {
return NextResponse.redirect(new URL('/', request.url));
}
const protectedPaths = ['/mypage'];
const isProtected = protectedPaths.some((path) => pathname.startsWith(path));
- if (isProtected && !accessToken && !refreshToken) {
+ if (isProtected && !authenticated) {
return NextResponse.redirect(new URL('/login', request.url));
}
return NextResponse.next();
}📝 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 accessToken = request.cookies.get('accessToken')?.value; | |
| const refreshToken = request.cookies.get('refreshToken')?.value; | |
| function isAuthenticated(accessToken?: string, refreshToken?: string): boolean { | |
| // 토큰 존재 여부와 기본적인 형식 검증 | |
| return Boolean(accessToken || refreshToken); | |
| } | |
| export async function middleware(request: NextRequest) { | |
| const accessToken = request.cookies.get('accessToken')?.value; | |
| const refreshToken = request.cookies.get('refreshToken')?.value; | |
| const authenticated = isAuthenticated(accessToken, refreshToken); | |
| const { pathname } = request.nextUrl; | |
| if ( | |
| (pathname === '/login' || pathname === '/signup') && | |
| authenticated | |
| ) { | |
| return NextResponse.redirect(new URL('/', request.url)); | |
| } | |
| const protectedPaths = ['/mypage']; | |
| const isProtected = protectedPaths.some((path) => pathname.startsWith(path)); | |
| if (isProtected && !authenticated) { | |
| return NextResponse.redirect(new URL('/login', request.url)); | |
| } | |
| return NextResponse.next(); | |
| } |
🤖 Prompt for AI Agents
In src/middleware.ts around lines 4 to 5, the current code only checks for the
presence of access and refresh tokens without validating their integrity or
expiration. To fix this, implement a separate token validation function that
verifies if the tokens are valid and not expired. Replace the direct token
presence checks with calls to this validation function to handle invalid or
expired tokens appropriately, improving security and reusability.
evaain706
left a comment
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.
구현 수고하셧습니다!
로그인 로직 에러별 핸들링을 팝업을 이용해서 잘 구현해주신거같아요!
BokyungCodes
left a comment
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.
인증 상태에 따라서 리다이렉션 흐름이 깔끔하게 잘 구현된 거 같아요! 로그인, 회원가입 코드 작성해본 적 없는데 은빈님이랑 광민님 코드 보고 많이 배워야겠어요...😓
LeeCh0129
left a comment
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.
스피너까지 구현하셨네요! 고생하셨습니다👍
📌 변경 사항 개요
빌드 오류 수정 및 알림창 변경, 미들웨어 설정, 기본 로딩 컴포넌트 및 카카오 로딩 컴포넌트 구현
📝 상세 내용
카카오 로그인, 회원가입에서 빌드 오류 나던 부분을 수정했습니다
카카오 로그인, 회원가입 시 alert로 나타나던 부분을 팝업으로 변경
로딩 스피너 구현
카카오톡으로 로그인, 회원가입 시 전용 로딩 스피너 구현
🔗 관련 이슈
🖼️ 스크린샷(선택사항)
💡 참고 사항
Summary by CodeRabbit
신규 기능
스타일
문서화