본문 바로가기
🖥 Programming/📱 Android (Kotlin)

[Android][Kotlin] 네이버 아이디 로그인(네아로) 연동(Naver Login)

by MinChan-Youn 2022. 4. 29.

안녕하세요~ 챠니입니다! :)

오늘은 네이버 아이디 로그인연동에 대해서 알아보겠습니다.

줄여서 "네아로"라고도 불리는데요 어렵지 않으니 하나씩 천천히 따라오시면 되겠습니다 :)

 

    Naver Developers 설정

     

    ●  Naver Developers 접속

    https://developers.naver.com/apps

     

    애플리케이션 - NAVER Developers

     

    developers.naver.com

     

    ● 우측상단 "Application 등록" 클릭

     

    ● 애플리케이션 이름, 사용 API(네이버 로그인) 선택

     

     

    ● 사용 API를 선택, 로그인 오픈 API 서비스 환경(안드로이드) 선택

     

     

    ● 다운로드 URL(앱 다운로드 가능한 URL, 없으면 https://www.naver.com 이렇게 막 입력해도 가능)

    안드로이드 앱 패키지 이름(안드로이드 프로젝트 - AndroidManifest.xml의 pakageName 입력)

    모두 입력했으면 마지막 "등록하기" 클릭

     

    ● Client ID, Client Secret 값을 잘 적어둡니다.

    (안드로이드 프로젝트에서 사용)

     

     

    Android Proejct

    네이버 개발가이드: https://developers.naver.com/docs/login/android/android.md#android

     

    Android - LOGIN

    Android Android용 네아로SDK는 서드파티 애플리케이션에서 네이버 로그인이 제공하는 로그인, 로그아웃, 토큰 관리 등의 기능을 쉽게 구현할 수 있게 합니다. Github을 참고해 주세요. 문의사항이 있

    developers.naver.com

    안드로이드 애플리케이션을 생성 및 다음 코드들을 추가합니다.

     

    ●  build.gradle(:app)

    //네이버 로그인
    implementation 'com.navercorp.nid:oauth-jdk8:5.1.0' // jdk 8
    
    implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-android:1.3.9'

     

    ●  strings.xml

    <string name="social_login_info_naver_client_id">ID_KEY</string>
    <string name="social_login_info_naver_client_secret">SECREY_KEY</string>
    <string name="social_login_info_naver_client_name">네이버아이디 로그인</string>

     

    ●  MainActivity.kt

    NaverIdLoginSDK.initialize 또는 NaverIdLoginSDK.authenticate 에서

     

    Activity     -> this (Activity / this로 표기)

    Fragment -> requireActivity() or Context가 아닌 Activity로 표기

    /** MainActivity.kt */
    class MainActivity : AppCompatActivity() {
        private lateinit var binding: ActivityMainBinding
    
        override fun onCreate(savedInstanceState: Bundle?) {
            super.onCreate(savedInstanceState)
            binding = ActivityMainBinding.inflate(layoutInflater)
            setContentView(binding.root)
    
            /** Naver Login Module Initialize */
            val naverClientId = getString(R.string.social_login_info_naver_client_id)
            val naverClientSecret = getString(R.string.social_login_info_naver_client_secret)
            val naverClientName = getString(R.string.social_login_info_naver_client_name)
            NaverIdLoginSDK.initialize(this, naverClientId, naverClientSecret , naverClientName)
    
            setLayoutState(false) 
    
            binding.tvNaverLogin.setOnClickListener {
                startNaverLogin()
            }
            binding.tvNaverLogout.setOnClickListener {
                startNaverLogout()
            }
            binding.tvNaverDeleteToken.setOnClickListener {
                startNaverDeleteToken()
            }
        }
    
        /**
         * 로그인
         * authenticate() 메서드를 이용한 로그인 */
        private fun startNaverLogin(){
            var naverToken :String? = ""
    
            val profileCallback = object : NidProfileCallback<NidProfileResponse> {
                override fun onSuccess(response: NidProfileResponse) {
                    val userId = response.profile?.id
                    binding.tvResult.text = "id: ${userId} \ntoken: ${naverToken}"
                    setLayoutState(true)
                    Toast.makeText(this@MainActivity, "네이버 아이디 로그인 성공!", Toast.LENGTH_SHORT).show()
                }
                override fun onFailure(httpStatus: Int, message: String) {
                    val errorCode = NaverIdLoginSDK.getLastErrorCode().code
                    val errorDescription = NaverIdLoginSDK.getLastErrorDescription()
                    Toast.makeText(this@MainActivity, "errorCode: ${errorCode}\n" +
                            "errorDescription: ${errorDescription}", Toast.LENGTH_SHORT).show()
                }
                override fun onError(errorCode: Int, message: String) {
                    onFailure(errorCode, message)
                }
            }
    
            /** OAuthLoginCallback을 authenticate() 메서드 호출 시 파라미터로 전달하거나 NidOAuthLoginButton 객체에 등록하면 인증이 종료되는 것을 확인할 수 있습니다. */
            val oauthLoginCallback = object : OAuthLoginCallback {
                override fun onSuccess() {
                    // 네이버 로그인 인증이 성공했을 때 수행할 코드 추가
                    naverToken = NaverIdLoginSDK.getAccessToken()
    //                var naverRefreshToken = NaverIdLoginSDK.getRefreshToken()
    //                var naverExpiresAt = NaverIdLoginSDK.getExpiresAt().toString()
    //                var naverTokenType = NaverIdLoginSDK.getTokenType()
    //                var naverState = NaverIdLoginSDK.getState().toString()
    
                    //로그인 유저 정보 가져오기
                    NidOAuthLogin().callProfileApi(profileCallback)
                }
                override fun onFailure(httpStatus: Int, message: String) {
                    val errorCode = NaverIdLoginSDK.getLastErrorCode().code
                    val errorDescription = NaverIdLoginSDK.getLastErrorDescription()
                    Toast.makeText(this@MainActivity, "errorCode: ${errorCode}\n" +
                            "errorDescription: ${errorDescription}", Toast.LENGTH_SHORT).show()
                }
                override fun onError(errorCode: Int, message: String) {
                    onFailure(errorCode, message)
                }
            }
    
            NaverIdLoginSDK.authenticate(this, oauthLoginCallback)
        }
    
        /**
         * 로그아웃
         * 애플리케이션에서 로그아웃할 때는 다음과 같이 NaverIdLoginSDK.logout() 메서드를 호출합니다. */
        private fun startNaverLogout(){
            NaverIdLoginSDK.logout()
            setLayoutState(false)
            Toast.makeText(this@MainActivity, "네이버 아이디 로그아웃 성공!", Toast.LENGTH_SHORT).show()
        }
    
        /**
         * 연동해제
         * 네이버 아이디와 애플리케이션의 연동을 해제하는 기능은 다음과 같이 NidOAuthLogin().callDeleteTokenApi() 메서드로 구현합니다.
            연동을 해제하면 클라이언트에 저장된 토큰과 서버에 저장된 토큰이 모두 삭제됩니다.
         */
        private fun startNaverDeleteToken(){
            NidOAuthLogin().callDeleteTokenApi(this, object : OAuthLoginCallback {
                override fun onSuccess() {
                    //서버에서 토큰 삭제에 성공한 상태입니다.
                    setLayoutState(false)
                    Toast.makeText(this@MainActivity, "네이버 아이디 토큰삭제 성공!", Toast.LENGTH_SHORT).show()
                }
                override fun onFailure(httpStatus: Int, message: String) {
                    // 서버에서 토큰 삭제에 실패했어도 클라이언트에 있는 토큰은 삭제되어 로그아웃된 상태입니다.
                    // 클라이언트에 토큰 정보가 없기 때문에 추가로 처리할 수 있는 작업은 없습니다.
                    Log.d("naver", "errorCode: ${NaverIdLoginSDK.getLastErrorCode().code}")
                    Log.d("naver", "errorDesc: ${NaverIdLoginSDK.getLastErrorDescription()}")
                }
                override fun onError(errorCode: Int, message: String) {
                    // 서버에서 토큰 삭제에 실패했어도 클라이언트에 있는 토큰은 삭제되어 로그아웃된 상태입니다.
                    // 클라이언트에 토큰 정보가 없기 때문에 추가로 처리할 수 있는 작업은 없습니다.
                    onFailure(errorCode, message)
                }
            })
        }
    
        private fun setLayoutState(login: Boolean){
            if(login){
                binding.tvNaverLogin.visibility = View.GONE
                binding.tvNaverLogout.visibility = View.VISIBLE
                binding.tvNaverDeleteToken.visibility = View.VISIBLE
            }else{
                binding.tvNaverLogin.visibility = View.VISIBLE
                binding.tvNaverLogout.visibility = View.GONE
                binding.tvNaverDeleteToken.visibility = View.GONE
                binding.tvResult.text = ""
            }
        }
    }

     

    ● activity_main.xml 추가

    <?xml version="1.0" encoding="utf-8"?>
    <androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:app="http://schemas.android.com/apk/res-auto"
        xmlns:tools="http://schemas.android.com/tools"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        tools:context=".MainActivity">
    
        <androidx.constraintlayout.widget.ConstraintLayout
            android:id="@+id/cl_login"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_marginTop="20dp"
            app:layout_constraintLeft_toLeftOf="parent"
            app:layout_constraintTop_toTopOf="parent">
    
            <TextView
                android:id="@+id/tv_naver_login"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:background="#2DB400"
                android:padding="20dp"
                android:text="Naver Login"
                android:textColor="#FFFFFF"
                app:layout_constraintLeft_toLeftOf="parent"
                app:layout_constraintRight_toLeftOf="@+id/tv_naver_logout"
                app:layout_constraintTop_toTopOf="parent" />
    
            <TextView
                android:id="@+id/tv_naver_logout"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:background="#2DB400"
                android:padding="20dp"
                android:text="Naver Logout"
                android:textColor="#FFFFFF"
                android:visibility="gone"
                app:layout_constraintLeft_toRightOf="@+id/tv_naver_login"
                app:layout_constraintRight_toLeftOf="@+id/tv_naver_delete_token"
                app:layout_constraintTop_toTopOf="parent" />
    
            <TextView
                android:id="@+id/tv_naver_delete_token"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:background="#2DB400"
                android:padding="20dp"
                android:text="Naver Delete Token"
                android:textColor="#FFFFFF"
                android:visibility="gone"
                app:layout_constraintLeft_toRightOf="@+id/tv_naver_logout"
                app:layout_constraintRight_toRightOf="parent"
                app:layout_constraintTop_toTopOf="parent" />
        </androidx.constraintlayout.widget.ConstraintLayout>
    
        <TextView
            android:id="@+id/tv_result"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginTop="20dp"
            android:text="id, token: "
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintTop_toBottomOf="@+id/cl_login" />
    
    </androidx.constraintlayout.widget.ConstraintLayout>

     

     

    결과

    좌: 로그인 전 / 우:&nbsp; 로그인 후

     

     

    전체 소스코드

    [소스코드]

    네이버 아이디 로그인: https://github.com/younminchan/kotlin-sns-samples/tree/main/kotlin-naver-login

     

    GitHub - younminchan/kotlin-sns-samples: SNS(kakao, naver, facebook, google) 로그인 예제

    SNS(kakao, naver, facebook, google) 로그인 예제. Contribute to younminchan/kotlin-sns-samples development by creating an account on GitHub.

    github.com

     

     

    질문 또는 궁굼한 부분은 댓글을 남겨주세요! 친절하게 답변드리겠습니다!

    응원의 댓글은 저에게 큰 힘이 된답니다! :)

    즐거운 하루되세요!

     

    깃허브 보러 놀러오세요 👇 (맞팔환영)

    https://github.com/younminchan

     

    younminchan - Overview

    안드로이드 2년차 개발자 •⚽️/🎤/🥁/🖥/🏃‍♂️/🚴‍♂️/🤟 TechBlog⬇️ minchanyoun.tistory.com - younminchan

    github.com