본문 바로가기
개발 및 알고리즘/알고리즘

[React Native] 리액트 네이티브에서 구글로그인 구현하기 (@react-native-google-signin/google-signin)

by 0xseo 2024. 7. 23.
반응형

 

 

 

리액트 네이티브 (안드로이드, ios)에서 구글로그인을 하는 방법을 정리하고자 한다.

 

구글 클라우드 콘솔에서 새 프로젝트를 생성한다.

왼쪽 위를 보면 드롭다운이 있다.

 

새 프로젝트를 생성한다.

 

프로젝트의 이름을 설정한다.

 

잠깐의 시간이 지나고 생성되었다는 팝업이 뜨면 아까 그 드롭다운을 눌러 생성한 프로젝트 콘솔로 들어간다.

 

 

왼쪽 사이드바를 열어서 API & Services (API 및 서비스) > Credentials (사용자 인증 정보)

 

Create Credentials > OAuth client ID

 

동의 화면을 설정해야 한다고 나온다. 설정하러 가보자.

 

유저타입: 외부

 

앱 이름과 이메일, 개발자 이메일을 설정한다.

 

 

그 외 범위, 테스트 유저 등은 일단 설정하지 않는다.

 

 

 

동의 화면이 설정되면 다시 아까처럼 API & Services (API 및 서비스) > Credentials (사용자 인증 정보) > CREATE CREDENTIALS > OAuth client ID

 


Application type을 설정해야 한다.
우리는 4가지 타입을 지정해줄 것이다.

  1. Web application
  2. Android (for debug)
  3. Android (for release)
  4. iOS

1. Web application

별로 할 건 없고 바로 create하면 된다.

 

 

여기서 나오는 client ID, client secret은 잘 복사해두자. 잃어버릴 것을 대비해서 json을 다운받아 놓는다.

 

2. Android (for debug)

마찬가지로 create credentials > OAuth client ID > Android

여긴 입력할 게 있다.

우선 Package name은 써 있는 것처럼 android/app/src/main/AndroidManifest.xml을 보면 알 수도 있지만, 없는 경우도 있으니 MainActivity.kt를 확인하자.

 

android/app/src/main/java/com/projectName/MainActivity.kt

 

맨 위에 패키지명이 있다.

 

sha-1키를 확인하기 위해서 콘솔에 다음 명령어를 입력한다.

cd android
./gradlew signingReport


이전에 keystore을 생성한 적 있다면 디버깅/배포에 따라 아래와 같은 결과가 나올 것이다.

(생성하는 방법은 다른 글 참조...나중에 올리고 링크를 걸 것이다.)

지금은 for debug이기 때문에 debug 버전의 SHA1 부분을 입력한다.

 

 

3. Android (for release)

2)와 같은 과정을 거치되, 마지막 SHA1키만 release 버전을 넣어준다.

 

 

4. iOS

마찬가지로 create credentials > OAuth client ID > iOS

bundle identifier가 필요하다.
마찬가지로 Info.plist에 있다고 나와 있는데, 있으면 여기서 가져가고 없으면 project.pbxproj에서 검색한다.
ios/projectName.xcodeproj/project.pbxproj
검색: PRODUCT_BUNDLE_IDENTIFIER

 

만약 검색했는데 org.reactjs.native.example~ 이렇게 길게 뜬다면 xcode에 가서 변경해주면 된다.

 

참고로 identifier니까 당연한 소리 같지만 이 부분은 unique해야 한다.

보통 com.project나 com.project.app, com.project.service 이런 식으로 설정한다.

안드로이드의 package명과 ios의 bundle id는 반드시 같아야 할 필요는 없지만 헷갈리지 않으려면 같게 하는 게 좋다.

 

 

2), 3)의 안드로이드는 created 창을 볼 필요도 딱히 없고 저장할 것도 없지만 1)의 Web application과 ios는 여기 나오는 정보가 필요하다.

 

 


.env로 가서 4가지 항목을 저장한다.


GOOGLE_CLIENT_ID=웹 클라이언트를 만들고 나서 나온 client id
GOOGLE_CLIENT_SECRET=웹 클라이언트를 만들고 나서 나온 client secret
GOOGLE_IOS_CLIENT_ID=ios 클라이언트를 만들고 나서 나온 client id
GOOGLE_IOS_REVERSED_CLIENT_ID=ios 클라이언트를 만들고 나서 나온 client id의 reversed

 

4번째만 다시 설명하자면,
ios client id가 12345678.apps.googleusercontent.com 이라면
ios reversed client id는 com.googleusercontent.apps.12345678이다.
.을 기준으로 잘라서 뒤집은 셈이다.
헷갈린다면 클라이언트 생성 후 다운받은 plist 파일을 보자. REVERSED_CLIENT_ID 항목이 있을 것이다.

 

이렇게 4가지의 클라이언트를 생성했다면 구글 클라우드 콘솔에서 할 일은 끝났다.
이제 iOS 폴더에서 자잘한 값을 변경하고 코드를 짜는 일만 남았다!

 


ios/projectName/Info.plist에 들어간다.
CFBundleURLTypes라는키를 검색하고, 없으면 생성하여 값을 설정한다.

<key>CFBundleURLTypes</key>
<array>
	<dict>
		<key>CFBundleTypeRole</key>
		<string>Editor</string>
		<key>CFBundleURLSchemes</key>
		<array>
			<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
			<string>~~~~~</string> // 여기에 reversed iOS client id를 입력한다.
		</array>
	</dict>
