Skip to content
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

[feat] 카카오 , 구글 로그인 구현 완료 #78

Merged
merged 7 commits into from
Mar 16, 2025

Conversation

JaeIn1
Copy link
Collaborator

@JaeIn1 JaeIn1 commented Mar 13, 2025

📌 개요

  • 카카오 , 구글 로그인 구현

📋 변경사항

  • 소셜 로그인 callback 페이지 경로 수정
    • 기존 경로: /app/auth/[provider]
    • 수정 경로: /app/api/auth/callback/[provider]

기능

  • 카카오 , 구글 로그인 구현 완료

화면

기능 스크린샷

전달사항

  • .env값은 슬랙에 공유하도록 하겠습니다.

✅ 체크사항

  • 기능이 정상적으로 동작하는지 확인
  • 코드 스타일 및 규칙 준수 확인
  • UI가 변경된 경우 스크린샷 첨부 여부 확인

Summary by CodeRabbit

  • 신규 기능

    • 소셜 로그인을 위한 새로운 인증 구성 시스템이 도입되어, 주요 제공자별 인증 URL이 자동으로 생성됩니다.
    • 환경 변수 검증 기능이 추가되어, 인증 설정의 신뢰성이 향상되었습니다.
  • 리팩토링

    • 로그인 버튼이 링크 기반 네비게이션으로 전환되어, 로그인 경험이 개선되었습니다.
    • 불필요한 페이지와 중복 로그인 처리 로직이 정리되어 시스템이 간소화되었습니다.
    • 카카오 로그인 관련 기능이 제거되어, 코드가 간결해졌습니다.

@JaeIn1 JaeIn1 added the 🚀 feature 새로운 기능 개발 label Mar 13, 2025
@JaeIn1 JaeIn1 self-assigned this Mar 13, 2025
Copy link

coderabbitai bot commented Mar 13, 2025

📝 Walkthrough

Walkthrough

이번 PR에서는 불필요한 파일과 함수들을 삭제하고, 소셜 로그인 기능의 구성을 개선하는 변경 사항이 포함되었습니다. 구체적으로, 메인 페이지와 Kakao 로그인 기능을 담당하던 파일이 제거되었으며, 로그인 제공자 설정이 수정되었습니다. 또한, 인증 설정을 위한 새로운 구성 파일과 환경 변수 유효성 검증 함수를 제공하는 유틸리티 파일이 추가되었고, 로그인 버튼 컴포넌트는 버튼 이벤트에서 링크 기반 네비게이션으로 변경되었습니다.

Changes

파일 변경 요약
src/app/main/page.tsx 간단한 React 컴포넌트를 포함한 메인 페이지 파일이 삭제되었습니다.
src/features/auth/login/model/providers/kakao.ts Kakao 로그인 프로세스를 시작하던 kakaoLogin 함수가 포함된 파일이 삭제되었습니다.
src/features/auth/login/config/loginProviderConfig.ts KakaoConfig 타입이 추가되고, loginFn 속성이 주석 처리되어 기존 함수 할당이 제거되었습니다.
src/features/auth/login/config/authConfig.ts 소셜 로그인 인증을 위한 설정 파일이 새로 추가되었으며, 인증 URL 생성 로직 및 환경 변수 기반 설정을 포함합니다.
src/features/auth/login/ui/LoginButton.tsx 로그인 버튼 컴포넌트가 Link를 사용하여 네비게이션 방식으로 변경되고, getAuthUrl을 통해 인증 URL을 가져오는 로직으로 개편되었습니다.
src/features/auth/login/utils/envVaild.ts 환경 변수 유효성을 확인하기 위한 requiredoptional 함수가 포함된 새로운 유틸리티 파일이 추가되었습니다.

Sequence Diagram(s)

