React Native Module for Naver Login
npm install @react-native-seoul/naver-login
!Android SDK - 5.9.1
!iOS SDK - 4.2.3


React Native 네이버 로그인 라이브러리 입니다.
- TypeScript
- Flow

> ❗️ 2.x 버전은 2.x branch 의 설치 가이드와 사용법을 따라주세요.
``shellnpm
npm install @react-native-seoul/naver-login --save
$3
- Auto Linking 이 적용됩니다.
- iOS의 경우 추가적으로 Cocoapods 설치가 필요합니다.
`shell
cd ios && pod install
`$3
-
0.60 미만의 React Native를 사용중이시라면 Manual Linking Guide를 참고해주세요.Configuration
$3
다음과 같이 앱의
index.js나 로그인이 필요한 시점 전에 초기화 함수를 호출합니다.`tsx
NaverLogin.initialize({
appName,
consumerKey,
consumerSecret,
serviceUrlSchemeIOS,
disableNaverAppAuthIOS: true,
});
`$3
#### 1. Launch Service Queries Schemes 추가
로그인 시에 네이버 앱을 실행시키기 위해 Launch Services Queries Schemes 를 등록해주어야 합니다.
Info.plist 파일안에 다음과 같은 항목을 추가합니다.-
naversearchapp
- naversearchthirdlogin이미
LSApplicationQueriesSchemes 가 항목으로 추가되어 있다면, 안에 두 가지만 더 추가해주세요.`xml
LSApplicationQueriesSchemes
naversearchapp
naversearchthirdlogin
`#### 2. custom URL scheme 추가
네이버 로그인이 완료된 뒤 다시 우리의 앱으로 돌아오기 위해
URL Scheme를 Info.plist 에 정의해주어야 합니다.아래 코드들에서
{{ CUSTOM URL SCHEME }}는 커스텀하게 정의할 우리 앱에 사용될 URL scheme라고 생각하시면 됩니다.주의할 점은 다음과 같습니다.
- 네이버 개발자 콘솔에 기입한
URL Scheme와 동일해야 합니다.
- initialize 함수 호출시에 serviceUrlSchemeIOS 로 동일하게 전달해주어야 합니다.대략 다음과 같이
Info.plist에 입력되게 됩니다.`xml
CFBundleURLTypes
CFBundleTypeRole
Editor
CFBundleURLName
naver
CFBundleURLSchemes
{{ CUSTOM URL SCHEME }}
...
`
!imagep.s
Info.plist에 naversearchapp 추가해도 작동이 안된다면 최대개수를 넘은걸 수 있습니다.(최대수 50개)
참조) https://developer.apple.com/documentation/uikit/uiapplication/canopenurl(_:)

