구글에 이어 네이버 로그인 달기

네이버는 한국 사이트라 자료도 몇 없더라..

네이버도 구글, 페이스북과 마찬가지로 개발자 계정으로 등록을 해야하고, 앱 역시 번들아이디와 함께 등록이 필요하다. 개발자 계정과 앱 등록을 마친 후에 아래 튜토리얼을 시도해 보자.


네이버 API 사용하기

https://developers.naver.com/docs/login/ios






1. 라이브러리 다운로드 및 프로젝트에 임포트



위에 게시한 주소에서 네이버 로그인 라이브러리를 다운받는다.

다운받을 땐 항상 최신 버전으로.


다운받은 라이브러리 안에는 Resources 폴더와 thirdPartyModule 폴더가 있다.

이 폴더를 프로젝트 내로 복사해주면 되는데, 폴더 째로 복사하면 타겟 - Build Pases - Link Binary와 Copy Bundle Resources 에서도 폴더 째로 추가된다. 그리고 이럴 경우, 안돌아간다....;;


수동으로 추가해 줄 수도 있겠지만, 편의상 폴더 내 파일들을 프로젝트로 복사 후, 그룹으로 분류했다.

그러면 Link Binary 와, Copy Bundle 에서도 자동으로 각각 추가가 될 것이다.






2. Other Linker Flags 설정


이건 사실 다른걸 다 끝내놓고 빌드에러를 보고 설정하는 방향을 추천하는데...

경우에 따라 정말 case by case 이기 때문 ㅎㅎㅎㅎㅎㅎ

네이버 공식 튜토리얼은 -ObjC -all_loaded를 추가하라고 하지만, -ObjC 따위 ㅎㅎㅎㅎㅎ 나한텐 수십개의 에러를 가져다주었음

그래서 열심히 구글링과 삽질 후 $(inherited) -all_loaded 로 추가해 주니 이상 무.

(경우에 따라, $(inherited) 만으로도 빌드될 수 있으니 참조하자)






3. 헤더 설정


Bridging-Header 를 만들어 주고, 프로젝트 - Build Settings - Objective-C Bridging Header 에 헤더 파일 명을 입력. 헤더파일 안에는 다음과 같이 라이브러리를 임포트


#import "NLoginThirdPartyOAuth20InAppBrowserViewController.h"

#import "NaverThirdPartyConstantsForApp.h"

#import "NaverThirdPartyLoginConnection.h"


이 라이브러리가 만약 xcodeproj 와 다른 폴더에 있다면 폴더명까지 명시해 주어야 한다.


그리고 NaverThirdPartyConstantsForApp.h 에서 값 몇개를 지정해 줘야 하는데, 이건 네이버 튜토리얼을 그대로 긁어옴..


// 콜백을 받을 URL Scheme

#define kUrlSampleAppUrlScheme @"thirdparty20samplegame"


// 애플리케이션에서 사용하는 클라이언트 아이디

#define kConsumerKey @"jyvqXeaVOVmV"


// 애플리케이션에서 사용하는 클라이언트 시크릿

#define kConsumerSecret @"527300A0_COq1_XV33cf"


// 애플리케이션 이름

#define@"네이버 아이디로 로그인하기"


여기에 들어갈 데이터는 네이버에 등록한 내 애플리케이션 정보를 참고하면 된다.






4. URL Scheme 등록

네이버에서 로그인 후, 앱으로 돌아와야 하는데, 이 때 돌아올 앱을 가리킬 수 있는 키가 URL Scheme.

타겟 - Info - URL Types 에서 등록해 줘야 한다.


Identifier 에는 번들 아이디를 넣고, URL Schemes 에는 적당한 값을 넣어주면 된다.

그리고 이 값은 곧, 네이버에 등록한 내 애플리케이션의 URL Scheme 와, 위의 헤더에 들어갈 kUrlSampleAppUrlScheme가 된다.


나는 심플하게 앱 이름으로. ㅎㅎㅎ







5. AppDelegate 설정


네이버 로그인 API를 사용하기 위해 앱을 기동할 때 몇 가지 값을 설정해줘야 하는데, 그것들은 아래와 같다.



// application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) 내에 설정


// Initialize Naver SignIn

let loginConn = NaverThirdPartyLoginConnection.getSharedInstance()

        

// 네이버앱으로 로그인 (네이버앱 미설치시, 사파리 연결)

loginConn?.isNaverAppOauthEnable = true

        

// 헤더에서 설정한 설정값 할당

loginConn?.serviceUrlScheme = kServiceAppUrlScheme

loginConn?.consumerKey = kConsumerKey

loginConn?.consumerSecret = kConsumerSecret

loginConn?.appName = kServiceAppName

        

// 화면 가로 회전 차단하기

loginConn?.setOnlyPortraitSupportInIphone(true)




그리고 아래는 로그인 실패 혹은 로그인을 거부했을 때 호출되는 메소드다.

로그인이 성공하면 호출이 안된다?

왜지... 네이버 뷰 컨트롤러에서 url을 오픈하면 항상 호출되어야 하는 거 아닌가....

라는 궁금증은 아직 미해결.


