
리액트 네이티브 (안드로이드, ios)에서 구글로그인을 하는 방법을 정리하고자 한다.
구글 클라우드 콘솔에서 새 프로젝트를 생성한다.
왼쪽 위를 보면 드롭다운이 있다.

새 프로젝트를 생성한다.

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

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

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

Create Credentials > OAuth client ID

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

유저타입: 외부

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


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

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

Application type을 설정해야 한다.
우리는 4가지 타입을 지정해줄 것이다.
- Web application
- Android (for debug)
- Android (for release)
- 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);
}
};
'개발 및 알고리즘 > 알고리즘' 카테고리의 다른 글
| [AWS] CloudWatch Alarm 설정해서 Slack에 알림 보내기 (1) | 2024.08.07 |
|---|---|
| [React Native] 리액트 네이티브에서 커스텀 폰트 일괄 적용하기 (0) | 2024.07.30 |
| [JS/typescript] Null 병합 연산자 ?? (물음표 2개) (1) | 2024.07.23 |
| [React Native] 리액트 네이티브에서 스플래시 스크린에 애니메이션 구현하기 (lottie + react-native-bootsplash) (0) | 2024.07.12 |
| [React Native] 리액트 네이티브에서 기기 설정 언어 확인하기 (react-native-localize) (1) | 2024.07.11 |