dev💻/프론트엔드

[React, Typescript] 구글 로그인

귤랑귤랑 2024. 10. 6. 15:35

Google Identity Services로의 마이그레이션

 
 

2023년 3월 이후, Google Sign-in platform library는 deprecated 되었으며, Google Identity Services library로 대체되었습니다. 기존에 사용하던 react-google-login 라이브러리를 삭제하고 새로운 라이브러리로 마이그레이션을 진행하였습니다. 이 글에서는 Google Identity Services를 활용한 Google 로그인 구현 방법을 설명합니다.

 

1. 사전 준비

GCP에서 Client ID 발급

Google Cloud Platform에서 Client ID를 발급받아야 합니다. 이 과정은 생략하였으며, 관련 자료는 구글링을 통해 쉽게 찾을 수 있습니다.
 
2. Google Login 구현

2.1. Typescript 설정 (google.d.ts)

Google Identity Services는 타입을 제공하지 않으므로, 필요한 타입을 직접 선언해야 합니다. .d.ts 파일을 생성하여 window.google 타입을 정의합니다.

구글에서 공식적으로 타입을 제공하진 않지만 인터넷 상에서 공유된 것이 있었습니다. reference를 참고하여 필요한 것을 추가하였습니다.

interface IdConfiguration {
  client_id: string;
  auto_select?: boolean;
  callback: (handleCredentialResponse: CredentialResponse) => void;
  login_uri?: string;
  native_callback?: (...args: any[]) => void;
  cancel_on_tap_outside?: boolean;
  prompt_parent_id?: string;
  nonce?: string;
  context?: string;
  state_cookie_domain?: string;
  ux_mode?: 'popup' | 'redirect';
  allowed_parent_origin?: string | string[];
  intermediate_iframe_close_callback?: (...args: any[]) => void;
}

interface ICredential {
  iss: string; // The JWT's issuer
  nbf: number;
  aud: string; // Your server's client ID
  sub: string; // The unique ID of the user's Google Account
  hd: string; // If present, the host domain of the user's GSuite email address
  email: string; // The user's email address
  email_verified: boolean; // true, if Google has verified the email address
  azp: string;
  name: string; // If present, a URL to user's profile picture
  picture: string;
  given_name: string;
  family_name: string;
  iat: number; // Unix timestamp of the assertion's creation time
  exp: number; // Unix timestamp of the assertion's expiration time
  jti: string;
}

interface CredentialResponse {
  credential?: string;
  select_by?:
    | 'auto'
    | 'user'
    | 'user_1tap'
    | 'user_2tap'
    | 'btn'
    | 'btn_confirm'
    | 'brn_add_session'
    | 'btn_confirm_add_session';
  clientId?: string;
}

interface GsiButtonConfiguration {
  type: 'standard' | 'icon';
  theme?: 'outline' | 'filled_blue' | 'filled_black';
  size?: 'large' | 'medium' | 'small';
  text?: 'signin_with' | 'signup_with' | 'continue_with' | 'signup_with';
  shape?: 'rectangular' | 'pill' | 'circle' | 'square';
  logo_alignment?: 'left' | 'center';
  width?: string;
  local?: string;
}

interface PromptMomentNotification {
  isDisplayMoment: () => boolean;
  isDisplayed: () => boolean;
  isNotDisplayed: () => boolean;
  getNotDisplayedReason: () =>
    | 'browser_not_supported'
    | 'invalid_client'
    | 'missing_client_id'
    | 'opt_out_or_no_session'
    | 'secure_http_required'
    | 'suppressed_by_user'
    | 'unregistered_origin'
    | 'unknown_reason';
  isSkippedMoment: () => boolean;
  getSkippedReason: () =>
    | 'auto_cancel'
    | 'user_cancel'
    | 'tap_outside'
    | 'issuing_failed';
  isDismissedMoment: () => boolean;
  getDismissedReason: () =>
    | 'credential_returned'
    | 'cancel_called'
    | 'flow_restarted';
  getMomentType: () => 'display' | 'skipped' | 'dismissed';
}

interface RevocationResponse {
  successful: boolean;
  error: string;
}

interface Credential {
  id: string;
  password: string;
}

interface Google {
  accounts: {
    id: {
      initialize: (input: IdConfiguration) => void;
      prompt: (
        momentListener?: (res: PromptMomentNotification) => void,
      ) => void;
      renderButton: (
        parent: HTMLElement,
        options: GsiButtonConfiguration,
      ) => void;
      disableAutoSelect: () => void;
      storeCredential: (credentials: Credential, callback: () => void) => void;
      cancel: () => void;
      onGoogleLibraryLoad: () => void;
      revoke: (
        hint: string,
        callback: (done: RevocationResponse) => void,
      ) => void;
    };
  };
}

interface Window {
  google?: Google;
}
2.2. index.html 설정

Google Identity Services를 사용하기 위해 index.html 파일에 스크립트를 추가합니다.

2.3. GoogleLogin 컴포넌트 구현

React 컴포넌트에서 Google 로그인 버튼을 렌더링하고, 로그인 성공 시 콜백을 처리합니다.

유저 데이터가 JWT 형태로 리턴되도록 변경되었기 때문에 decode가 필요합니다.

3. 참고 자료

 

 

 

 

 

 

틀린 부분이 있다면 알려주시면 감사하겠습니다!