`xml
...
naversearchapp // 51번째일때에 미작동
`#### 3.
AppDelegate의 application:openURL:options 에서 URL 핸들링 로직 추가네이버 로그인이 성공한 후 우리앱으로 다시 돌아와 URL을 처리하기 위해 필요한 과정입니다.
- 다른 URL 핸들링 로직이 없는경우
`objc
#import
...
- (BOOL)application:(UIApplication *)application
openURL:(NSURL *)url
options:(NSDictionary *)options {
return [[NaverThirdPartyLoginConnection getSharedInstance] application:app openURL:url options:options];
}
`- 다른 URL 핸들링 로직이 같이 있는 경우
`objc
- (BOOL)application:(UIApplication *)application
openURL:(NSURL *)url
options:(NSDictionary *)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];
}
...
}
`- AppDelegate.swift 사용 시
`swift
import NaverThirdPartyLoginfunc application(_ app: UIApplication, open url: URL, options: [UIApplication.OpenURLOptionsKey : Any] = [:]) -> Bool {
// naver
if url.scheme == "{{ CUSTOM URL SCHEME }}" {
return NaverThirdPartyLoginConnection.getSharedInstance().application(app, open: url, options: options)
}
}
`$3
#### 1. Proguard
만약 Release build에서 R8 컴파일러를 이용해 code obfuscating을 하신다면, app/build.gradle 설정에
minifyEnabled이 true로 설정이 되어있을 것입니다.그 경우 다음과 같은 Proguard 규칙이 필요합니다.
만약 그렇지 않다면 별도의 설정이 필요하지 않습니다.
`text
-keep public class com.navercorp.nid.* { ; }
`> [!NOTE]
> 이 규칙은 확실하지 않으나 Android Native SDK 코드에서 proguard consumer rules가 정의되어있지 않아 삽입된 구문입니다.
>
> 이것을 추가해주었음에도 난독화로 인해 에러가 나는 상황에서는 OKHttp, Retrofit 라이브러리들의 Proguard Rule들을 직접 같이 추가해주는 것을 추천드립니다.
>
> R8 컴파일러로 안드로이드 프로젝트를 빌드하면 Okhtttp, Retrofit과 같은 라이브러리들은 내부적으로 JAR, AAR에 rule을 포함시켜두었기 때문에 문제가 되지 않아야 정상입니다.
$3
1. app.json 파일을 아래와 같이 수정합니다.
`json
{
"expo": {
...
"plugins": [
...,
[
"@react-native-seoul/naver-login",
{
"urlScheme": "CUSTOM URL SCHEME" // 네이버 url scheme를 적어주세요.
}
]
],
...
}
}
`- Bare workflow의 경우에는
expo prebuild를 이용합니다.
- Managed Workflow의 경우에는 EAS Build 이후 expo start --dev-client를 이용합니다.2. (Optional) Android에서 proguard rules 등을 적용하실 경우, Expo BuildProperties 를 참고하세요.
API
| Func | Param | Return | Description |
| :----------- | :--------------------: | :-----------------------------: | :------------------------------- |
| initialize |
NaverLoginInitParams | void | 네이버 SDK 초기화 |
| login | | Promise | 로그인 |
| getProfile | String | Promise | 프로필 불러오기 |
| getAgreement | String | Promise | 약관 동의 대행 동의여부 불러오기 |
| logout | | Promise | 로그아웃 |
| deleteToken | | Promise | 네이버 계정 연동 해제 |$3
NaverLoginInitParams
`typescript
export interface NaverLoginInitParams {
consumerKey: string;
consumerSecret: string;
appName: string;
/* (iOS) 네이버앱을 사용하는 인증을 비활성화 한다. (default: false) /
disableNaverAppAuthIOS?: boolean;
/* (iOS) /
serviceUrlSchemeIOS?: string;
}
`NaverLoginResponse
`ts
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
`ts
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;
};
}
`GetAgreementResponse
`ts
export interface GetAgreementResponse {
result: string;
accessToken: string;
agreementInfos: AgreementInfo[];
}export interface AgreementInfo {
termCode: string;
clientId: string;
agreeDate: string;
}
`Usage
- 자세한 예제는 예제 프로젝트를 참고해주세요
`tsx
/* 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();
const [failure, setFailureResponse] =
useState();
const [getProfileRes, setGetProfileRes] = useState();
const login = async (): Promise => {
const { failureResponse, successResponse } = await NaverLogin.login();
setSuccessResponse(successResponse);
setFailureResponse(failureResponse);
};
const logout = async (): Promise => {
try {
await NaverLogin.logout();
setSuccessResponse(undefined);
setFailureResponse(undefined);
setGetProfileRes(undefined);
} catch (e) {
console.error(e);
}
};
const getProfile = async (): Promise => {
try {
const profileResult = await NaverLogin.getProfile(success!.accessToken);
setGetProfileRes(profileResult);
} catch (e) {
setGetProfileRes(undefined);
}
};
const deleteToken = async (): Promise => {
try {
await NaverLogin.deleteToken();
setSuccessResponse(undefined);
setFailureResponse(undefined);
setGetProfileRes(undefined);
} catch (e) {
console.error(e);
}
};
return (
style={{ alignItems: 'center', justifyContent: 'center', flex: 1 }}
>
style={{ flex: 1 }}
contentContainerStyle={{ flexGrow: 1, padding: 24 }}
>
{success ? (
<>
>
) : null}
{success ? (
) : null}
{failure ? : null}
{getProfileRes ? (
) : null}
);
};
``See the contributing guide to learn how to contribute to the repository and the development workflow.
MIT