React Native에서 카카오 소셜로그인 하기
네이버와 카카오톡 소셜로그인은 javascript나, ios, android sdk는 제공하지만 react-native를 위한 sdk는 따로 없기 때문에 native module을 사용하거나, (있다면) 해당 라이브러리를 사용해야 한다. 지난 프로젝트에서는 passport 라이브러리를 사용하여 웹뷰로 소셜로그인을 진행했지만 이번엔 React Native Seoul에서 만든 react-native-kakao-login 라이브러리를 사용해 보기로 했다.
install
먼저, 모듈을 설치하고 추가적으로 ios와 android 설정을 진행한다.
yarn add @react-native-seoul/kakao-login
kakao API 사용 등록
kakao 에서 제공하는 API를 사용하기 위해서는 kakao developers 페이지에서 앱 등록을 진행해야 한다. 계정 로그인을 한 후, 앱 만들기 버튼을 통해 앱을 만들면 앱 키를 발급받을 수 있다. 네이티브 SDK를 사용할 예정이기 때문에 네이티브 앱 키가 필요하다.
ios 설정
먼저, kakao developers 페이지의 앱에 ios 플랫폼을 추가한다. 이때 번들 ID를 필수로 입력해야 하는데, .xcworkspace
General 탭에서 확인할 수 있다.
플랫폼 등록을 마쳤으면, (RN >= 0.60 의 경우) pod install을 해주는데, ./ios/Podfile
에 아래 내용을 추가해 준 뒤 pod install을 해주면 된다.
target 'yourApp' do
...
pod 'KakaoOpenSDK', '~> 1.16.0'
...
end
그리고 카카오 공식문서를 참고해서 몇 가지 추가로 설정해 주어야 하는데,
-
먼저
info.plist
파일에LSApplicationQueriesSchemes
의 키로kakao{네이티브 앱 키}
와kakaokompassauth
를 추가한다. -
그리고
info
탭에서 URL Types를 추가해 주는데, URL Schemes에kakao{네이티브 앱 키}
를 등록해 준다. -
AppDelegate.m
파일에 아래 내용을 추가해 준다.
#import <KakaoOpenSDK/KakaoOpenSDK.h>
- (BOOL)application:(UIApplication *)application openURL:(NSURL *)url
sourceApplication:(NSString *)sourceApplication
annotation:(id)annotation {
if ([KOSession isKakaoAccountLoginCallback:url]) {
return [KOSession handleOpenURL:url];
}
return false;
}
- (BOOL)application:(UIApplication *)application openURL:(NSURL *)url
options:(NSDictionary<NSString *,id> *)options {
if ([KOSession isKakaoAccountLoginCallback:url]) {
return [KOSession handleOpenURL:url];
}
return false;
}
- (void)applicationDidBecomeActive:(UIApplication *)application
{
[KOSession handleDidBecomeActive];
}
android 설정
안드로이드도 , kakao developers 페이지의 플랫폼을 추가해 주어야 한다. 먼저 패키지 명과 마켓 URL을 입력해야 하는데, 패키지 명을 입력하면 마켓 URL은 자동으로 입력된다. 패키지 명은 ./android/app/src/manifests/AndroidMenifest.xml
파일의 manifest
태그에서 확인할 수 있다.
bundle.gridle
파일에 아래 내용을 추가해 준다.
subprojects {
repositories {
mavenCentral()
maven { url 'http://devrepo.kakao.com:8088/nexus/content/groups/public/' }
}
}
./android/app/src/res/values
폴더에kakao_strings.xml
파일을 만들고, 아래와 같이 카카오 앱키를 입력한 뒤 저장한다.
<resources>
<string name="kakao_app_key">{kakao_app_key}</string>
</resources>
./android/app/src/manifests/AndroidMenifest.xml
파일의allowBackup
를true
로 수정해 주고,application
태그 내부에 아래 내용을 추가해 준다.
...
<meta-data
android:name="com.kakao.sdk.AppKey"
android:value="@string/kakao_app_key" />
...
여기까지 하고 카카오 로그인을 진행하면 Login Failed:E_AUTHORIZATION_FAILED invalid android_key_hash or ios_bundle_id or web_site_url
라는 에러 메시지를 받게 되는데, 안드로이드는 키해시를 개발자 콘솔에 입력해주어야 정상적으로 동작하기 때문이다.
키해시는 디버그와 릴리즈 용으로 나뉘는데, 먼저 디버그용 키해시를 얻기 위해 ./android/app/src/java/MainApplication.java
파일의 onCreate()
함수 내에 아래 내용을 추가하고 빌드하면 키해시를 확인할 수 있다.
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.content.pm.Signature;
import android.util.Base64;
import android.util.Log;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
...
@Override
public void onCreate() {
super.onCreate();
SoLoader.init(this, /* native exopackage */ false);
initializeFlipper(this); // Remove this line if you don't want Flipper enabled
try {
PackageInfo info = getPackageManager().getPackageInfo(
"com.rn_social_login",
PackageManager.GET_SIGNATURES);
for (Signature signature : info.signatures) {
MessageDigest md = MessageDigest.getInstance("SHA");
md.update(signature.toByteArray());
Log.d("KeyHash:", Base64.encodeToString(md.digest(), Base64.DEFAULT));
}
} catch (PackageManager.NameNotFoundException e) {
} catch (NoSuchAlgorithmException e) {
}
}
이렇게 얻어진 키해시 값을 kakao developers 어플리케이션 안드로이드 플랫폼에 입력해 주면 정상적으로 작동된다.
구현
구현은 간단한데, KakaoLogins
로 클래스를 호출하고, login()
, getProfile()
, logout()
등의 API를 사용하면 된다.
import * as React from "react";
import { SafeAreaView, Text, TouchableOpacity } from "react-native";
import AsyncStorage from "@react-native-community/async-storage";
import KakaoLogins from "@react-native-seoul/kakao-login";
import { NavigationScreenProp, NavigationState } from "react-navigation";
if (!KakaoLogins) {
console.error("KakaoLogins Module is Not Linked");
}
type Navigation = NavigationScreenProp<NavigationState>;
interface Props {
navigation: Navigation;
}
class SignInScreen extends React.Component<Props> {
kakaoLogin = async () => {
try {
let result = await KakaoLogins.login();
if (result) {
await this.getProfile();
await AsyncStorage.setItem("userToken", result.accessToken);
this.props.navigation.navigate("App");
console.log(`Login Finished:${JSON.stringify(result)}`);
}
} catch (err) {
if (err.code === "E_CANCELLED_OPERATION") {
console.log(`Login Cancelled:${err.message}`);
} else {
console.log(`Login Failed:${err.code} ${err.message}`);
}
}
};
getProfile = async () => {
try {
let result = await KakaoLogins.getProfile();
await console.log(`Get Profile Finished:${JSON.stringify(result)}`);
} catch (err) {
console.log(`Get Profile Failed:${err.code} ${err.message}`);
}
};
render() {
return (
<SafeAreaView>
<TouchableOpacity onPress={this.kakaoLogin}>
<Text>SignIn with Kakao</Text>
</TouchableOpacity>
</SafeAreaView>
);
}
}
export default SignInScreen;
네이버 로그인도 진행을 해야 하는데, @react-native-seoul/naver-login
에 react native 0.60 이상 버전의 업데이트 내용이 반영이 잘 되어있지 않아 native module을 직접 만들어서 사용해봐야 겠다.
👩🏻💻 배우는 것을 즐기는 프론트엔드 개발자 입니다
부족한 블로그에 방문해 주셔서 감사합니다 🙇🏻♀️
in the process of becoming the best version of myself