sequenceDiagram
    participant U as 사용자
    participant LB as LoginButton 컴포넌트
    participant AC as AuthConfig 모듈
    participant SP as 소셜 인증 제공자

    U->>LB: 소셜 로그인 링크 클릭
    LB->>AC: getAuthUrl[provider]() 호출
    AC-->>LB: 인증 URL 반환
    LB->>U: Link를 통한 사용자 리디렉션
    U->>SP: 소셜 로그인 프로세스 시작
Loading

Suggested reviewers

  • jangwonyoon
  • youngju6143
  • evenway2025

Tip

⚡🧪 Multi-step agentic review comment chat (experimental)
  • We're introducing multi-step agentic chat in review comments. This experimental feature enhances review discussions with the CodeRabbit agentic chat by enabling advanced interactions, including the ability to create pull requests directly from comments.
    - To enable this feature, set early_access to true under in the settings.

📜 Recent review details

Configuration used: .coderabbit.yml
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 29fe833 and 9f96711.

📒 Files selected for processing (1)
  • src/features/auth/login/config/authConfig.ts (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • src/features/auth/login/config/authConfig.ts

🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Generate unit testing code for this file.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query. Examples:
    • @coderabbitai generate unit testing code for this file.
    • @coderabbitai modularize this function.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read src/utils.ts and generate unit testing code.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.
    • @coderabbitai help me debug CodeRabbit configuration file.

Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments.

CodeRabbit Commands (Invoked using PR comments)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai full review to do a full review from scratch and review all the files again.
  • @coderabbitai summary to regenerate the summary of the PR.
  • @coderabbitai generate docstrings to generate docstrings for this PR.
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai configuration to show the current CodeRabbit configuration for the repository.
  • @coderabbitai help to get help.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

Documentation and Community

  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 0

🧹 Nitpick comments (1)
src/features/auth/login/model/providers/google.ts (1)

1-12: 구글 로그인 기능 구현이 완료되었습니다.

구글 로그인 기능이 잘 구현되었습니다. 환경 변수 검증 및 오류 처리도 잘 되어 있습니다. 다만 몇 가지 개선 사항을 제안합니다:

  1. NEXT_PUBLIC_GOOGLE_REDIRECT_URI_LOCAL이라는 이름은 로컬 개발 환경만을 위한 것으로 보입니다. 프로덕션 환경을 위한 리다이렉트 URI도 필요할 것 같습니다.
  2. 콘솔 오류 메시지만으로는 사용자가 문제를 인지하기 어렵습니다. 사용자에게 표시할 오류 처리 방법을 추가하는 것이 좋겠습니다.
export const googleLogin = () => {
  const clientId = process.env.NEXT_PUBLIC_GOOGLE_CLIENT_ID;
-  const redirectUri = process.env.NEXT_PUBLIC_GOOGLE_REDIRECT_URI_LOCAL;
+  // 환경에 따라 적절한 리다이렉트 URI 사용
+  const redirectUri = process.env.NODE_ENV === 'production' 
+    ? process.env.NEXT_PUBLIC_GOOGLE_REDIRECT_URI 
+    : process.env.NEXT_PUBLIC_GOOGLE_REDIRECT_URI_LOCAL;

  if (!clientId || !redirectUri) {
    console.error('구글 로그인 설정이 잘못되었습니다.');
+    // 사용자에게 오류 표시를 위한 처리 추가
+    // 예: 오류 상태 설정 또는 토스트 메시지 표시
    return;
  }

  const googleAuthUrl = `https://accounts.google.com/o/oauth2/v2/auth?client_id=${clientId}&redirect_uri=${redirectUri}&response_type=code&scope=email profile`;
  window.location.href = googleAuthUrl;
};
📜 Review details

Configuration used: .coderabbit.yml
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between f99275c and 69f5202.

📒 Files selected for processing (3)
  • src/app/main/page.tsx (0 hunks)
  • src/features/auth/login/config/loginProviderConfig.ts (2 hunks)
  • src/features/auth/login/model/providers/google.ts (1 hunks)
💤 Files with no reviewable changes (1)
  • src/app/main/page.tsx
🔇 Additional comments (2)
src/features/auth/login/config/loginProviderConfig.ts (2)

1-1: 구글 로그인 import 구문이 추가되었습니다.

구글 로그인 함수를 가져오는 import 구문이 잘 추가되었습니다.


27-27: 구글 로그인 함수가 올바르게 설정되었습니다.

loginFn이 카카오 로그인에서 구글 로그인으로 정상적으로 변경되었습니다. 주석에 명시된 대로 변경이 이루어졌습니다.

참고: 35번 라인의 Apple 로그인 함수도 향후 appleLogin으로 변경될 예정인 것으로 보입니다. 이 부분도 구현이 완료되면 업데이트가 필요합니다.

Copy link
Collaborator

@semnil5202 semnil5202 left a comment

Choose a reason for hiding this comment

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

넵넵 확인했습니다. 👍👍👍

로컬에서 로그인 확인 가능하던가요??

@JaeIn1
Copy link
Collaborator Author

JaeIn1 commented Mar 14, 2025

네 구글, 카카오 모두 토큰 정상적으로 저장 되고있습니다 😊

Copy link
Collaborator

@youngju6143 youngju6143 left a comment

Choose a reason for hiding this comment

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

수고 많으셨어요!! 👍

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 2

🧹 Nitpick comments (5)
src/features/auth/login/ui/LoginButton.tsx (2)

42-42: console.log 제거 필요

디버깅 목적의 console.log는 배포 전에 제거하는 것이 좋습니다. 프로덕션 환경에서는 로그가 남지 않도록 해주세요.

- console.log('authUrl : ' + authUrl);

45-47: 버튼에서 링크로 적절하게 변경

버튼 요소에서 앵커(<a>) 요소로 변경하여 직접 인증 URL로 이동하도록 구현한 것은 적절합니다. 하지만 웹 접근성을 위해 다음과 같은 속성을 추가하는 것이 좋습니다:

<a
  href={authUrl}
+ rel="noopener noreferrer"
+ target="_blank"
  className={`flex w-full items-center justify-center rounded-md ${config.bgColor} px-4 py-[15px] ${config.textColor}`}
>
src/features/auth/login/config/authConfig.ts (3)

34-48: 리다이렉트 URL 로직 개선 가능

현재 getRedirectUrl 함수는 switch 문을 사용하여 각 제공자별로 리다이렉트 URL을 반환합니다. 코드를 더 간결하게 만들기 위해 직접 해당 속성에 접근하는 방식으로 리팩토링할 수 있습니다.

export const getRedirectUrl = (provider: SocialProvider): string => {
-  switch (provider) {
-    case 'KAKAO':
-      return providerEnvConfig.KAKAO.redirectUrl;
-    case 'GOOGLE':
-      return providerEnvConfig.GOOGLE.redirectUrl;
-    case 'APPLE':
-      return providerEnvConfig.APPLE.redirectUrl;
-    default:
-      return '';
-  }
+  return providerEnvConfig[provider]?.redirectUrl || '';
};

50-77: 인증 URL 생성 함수 중복 코드 개선

각 제공자별 인증 URL 생성 코드에 중복이 있습니다. 공통 로직을 추출하여 코드 중복을 줄이고 유지보수성을 높일 수 있습니다.

export const getAuthUrl = {
+  _createUrl: (baseUrl: string, params: Record<string, string>) => {
+    const queryParams = Object.entries(params)
+      .map(([key, value]) => 
+        key === 'scope' && value ? 
+          `${key}=${encodeURIComponent(value)}` : 
+          `${key}=${value}`
+      )
+      .join('&');
+    return `${baseUrl}?${queryParams}`;
+  },

  KAKAO: () => {
    const { restApiKey } = providerEnvConfig.KAKAO;
    const redirectUrl = getRedirectUrl('KAKAO');
    const scope = providerEnvConfig.KAKAO.scope;

-    return `${AUTH_BASE_URLS.KAKAO}?client_id=${restApiKey}&redirect_uri=${redirectUrl}&response_type=code&scope=${scope}`;
+    return getAuthUrl._createUrl(AUTH_BASE_URLS.KAKAO, {
+      client_id: restApiKey,
+      redirect_uri: redirectUrl,
+      response_type: 'code',
+      scope
+    });
  },

  GOOGLE: () => {
    const { clientId } = providerEnvConfig.GOOGLE;
    const redirectUrl = getRedirectUrl('GOOGLE');
    const scope = providerEnvConfig.GOOGLE.scope;

-    return `${AUTH_BASE_URLS.GOOGLE}?client_id=${clientId}&redirect_uri=${redirectUrl}&response_type=code&scope=${encodeURIComponent(scope)}`;
+    return getAuthUrl._createUrl(AUTH_BASE_URLS.GOOGLE, {
+      client_id: clientId,
+      redirect_uri: redirectUrl,
+      response_type: 'code',
+      scope
+    });
  },

  // APPLE도 동일하게 수정
};

1-77: 전체적인 구조와 보안 고려사항

전반적인 파일 구조와 인증 URL 생성 로직은 잘 구현되었습니다. 그러나 다음 사항을 고려해 보세요:

  1. 현재 코드에서는 scope 값 외에는 URL 파라미터에 대한 인코딩이 되지 않고 있습니다. 모든 URL 파라미터에 대해 encodeURIComponent를 적용하는 것이 안전합니다.

  2. 각 제공자의 상태(state) 파라미터를 추가하여 CSRF 공격을 방지하는 것이 좋습니다. 특히 OAuth 인증에서는 이 값을 사용하여 요청과 응답의 일치 여부를 확인합니다.

  3. 각 소셜 로그인 별로 오류 처리 로직을 추가하는 것을 고려해보세요.

📜 Review details

Configuration used: .coderabbit.yml
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 69f5202 and 4ef6f84.

📒 Files selected for processing (4)
  • src/features/auth/login/config/authConfig.ts (1 hunks)
  • src/features/auth/login/config/loginProviderConfig.ts (1 hunks)
  • src/features/auth/login/model/providers/kakao.ts (0 hunks)
  • src/features/auth/login/ui/LoginButton.tsx (2 hunks)
💤 Files with no reviewable changes (1)
  • src/features/auth/login/model/providers/kakao.ts
🚧 Files skipped from review as they are similar to previous changes (1)
  • src/features/auth/login/config/loginProviderConfig.ts
🔇 Additional comments (3)
src/features/auth/login/ui/LoginButton.tsx (2)

8-8: 적절한 import 추가

getAuthUrl 함수를 import 하여 소셜 로그인 URL을 가져오는 패턴으로 변경한 것은 좋은 접근 방식입니다.


40-41: 소셜 로그인 URL 생성 로직 구현

소셜 로그인 제공자에 따라 동적으로 인증 URL을 생성하는 방식으로 변경한 것은 좋습니다. 이렇게 함으로써 각 제공자별 로그인 로직이 분리되어 유지보수성이 향상됩니다.

src/features/auth/login/config/authConfig.ts (1)

1-11: 인증 URL 상수 정의 적절

각 소셜 로그인 제공자별 인증 기본 URL을 상수로 정의한 것은 좋은 접근 방식입니다. 코드의 가독성과 유지보수성이 향상됩니다.

Comment on lines 13 to 32
/**
* 각 소셜 로그인 제공자별 환경 변수 설정
*/
export const providerEnvConfig = {
KAKAO: {
restApiKey: process.env.NEXT_PUBLIC_KAKAO_REST_API_KEY || '',
redirectUrl: process.env.NEXT_PUBLIC_KAKAO_REDIRECT_URI_LOCAL || '',
scope: '',
},
GOOGLE: {
clientId: process.env.NEXT_PUBLIC_GOOGLE_CLIENT_ID || '',
redirectUrl: process.env.NEXT_PUBLIC_GOOGLE_REDIRECT_URI_LOCAL || '',
scope: 'email profile',
},
APPLE: {
clientId: process.env.NEXT_PUBLIC_APPLE_CLIENT_ID || '',
redirectUrl: process.env.NEXT_PUBLIC_APPLE_REDIRECT_URI_LOCAL || '',
scope: 'email profile',
},
};
Copy link

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

환경 변수 설정 및 예외 처리

환경 변수를 통해 설정 값들을 관리하는 것은 좋습니다. 하지만 환경 변수가 없을 경우 빈 문자열('')로 설정하고 있어, 이로 인해 런타임 에러가 발생할 수 있습니다. 환경 변수가 없을 때의 예외 처리를 추가하고, 빈 값이면 경고를 표시하는 로직을 고려해보세요.

export const providerEnvConfig = {
  KAKAO: {
    restApiKey: process.env.NEXT_PUBLIC_KAKAO_REST_API_KEY || '',
    redirectUrl: process.env.NEXT_PUBLIC_KAKAO_REDIRECT_URI_LOCAL || '',
    scope: '',
  },
  // ... 다른 제공자들
};

+ // 환경 변수 유효성 검사
+ const validateEnvConfig = () => {
+   if (!providerEnvConfig.KAKAO.restApiKey) {
+     console.warn('카카오 REST API Key가 설정되지 않았습니다.');
+   }
+   if (!providerEnvConfig.KAKAO.redirectUrl) {
+     console.warn('카카오 리다이렉트 URL이 설정되지 않았습니다.');
+   }
+   // 구글, 애플도 유사하게 체크
+ };
+ 
+ // 앱 초기화 시 유효성 검사 실행
+ validateEnvConfig();
📝 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
/**
* 소셜 로그인 제공자별 환경 변수 설정
*/
export const providerEnvConfig = {
KAKAO: {
restApiKey: process.env.NEXT_PUBLIC_KAKAO_REST_API_KEY || '',
redirectUrl: process.env.NEXT_PUBLIC_KAKAO_REDIRECT_URI_LOCAL || '',
scope: '',
},
GOOGLE: {
clientId: process.env.NEXT_PUBLIC_GOOGLE_CLIENT_ID || '',
redirectUrl: process.env.NEXT_PUBLIC_GOOGLE_REDIRECT_URI_LOCAL || '',
scope: 'email profile',
},
APPLE: {
clientId: process.env.NEXT_PUBLIC_APPLE_CLIENT_ID || '',
redirectUrl: process.env.NEXT_PUBLIC_APPLE_REDIRECT_URI_LOCAL || '',
scope: 'email profile',
},
};
/**
* 소셜 로그인 제공자별 환경 변수 설정
*/
export const providerEnvConfig = {
KAKAO: {
restApiKey: process.env.NEXT_PUBLIC_KAKAO_REST_API_KEY || '',
redirectUrl: process.env.NEXT_PUBLIC_KAKAO_REDIRECT_URI_LOCAL || '',
scope: '',
},
GOOGLE: {
clientId: process.env.NEXT_PUBLIC_GOOGLE_CLIENT_ID || '',
redirectUrl: process.env.NEXT_PUBLIC_GOOGLE_REDIRECT_URI_LOCAL || '',
scope: 'email profile',
},
APPLE: {
clientId: process.env.NEXT_PUBLIC_APPLE_CLIENT_ID || '',
redirectUrl: process.env.NEXT_PUBLIC_APPLE_REDIRECT_URI_LOCAL || '',
scope: 'email profile',
},
};
// 환경 변수 유효성 검사
const validateEnvConfig = () => {
if (!providerEnvConfig.KAKAO.restApiKey) {
console.warn('카카오 REST API Key가 설정되지 않았습니다.');
}
if (!providerEnvConfig.KAKAO.redirectUrl) {
console.warn('카카오 리다이렉트 URL이 설정되지 않았습니다.');
}
// 구글, 애플도 유사하게 체크
};
// 앱 초기화 시 유효성 검사 실행
validateEnvConfig();

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 0

🧹 Nitpick comments (1)
src/features/auth/login/ui/LoginButton.tsx (1)

43-43: 프로덕션 코드에서 콘솔 로그 제거 필요.

디버깅 목적의 콘솔 로그는 개발 과정에서는 유용하지만, 프로덕션 배포 전에 제거하는 것이 좋습니다.

- console.log('authUrl : ' + authUrl);
📜 Review details

Configuration used: .coderabbit.yml
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 4ef6f84 and e5eceff.

📒 Files selected for processing (1)
  • src/features/auth/login/ui/LoginButton.tsx (2 hunks)
🔇 Additional comments (4)
src/features/auth/login/ui/LoginButton.tsx (4)

4-4: Link 컴포넌트 도입으로 네비게이션 기능 개선.

Next.js의 Link 컴포넌트를 사용하여 사용자를 인증 URL로 리다이렉션하는 좋은 접근 방식입니다. 이는 OAuth 인증 흐름에 적합합니다.


9-9: 인증 URL 설정을 별도 파일로 분리한 점이 좋습니다.

인증 URL 로직을 별도의 설정 파일로 분리하는 것은 관심사의 분리(separation of concerns) 원칙을 잘 반영한 설계입니다.


41-42: 동적 인증 URL 생성 로직 구현.

제공자(provider)에 따라 적절한 인증 URL을 동적으로 가져오는 방식으로 잘 구현되었습니다.


46-48: 버튼에서 Link 컴포넌트로의 전환.

기존 버튼 대신 Link 컴포넌트를 사용하여 소셜 로그인 흐름을 구현한 것은 좋은 개선입니다. 이러한 접근 방식은 OAuth 인증 흐름에 더 적합하며, 사용자 경험을 향상시킵니다.

Also applies to: 52-52

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🧹 Nitpick comments (1)
src/features/auth/login/ui/LoginButton.tsx (1)

44-46: 버튼에서 Link 컴포넌트로 마이그레이션.

기존 버튼에서 next/link의 Link 컴포넌트로 변경한 것은 적절한 선택입니다. 이는 다음과 같은 이점을 제공합니다:

  1. 클라이언트 측 라우팅 최적화
  2. 사전 페이지 로딩 지원
  3. 접근성 향상

다만, Link 컴포넌트에 추가할 수 있는 다음 속성들을 고려해볼 수 있습니다:

<Link
  href={authUrl}
+ prefetch={false}
+ target="_blank"
+ rel="noopener noreferrer"
  className={`flex w-full items-center justify-center rounded-md ${config.bgColor} px-4 py-[15px] ${config.textColor}`}
>
  • prefetch={false}: 소셜 로그인 페이지는 미리 로드할 필요가 없습니다.
  • target="_blank": 로그인 페이지를 새 탭에서 열어 기존 상태를 유지할 수 있습니다.
  • rel="noopener noreferrer": 새 탭 열 때의 보안 취약점 방지를 위한 속성입니다.
📜 Review details

Configuration used: .coderabbit.yml
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between e5eceff and 29fe833.

📒 Files selected for processing (3)
  • src/features/auth/login/config/authConfig.ts (1 hunks)
  • src/features/auth/login/ui/LoginButton.tsx (2 hunks)
  • src/features/auth/login/utils/envVaild.ts (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • src/features/auth/login/config/authConfig.ts
🔇 Additional comments (5)
src/features/auth/login/ui/LoginButton.tsx (4)

4-4: next/link 컴포넌트 활용으로 네비게이션 개선.

Link 컴포넌트를 가져와서 소셜 로그인 버튼을 클릭하여 인증 URL로 이동하는 방식으로 변경한 점이 좋습니다. 이는 내비게이션에 최적화된 Next.js의 권장 방식입니다.


9-9: 인증 URL 구성 분리로 코드 모듈화 개선.

인증 URL을 가져오는 로직을 별도의 authConfig 파일로 분리하여 코드 모듈화와 관심사 분리를 잘 구현했습니다. 이렇게 함으로써 소셜 로그인 설정이 변경되더라도 컴포넌트 수정 없이 설정 파일만 수정하면 되므로 유지보수성이 향상됩니다.


41-41: 제공자별 인증 URL 동적 설정 구현.

getAuthUrl[provider]() 방식으로 동적으로 소셜 로그인 제공자에 맞는 인증 URL을 가져오는 접근 방식이 효율적입니다. 이는 코드 중복을 줄이고 새로운 로그인 제공자 추가 시 확장성을 제공합니다.


50-50: Link 컴포넌트 구조 변경 완료.

컴포넌트 구조를 일관되게 유지하며 닫는 태그까지 적절하게 변경하였습니다.

src/features/auth/login/utils/envVaild.ts (1)

1-6: 환경 변수 유효성 검사 함수가 잘 구현되었습니다.

환경 변수가 정의되어 있는지 확인하고 적절한 오류 메시지를 표시하는 함수입니다. 코드가 간결하고 목적에 맞게 잘 작성되었습니다.

Comment on lines +8 to +13
export function optional(value: string | undefined, defaultValue: string = '') {
if (value === undefined) {
throw new Error('scope가 설정되지 않았습니다');
}
return value || defaultValue;
}
Copy link

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

optional 함수의 이름과 동작이 일치하지 않습니다.

함수 이름이 optional이지만 valueundefined인 경우 오류를 발생시키고 있습니다. 또한 오류 메시지가 "scope가 설정되지 않았습니다"로 특정 사용 사례에 맞춰져 있어 범용적인 유틸리티 함수로 사용하기 어렵습니다.

아래와 같이 수정하는 것을 고려해보세요:

-export function optional(value: string | undefined, defaultValue: string = '') {
-  if (value === undefined) {
-    throw new Error('scope가 설정되지 않았습니다');
-  }
-  return value || defaultValue;
+export function optional(value: string | undefined, defaultValue: string = '') {
+  return value || defaultValue;
+}
+
+export function validateScope(scope: string | undefined, defaultValue: string = '') {
+  if (scope === undefined) {
+    throw new Error('scope가 설정되지 않았습니다');
+  }
+  return scope || defaultValue;
}

또는 범용적인 함수로 사용하려면:

-export function optional(value: string | undefined, defaultValue: string = '') {
-  if (value === undefined) {
-    throw new Error('scope가 설정되지 않았습니다');
-  }
-  return value || defaultValue;
+export function optional(value: string | undefined, defaultValue: string = '') {
+  return value || defaultValue;
+}
+
+export function requiredWithIdentifier(key: string, value: string | undefined, defaultValue: string = '') {
+  if (value === undefined) {
+    throw new Error(`${key}가 설정되지 않았습니다`);
+  }
+  return value || defaultValue;
}
📝 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
export function optional(value: string | undefined, defaultValue: string = '') {
if (value === undefined) {
throw new Error('scope가 설정되지 않았습니다');
}
return value || defaultValue;
}
export function optional(value: string | undefined, defaultValue: string = '') {
return value || defaultValue;
}
export function validateScope(scope: string | undefined, defaultValue: string = '') {
if (scope === undefined) {
throw new Error('scope가 설정되지 않았습니다');
}
return scope || defaultValue;
}
Suggested change
export function optional(value: string | undefined, defaultValue: string = '') {
if (value === undefined) {
throw new Error('scope가 설정되지 않았습니다');
}
return value || defaultValue;
}
export function optional(value: string | undefined, defaultValue: string = '') {
return value || defaultValue;
}
export function requiredWithIdentifier(key: string, value: string | undefined, defaultValue: string = '') {
if (value === undefined) {
throw new Error(`${key}가 설정되지 않았습니다`);
}
return value || defaultValue;
}

@JaeIn1 JaeIn1 merged commit 66d3062 into develop Mar 16, 2025
2 checks passed
@JaeIn1 JaeIn1 deleted the feat/#77-google-login branch March 16, 2025 07:49
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
🚀 feature 새로운 기능 개발
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants