관리 메뉴

나만을 위한 블로그

[Android] 코틀린으로 네이버 로그인 구현하는 법 본문

Android

[Android] 코틀린으로 네이버 로그인 구현하는 법

참깨빵위에참깨빵_ 2022. 5. 20. 22:20
728x90
반응형

사용한 안드로이드 스튜디오는 범블비 버전이다.

 


만들어야 할 때마다 찾아보기 귀찮아서 쓴다.

 

먼저 네이버 디벨로퍼에서 네이버 로그인 API 사용 신청을 해야 한다.

https://developers.naver.com/main/

 

NAVER Developers

네이버 오픈 API들을 활용해 개발자들이 다양한 애플리케이션을 개발할 수 있도록 API 가이드와 SDK를 제공합니다. 제공중인 오픈 API에는 네이버 로그인, 검색, 단축URL, 캡차를 비롯 기계번역, 음

developers.naver.com

 

API를 신청할 계정으로 로그인한 다음 Application > 애플리케이션 등록을 누른다. 기존에 사용하던 API에서 네이버 로그인을 추가하고 싶다면 '내 애플리케이션'에서 선택한 다음 추가하면 된다.

여기선 처음부터 진행한다는 걸 가정하고 애플리케이션 등록부터 진행한다.

 

 

그리고 사용 API 옆 드롭다운을 눌러서 네이버 로그인을 선택하고 사용자한테 받을 정보 등을 대충 설정해주면 아래처럼 된다.

여기서 어떤 정보들이 필수고 필수가 아닌지 미리 메모장에 써두자. 나중에 앱 화면에서 아래 설정대로 정보를 요청하는지 확인해 보기 위함이다.

 

 

다운로드 URL은 개발 단계라면 랜딩 페이지 같은 임의의 URL을 입력해도 된다. 단 애플리케이션이 스토어에 등록됐다면 곧장 변경해줘야 한다. 네이버의 오픈 API 가이드에서도 명시하고 있는 부분이다. 임의의 URL은 아무거나 넣어도 상관없는데 심지어 네이버 사전 URL을 넣어도 작동한다.

 

https://developers.naver.com/docs/common/openapiguide/appregister.md

 

사전 준비 사항 - Open API 가이드

사전 준비 사항 네이버 오픈API를 사용하려면 먼저 네이버 개발자 센터에서 애플리케이션을 등록하고 클라이언트 아이디와 클라이언트 시크릿을 발급받아야 합니다. 클라이언트 아이디와 클라

developers.naver.com

 

그리고 등록하기를 눌러 등록했다면 멤버관리 탭을 눌러 테스터 ID를 등록해준다. 네이버 로그인 작동 테스트할 때 해당 아이디로 로그인하기 위함이다. 최대 20개까지 등록 가능하긴 한데 그렇게까지 많이 등록할 일은 없을 것이다.

 

 

그리고 API를 신청한 계정은 테스터 ID 등록을 할 필요가 없다. 위의 사진들을 찍기 위해 로그인한 계정의 아이디를 테스터 ID 등록 옆 입력란에 넣으면 아래와 같은 메시지가 뜨는 걸 볼 수 있다.

 

 

그러니 API를 생성한 계정이 아닌 다른 계정으로 테스트할 경우에만 넣어주고, API 생성 계정의 아이디는 넣을 필요가 없다.

이제 개요 탭을 눌러서 확인해야 할 정보들을 확인한다.

개발에 필요한 것은 Client ID, SECRET 2가지다.

 

 

처음에 Secret은 마스킹 처리돼서 안 보이고 녹색 보기 버튼을 누르면 보인다. 이 2가지 값들을 메모장 같은 곳에 복붙해둔다.

 

이제 안드로이드 스튜디오에서 네이버 로그인을 붙일 프로젝트를 실행한 다음, 앱 수준 gradle 파일에 아래 의존성을 복붙한다.

코루틴 의존성을 넣는 이유는 로그인한 유저 정보를 가져오는 메서드가 코루틴으로 실행되기 때문이다. 없으면 해당 메서드 밑에 빨간 줄이 생기면서 의존성을 넣으라는 컴파일 에러가 발생한다.

 

implementation 'com.navercorp.nid:oauth:5.1.0'
implementation "org.jetbrains.kotlinx:kotlinx-coroutines-android:1.6.0"

 

그리고 액티비티에서 바로 버튼 아이디에 접근할 수 있게 데이터 바인딩을 설정한다.

 

buildFeatures {
        dataBinding = true
    }

 

그리고 앞서 복사해둔 Client ID, SECRET을 사용하기 편하게 res/value의 strings.xml에 넣겠다.

local.properties에 넣어서 BuildConfig 상수로 만든 다음 필요할 때만 호출하는 방법도 있지만 귀찮으니 생략한다.

 

<string name="naver_client_id">client_id 값</string>
<string name="naver_client_secret">client_secret 값</string>

 

그리고 매니페스트를 수정한다. 매니페스트는 대충 아래와 같은 형태여야 한다. 인터넷 퍼미션은 당연히 있어야 한다.

 

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.example.snsloginpractice">
    <uses-permission android:name="android.permission.INTERNET" />
    <application
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:roundIcon="@mipmap/ic_launcher_round"
        android:supportsRtl="true"
        android:theme="@style/Theme.SnsLoginPractice">
        <activity
            android:name=".MainActivity"
            android:exported="true">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
    </application>

</manifest>

 

그리고 네이버 로그인을 호출할 버튼을 만들어준다.

 

<?xml version="1.0" encoding="utf-8"?>
<layout 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">

    <androidx.constraintlayout.widget.ConstraintLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        tools:context=".MainActivity">

        <Button
            android:id="@+id/naver_login_button"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintTop_toTopOf="parent"
            app:layout_constraintBottom_toBottomOf="parent"
            android:text="네이버 로그인"/>

    </androidx.constraintlayout.widget.ConstraintLayout>

</layout>

 

그리고 아래의 메인 액티비티 코틀린 파일 코드를 적당히 복붙한다.

 

import android.os.Bundle
import android.util.Log
import androidx.appcompat.app.AppCompatActivity
import androidx.databinding.DataBindingUtil
import com.example.snsloginpractice.databinding.ActivityMainBinding
import com.navercorp.nid.NaverIdLoginSDK
import com.navercorp.nid.oauth.NidOAuthLogin
import com.navercorp.nid.oauth.OAuthLoginCallback
import com.navercorp.nid.profile.NidProfileCallback
import com.navercorp.nid.profile.data.NidProfileResponse

class MainActivity : AppCompatActivity() {

    private val TAG = this.javaClass.simpleName

    private lateinit var binding: ActivityMainBinding
    private var email: String = ""
    private var gender: String = ""
    private var name: String = ""

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        binding = DataBindingUtil.setContentView(this, R.layout.activity_main)

        binding.run {
            naverLoginButton.setOnClickListener {
                val oAuthLoginCallback = object : OAuthLoginCallback {
                    override fun onSuccess() {
                        // 네이버 로그인 API 호출 성공 시 유저 정보를 가져온다
                        NidOAuthLogin().callProfileApi(object : NidProfileCallback<NidProfileResponse> {
                            override fun onSuccess(result: NidProfileResponse) {
                                name = result.profile?.name.toString()
                                email = result.profile?.email.toString()
                                gender = result.profile?.gender.toString()
                                Log.e(TAG, "네이버 로그인한 유저 정보 - 이름 : $name")
                                Log.e(TAG, "네이버 로그인한 유저 정보 - 이메일 : $email")
                                Log.e(TAG, "네이버 로그인한 유저 정보 - 성별 : $gender")
                            }

                            override fun onError(errorCode: Int, message: String) {
                                //
                            }

                            override fun onFailure(httpStatus: Int, message: String) {
                                //
                            }
                        })
                    }

                    override fun onError(errorCode: Int, message: String) {
                        val naverAccessToken = NaverIdLoginSDK.getAccessToken()
                        Log.e(TAG, "naverAccessToken : $naverAccessToken")
                    }

                    override fun onFailure(httpStatus: Int, message: String) {
                        //
                    }
                }

                NaverIdLoginSDK.initialize(this@MainActivity, getString(R.string.naver_client_id), getString(R.string.naver_client_secret), "앱 이름")
                NaverIdLoginSDK.authenticate(this@MainActivity, oAuthLoginCallback)
            }
        }
    }
}

 

처음에 API를 설정할 때 이름과 이메일, 성별을 받아오게 했으니 이것들을 요청하면 된다.

여기서 callProfileApi()가 사용자 정보를 요청하는 부분인데, 위에서 코루틴 의존성을 넣은 이유가 로그인한 사용자 정보를 가져오기 위해서라고 했다.

이 메서드명을 컨트롤 + 좌클릭해서 원형을 확인해 보면 아래와 같다. 아래처럼 만들어져 있어서 코루틴 의존성이 필요한 것이다.

 

fun callProfileApi(callback: NidProfileCallback<NidProfileResponse>) = CoroutineScope(Dispatchers.Main).launch {
        val response: Response<NidProfileResponse>
        try {
            response = withContext(Dispatchers.IO) {
                NidProfileApi().requestApi()
            }
        } catch (t: Throwable) {
            errorHandling(throwable = t)
            callback.onError(-1, t.toString())
            return@launch
        }

        val res = response.body()

        when (response.code()) {
            in 200 until 300 -> {
                if (res?.profile != null && !res.profile.id.isNullOrEmpty()) {
                    callback.onSuccess(res)
                } else {
                    callback.onFailure(response.code(), "${res?.resultCode ?: ""} ${res?.message ?: ""}")
                }
            }
            in 400 until 500 -> callback.onFailure(response.code(), response.message())
            else -> {
                errorHandling(errorCode = response.code())
                callback.onError(response.code(), response.message())
            }
        }
    }

 

initialize()의 4번 인자로 뭘 넣어야 하는지는 네이버 로그인 공식문서 기준 아래와 같이 말하고 있다.

 

네이버 앱의 로그인 화면에 표시할 애플리케이션 이름. 모바일 웹의 로그인 화면을 사용할 때는 서버에 저장된 애플리케이션 이름이 표시된다

 

근데 예제 코드처럼 "앱 이름" 이라고 써서 실행해봤는데 "앱 이름"이란 문자열은 보이지 않았다. 그렇지만 혹시 모르니 실제 프로젝트를 구현 중이라면 앱 이름을 넣어주자. 이 글처럼 "앱 이름" 이라고 썼다가 나중에 진짜로 저렇게 나오면 낭패다.

이렇게 하고 실행하면 에뮬레이터 기준 아래와 같은 화면이 나온다.

 

 

버튼 하나만 놨으니 당연히 이런 화면이 나온다. 이제 저 버튼을 누르면 아이디, 비밀번호를 입력하는 것부터 네이버 로그인 API가 작동 시작한다.

나타나는 인증 요청들을 처리해주고 나면 이런 화면이 나온다.

 

 

처음에 API를 설정할 때 이메일, 성별을 필수로 받아야 하는 정보로 설정하고 이름은 선택적으로 받는 정보로 설정했었다. 위 화면에서 그 설정이 제대로 먹힌 걸 볼 수 있다.

여기서 선택값인 이름을 제외하고 체크하면 어떻게 나오는지 확인해보자.

 

 

이제 OK를 누르면 로그인이 완료되면서 아래 로그가 출력된다.

 

 

이메일과 성별은 로그인 시 넘기도록 체크했기 때문에 로그를 확인하면 제대로 출력되는 걸 볼 수 있다.

그러나 이름만은 체크하지 않았기 때문에 로그에 null로 출력되는 걸 볼 수 있다.

 

오랜만에 네이버 로그인 API를 자바가 아닌 코틀린으로 구현했는데 로그인 화면이 조금 바뀌어서 신선했다.

나머지 다른 기능이 어떤 게 더 있는지 궁금하면 공식 문서를 찾아보자.

반응형
Comments