시작
Kakao 로그인에 이어서 Naver 로그인도 구현해 봅시다.
Naver 개발 문서는 정말 친절하지도 않고
설명도 Obj-c로 구현돼 있어서 짜증 나고 어려웠던 거 같습니다.
막상 해보니 구현 방법은 Kakao 로그인이랑 비슷하긴 하네요.
만약, 소셜로그인을 구현이 처음이시라면
Kakao 로그인을 구현해 보고 Naver 로그인을 해보시는 걸 추천드립니다.
Naver Dev. 사이트 설정
처음해야 할 일은 애플리케이션 등록 입니다.
아래 그림과 같이 먼저 애플리케이션 이름을 설정합니다.
다음으로 사용할 API를 설정해 주세요.
개발 환경 iOS를 선택합니다.
여기선 테스트 목적으로 사용했기 때문에, 다운로드 URL은 때문에 아무 주소나 적어줬습니다.
(이미 앱스토어에 올라가 있다면 그 주소를 사용해 줍시다)
그리고 저 같은 경우 URL Scheme은 Bundle Identifier로 설정해 줬습니다.
이건 나중에 프로젝트 설정에 필요하니 기억해 둡시다.
프로젝트 설정
프로젝트 타겟 -> Info -> URL Types로 들어가 URL Schemes를 설정해 줍시다.
개발자 사이트에서 설정한 값을 넣어주세요.
(Identifier는 식별할 수 있게 편하게 만들어 주세요)
다음으로 Info.plist 설정이 필요합니다.
iOS 9+부터 다른 앱을 실행하기 위해선
LSApplicationQueriesSchemes를 설정해줘야 합니다.
코드로 작성하고 싶다면
Info.plist 우 클릭-> Open As -> Source Code에서 추가가 가능합니다.
<key>LSApplicationQueriesSchemes</key>
<array>
<string>naversearchapp</string>
<string>naversearchthirdlogin</string>
</array>
라이브러리 설치
저는 Pod 말고 Swift Package Manger로 설치했습니다.
네이버 로그인 - GitHub 을 참고하세요.
여기서 수정할 부분이 있는데,
공식문서에서는 NaverThirdPartyConstantsForApp.h 파일의 값을 수정해 주라고 합니다.
하지만 문제는 Swift Package Manger를 사용한다면 편집이 불가능 합니다.
SPM를 사용하면 편집이 안 돼서 고민하다가
그냥 구현 코드에 설정 값들을 넣어주고 테스트를 해보니 문제없이 동작하더라고요!
그래서 위 작업은 일단 패스하고, 바로 구현으로 넘어가 봅시다.
구현
먼저, AppDelegate에서 로그인 실행에 필요한 기본적인 설정을 해봅시다.
import NaverThirdPartyLogin
@main
class AppDelegate: UIResponder, UIApplicationDelegate {
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
let instance = NaverThirdPartyLoginConnection.getSharedInstance()
// 네이버 앱으로 인증하는 방식 활성화(true)
instance?.isNaverAppOauthEnable = true
// SafariViewContoller에서 인증하는 방식 활성화(true)
instance?.isInAppOauthEnable = true
// 인증 화면을 iPhone의 세로 모드에서만 활성화(true)
instance?.setOnlyPortraitSupportInIphone(true)
// 로그인 설정
instance?.serviceUrlScheme = "com.github.DanielY1108.Login" // 콜백을 받을 URL Scheme
instance?.consumerKey = "6HR78H418KNRJ7czuJYg" // 애플리케이션에서 사용하는 클라이언트 아이디
instance?.consumerSecret = "HvtNmfy1g" // 애플리케이션에서 사용하는 클라이언트 시크릿
instance?.appName = "LoginTest" // 애플리케이션 이름
return true
}
func application(_ app: UIApplication, open url: URL, options: [UIApplication.OpenURLOptionsKey : Any] = [:]) -> Bool {
NaverThirdPartyLoginConnection.getSharedInstance().application(app, open: url, options: options)
}
}
위의 코드의 로그인 설정값들은
Naver 개발자 홈페이지 -> 내 애플리케이션에서 확인가능합니다.
다음으로 SceneDelegate에서 아래 코드를 추가해 줍시다.
import NaverThirdPartyLogin
class SceneDelegate: UIResponder, UIWindowSceneDelegate {
func scene(_ scene: UIScene, openURLContexts URLContexts: Set<UIOpenURLContext>) {
NaverThirdPartyLoginConnection
.getSharedInstance()
.receiveAccessToken(url)
}
}
}
로그인, 로그아웃, 사용자 정보 등을 받는 코드입니다.
import UIKit
import NaverThirdPartyLogin
import Alamofire
class NaverAuthVM: NSObject {
let instance = NaverThirdPartyLoginConnection.getSharedInstance()
override init() {
super.init()
instance?.delegate = self
}
func login() {
instance?.requestThirdPartyLogin()
}
func logout() {
// 저장된 토큰 정보만 삭제
// instance?.resetToken()
// 연동 해제(토큰 + 유저 정보 삭제)
instance?.requestDeleteToken()
print("저장된 토큰 제거 완료!")
}
func getNaverInfo() {
// 사용 가능한 토큰이 있는지 확인하는 메서드
guard let isVaildAccessToken = instance?.isValidAccessTokenExpireTimeNow() else { return }
guard isVaildAccessToken else {
print("저장된 토큰이 없습니다. 로그인 필요!")
return
}
guard let tokenType = instance?.tokenType,
let accessToken = instance?.accessToken else { return }
let authorization = "\(tokenType) \(accessToken)"
let urlStr = "https://openapi.naver.com/v1/nid/me"
guard let url = URL(string: urlStr) else { return }
let req = AF.request(url,
method: .get,
parameters: nil,
encoding: JSONEncoding.default,
headers: ["Authorization": authorization])
req.responseDecodable(of: NaverUserModel.self) { response in
switch response.result {
case .success(let model):
let resultCode = model.resultCode
let message = model.message
let value = model.value
print("Result Code: \(resultCode), Message: \(message)")
let email = value.email
let nickname = value.nickname
let age = value.age
let gender = value.gender
let id = value.id
let name = value.name
let birthday = value.birthday
let birthyear = value.birthyear
let mobile = value.mobile
let profileImage = value.profileImage
print("이메일: \(email)")
print("닉네임: \(nickname)")
print("이름: \(name)")
print("나이: \(age)")
print("성별: \(gender)")
print("아이디: \(id)")
print("생일: \(birthday)\(birthyear)")
print("휴대폰: \(mobile)")
case .failure(let error):
print(error)
}
}
}
}
extension NaverAuthVM: NaverThirdPartyLoginConnectionDelegate {
func oauth20ConnectionDidFinishRequestACTokenWithAuthCode() {
print("네이버 로그인 성공")
}
func oauth20ConnectionDidFinishRequestACTokenWithRefreshToken() {
print("네이버 토큰 갱신 성공")
}
func oauth20ConnectionDidFinishDeleteToken() {
print("네이버 연동 해제 성공")
}
func oauth20Connection(_ oauthConnection: NaverThirdPartyLoginConnection!, didFailWithError error: (any Error)!) {
print("에러 : \(error.localizedDescription)")
}
}
API로 통신으로 유저 정보를 받아오기 때문에
사용하기 편리하게 모델로 만들었습니다.
struct NaverUserModel: Codable {
let resultCode: String
let message: String
let value: NaverUserInfo
enum CodingKeys: String, CodingKey {
case resultCode = "resultcode"
case value = "response"
case message
}
}
struct NaverUserInfo: Codable {
let email: String
let nickname: String
let profileImage: String
let age: String
let gender: String
let id: String
let name: String
let birthday: String
let birthyear: String
let mobile: String
enum CodingKeys: String, CodingKey {
case email, nickname, age, gender, id, name, birthday, birthyear, mobile
case profileImage = "profile_image"
}
}
유저 정보 API 출력 값
사용자 정보 API 출력 결과 값은 이렇게 존재합니다.
프로젝트에 필요한 정보를 확인해서 구현해 주면 될 것 같습니다.
자세한 내용은 여기 를 참고해 주세요.
'UIKit > Swift' 카테고리의 다른 글
[iOS/Swift] Kakao 로그인 구현 방법 (0) | 2024.07.05 |
---|---|
[iOS/Swift] Apple 로그인 구현 방법 (0) | 2024.07.02 |
[iOS/Swift] TextField를 바인딩 시켜보자(MVVM, RxCocoa 원리) (0) | 2023.11.28 |
[iOS/Swift] sizeToFit, sizeThatFits 사용법 (0) | 2023.04.10 |
[iOS/Swift] NavigationController의 ToolBar를 코드로 만들어 봅시다 (0) | 2023.04.10 |