React Native 네이버 로그인 라이브러리 입니다.
❗️
2.x
버전은 2.x branch 의 설치 가이드와 사용법을 따라주세요.
# npm
npm install @react-native-seoul/naver-login --save
# yarn
yarn add @react-native-seoul/naver-login
0.60
cd ios && pod install
0.60
0.60
미만의 React Native를 사용중이시라면 Manual Linking Guide를 참고해주세요.initialize
함수 호출다음과 같이 앱의 index.js
나 로그인이 필요한 시점 전에 초기화 함수를 호출합니다.
NaverLogin.initialize({
appName,
consumerKey,
consumerSecret,
serviceUrlSchemeIOS,
disableNaverAppAuthIOS: true,
});
로그인 시에 네이버 앱을 실행시키기 위해 Launch Services Queries Schemes 를 등록해주어야 합니다.
Info.plist
파일안에 다음과 같은 항목을 추가합니다.
naversearchapp
naversearchthirdlogin
이미 LSApplicationQueriesSchemes
가 항목으로 추가되어 있다면, <array>
안에 두 가지만 더 추가해주세요.
<key>LSApplicationQueriesSchemes</key>
<array>
<string>naversearchapp</string>
<string>naversearchthirdlogin</string>
</array>
네이버 로그인이 완료된 뒤 다시 우리의 앱으로 돌아오기 위해 URL Scheme
를 Info.plist
에 정의해주어야 합니다.
아래 코드들에서 {{ CUSTOM URL SCHEME }}
는 커스텀하게 정의할 우리 앱에 사용될 URL scheme라고 생각하시면 됩니다.
주의할 점은 다음과 같습니다.
URL Scheme
와 동일해야 합니다.initialize
함수 호출시에 serviceUrlSchemeIOS
로 동일하게 전달해주어야 합니다.대략 다음과 같이 Info.plist
에 입력되게 됩니다.
<key>CFBundleURLTypes</key>
<array>
<dict>
<key>CFBundleTypeRole</key>
<string>Editor</string>
<key>CFBundleURLName</key>
<string>naver</string>
<key>CFBundleURLSchemes</key>
<array>
<string>{{ CUSTOM URL SCHEME }}</string>
</array>
</dict>
...
</array>
AppDelegate
의 application:openURL:options
에서 URL 핸들링 로직 추가네이버 로그인이 성공한 후 우리앱으로 다시 돌아와 URL을 처리하기 위해 필요한 과정입니다.
#import <NaverThirdPartyLogin/NaverThirdPartyLoginConnection.h>
...
- (BOOL)application:(UIApplication *)application
openURL:(NSURL *)url
options:(NSDictionary<UIApplicationOpenURLOptionsKey,id> *)options {
return [[NaverThirdPartyLoginConnection getSharedInstance] application:app openURL:url options:options];
}
- (BOOL)application:(UIApplication *)application
openURL:(NSURL *)url
options:(NSDictionary<UIApplicationOpenURLOptionsKey,id> *)options {
// naver
if ([url.scheme isEqualToString:@"{{ CUSTOM URL SCHEME }}"]) {
return [[NaverThirdPartyLoginConnection getSharedInstance] application:app openURL:url options:options];
}
// kakao
if([RNKakaoLogins isKakaoTalkLoginUrl:url]) {
return [RNKakaoLogins handleOpenUrl: url];
}
...
}
만약 Release build에서 R8 컴파일러를 이용해 code obfuscating을 하신다면, app/build.gradle 설정에 minifyEnabled
이 true
로 설정이 되어있을 것입니다.
그 경우 다음과 같은 Proguard 규칙이 필요합니다.
만약 그렇지 않다면 별도의 설정이 필요하지 않습니다.
-keep public class com.navercorp.nid.** { *; }
[!NOTE] 이 규칙은 확실하지 않으나 Android Native SDK 코드에서 proguard consumer rules가 정의되어있지 않아 삽입된 구문입니다.
이것을 추가해주었음에도 난독화로 인해 에러가 나는 상황에서는 OKHttp, Retrofit 라이브러리들의 Proguard Rule들을 직접 같이 추가해주는 것을 추천드립니다.
R8 컴파일러로 안드로이드 프로젝트를 빌드하면 Okhtttp, Retrofit과 같은 라이브러리들은 내부적으로 JAR, AAR에 rule을 포함시켜두었기 때문에 문제가 되지 않아야 정상입니다.
{
"expo": {
...
"plugins": [
...,
[
"@react-native-seoul/naver-login",
{
"urlScheme": "CUSTOM URL SCHEME" // 네이버 url scheme를 적어주세요.
}
]
],
...
}
}
expo prebuild
를 이용합니다.expo start --dev-client
를 이용합니다.Func | Param | Return | Description |
---|---|---|---|
initialize | NaverLoginInitParams |
void |
네이버 SDK 초기화 |
login | Promise<NaverLoginResponse> |
로그인 | |
getProfile | String |
Promise<GetProfileResponse> |
프로필 불러오기 |
logout | Promise<void> |
로그아웃 | |
deleteToken | Promise<void> |
네이버 계정 연동 해제 |
NaverLoginInitParams
export interface NaverLoginInitParams {
consumerKey: string;
consumerSecret: string;
appName: string;
/** (iOS) 네이버앱을 사용하는 인증을 비활성화 한다. (default: false) */
disableNaverAppAuthIOS?: boolean;
/** (iOS) */
serviceUrlSchemeIOS?: string;
}
NaverLoginResponse
export interface NaverLoginResponse {
isSuccess: boolean;
/** isSuccess가 true일 때 존재합니다. */
successResponse?: {
accessToken: string;
refreshToken: string;
expiresAtUnixSecondString: string;
tokenType: string;
};
/** isSuccess가 false일 때 존재합니다. */
failureResponse?: {
message: string;
isCancel: boolean;
/** Android Only */
lastErrorCodeFromNaverSDK?: string;
/** Android Only */
lastErrorDescriptionFromNaverSDK?: string;
};
}
GetProfileResponse
export interface GetProfileResponse {
resultcode: string;
message: string;
response: {
id: string;
profile_image: string | null;
email: string;
name: string;
birthday: string | null;
age: string | null;
birthyear: number | null;
gender: string | null;
mobile: string | null;
mobile_e164: string | null;
nickname: string | null;
};
}
/** Fill your keys */
const consumerKey = '';
const consumerSecret = '';
const appName = 'testapp';
/** This key is setup in iOS. So don't touch it */
const serviceUrlSchemeIOS = 'navertest';
const App = (): ReactElement => {
useEffect(() => {
NaverLogin.initialize({
appName,
consumerKey,
consumerSecret,
serviceUrlSchemeIOS,
disableNaverAppAuthIOS: true,
});
}, []);
const [success, setSuccessResponse] =
useState<NaverLoginResponse['successResponse']>();
const [failure, setFailureResponse] =
useState<NaverLoginResponse['failureResponse']>();
const [getProfileRes, setGetProfileRes] = useState<GetProfileResponse>();
const login = async (): Promise<void> => {
const { failureResponse, successResponse } = await NaverLogin.login();
setSuccessResponse(successResponse);
setFailureResponse(failureResponse);
};
const logout = async (): Promise<void> => {
try {
await NaverLogin.logout();
setSuccessResponse(undefined);
setFailureResponse(undefined);
setGetProfileRes(undefined);
} catch (e) {
console.error(e);
}
};
const getProfile = async (): Promise<void> => {
try {
const profileResult = await NaverLogin.getProfile(success!.accessToken);
setGetProfileRes(profileResult);
} catch (e) {
setGetProfileRes(undefined);
}
};
const deleteToken = async (): Promise<void> => {
try {
await NaverLogin.deleteToken();
setSuccessResponse(undefined);
setFailureResponse(undefined);
setGetProfileRes(undefined);
} catch (e) {
console.error(e);
}
};
return (
<SafeAreaView
style={{ alignItems: 'center', justifyContent: 'center', flex: 1 }}
>
<ScrollView
style={{ flex: 1 }}
contentContainerStyle={{ flexGrow: 1, padding: 24 }}
>
<Button title={'Login'} onPress={login} />
<Gap />
<Button title={'Logout'} onPress={logout} />
<Gap />
{success ? (
<>
<Button title="Get Profile" onPress={getProfile} />
<Gap />
</>
) : null}
{success ? (
<View>
<Button title="Delete Token" onPress={deleteToken} />
<Gap />
<ResponseJsonText name={'Success'} json={success} />
</View>
) : null}
<Gap />
{failure ? <ResponseJsonText name={'Failure'} json={failure} /> : null}
<Gap />
{getProfileRes ? (
<ResponseJsonText name={'GetProfile'} json={getProfileRes} />
) : null}
</ScrollView>
</SafeAreaView>
);
};
See the contributing guide to learn how to contribute to the repository and the development workflow.
MIT