func application(_ app: UIApplication, open url: URL, options: [UIApplicationOpenURLOptionsKey : Any] = [:]) -> Bool {

    printDebug(message: url)

        

    var naverSignInResult = false

        

    if url.scheme == kServiceAppUrlScheme {

        if url.host == kCheckResultPage {

            let loginConn = NaverThirdPartyLoginConnection.getSharedInstance()

            let resultType = loginConn?.receiveAccessToken(url)

                

            if resultType == SUCCESS {

                printDebug(message: "Naver login success")

                naverSignInResult = true

            } else {

                printDebug(message: "ERROR : Naver Sign In Failed")

            }

        }

    }

        

    return naverSignInResult

}







6. 로그인


대충 버튼을 하나 만들고.


class viewController: UIViewController, NaverThirdPartyLoginConnectionDelegate {


    @IBAction func onTapNaverSignIn(_ sender: UIButton) {

        let loginConn = NaverThirdPartyLoginConnection.getSharedInstance()

        loginConn?.delegate = self

        loginConn?.requestThirdPartyLogin()

    }


    // 로그인 토큰이 없는 경우, 로그인 화면을 오픈한다.

    func oauth20ConnectionDidOpenInAppBrowser(forOAuth request: URLRequest!) {

        // Open Naver SignIn View Controller

        

        let naverSignInViewController = NLoginThirdPartyOAuth20InAppBrowserViewController(request: request)!

        present(naverSignInViewController, animated: true, completion: nil)

    }

    

    // ------------------------로그인 완료시 호출

    

    // 로그인 토큰이 없는 경우

    func oauth20ConnectionDidFinishRequestACTokenWithRefreshToken() {

        getNaverEmailFromURL()

    }

    

    // 로그인 토큰이 있는 경우

    func oauth20ConnectionDidFinishRequestACTokenWithAuthCode() {

        getNaverEmailFromURL()

    }





}


네이버로그인은 앱이 없는 경우, 로그인화면을 직접 오픈해줘야 하더라. 

- oauth20ConnectionDidOpenInAppBrowser


그리고 로그인 완료 후 호출되는 메소드가 로그인 동작 전에 로그인 토큰이 있었던 경우와 없었던 경우가 달랐다!

- oauth20ConnectionDidFinishRequestACTokenWithRefreshToken

- oauth20ConnectionDidFinishRequestACTokenWithAuthCode


그래서 두 메소드 모두 같은 동작을 수행하도록 사용자 정보를 가져오는 메소드를 따로 분류.

그리고 난 로그인 팝업을 항상 열도록 할거기 땜에 로그인 완료 후 토큰 삭제! (는 사실 아래 메소드로 분리..)







7. 사용자 정보 가져오기


사용자 정보 중 대표적으로 이메일을 가져와 보자.

이 방법을 찾는데 꽤 애를 먹었는데,

http://developer.naver.com/wiki/pages/NaverLogin_spec


이 페이지의 6.1 네이버 사용자 기본 정보 조회 - 인증 요청문 명세 에 있었다...



실제로 사용자의 정보가 담겨있는 데이터는 str 이라고 지정한 String.

이것을 (내가 만든) xmlParser 라는 메소드에 넣고 파싱한다.

이메일 외 다른 파라미터를 가져오고 싶다면, "email" 외에 네이버에서 지정한 다른 파라미터 키를 넣어주면 된다.

이것 역시 위 링크를 참조.



func getNaverEmailFromURL() {

    // Naver SignIn Success

        

    let loginConn = NaverThirdPartyLoginConnection.getSharedInstance()

    let tokenType = loginConn?.tokenType

    let accessToken = loginConn?.accessToken

        

    // Get User Profile

    if let url = URL(string: "https://apis.naver.com/nidlogin/nid/getUserProfile.xml") {

        if tokenType != nil && accessToken != nil {

                

            let authorization = "\(tokenType!) \(accessToken!)"

                

            var request = URLRequest(url: url)

            request.setValue(authorization, forHTTPHeaderField: "Authorization")

                

            let dataTask = URLSession.shared.dataTask(with: request) {(data, response, error) in

                    

                if let str = String(data: data!, encoding: .utf8) {

                    var email = CommonUtil().xmlParser(xml: str, title: "email")

                    email = email.components(separatedBy: "[")[2].components(separatedBy: "]")[0]

                    self.printDebug(message: "Naver email : " + email)

                        

                    // Naver Sign Out

                    loginConn?.resetToken()

                }

            }

            dataTask.resume()

        }

    }

}


사실 이건... 과잉친절같지만....





암튼 그러면 끝 ㅎㅎㅎㅎ

아.


printDebug(message: Any) 역시 간편한 디버깅을 위해 자체제작한 메소드입니다.




'Development > Solutions' 카테고리의 다른 글

CXErrorCodeCallDirectoryManagerError  (0) 2018.04.13
[Swift3] 그림자를 만들자  (0) 2017.02.08
[iOS - swift] 구글 로그인 달기  (1) 2016.10.21
퀵 정렬 알고리즘 (Quick Sort)  (0) 2016.10.18

WRITTEN BY
minjee
우리는 무엇을 할 수 있을까?

,