-
Notifications
You must be signed in to change notification settings - Fork 3
Feat: 카카오 소셜 로그인/회원가입 기능 통합 및 개선 #514
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 인증 및 회원가입 플로우를 위한 새로운 API 라우트와 클라이언트 컴포넌트가 추가되었습니다. OAuth 버튼 컴포넌트가 단순화되었고, 인증 전환 페이지가 도입되었습니다. 미들웨어, 환경설정, .gitignore 등에도 소규모 보완이 있었습니다. Changes
Sequence Diagram(s)sequenceDiagram
participant User
participant Kakao
participant NextAPI as Next.js API Route
participant Backend
User->>Kakao: OAuth 인증 요청 (인가 코드 요청)
Kakao->>User: 인가 코드 전달 (redirect)
User->>NextAPI: 인가 코드 포함 GET 요청
NextAPI->>Backend: 인가 코드, redirect URI로 인증/회원가입 요청
Backend-->>NextAPI: 인증/회원가입 결과 및 토큰
alt 인증 성공
NextAPI->>User: 쿠키 설정 후 메인 페이지로 리다이렉트
else 회원가입 필요/에러
NextAPI->>User: KakaoTransition 페이지 또는 에러 페이지로 리다이렉트
end
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~20 minutes Suggested labels
Suggested reviewers
Poem
📜 Recent review detailsConfiguration used: CodeRabbit UI 📒 Files selected for processing (1)
✅ Files skipped from review due to trivial changes (1)
⏰ 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)
✨ 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. CodeRabbit Commands (Invoked using PR comments)
Other keywords and placeholders
CodeRabbit Configuration File (
|
✅ Preview Deployment Ready!🔗 Preview URL: https://roam-ready-6o43f60lg-yongmins-projects-bf5f7733.vercel.app This preview will be automatically updated on new commits. |
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: 6
🧹 Nitpick comments (5)
src/domain/Auth/components/KakaoTransition.tsx (1)
43-46: OAuth URL 구성 로직 중앙화를 고려해보세요.
OAuth.tsx와 동일한 URL 구성 로직이 중복되고 있습니다. 공통 유틸리티 함수로 추출하면 유지보수성이 향상됩니다.다음과 같은 유틸리티 함수 생성을 고려해보세요:
// utils/kakaoAuth.ts export function buildKakaoAuthUrl(clientId: string, redirectUri: string): string { return `https://kauth.kakao.com/oauth/authorize?response_type=code&client_id=${clientId}&redirect_uri=${redirectUri}`; }src/domain/Auth/components/OAuth.tsx (1)
67-67: UI 텍스트 색상 일관성을 확인하세요.KakaoTransition 컴포넌트에서는
text-gray-800을, 여기서는text-gray-700을 사용하고 있습니다. 디자인 시스템의 일관성을 위해 통일하는 것을 고려해보세요.src/app/api/auth/kakao/signin/route.ts (3)
82-84: 사용하지 않는 주석 코드 제거주석 처리된 코드는 제거해주세요. 버전 관리 시스템에서 필요시 복원할 수 있습니다.
const responseData = await handleOauthSignIn(code); - // const response = NextResponse.redirect( - // new URL(ROUTES.ACTIVITIES.ROOT, request.url), - // ); const response = new NextResponse(null, {
85-93: NextResponse.redirect 사용으로 코드 단순화수동으로 302 응답을 구성하는 대신
NextResponse.redirect를 사용하면 코드가 더 간결해집니다.- const response = new NextResponse(null, { - status: 302, - statusText: 'Found', - }); - response.headers.set( - 'Location', - new URL(ROUTES.ACTIVITIES.ROOT, request.url).toString(), - ); + const response = NextResponse.redirect( + new URL(ROUTES.ACTIVITIES.ROOT, request.url) + );
102-105: 에러 타입 처리 개선타입 단언보다는 타입 가드를 사용하여 더 안전한 타입 처리를 할 수 있습니다.
+ interface ErrorWithStatus extends Error { + status?: number; + } + + function hasStatus(error: unknown): error is ErrorWithStatus { + return error instanceof Error && 'status' in error; + } + const errorStatus = - error instanceof Error && 'status' in error - ? (error as Error & { status: number }).status - : undefined; + hasStatus(error) ? error.status : undefined;
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (11)
src/app/(app)/error.tsx(1 hunks)src/app/(auth)/kakao/transition/page.tsx(1 hunks)src/app/(auth)/signin/page.tsx(1 hunks)src/app/(auth)/signup/page.tsx(1 hunks)src/app/api/auth/kakao/signin/route.ts(1 hunks)src/app/api/auth/kakao/signup/route.ts(1 hunks)src/app/api/test/error/route.ts(1 hunks)src/app/error.tsx(1 hunks)src/domain/Auth/components/KakaoTransition.tsx(1 hunks)src/domain/Auth/components/OAuth.tsx(2 hunks)src/middleware.ts(2 hunks)
🔇 Additional comments (10)
src/app/api/test/error/route.ts (1)
52-55: 409 에러 메시지 수정 확인중복 필드가 ‘이메일’임을 명확히 해 주어 UX 일관성이 향상되었습니다. 기존 클라이언트 로직(특히
getErrorMessageByStatus)과도 잘 맞물리는지 한번 더 통합 테스트만 진행해 주세요.src/app/error.tsx (1)
50-52:min-h-screen추가로 레이아웃 안정성 확보최상위 에러 페이지가 뷰포트 높이를 최소 확보하도록 개선되었습니다. 모바일-Safari에서 주소창 높이 변동 시 세로 스크롤이 과도하게 생기지 않는지만 QA 중 확인 부탁드립니다.
src/app/(app)/error.tsx (1)
49-51: 세그먼트 에러 페이지에도 동일한 높이 정책 적용 👍
GlobalError와 동일하게min-h-screen을 부여해 시각적 일관성이 생겼습니다. 추가 작업 없습니다.src/app/(auth)/signup/page.tsx (1)
47-48: OAuth 컴포넌트pageTypeprop 제거 검증 완료
프로젝트 전반(회원가입·로그인 페이지, 테스트·스토리북 등)에서 더 이상pageTypeprop 전달 흔적이 발견되지 않았습니다.
- src/app/(auth)/signup/page.tsx:
<OAuth />호출부 (prop 없음)- src/app/(auth)/signin/page.tsx:
<OAuth />호출부 (prop 없음)- 테스트·스토리북 파일 전체:
pageTypeprop 사용 없음변경 사항을 안전하게 병합할 수 있습니다.
src/app/(auth)/signin/page.tsx (1)
48-49:OAuth컴포넌트 호출부 정리 완료
pageType삭제가 제대로 반영되었습니다. 위 signup 페이지와 동일하게 잔존 사용처 확인만 마무리하면 될 것 같습니다.src/app/(auth)/kakao/transition/page.tsx (1)
1-16: 구현이 올바르게 되어 있습니다.클라이언트 전용 컴포넌트에 대한 동적 임포트와 SSR 비활성화가 OAuth 플로우에 적합하며, Suspense 래퍼 사용도 좋습니다.
src/middleware.ts (2)
3-3: 쿠키 관리 로직 중앙화가 좋습니다.
setAuthCookies유틸리티 함수 도입으로 코드 일관성이 향상되었습니다.
139-146: 토큰 갱신 로직 리팩토링이 적절합니다.수동 쿠키 설정을 유틸리티 함수로 교체하여 코드 중복을 제거하고 유지보수성을 향상시켰습니다.
src/app/api/auth/kakao/signup/route.ts (2)
85-85: 랜덤 닉네임 생성 로직이 적절합니다.UUID 기반 랜덤 닉네임 생성이 충돌 가능성을 최소화하며, 접두사
K_로 카카오 가입자임을 구분할 수 있어 좋습니다.
22-56: 에러 처리와 스키마 검증이 잘 구현되어 있습니다.백엔드 응답 검증, HTTP 상태 코드 포함 에러 처리, Zod 스키마를 통한 응답 검증이 모두 적절하게 구현되어 있습니다.
| const signInRes = await fetch( | ||
| `${process.env.API_BASE_URL}${API_ENDPOINTS.OAUTH.SIGNIN_PROVIDER('kakao')}`, | ||
| { | ||
| method: 'POST', | ||
| headers: { 'Content-Type': 'application/json' }, | ||
| body: JSON.stringify({ | ||
| token: kakaoAuthCode, | ||
| redirectUri, | ||
| }), | ||
| }, | ||
| ); |
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.
API_BASE_URL 환경 변수 검증 필요
process.env.API_BASE_URL가 설정되지 않은 경우를 처리하지 않고 있습니다. 이는 런타임 오류를 발생시킬 수 있습니다.
+ const apiBaseUrl = process.env.API_BASE_URL;
+ if (!apiBaseUrl) {
+ throw new Error('API_BASE_URL이 설정되지 않았습니다.');
+ }
+
const signInRes = await fetch(
- `${process.env.API_BASE_URL}${API_ENDPOINTS.OAUTH.SIGNIN_PROVIDER('kakao')}`,
+ `${apiBaseUrl}${API_ENDPOINTS.OAUTH.SIGNIN_PROVIDER('kakao')}`,📝 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 signInRes = await fetch( | |
| `${process.env.API_BASE_URL}${API_ENDPOINTS.OAUTH.SIGNIN_PROVIDER('kakao')}`, | |
| { | |
| method: 'POST', | |
| headers: { 'Content-Type': 'application/json' }, | |
| body: JSON.stringify({ | |
| token: kakaoAuthCode, | |
| redirectUri, | |
| }), | |
| }, | |
| ); | |
| const apiBaseUrl = process.env.API_BASE_URL; | |
| if (!apiBaseUrl) { | |
| throw new Error('API_BASE_URL이 설정되지 않았습니다.'); | |
| } | |
| const signInRes = await fetch( | |
| `${apiBaseUrl}${API_ENDPOINTS.OAUTH.SIGNIN_PROVIDER('kakao')}`, | |
| { | |
| method: 'POST', | |
| headers: { 'Content-Type': 'application/json' }, | |
| body: JSON.stringify({ | |
| token: kakaoAuthCode, | |
| redirectUri, | |
| }), | |
| }, | |
| ); |
🤖 Prompt for AI Agents
In src/app/api/auth/kakao/signin/route.ts around lines 31 to 41, the code uses
process.env.API_BASE_URL without checking if it is defined, which can cause
runtime errors. Add a validation step before the fetch call to verify that
process.env.API_BASE_URL is set; if it is not, throw an appropriate error or
handle the missing environment variable gracefully to prevent runtime failures.
🛠️ Refactor suggestion
fetch 요청에 타임아웃 설정 권장
외부 API 호출 시 네트워크 지연이나 서버 응답 지연으로 인한 무한 대기를 방지하기 위해 타임아웃을 설정하는 것이 좋습니다.
+ const controller = new AbortController();
+ const timeoutId = setTimeout(() => controller.abort(), 10000); // 10초 타임아웃
+
const signInRes = await fetch(
`${process.env.API_BASE_URL}${API_ENDPOINTS.OAUTH.SIGNIN_PROVIDER('kakao')}`,
{
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
token: kakaoAuthCode,
redirectUri,
}),
+ signal: controller.signal,
},
- );
+ ).finally(() => clearTimeout(timeoutId));📝 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 signInRes = await fetch( | |
| `${process.env.API_BASE_URL}${API_ENDPOINTS.OAUTH.SIGNIN_PROVIDER('kakao')}`, | |
| { | |
| method: 'POST', | |
| headers: { 'Content-Type': 'application/json' }, | |
| body: JSON.stringify({ | |
| token: kakaoAuthCode, | |
| redirectUri, | |
| }), | |
| }, | |
| ); | |
| const controller = new AbortController(); | |
| const timeoutId = setTimeout(() => controller.abort(), 10000); // 10초 타임아웃 | |
| const signInRes = await fetch( | |
| `${process.env.API_BASE_URL}${API_ENDPOINTS.OAUTH.SIGNIN_PROVIDER('kakao')}`, | |
| { | |
| method: 'POST', | |
| headers: { 'Content-Type': 'application/json' }, | |
| body: JSON.stringify({ | |
| token: kakaoAuthCode, | |
| redirectUri, | |
| }), | |
| signal: controller.signal, | |
| }, | |
| ).finally(() => clearTimeout(timeoutId)); |
🤖 Prompt for AI Agents
In src/app/api/auth/kakao/signin/route.ts around lines 31 to 41, the fetch
request lacks a timeout, which can cause indefinite waiting if the external API
is slow or unresponsive. Implement a timeout mechanism by using an
AbortController to abort the fetch request after a specified duration, such as 5
seconds, to prevent hanging requests.
| 'message', | ||
| error instanceof Error ? error.message : '회원가입 먼저 해주세요.', | ||
| ); |
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.
💡 Verification agent
🧩 Analysis chain
URL 쿼리 파라미터로 전달되는 에러 메시지 보안 검토
에러 메시지를 URL 쿼리 파라미터로 전달하는 것은 다음과 같은 보안 위험이 있을 수 있습니다:
- 민감한 정보가 브라우저 히스토리나 서버 로그에 노출될 수 있음
- 클라이언트에서 적절히 sanitize하지 않으면 XSS 공격에 취약할 수 있음
Also applies to: 125-126
🏁 Script executed:
#!/bin/bash
# Description: 에러 메시지가 표시되는 컴포넌트에서 적절한 sanitization이 이루어지는지 확인
# KakaoTransition 컴포넌트에서 쿼리 파라미터 처리 확인
rg -A 10 "searchParams.*message" src/domain/Auth/components/KakaoTransition.tsx src/app/\(auth\)/kakao/transition/page.tsx
# Signin 페이지에서 에러 메시지 처리 확인
rg -A 10 "searchParams.*message|error.*message" src/app/\(auth\)/signin/page.tsx src/domain/Auth/components/Length of output: 2041
XSS 및 민감 정보 노출 위험: URL 쿼리로 전달되는 에러 메시지 처리 필요
현재 구현
src/app/api/auth/kakao/signin/route.ts(114–116):raw'message', error instanceof Error ? error.message : '회원가입 먼저 해주세요.',
error.message를 쿼리 파라미터로 전달src/domain/Auth/components/KakaoTransition.tsx:const message = searchParams.get('message'); // 별도 이스케이프 없이 렌더링될 경우 XSS 공격 벡터 될 수 있음
위험
- URL 히스토리, 서버 로그에 민감 정보(스택 트레이스 등) 노출
- 클라이언트에서 별도 sanitize/escape 없이 출력 시 XSS 취약점 가능
권장 조치
- 쿼리 파라미터에는 에러 코드를 전달하고, 클라이언트에서 사용자용 메시지로 매핑
- 불가피하게 메시지를 전달할 경우
encodeURIComponent()적용 후, React의 기본 이스케이프 기능으로 렌더링 - 필요 시
DOMPurify등 라이브러리로 sanitize 검증 추가 - Sign-in 페이지(
src/app/(auth)/signin/page.tsx)에서도 동일한 패턴이 있는지 확인 후 위 조치 적용
🤖 Prompt for AI Agents
In src/app/api/auth/kakao/signin/route.ts lines 114 to 116, avoid passing raw
error.message directly as a URL query parameter to prevent XSS and sensitive
data exposure. Instead, pass a sanitized error code or identifier in the query
parameter. On the client side, map this code to a user-friendly message for
display. If passing messages is unavoidable, apply encodeURIComponent() before
adding to the URL and ensure React's escaping handles rendering safely. Also,
review src/app/(auth)/signin/page.tsx for similar patterns and apply the same
fixes.
| // const errorStatus = | ||
| // error instanceof Error && 'status' in error | ||
| // ? (error as Error & { status: number }).status | ||
| // : undefined; | ||
|
|
||
| // if (errorStatus === 409 || errorStatus === 400) { | ||
| // const redirectToTransition = new URL( | ||
| // '/kakao/transition', | ||
| // request.nextUrl.origin, | ||
| // ); | ||
| // redirectToTransition.searchParams.set('status', 'already-exists'); | ||
| // redirectToTransition.searchParams.set( | ||
| // 'message', | ||
| // error instanceof Error | ||
| // ? error.message | ||
| // : '이미 가입된 회원입니다. 로그인해주세요.', | ||
| // ); | ||
| // return NextResponse.redirect(redirectToTransition); | ||
| // } |
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.
💡 Verification agent
🧩 Analysis chain
주석 처리된 에러 핸들링 코드 정리가 필요합니다.
주석 처리된 transition 페이지 리다이렉션 로직이 있습니다. 이 기능이 향후 구현 예정인지, 아니면 제거해야 할 코드인지 명확히 하시기 바랍니다.
이 기능의 구현 상태를 확인하기 위해 다음 스크립트를 실행해보세요:
🏁 Script executed:
#!/bin/bash
# Description: Check if KakaoTransition component handles 'already-exists' status
# Search for 'already-exists' status handling in KakaoTransition component
rg -A 5 -B 5 "already-exists" src/domain/Auth/components/KakaoTransition.tsx
# Search for similar error handling patterns in signin route
rg -A 5 -B 5 "transition" src/app/api/auth/kakao/signin/route.tsLength of output: 801
불필요한 주석 정리 또는 기능 구현 결정 필요
src/app/api/auth/kakao/signup/route.ts의 101–119라인에 409/400 에러 발생 시 /kakao/transition?status=already-exists로 리다이렉트하는 주석 처리된 코드가 남아 있습니다. 하지만 src/domain/Auth/components/KakaoTransition.tsx는 현재 need-signup만 처리하며, already-exists 상태에 대한 핸들링이 없습니다.
다음 중 하나를 선택해 주세요:
- 기능 구현
- signup 라우트에서 409/400 에러 처리 로직 주석 해제
- KakaoTransition 컴포넌트에
already-exists상태에 대한 UI/메시지 추가
- 기능 제거
- 위 주석 코드를 삭제
점검이 필요한 위치:
- src/app/api/auth/kakao/signup/route.ts (라인 101–119)
- src/domain/Auth/components/KakaoTransition.tsx
🤖 Prompt for AI Agents
In src/app/api/auth/kakao/signup/route.ts lines 101 to 119, decide whether to
implement or remove the commented-out error handling code for 409/400 status
redirecting to /kakao/transition with status=already-exists. To implement,
uncomment this code and add UI/message handling for the already-exists status in
src/domain/Auth/components/KakaoTransition.tsx. To remove, delete the commented
code entirely from the signup route file.
| const KAKAO_REDIRECT_URI = process.env.NEXT_PUBLIC_KAKAO_SIGNUP_REDIRECT_URI!; | ||
| const KAKAO_CLIENT_ID = process.env.NEXT_PUBLIC_KAKAO_REST_API_KEY!; | ||
|
|
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 KAKAO_REDIRECT_URI = process.env.NEXT_PUBLIC_KAKAO_SIGNUP_REDIRECT_URI!;
-const KAKAO_CLIENT_ID = process.env.NEXT_PUBLIC_KAKAO_REST_API_KEY!;
+const KAKAO_REDIRECT_URI = process.env.NEXT_PUBLIC_KAKAO_SIGNUP_REDIRECT_URI;
+const KAKAO_CLIENT_ID = process.env.NEXT_PUBLIC_KAKAO_REST_API_KEY;
+
+if (!KAKAO_REDIRECT_URI || !KAKAO_CLIENT_ID) {
+ throw new Error('카카오 OAuth 환경 변수가 설정되지 않았습니다.');
+}📝 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 KAKAO_REDIRECT_URI = process.env.NEXT_PUBLIC_KAKAO_SIGNUP_REDIRECT_URI!; | |
| const KAKAO_CLIENT_ID = process.env.NEXT_PUBLIC_KAKAO_REST_API_KEY!; | |
| const KAKAO_REDIRECT_URI = process.env.NEXT_PUBLIC_KAKAO_SIGNUP_REDIRECT_URI; | |
| const KAKAO_CLIENT_ID = process.env.NEXT_PUBLIC_KAKAO_REST_API_KEY; | |
| if (!KAKAO_REDIRECT_URI || !KAKAO_CLIENT_ID) { | |
| throw new Error('카카오 OAuth 환경 변수가 설정되지 않았습니다.'); | |
| } |
🤖 Prompt for AI Agents
In src/domain/Auth/components/KakaoTransition.tsx around lines 9 to 11, the
environment variables KAKAO_REDIRECT_URI and KAKAO_CLIENT_ID are accessed with
non-null assertions but lack runtime validation. Add checks to verify these
environment variables are defined at runtime, and throw an error or handle the
missing case gracefully to prevent runtime failures due to missing environment
variables.
ea0b23a to
ed2ebee
Compare
9053e81 to
bda0d7c
Compare
✅ Preview Deployment Ready!🔗 Preview URL: https://roam-ready-63tuizhux-yongmins-projects-bf5f7733.vercel.app This preview will be automatically updated on new commits. |
b7fb2b9 to
4f08ab6
Compare
…-15-Part4-Team1/RoamReady into feat/473/oauth-unified
✅ Preview Deployment Ready!🔗 Preview URL: https://roam-ready-kbi5i89nr-yongmins-projects-bf5f7733.vercel.app This preview will be automatically updated on new commits. |
👻 관련 이슈 번호
👻 요약
👻 주요 변경 사항
👻 체크리스트
📷 UI 변경 사항
👻 문제 사항
👻 논의 사항
👻 기타 참고 사항
Summary by CodeRabbit
신규 기능
기능 개선
버그 수정
문서 및 설정