시작말
react-native-seoul/naver-login
라이브러리를 사용하여 네이버 로그인을 구현하려고 했으나 Firebase Authentication에서 제공하는 OpenID Connect Provider를 활용하는 방식과는 맞지 않아 어려움을 겪었습니다.
하루 정도 이 문제를 해결하느라 소요했는데, react-native-seoul/naver-login
과 Firebase Authentication을 함께 사용하는 방법에 대해 정리된 자료가 부족한 것 같아서 정리해봅니다!
기존에 구현한 카카오 로그인(OpenID Connect)
아래 코드는 기존에 구현한 카카오 로그인 방식입니다.
Firebase의 OpenID Connect Provider를 활용한 방식인데요. idToken
을 이용해 credential
을 생성하고 이를 signInWithCredential
에 전달하면 Firebase에 로그인 또는 회원가입이 이루어집니다.
import { login } from '@react-native-kakao/user';
import { signInWithCredential, OAuthProvider } from 'firebase/auth';
const kakaoLogin = async (): Promise<boolean> => {
const kakaoTokenInfo = await login();
const provider = new OAuthProvider('oidc.kakao');
const credential = provider.credential({
idToken: kakaoTokenInfo.idToken,
});
const result = await signInWithCredential(auth, credential);
// ...
};
네이버 로그인 문제
이 방식을 react-native-seoul/naver-login
를 사용해 똑같이 적용하려고 했으나 문제가 있었습니다.react-native-seoul/naver-login
의 로그인 함수의 반환값에는 idToken
이 포함되지 않았고, accessToken
과 refreshToken
만 제공되었습니다.
하지만 Firebase의 OpenID Connect는 idToken
을 필요로 하기 때문에 Firebase Custom Token을 생성하여 로그인하는 방식을 적용해야 했습니다.
import NaverLogin from '@react-native-seoul/naver-login';
const naverLogin = async (): Promise<void> => {
const { failureResponse, successResponse } = await NaverLogin.login();
if (failureResponse) return;
const provider = new OAuthProvider('oidc.naver');
const credential = provider.credential({
idToken: successResponse.accessToken,
});
await signInWithCredential(auth, credential); // ❌ FirebaseError: Unable to parse the ID Token
};
Firebase Custom Token 생성 함수
Firebase Custom Token이란?
Firebase는 OpenID Connect Provider를 이용한 idToken 기반 로그인 외에도, Custom Authentication 방식을 제공합니다.
이를 활용하면 임의의 uid로 Firebase Custom Token을 생성하여 인증할 수 있습니다.
네이버 로그인에서 받은 accessToken을 Firebase Custom Token으로 변환해주면 Firebase 인증이 가능해집니다.
📌 공식 문서: https://firebase.google.com/docs/auth/admin/create-custom-tokens?hl=ko#create_custom_tokens_using_the_firebase_admin_sdk
아래 코드는 accessToken
을 입력받아 Firebase Custom Token을 생성하여 반환해주는 함수입니다.
import axios from 'axios';
import * as admin from 'firebase-admin';
import * as functions from 'firebase-functions';
admin.initializeApp();
export const getFirebaseCustomToken = functions.https.onCall(
async (request) => {
const { data: { accessToken } } = request;
if (!accessToken) {
throw new functions.https.HttpsError(
'invalid-argument',
'oauthType 및 accessToken 파라미터가 누락되었습니다.',
);
}
try {
// 네이버 API 호출
const { data } = await axios.get(
'https://openapi.naver.com/v1/nid/me',
{ headers: { Authorization: `Bearer ${accessToken}` } },
);
if (data.resultcode !== '00') {
throw new Error('네이버 사용자 정보 조회 실패');
}
const { id, email, nickname } = data.response;
// Firebase Custom Token 생성
const customToken = await admin.auth().createCustomToken(id);
return {
firebaseToken: customToken,
user: { email, nickname },
};
} catch (e: any) {
console.error('Firebase Custom Token 생성 실패:', e);
throw new functions.https.HttpsError(
'internal',
'Firebase Custom Token 생성 중 오류가 발생했습니다.',
e.message,
);
}
},
);
Cloud Functions 배포
그리고 이 함수를 Firebase Cloud Functions에 배포했습니다.
firebase deploy --only functions
배포가 완료되면 이제 클라이언트에서 해당 함수를 호출해보겠습니다.
✔ Deploy complete!
Custom Token 요청 함수
const getCustomToken = async (accessToken: string) => {
const getFirebaseCustomToken = httpsCallable(functions, 'getFirebaseCustomToken');
const { data } = await getFirebaseCustomToken({ oauthType, accessToken });
return data; // { firebaseToken: string; user: { email: string; nickname: string } }
};
이렇게 얻은 Firebase Custom Token을 signInWithCustomToken
에 전달하면 됩니다.
최종 네이버 로그인 함수
import NaverLogin from '@react-native-seoul/naver-login';
import { signInWithCustomToken } from 'firebase/auth';
const naverLogin = async (): Promise<void> => {
const { failureResponse, successResponse } = await NaverLogin.login();
if (failureResponse) return;
const firebaseCustomToken = await getCustomToken(successResponse.accessToken);
await signInWithCustomToken(auth, firebaseCustomToken);
// ...
};
최종 로그인 흐름
- 사용자가 네이버 로그인 버튼 클릭
NaverLogin.login()
을 통해 네이버access_token
획득access_token
을 Firebase Cloud Function으로 전송- Cloud Function이 Firebase Custom Token을 생성하여 반환
- 반환된 토큰으로
signInWithCustomToken(auth, firebaseToken)
을 호출해 Firebase 로그인
맺음말
처음에는 라이브러리만 사용하면 간단하게 구현할 수 있을 거라 생각했지만, 예상치 못한 문제들을 마주하게 되면서 많은 시간을 투자하게 되었습니다.. 더 좋은 해결 방법이 있을 수도 있겠지만, 나름 직접 문제를 분석하고 해결했다는 점에서 뿌듯함을 느꼈네요.
이 글이 저처럼 react-native-seoul/naver-login
과 Firebase를 연동하는 과정에서 어려움을 겪는 분들에게 도움이 되었으면 좋겠습니다.
도움이 많이 됐던 글 🫶
[RN] React Native에서 Firebase Cloud Funtions를 활용한 카카오 커스텀 토큰 로그인
'React Native' 카테고리의 다른 글
React Native: FlatList 성능 최적화하기 (0) | 2025.04.22 |
---|---|
React Native에서 요소 크기 측정하기 (onLayout, ref.measure, ref.measureWindow) (0) | 2025.01.17 |
React Native에서 .env 사용하기 (0) | 2025.01.13 |