전에 RN을 이용해서 프로젝트를 진행해 본 경험이 있는데
너무나도 많은 오류를 봐서 손 놓고 있었는데 요번 프로젝트에서도
webView와 firebase OAuth를 이용할 일이 생겨서 다시 손을 잡게 되었습니다...
이번 포스트에서는 firebase + expo auth를 이용해서 소셜 로그인을 구현하는 방법을 다뤄보려고 합니다.
좀 더 프로젝트 setting을 편하게 가져가보려다가 역시나 많은 오류를 만났기에 😂
그럼 같이 차근차근 해나 가볼까요?
환경은
expo : ~48.0.15
react-native : 0.71.1
react : 18.2.0
입니다.
요번에 expo sdk48에서 새로운 기능으로
expo-router가 새로 나와 프로젝트에 적용해 본 버전입니다.
기본적인 expo 설치의 경우 아래의 공식 문서를 참고하시면 됩니다.
https://docs.expo.dev/get-started/create-a-project/
https://blog.expo.dev/expo-sdk-48-ccb8302e231
1. firebase 설치
이 또한 공식문서에 잘 나와있습니다.
특별한 사항으로는 중간에 metro.config.js를 설정하는 부분이 있는데
이게 왜 필요하냐면
firebase의 경우 native 모듈의 기능을 사용해야 하는 부분이 많은데
이 모듈들은 Expo의 기본 세팅만으로는 완전하게 동작하지 않습니다.
그렇기에 다음과 같은 설정을 통해서 native 모듈의 기능을 사용하게 해 주는 거죠
const { getDefaultConfig } = require('@expo/metro-config');
const defaultConfig = getDefaultConfig(__dirname);
module.exports = {
resolver: {
...defaultConfig.resolver,
sourceExts: [...defaultConfig.resolver.sourceExts, 'cjs'],
},
transformer: {
...defaultConfig.transformer,
babelTransformerPath: require.resolve('expo-module-scripts/babel-transformer'),
},
};
- sourceExts : CommonJS 모듈을 사용할 수 있도록 해줌
- babelTransformerPath : Metro 번들러에게 Expo가 제공하는 Babel Transformer를 사용하도록 해줌
그렇다면 Metro 번들러가 뭘까요?
FaceBook에서 제공한 JS 번들러로 RN을 위한 모듈 번들링 및 변환을 처리해 줍니다.
번들러는 모든 JS 파일과 의존성을 하나의 번들로 결합해 주는 거죠.
Metro 번들러가 제공하는 기능으로는
1. 빠른 변환 : 캐싱을 지원하여 빠른 코드 변환
2. hot-reload : 저희가 저장을 하면 변경사항만 반영되도록
3. Asset 처리 : 이미지, 폰트 정적 리소스 처리 및 모듈로의 변환
4. 소스 맵 생성 : 디버깅에 도움이 되는 소스 맵을 생성 하여 원본 코드와 변환 코드 사이의 매핑 제공
위와 같은 역할을 하는 게 Metro 번들러입니다.
2. 구글 로그인 연동
구글 로그인의 경우 expo에서 expo-auth-session을 지원합니다.
https://docs.expo.dev/versions/latest/sdk/auth-session/
필요한 clientId의 경우 구글 cloud에서 추가가 가능하며
다음과 같은 과정을 통해 확인하실 수 있습니다.
1. Google Cloud 접속
https://console.cloud.google.com/apis/credentials/oauthclient
2. 프로젝트가 없다면 프로젝트 생성
3. 사용자 인증 정보
4. 클라이언트 ID 정보 복사
5. 승인된 자바스크립트 원본에 expo 추가
6. 승인된 리디렉션 URI 추가
그리고 다음과 같이 코드를 사용해 주면 됩니다.
간단하게 코드를 설명하면
1. 지정된 googleClient를 기반으로 웹뷰 로그인을 요청하고
2. 로그인이 성공한다면 로그인 정보를 가지고 firebase에 로그인 정보를 전송
하는 로직입니다.
import * as WebBrowser from 'expo-web-browser';
import * as Google from 'expo-auth-session/providers/google';
import {
getAuth,
GoogleAuthProvider,
signInWithCredential,
onAuthStateChanged,
} from 'firebase/auth';
WebBrowser.maybeCompleteAuthSession();
import { useEffect } from 'react';
const useGetGoogleAuth = () => {
const [request, response, promptAsync] = Google.useIdTokenAuthRequest({
clientId: process.env.GOOGLE_CLIENT_ID,
});
const auth = getAuth();
useEffect(() => {
if (response?.type === 'success') {
const { id_token } = response.params;
const credential = GoogleAuthProvider.credential(id_token);
signInWithCredential(auth, credential);
}
}, [response]);
useEffect(() => {
const unsubscribe = onAuthStateChanged(auth, async (user) => {
if (user) {
const { uid, email, displayName, refreshToken } = user;
console.log('uid :', uid);
console.log('email :', email);
console.log('displayName :', displayName);
console.log('refreshToken :', refreshToken);
}
});
return () => {
unsubscribe();
};
}, [auth]);
return { request, response, promptAsync };
};
export default useGetGoogleAuth;
이렇게 하면 구글 로그인이 정상적으로 동작하는 걸 확인할 수 있습니다. 😃
3. 애플 로그인
요번에 좀 난관을 많이 겪은 부분입니다. ㅠㅠ
애플 로그인의 경우 expo 환경에서 지원을 해줍니다. 이전에는 rn의 기본을 사용해서 사용했는데
확실히 편하긴 하더라고요
주의점은 ios의 경우 개발자 계정이 필요합니다.
1년에 13만 원 정도의 값을 지불하고 앱을 올릴 수 있는 혜택?을 주는데
없으시다면 등록을 하셔야 앱을 올릴 수 있습니다.
그다음 과정으로 앱 정보를 등록해 주고 Credentials를 설정해야 하는데
이는 다른 링크를 참고하였습니다.
과정이 조금 복잡하니 순서대로 잘 따라 하시면 됩니다.
https://imweb.me/faq?mode=view&category=29&category2=47&idx=71719
대기업의 횡포
다음으로는 expo에서 이를 사용해 줘야겠죠
https://docs.expo.dev/versions/latest/sdk/apple-authentication/
1. 라이브러리 설치
npx expo install expo-apple-authentication
2. 공식 문서 내용대로 Apple 로그인 버튼 추가
3. 코드 추가
아까 구글 로그인과 로직은 동일합니다.
import * as AppleAuthentication from 'expo-apple-authentication';
import {
getAuth,
signInWithCredential,
OAuthProvider,
onAuthStateChanged,
OAuthCredential,
} from 'firebase/auth';
import { useEffect } from 'react';
const useGetAppleAuth = () => {
const auth = getAuth();
const signInWithApple = async () => {
try {
const result = await AppleAuthentication.signInAsync({
requestedScopes: [
AppleAuthentication.AppleAuthenticationScope.FULL_NAME,
AppleAuthentication.AppleAuthenticationScope.EMAIL,
],
});
if (result) {
const { identityToken } = result;
const credential = OAuthCredential.fromJSON({
providerId: 'apple.com',
signInMethod: 'oauth',
idToken: identityToken,
});
if (credential) {
signInWithCredential(auth, credential)
.then(() => {
console.log('Apple sign in success');
})
.catch((error) => {
console.log('Error:', error);
});
} else {
console.log('Failed to create credential for Apple sign in');
}
}
} catch (error) {
console.log('Error:', error);
}
};
useEffect(() => {
const unsubscribe = onAuthStateChanged(auth, async (user) => {
if (user) {
const { uid, email, displayName } = user;
console.log('uid:', uid);
console.log('email:', email);
console.log('displayName:', displayName);
}
});
return () => {
unsubscribe();
};
}, [auth]);
return { signInWithApple };
};
export default useGetAppleAuth;
4. firebase에 애플 로그인 추가
가장 애를 많이 먹었던 부분입니다.
firebase Authentication 부분에서 로그인 제공업체를 추가한 뒤
서비스 ID를 다음과 설정해주셔야 합니다.
저희가 만든 서비스 ID가 아닌
host.exp.Exponent를 설정해 줘야 제대로 동작합니다.
다른 값으로 설정하게 되면 다음과 같은 오류가 납니다.
Error: [FirebaseError: Firebase: The audience in ID Token [host.exp.Exponent] does not match the expected audience com.ww8007.pickly. (auth/invalid-credential).]
이게 찾아보니까 host.exp.Exponent 자체는 expo 기본 설정이고
개발자가 따로 건드릴 수 없는 값이라고 하네요.
expo-dev-client를 사용하여 다른 프로젝트 환경을 구성하여 문제를 해결할 수 있긴 하지만
이를 production 환경과 dev 환경을 다른 프로젝트를 가져갈 필요는 없으니
다음과 같이 설정해 주는 게 맘 편할 것 같습니다...
그러면 다음과 같이 정상적으로 애플 로그인이 동작하는 모습을 확인하실 수 있습니다.
결과
이제 저희는 두 개의 OAuth를 사용할 수 있게 되었습니다.
OAuth에서 받아온 정보를 토대로 이제 사용자 인증을 하고 서버에 요청을 하는 일들만 남았네요!
React Native를 오랜만에 해보니 바뀐 부분들이 많고
이전에 사용하던 라이브러리들이 바뀌고 Expo Router에 대해서는 사용하면서 Next.js와 비슷하다는 생각이 많이 들었네요.
끝으로 지금 만들고 있는 프로젝트의 로그인 창을 남겨두고 글을 마무리하도록 하겠습니다 😃
'React Native' 카테고리의 다른 글
Webview에서 Background Timer 구현하기 (0) | 2023.09.23 |
---|---|
JavaScript webview에서 카메라 / 영상 촬영 기능 사용하기 (0) | 2023.09.15 |
React Native에서 Share Intent Native Module 개발하기 (0) | 2023.08.31 |
React Native Webview와 expo router에서 페이지 전환 애니메이션 전환 효과 구현하기 (0) | 2023.08.09 |
[R/N] react-native-vector-icons 오류 해결 (0) | 2021.08.12 |