[iOS] 네이버 아이디로 로그인 구현하기 with SwiftUI

💻 이 글은 Swift 5.0, Xcode Version 13.2.1 를 바탕으로 작성하였습니다.

Naver ID Login SDK for iOS

네이버 로그인 SDK는 서드파티 애플리케이션에서 네이버 계정, 애플리케이션으로 로그인, 로그아웃, 토큰 관리, 연동 해제 등의 기능을 쉽게 구현할 수 있게 합니다.

인증 절차

네이버 아이디로 로그인은 OAuth2.0 프로토콜을 기반으로 사용자 인증 기능을 제공합니다.

1. Authorization Code 얻기
네이버 앱 또는 브라우져에서 간편 로그인 프로세스 (Authentication) 를 거쳐 Authorization Code 를 얻고, URL Scheme 으로 등록된 자신의 앱으로 코드가 포함된 URL 을 가지고 리다이렉트 됩니다. 그리고 앱에서 이 URL이 네이버 로그인을 위한 URL인지 판단합니다.

2. Authorization Code로 Token 얻기
네이버 로그인을 위한 URL이라고 판단이 되면, Authorization Code 로 네이버 서버에 Access Token 과 Refresh Token 을 요청합니다.

3. API 호출
발급받은 Access Token 을 헤더에 담아 다른 API를 요청할 수 있습니다.

요구사항

iOS 9.0 이상
XCode 9.0 이상

요구하는 환경의 버전이 상당히 낮은데, iOS용 네이버 로그인 SDK는 Objective-C...로 만들어졌습니다. 그리고 대다수의 자료들이 UIKit Lifecycle 기반이라서 구현에 조금 어려움을 겪었는데요, SwiftUI Lifecycle 로 구현하는 방법을 기술해보도록 하겠습니다.


설치방법

Cocoapods로 설치하기

프로젝트 폴더에서 Pod init → Podfile에 아래 코드를 추가 → Pod install

pod 'naveridlogin-sdk-ios'

프로젝트 설정

애플리케이션 등록

Naver Developers (https://developers.naver.com/main/) 의 [Application] 탭으로 이동해서 애플리케이션을 등록합니다. 사용할 네이버 오픈 API와 제공받을 정보를 선택하고, URL Scheme을 등록합니다. 이때 URL Scheme은 소문자로만 구성하는 것을 권장드립니다.

info.plist 설정

  • [Info] > [Custom iOS Target Properties]에 LSApplicationQueriesSchemes를 추가 (Array 타입)
  • 해당 키의 아이템으로 커스텀 URL 스킴에 사용할 값인 naversearchapp, naversearchthirdlogin을 추가

URL Schemes 설정

바로 아래의 URL Types을 펼쳐 아까 등록했던 URL Scheme을 추가합니다.

상수값 설정

프로젝트 폴더에서 [Pods > naveridlogin-sdk-ios > NaverThirdPartyLogin.framework 우클릭후 패키지 내용 보기 > Headeras > NaverThirdPartyConstantsForApp.h] 를 열어 제일 아래 define된 4개의 변수를 자신의 프로젝트에 맞게 수정해줍니다.

#define kServiceAppUrlScheme    @"[앱 등록때 설정한 URL Scheme]"
#define kConsumerKey            @"[애플리케이션 정보 > Client ID]"
#define kConsumerSecret         @"[애플리케이션 정보 > Client Secret]"
#define kServiceAppName         @"[앱 이름]"

초기화

프로젝트 최상위 코드인 [project name]App.swift 의 초기화 함수 init() 에서 NaverThirdPartyLogin 초기화 코드를 작성해줍니다.

import SwiftUI
import NaverThirdPartyLogin

@main
struct NanuriApp: App {
    init() {
        // Naver SDK Initializing
 
 		// 네이버 앱으로 로그인 허용
        NaverThirdPartyLoginConnection.getSharedInstance()?.isNaverAppOauthEnable = true 
        // 브라우저 로그인 허용
        NaverThirdPartyLoginConnection.getSharedInstance()?.isInAppOauthEnable = true 
 
        // 네이버 로그인 세로모드 고정
        NaverThirdPartyLoginConnection.getSharedInstance().setOnlyPortraitSupportInIphone(true)
        
        // NaverThirdPartyConstantsForApp.h에 선언한 상수 등록
        NaverThirdPartyLoginConnection.getSharedInstance().serviceUrlScheme = kServiceAppUrlScheme
        NaverThirdPartyLoginConnection.getSharedInstance().consumerKey = kConsumerKey
        NaverThirdPartyLoginConnection.getSharedInstance().consumerSecret = kConsumerSecret
        NaverThirdPartyLoginConnection.getSharedInstance().appName = kServiceAppName
    }
    
	var body : some View {
    	WindowGroup {
	    	ContentView()
            	.onOpenURL { url in 
            		if NaverThirdPartyLoginConnection
                    		.getSharedInstance()
                            .isNaverThirdPartyLoginAppschemeURL(url) 
                    {                            
	                	// Token 발급 요청
	    	            NaverThirdPartyLoginConnection
    	    	            .getSharedInstance()
        	    	        .receiveAccessToken(url)
            		}
        }
	}
}

네이버 로그인은 로그인을 위해 네이버 앱 또는 브라우저로 이동한 후, 사용자의 동의 이후에 다시 앱으로 이동하는 과정을 거칩니다. 이때 다시 앱으로 돌아왔을 때 네이버 로그인을 처리하기 위해 .onOpenURL { ... } 다음 코드를 추가해야 합니다. 리다이렉트되어 돌아올때 갖고 있는 URL 이 네이버 로그인을 위한 URL 인지 판단을 하고 맞다면 토큰을 요청하는 것 입니다.


Delegate 구현

네이버 로그인을 구현하기 위해서는 네이버 로그인이 실행되었을때 필요한 delegate가 필요한데 스유에서 구현하기 위해서 viewModel 을 extension 했습니다. 그리고 viewModel 은 NSObject와 UIApplicationDelegate 를 상속해야 합니다.

extension MyPageViewModel : UIApplicationDelegate, NaverThirdPartyLoginConnectionDelegate {
    // 토큰 발급 성공시
    func oauth20ConnectionDidFinishRequestACTokenWithAuthCode() { ... }
    // 토큰 갱신시 
    func oauth20ConnectionDidFinishRequestACTokenWithRefreshToken() { ... }
    // 로그아웃(토큰 삭제)시 
    func oauth20ConnectionDidFinishDeleteToken() { ... }
    // Error 발생
    func oauth20Connection(_ oauthConnection: NaverThirdPartyLoginConnection!, didFailWithError error: Error!) { ... }
}

Naver Login

네이버 로그인은 NaverThirdPartyLoginConnection의 싱글턴 객체인 .getSharedInstance() 를 통해서 모든 작업이 이루어집니다!

네이버 로그인 호출

Button {
	if NaverThirdPartyLoginConnection
		.getSharedInstance()
		.isPossibleToOpenNaverApp() // Naver App이 깔려있는지 확인하는 함수
	{
		NaverThirdPartyLoginConnection.getSharedInstance().delegate = viewModel.self
		NaverThirdPartyLoginConnection
        	.getSharedInstance()
			.requestThirdPartyLogin()
	} else { // 네이버 앱 안깔려져 있을때
		// Appstore에서 네이버앱 열기
		NaverThirdPartyLoginConnection.getSharedInstance().openAppStoreForNaverApp()

	}
} label : {
	Image("naver_login")
		.resizable()
		.aspectRatio(contentMode: .fit)
}

네이버 로그인은 카카오 로그인과 다르게 .requestThirdPartyLogin() 이 실행되면 앱 설치여부를 자동으로 판단해서 네이버 앱으로 이동 또는 웹 브라우져 모달을 띄우지만, 앱스토어 이동을 위해서 따로 조건을 나누어 주었습니다.

여기서 실제 데이터의 Flow

  • .requestThirdPartyLogin() 후 네이버 앱 또는 브라우져에서 네이버 계정1 로그인
  • 앱에 사용자 정보 제공을 위한 동의
  • Authorization Code를 담고 있는 URL을 가지고 앱으로 돌아옴 (Redirect)
  • .onOpenURL { ... } 에서 URL이 네이버 로그인을 위한 URL이라고 판단되면 .receiveAccessToken(url) 를 호출해서 토큰 발급

성공적으로 토큰을 발급받은 후 아까 구현한 Delegate 내의 oauth20ConnectionDidFinishRequestACTokenWithAuthCode() 가 실행됩니다.

유저 정보 받아오기

네이버 로그인 SDK 에서는 따로 유저정보를 받아오는 함수가 정의 되어있지 않습니다. 그래서 https 요청을 이용해서 정보를 받아올 수 있습니다. 아래는 Alamofire 를 이용해서 유저 정보를 요청하는 함수입니다.

func getUserInfo() {        
        guard let tokenType = NaverThirdPartyLoginConnection.getSharedInstance().tokenType else { return }
        guard let accessToken = NaverThirdPartyLoginConnection.getSharedInstance().accessToken else { return }
        let url = "https://openapi.naver.com/v1/nid/me"
        
        AF.request(url,
                   method: .get,
                   encoding: JSONEncoding.default,
                   headers: ["Authorization": "\(tokenType) \(accessToken)"]
        ).responseJSON { [weak self] response in
            guard let result = response.value as? [String: Any] else { return }
            guard let object = result["response"] as? [String: Any] else { return }
            
            guard let name = object["name"] as? String else { return }
            guard let email = object["email"] as? String else { return }
            guard let profileimage = object["profile_image"] as? String else { return }

            self?.profileImage = URL(string: profileimage)
            self?.userMail = email
            self?.userName = name
        }
    }

토큰 관련

// Refresh Token 
let refreshToken = NaverThirdPartyLoginConnection.getSharedInstance().refreshToken
// Access Toekn 
let accessToken = NaverThirdPartyLoginConnection.getSharedInstance().accessToken

// 유효한 Token 존재 여부 확인 
NaverThirdPartyLoginConnection.getSharedInstance().isValidAccessTokenExpireTimeNow()
// Token Refreshing
NaverThirdPartyLoginConnection.getSharedInstance().requestAccessTokenWithRefreshToken()

로그아웃 (토큰 삭제)

NaverThirdPartyLoginConnection.getSharedInstance().resetToken()

연결 끊기 (연동 해제)

NaverThirdPartyLoginConnection.getSharedInstance().requestDeleteToken()

마무리

SwiftUI 로 네이버 아이디로 로그인을 구현하는 방법을 알아보았습니다. 네이버 아이디로 로그인은 SDK 자체가 오래되기도 하였고, Objective-C 를 처음 봐서 신기하기도 했습니다😅

틀린 정보 또는 궁금한 점이 있다면 댓글 부탁드립니다! 읽어주셔서 감사합니다‼️

좋은 웹페이지 즐겨찾기