</array>

 

GIDClientID라는 키를 생성하고 값을 입력한다.

<key>GIDClientID</key>
<string>~~~~~</string> // 여기에 ios client id를 입력한다.

이번엔 reversed가 아닌 원래 client id를 입력한다.

 


마지막으로 구글로그인을 하는 코드를 만들어 보자.

 

0. 콘솔에서 모듈을 다운로드한다.

npm i @react-native-google-signin/google-signin
cd ios
pod install

 

1. import한다.

import {GoogleSignin} from '@react-native-google-signin/google-signin';

 

2. 구글로그인은 sdk 초기화가 필요하다. web application의 client id와, ios라면 ios client id로 초기화해주자.

useEffect(() => {
  if (Platform.OS === 'ios') {
	GoogleSignin.configure({
	  iosClientId: Config.GOOGLE_IOS_CLIENT_ID,
	  webClientId: Config.GOOGLE_CLIENT_ID,
	  offlineAccess: true,
	});
  } else {
	GoogleSignin.configure({
	  webClientId: Config.GOOGLE_CLIENT_ID,
	  offlineAccess: true,
	});
  }
}, []);


3. 모바일 폰에서 구글로그인을 진행한 후 authorization code, idToken을 받아온다.

await GoogleSignin.hasPlayServices();
const userInfo = await GoogleSignin.signIn();

 

{
    "idToken": "~~~", 
    "scopes": ["허용범위들"], 
    "serverAuthCode": "~~",
    "user": {
        "email": "이메일 주소", 
        "familyName": "성", 
        "givenName": "이름",
        "id": "숫자코드",
        "name": "성명",
        "photo": "사진"
	}
}
userInfo를 콘솔에 찍어보면 위와 같은 형태로 데이터가 나온다.

 

여기서 idToken만으로도 유저 정보를 가져올 수 있다고 하지만, 우리가 필요한 건 accessToken이라 한 단계가 더 필요하다.

 

4. 방금 받은 authCode와 client secret을 통해 구글 서버에게서 accessToken과 refreshToken을 받아온다.

const res = await fetch('https://www.googleapis.com/oauth2/v3/token', {
  method: 'POST',
  body: JSON.stringify({
	code: userInfo.serverAuthCode,
	clientId: Config.GOOGLE_CLIENT_ID,
	clientSecret: Config.GOOGLE_CLIENT_SECRET,
	grant_type: 'authorization_code',
  }),
});

 

이 부분은 프론트와 백엔드의 구분이 분명하지 않은 부분이다. 백엔드의 작동 로직에 따라 필요하면 진행한다.
백엔드가 idToken만을 필요로 한다면 굳이 진행할 필요 없다. 하지만 보안상 accessToken이 백엔드에게 건네주기에는 더 좋을 것이다.

 

5. response를 JSON 형태로 가공한다.

const data = await res.json();
{
    "access_token": "~~~",
    "expires_in": 3598, 
    "id_token": "~~~", 
    "scope": "~~~", 
    "token_type": "Bearer"
}
data를 콘솔에 찍어보면 위와 같은 형태로 데이터가 나온다.

 

이제 data에서 받은 accessToken을 백엔드에 전송한다.

백엔드에서는 내가 보낸 accessToken을 구글 서버에 한번 더 검증하고 다른 정보들을 받아올 것이다.

 

+) 24년 8월 30일 추가 (안드로이드)

aab 파일을 구글 플레이 콘솔에 올리기 위해서는 구글 플레이 콘솔에 등록된 SHA-1 키를 클라우드 콘솔에 연동하는 작업이 필요하다.

구글 플레이 콘솔 > 앱 설정 (Setup) > 앱 무결성 (App Signing) > SHA-1키 복사

구글 클라우드 콘솔에서 아까처럼 API & Services (API 및 서비스) > Credentials (사용자 인증 정보) > CREATE CREDENTIALS > OAuth client ID로 안드로이드 설정하고 sha-1키 하나 더 등록해주면 진짜 끝!


구글로그인 끝.

 

(코드 전문)

import {GoogleSignin} from '@react-native-google-signin/google-signin';
import Config from 'react-native-config';

useEffect(() => {
  if (Platform.OS === 'ios') {
    GoogleSignin.configure({
      iosClientId: Config.GOOGLE_IOS_CLIENT_ID,
      webClientId: Config.GOOGLE_CLIENT_ID,
      offlineAccess: true,
    });
  } else {
    GoogleSignin.configure({
      webClientId: Config.GOOGLE_CLIENT_ID,
      offlineAccess: true,
    });
  }
}, []);

const LoginWithGoogle = async () => {
  console.log('구글 로그인');
  try {
    await GoogleSignin.hasPlayServices();
    const userInfo = await GoogleSignin.signIn();
    const res = await fetch('https://www.googleapis.com/oauth2/v3/token', {
      method: 'POST',
      body: JSON.stringify({
        code: userInfo.serverAuthCode,
        clientId: Config.GOOGLE_CLIENT_ID,
        clientSecret: Config.GOOGLE_CLIENT_SECRET,
        grant_type: 'authorization_code',
      }),
    });
    const data = await res.json();
  } catch (error) {
    console.log(error);
  }
};

 

반응형