페이지 이동경로
  • 문서>
  • 카카오 로그인>
  • iOS

카카오 로그인

iOS

이 문서는 Kakao SDK for iOS(이하 iOS SDK)를 사용한 카카오 로그인 구현 방법을 안내합니다.

카카오 로그인 구현에 필요한 로그인 버튼 이미지는 [도구] > [리소스 다운로드]에서 제공합니다. 해당 로그인 버튼은 디자인 가이드를 참고하여 서비스 UI에 적합한 크기로 수정하여 사용할 수 있습니다.

시작하기 전에

구현 방식 선택

사용자의 카카오계정을 인증하는 방식에 따라, iOS SDK를 사용한 카카오 로그인 구현 방법은 두 가지로 나뉩니다.

구현 방법 메서드 설명
카카오톡으로 로그인(권장) loginWithKakaoTalk() 카카오톡에 연결된 카카오계정 및 인증 정보를 사용
사용자가 카카오계정 정보를 직접 입력하지 않아도 간편하게 로그인 가능
카카오계정으로 로그인 loginWithKakaoAccount() 기본 웹 브라우저(Default Browser)를 통해 카카오계정 정보를 입력하고 로그인
사용자가 카카오계정 정보를 직접 입력하는 단계를 거침
사용자가 여러 개의 카카오계정을 사용하는 서비스, 카카오톡 미설치 또는 미지원 디바이스에서 사용

각 인증 방법의 특징과 서비스의 사용자 로그인 동선을 고려하여 어느 인증 방법이 적합한지 판단합니다. 두 가지 인증 방법을 함께 사용할 수도 있습니다. 인증 방법에 따라 필요한 설정이나 예외 처리에 차이가 있으므로, 인증 방법별 개발 가이드를 참고합니다.

필요한 모듈 설치하기

카카오 로그인 API를 사용하려면 카카오 로그인 모듈인 KakaoSDKUser, 사용자 인증 및 토큰 관리자 모듈인 KakaoSDKAuth를 설치해야 합니다. 모듈 설치 방법은 설치하기를 참고합니다.

모듈 설치 후 카카오 로그인 및 토큰 관련 API를 사용하려면 다음과 같이 모듈을 import합니다.

Swift
RxSwift
import KakaoSDKCommon
import KakaoSDKAuth
import KakaoSDKUser
import KakaoSDKCommon
import RxKakaoSDKCommon
import KakaoSDKAuth
import RxKakaoSDKAuth
import KakaoSDKUser
import RxKakaoSDKUser
주의: 카카오 로그인 모듈 개선에 따른 변경사항

기존에는 카카오 로그인 API를 KakaoSDKAuth 모듈의 AuthApi와 KakaoSDKUser 모듈의 UserApi를 통해 호출해야 했으나, iOS SDK 2.4.0 버전부터는 UserApi 하나로 호출할 수 있도록 개선하였습니다. 단, 사용자 인증 관련 API인 토큰 존재 여부 확인하기 API는 AuthApi를 통해 호출합니다. 문서의 예제 또한 최신 버전에 맞게 업데이트되었습니다.

카카오톡으로 로그인을 위한 설정

카카오톡으로 로그인 기능을 구현하기 위한 필수 설정입니다.

설정하기를 참고하여 앱에서 카카오톡을 실행시키기 위해 앱 실행 허용 목록(Allowlist)에 카카오톡을 등록하고, 서비스 앱으로 돌아올 때 쓰일 커스텀 URL 스킴을 설정합니다.

카카오톡으로 로그인은 서비스 앱에서 카카오톡으로 이동한 후, 사용자가 [동의하고 계속하기] 버튼 또는 로그인 취소 버튼을 누르면 다시 카카오톡에서 서비스 앱으로 이동하는 과정을 거칩니다. 카카오톡에서 서비스 앱으로 돌아왔을 때 카카오 로그인 처리를 정상적으로 완료하기 위해 AppDelegate.swift 파일에 handleOpenUrl()을 추가합니다.

Swift
RxSwift
import KakaoSDKAuth
...

class AppDelegate: UIResponder, UIApplicationDelegate {
    ...
    func application(_ app: UIApplication, open url: URL, options: [UIApplication.OpenURLOptionsKey : Any] = [:]) -> Bool {
        if (AuthApi.isKakaoTalkLoginUrl(url)) {
            return AuthController.handleOpenUrl(url: url)
        }

        return false
    }
    ...
}
import RxKakaoSDKAuth
import KakaoSDKAuth
...

class AppDelegate: UIResponder, UIApplicationDelegate {
    ...
    func application(_ app: UIApplication, open url: URL, options: [UIApplication.OpenURLOptionsKey : Any] = [:]) -> Bool {
        if (AuthApi.isKakaoTalkLoginUrl(url)) {
            return AuthController.rx.handleOpenUrl(url: url)
        }

        return false
    }
    ...
}

Deployment target이 iOS 13 이상으로 생성된 프로젝트라면 Info.plist 파일에 UIApplicationSceneManifest 설정이 추가되며, UISceneDelegate.swift를 기본으로 사용하도록 설정됩니다. UISceneDelegate.swift를 기본으로 사용하는 경우, AppDelegate.swift 파일 대신 SceneDelegate.swift 파일에 handleOpenUrl()을 추가합니다.

SwiftUI App Life Cycle 사용 시에는 SDK 초기화와 마찬가지로 ${PROJECT_NAME}App 클래스 내부에 onOpenURL()을 사용하여 handleOpenUrl()을 추가합니다.

아래 예제를 참고합니다.

Swift
RxSwift
SwiftUI App
import KakaoSDKAuth
...

class SceneDelegate: UIResponder, UIWindowSceneDelegate {
    ...
    func scene(_ scene: UIScene, openURLContexts URLContexts: Set<UIOpenURLContext>) {
        if let url = URLContexts.first?.url {
            if (AuthApi.isKakaoTalkLoginUrl(url)) {
                _ = AuthController.handleOpenUrl(url: url)
            }
        }
    }
    ...
}
import RxKakaoSDKAuth
import KakaoSDKAuth
...

class SceneDelegate: UIResponder, UIWindowSceneDelegate {
    ...
    func scene(_ scene: UIScene, openURLContexts URLContexts: Set<UIOpenURLContext>) {
        if let url = URLContexts.first?.url {
            if (AuthApi.isKakaoTalkLoginUrl(url)) {
                _ = AuthController.rx.handleOpenUrl(url: url)
            }
        }
    }
    ...
}
import SwiftUI
import KakaoSDKCommon
import KakaoSDKAuth
...

@main
struct SwiftUI_testApp: App {

    ...
    init() {
        // Kakao SDK 초기화
        KakaoSDK.initSDK(appKey: "NATIVE_APP_KEY")
    }

    var body: some Scene {
        WindowGroup {
            // onOpenURL()을 사용해 커스텀 URL 스킴 처리
            ContentView().onOpenURL(perform: { url in
                if (AuthApi.isKakaoTalkLoginUrl(url)) {
                    AuthController.handleOpenUrl(url: url)
                }
            })
        }
    }
    ...

}

카카오톡으로 로그인

기본 정보

사전 설정 사용자 동의 레퍼런스
플랫폼 등록
카카오 로그인 활성화
동의 항목
OpenID Connect 활성화(선택)
필요:
필수 동의 항목
공통
isKakaoTalkLoginAvailable()
AuthFailureReason
iOS SDK
loginWithKakaoTalk()
ReactiveX iOS SDK
loginWithKakaoTalk()

사전 설정 후, UserApiloginWithKakaoTalk()를 호출합니다. 먼저 isKakaoTalkLoginAvailable()로 카카오톡 설치 여부를 확인할 것을 권장합니다.

카카오톡으로 로그인 API가 호출되면 iOS SDK가 카카오톡을 실행시키고 사용자에게 앱 이용 관련 동의를 구하는 동의 화면을 출력합니다. API 호출 시 결과 처리를 클로저(Closure) 객체로 정의하여 전달해야 합니다.

동의 화면에서 사용자는 필수 항목에 모두 동의하여야 로그인할 수 있으며, 동의하지 않고 로그인을 취소할 수도 있습니다. 예외 처리를 위해 사용자의 로그인 취소 등 주요 에러가 공통 모듈인 KakaoSDKCommonAuthFailureReason에 정의되어 있습니다.

동의 화면에서 사용자가 모든 필수 항목에 동의하고 [동의하고 계속하기]를 선택하면, iOS SDK는 카카오톡에서 서비스 앱으로 돌아와 다음 단계인 인가 코드 발급과 토큰 발급을 처리하고 카카오 로그인을 완료합니다.

OpenID Connect를 사용하는 앱인 경우, ID 토큰을 함께 발급받습니다.

Swift
RxSwift
// 카카오톡 설치 여부 확인
if (UserApi.isKakaoTalkLoginAvailable()) {
    UserApi.shared.loginWithKakaoTalk {(oauthToken, error) in
        if let error = error {
            print(error)
        }
        else {
            print("loginWithKakaoTalk() success.")

            //do something
            _ = oauthToken            
        }
    }    
}
// Class member property
let disposeBag = DisposeBag()

// 카카오톡 설치 여부 확인
if (UserApi.isKakaoTalkLoginAvailable()) {   
    UserApi.shared.rx.loginWithKakaoTalk()
        .subscribe(onNext:{ (oauthToken) in
            print("loginWithKakaoTalk() success.")
        
            //do something
            _ = oauthToken
        }, onError: {error in
            print(error)
        })
    .disposed(by: disposeBag)
}
참고: 보안을 위한 파라미터

카카오 로그인은 OAuth 2.0 및 OpenID Connect 표준에 따라 보안을 위한 파라미터인 state, nonce 파라미터를 제공합니다. 사용자가 안전하게 카카오 로그인을 완료할 수 있도록 해당 파라미터 사용을 권장합니다.

stateCross-Site Request Forgery(CSRF) 공격으로부터 카카오 로그인 요청을 보호하기 위해 사용합니다. state는 카카오 로그인이 시작될 때부터 완료될 때까지 고유하고 동일한 값을 유지해야 합니다.

nonceOpenID Connect 사용 시 지원되는 파라미터로, ID 토큰 재생 공격을 방지하기 위해 사용합니다. 카카오 로그인 요청 시 전달된 nonce 값이 ID 토큰에 포함되며, ID 토큰 유효성 검증을 통해 요청 시 전달된 값과 ID 토큰에 포함된 값이 일치하는지 검증해야 합니다.

카카오계정으로 로그인

기본 정보

사전 설정 사용자 동의 레퍼런스
플랫폼 등록
카카오 로그인 활성화
동의 항목
OpenID Connect 활성화(선택)
필요:
필수 동의 항목
공통
AuthFailureReason
iOS SDK
loginWithKakaoAccount()
ReactiveX iOS SDK
loginWithKakaoAccount()

카카오계정 정보를 입력하여 로그인합니다. iOS SDK는 웹뷰(Web View)를 사용하지 않고 기본 웹 브라우저를 사용하여 로그인을 진행합니다. 사용자가 해당 기기의 동일한 웹 브라우저에서 이미 카카오계정으로 로그인한 상태라면 ID 및 비밀번호 입력 과정을 생략하고 간편하게 로그인할 수 있습니다.

UserApiloginWithKakaoAccount()를 호출합니다. 호출 시 iOS SDK가 웹 브라우저를 실행하고 카카오 로그인 화면을 띄웁니다. 카카오톡으로 로그인 요청과 마찬가지로 로그인 요청 결과 처리를 클로저 객체로 전달해야 합니다.

카카오계정으로 로그인 요청 시, iOS SDK는 OS 기본 웹 브라우저를 통해 사용자로부터 카카오계정 정보를 받아 인증을 완료한 뒤, 사용자에게 앱 이용 관련 동의를 요청하는 동의 화면을 출력합니다. 동의 화면에서 사용자가 모든 필수 항목에 동의하고 [동의하고 계속하기]를 선택하면 iOS SDK는 인가 코드 및 토큰 발급을 처리하고 카카오 로그인을 완료합니다.

OpenID Connect를 사용하는 앱인 경우, ID 토큰을 함께 발급받습니다.

Swift
RxSwift
UserApi.shared.loginWithKakaoAccount {(oauthToken, error) in
        if let error = error {
            print(error)
        }
        else {
            print("loginWithKakaoAccount() success.")            

            //do something
            _ = oauthToken            
        }
    }
// Class member property
let disposeBag = DisposeBag()

UserApi.shared.rx.loginWithKakaoAccount()
    .subscribe(onNext:{ (oauthToken) in
        print("loginWithKakaoAccount() success.")

        //do something
        _ = oauthToken        
    }, onError: {error in
        print(error)
    })
    .disposed(by: disposeBag)
참고: 보안을 위한 파라미터

카카오 로그인은 OAuth 2.0 및 OpenID Connect 표준에 따라 보안을 위한 파라미터인 state, nonce 파라미터를 제공합니다. 사용자가 안전하게 카카오 로그인을 완료할 수 있도록 해당 파라미터 사용을 권장합니다.

stateCross-Site Request Forgery(CSRF) 공격으로부터 카카오 로그인 요청을 보호하기 위해 사용합니다. state는 카카오 로그인이 시작될 때부터 완료될 때까지 고유하고 동일한 값을 유지해야 합니다.

nonceOpenID Connect 사용 시 지원되는 파라미터로, ID 토큰 재생 공격을 방지하기 위해 사용합니다. 카카오 로그인 요청 시 전달된 nonce 값이 ID 토큰에 포함되며, ID 토큰 유효성 검증을 통해 요청 시 전달된 값과 ID 토큰에 포함된 값이 일치하는지 검증해야 합니다.

참고: 기존 로그인 여부와 상관없이 로그인 요청

보안을 위해 기존의 로그인 여부와 상관없이 사용자에게 재인증을 요청하려면, prompts.Login으로 지정하여 전달합니다. 사용자가 해당 기기의 동일한 웹 브라우저에서 이미 카카오계정으로 로그인한 상태임에도 로그인 화면을 출력합니다.

Swift
RxSwift
UserApi.shared.loginWithKakaoAccount(prompts:[.Login]) {(oauthToken, error) in
    if let error = error {
        print(error)
    }
    else {
        print("loginWithKakaoAccount() success.")           
        
        //do something
        _ = oauthToken
            
    }
}
// Class member property
let disposeBag = DisposeBag()

UserApi.shared.rx.loginWithKakaoAccount(prompts: [.Login])
    .subscribe(onNext:{ (oauthToken) in
        print("loginWithKakaoAccount() success.")

        //do something
        _ = oauthToken        
    }, onError: {error in
        print(error)
    })
    .disposed(by: disposeBag)

토큰 존재 여부 확인하기

기본 정보

사전 설정 카카오 로그인 레퍼런스
플랫폼 등록
카카오 로그인 활성화
필요 공통
hasToken()

앱 실행 시 사용자가 앞서 로그인을 통해 발급 받은 토큰이 있는지 확인하려면 AuthApihasToken()을 호출합니다. 호출 결과는 기존에 발급 받은 액세스 토큰 또는 리프레시 토큰의 존재 여부를 Boolean 값으로 알려줍니다. 단, hasToken()의 결과가 true라도 현재 사용자가 로그인 상태임을 보장하지 않습니다.

Swift
RxSwift
if (AuthApi.hasToken()) {
    UserApi.shared.accessTokenInfo { (_, error) in
        if let error = error {
            if let sdkError = error as? SdkError, sdkError.isInvalidTokenError() == true  {
                //로그인 필요
            }
            else {
                //기타 에러
            }
        }
        else {
            //토큰 유효성 체크 성공(필요 시 토큰 갱신됨)
        }
    }
}
else {
    //로그인 필요
}
// Class member property
let disposeBag = DisposeBag()
                    
if (AuthApi.hasToken()) {
    UserApi.shared.rx.accessTokenInfo()
        .subscribe(onSuccess:{ (_) in
            //토큰 유효성 체크 성공(필요 시 토큰 갱신됨)
        }, onFailure: {error in
            if let sdkError = error as? SdkError, sdkError.isInvalidTokenError() == true  {
                //로그인 필요
            }
            else {
                //기타 에러
            }
        })
        .disposed(by: disposeBag)
}
else {
    //로그인 필요
}

hasToken() API의 결과가 false라면 토큰이 없는 상태이므로 사용자가 로그인할 수 있도록 처리합니다. 반면 결과가 true라면 UserApiaccessTokenInfo() API를 통해 액세스 토큰의 유효성을 확인할 수 있으며, 요청 결과에 따라 다음과 같이 처리합니다.

  • 요청 성공, 액세스 토큰 정보 반환
    • 액세스 토큰이 유효한 상태이므로 사용자 로그인 불필요
    • 해당 액세스 토큰으로 카카오 API 호출 가능
  • 에러 발생
    • 액세스 토큰 및 리프레시 토큰이 유효하지 않아 사용자 로그인 필요
    • 각 에러에 맞는 처리 필요, 레퍼런스 참고

토큰 정보 보기

기본 정보

사전 설정 카카오 로그인 레퍼런스
플랫폼 등록
카카오 로그인 활성화
필요 공통
AccessTokenInfo
iOS SDK
accessTokenInfo()
ReactiveX iOS SDK
accessTokenInfo()

UserApiaccessTokenInfo() API로 토큰 정보를 조회할 수 있습니다. 다음은 현재 캐시에 저장하여 사용 중인 사용자 액세스 토큰 정보를 출력하는 예제입니다.

Swift
RxSwift
// 사용자 액세스 토큰 정보 조회
UserApi.shared.accessTokenInfo {(accessTokenInfo, error) in
    if let error = error {
        print(error)
    }
    else {
        print("accessTokenInfo() success.")

        //do something
        _ = accessTokenInfo        
    }
}
// Class member property
let disposeBag = DisposeBag()

// 사용자 액세스 토큰 정보 조회
UserApi.shared.rx.accessTokenInfo()
    .subscribe(onSuccess:{ (accessTokenInfo) in        
        print("accessTokenInfo() success.")

        //do something
        _ = accessTokenInfo 
        
    }, onFailure: {error in
        print(error)
    })
    .disposed(by: disposeBag)

로그아웃

기본 정보

사전 설정 카카오 로그인 레퍼런스
플랫폼 등록
카카오 로그인 활성화
필요 iOS SDK
logout()
ReactiveX iOS SDK
logout()

사용자 액세스 토큰과 리프레시 토큰을 모두 만료시켜, 더 이상 해당 사용자 정보로 카카오 API를 호출할 수 없도록 합니다. UserApilogout()을 호출합니다.

로그아웃은 요청 성공 여부와 관계없이 토큰을 삭제 처리한다는 점에 유의합니다.

다음은 로그아웃 요청 예제입니다.

Swift
RxSwift
UserApi.shared.logout {(error) in
    if let error = error {
        print(error)
    }
    else {
        print("logout() success.")
    }
}
// Class member property
let disposeBag = DisposeBag()

UserApi.shared.rx.logout()
    .subscribe(onCompleted:{
        print("logout() success.")
    }, onError: {error in
        print(error)
    })
    .disposed(by: disposeBag)

연결 끊기

기본 정보

사전 설정 카카오 로그인 레퍼런스
플랫폼 등록
카카오 로그인 활성화
필요 iOS SDK
unlink()
ReactiveX iOS SDK
unlink()

카카오 플랫폼 안에서 앱과 사용자 카카오계정의 연결 상태를 해제합니다. UserApiunlink()를 호출합니다.

연결이 끊어지면 기존의 토큰은 더 이상 사용할 수 없으므로, 연결 끊기 요청 성공 시 로그아웃 처리가 함께 이뤄져 토큰이 삭제됩니다.

다음은 연결 끊기 요청 예제입니다.

Swift
RxSwift
UserApi.shared.unlink {(error) in
    if let error = error {
        print(error)
    }
    else {
        print("unlink() success.")
    }
}
// Class member property
let disposeBag = DisposeBag()

UserApi.shared.rx.unlink()
    .subscribe(onCompleted:{
        print("unlink() success.")
    }, onError: {error in
        print(error)
    })
    .disposed(by: disposeBag)

연결 끊기를 직접 호출한 경우가 아닌, 사용자가 서비스와의 연결을 직접 끊었을 때 알림을 받으려면 연결 끊기 알림 받기 기능을 사용합니다. 자세한 구현 방법 및 콜백 요청 정보는 연결 끊기 알림을 참고합니다.

사용자 정보 가져오기

기본 정보

사전 설정 카카오 로그인 사용자 동의 레퍼런스
플랫폼 등록
카카오 로그인 활성화
동의 항목
필요 필요:
사용자 정보를 요청할 모든 동의 항목
공통
User
iOS SDK
me()
ReactiveX iOS SDK
me()

현재 로그인한 사용자의 정보를 불러옵니다. UserApime()를 호출합니다.

다음은 사용자 정보 요청 예제입니다.

Swift
RxSwift
UserApi.shared.me() {(user, error) in
    if let error = error {
        print(error)
    }
    else {
        print("me() success.")
        
        //do something
        _ = user
    }
}
// Class member property
let disposeBag = DisposeBag()

UserApi.shared.rx.me()
    .subscribe (onSuccess:{ user in
        print("me() success.")
        
        //do something
        _ = user        
    }, onFailure: {error in
        print(error)
    })
    .disposed(by: disposeBag)

사용자 정보 응답은 KakaoSDKUser에 정의되어 있는 User 클래스 객체로 전달됩니다. 예를 들어 회원번호 값을 조회하려면 user.id, 카카오계정 프로필 정보들은 user.kakaoAccount.profile, 이메일은 user.kakaoAccount.email과 같이 접근할 수 있습니다.

하지만 사용자 정보 중 동의 항목으로 설정되지 않았거나, 사용자가 정보 제공에 동의하지 않았거나, 사용자가 해당 정보를 카카오에 제공한 적 없는 경우에는 값이 존재하지 않을 수 있으므로 예외 처리에 유의해야 합니다.

사용자 정보 종류는 사용자 정보를, 각 항목의 자료형 등 상세 정보는 레퍼런스를 참고합니다.

사용자 정보 저장하기

기본 정보

사전 설정 카카오 로그인 레퍼런스
플랫폼 등록
카카오 로그인 활성화
사용자 프로퍼티
필요 iOS SDK
updateProfile()
ReactiveX iOS SDK
updateProfile()

사용자 정보 저장하기 기능은 사용자 프로퍼티properties 하위 정보의 값을 저장합니다. 키 값은 [내 애플리케이션] > [사용자 프로퍼티]에 정의한 값을 사용해야 합니다.

UserApiupdateProfile()을 호출합니다. 업데이트할 사용자 프로퍼티의 키와 값 목록은 배열로 전달해야 합니다. 다음 예제와 같이 요청합니다.

Swift
RxSwift
UserApi.shared.updateProfile(properties: ["${CUSTOM_PROPERTY_KEY}":"${CUSTOM_PROPERTY_VALUE}"]) {(error) in
    if let error = error {
        print(error)
    }
    else {
        print("updateProfile() success.")
    }
}
// Class member property
let disposeBag = DisposeBag()

UserApi.shared.rx.updateProfile(properties:["${CUSTOM_PROPERTY_KEY}":"${CUSTOM_PROPERTY_VALUE}"])
    .subscribe(onCompleted:{
        print("updateProfile() success.")  
    }, onError: {error in
        print(error)
    })
    .disposed(by: disposeBag)

사용자 정보 저장 시 발생할 수 있는 에러와 원인에 대해서는 REST API 레퍼런스의 응답 코드를 참고합니다.

추가 항목 동의 받기

기본 정보

사전 설정 카카오 로그인 사용자 동의 레퍼런스
플랫폼 등록
카카오 로그인 활성화
동의 항목
필요 필요:
추가 동의를 요청할 모든 동의 항목
iOS SDK
loginWithKakaoTalk()
loginWithKakaoAccount()

추가 항목 동의 받기는 사용자가 첫 카카오 로그인 시 동의 화면에서 동의하지 않았지만, 서비스 이용 중 추가로 동의해야 하는 항목을 동의 요청하는 기능입니다. 추가 항목 동의 받기의 상세 설명을 확인한 후 사용해야 합니다.

직접 사용자에게 추가 동의를 요청하려면 UserApiloginWithKakaoTalk() 또는 loginWithKakaoAccount()를 호출합니다. 요청 시 추가 동의받을 항목의 키를 scopes 파라미터에 문자열 배열로 전달해야 합니다.

주의: OpenID Connect

OpenID Connect를 사용하는 앱의 경우, 추가 항목 동의 받기 요청 시 동의 항목 키를 전달하는 scope 파라미터 값에 openid를 반드시 포함해야 합니다. 해당 파라미터 값을 포함하지 않을 경우, ID 토큰이 재발급되지 않습니다. (참고: scope 파라미터)

요청 성공 시 iOS SDK는 사용자에게 추가 동의받을 항목의 동의를 요청하는 화면을 출력합니다. 사용자가 해당 항목에 동의하면 추가 동의가 성공 및 완료되고, 사용자가 취소하면 추가 동의 요청이 실패합니다. 이 기능은 카카오 로그인의 변형으로, 추가 동의 완료 시 토큰을 다시 발급받습니다.

다음은 me() API를 통해 추가 동의받을 항목을 확인한 후, 사용자에게 추가 동의를 요청하는 예제입니다. 예제에서는 모든 사용자 정보의 동의 여부를 확인하지만, 실제 구현 시에는 필요한 사용자 정보에 한해 구현해야 합니다.

Swift
RxSwift
UserApi.shared.me() { (user, error) in
    if let error = error {
        print(error)
    }
    else {
        if let user = user {
            var scopes = [String]()
            if (user.kakaoAccount?.profileNeedsAgreement == true) { scopes.append("profile") }
            if (user.kakaoAccount?.emailNeedsAgreement == true) { scopes.append("account_email") }
            if (user.kakaoAccount?.birthdayNeedsAgreement == true) { scopes.append("birthday") }
            if (user.kakaoAccount?.birthyearNeedsAgreement == true) { scopes.append("birthyear") }
            if (user.kakaoAccount?.genderNeedsAgreement == true) { scopes.append("gender") }
            if (user.kakaoAccount?.phoneNumberNeedsAgreement == true) { scopes.append("phone_number") }
            if (user.kakaoAccount?.ageRangeNeedsAgreement == true) { scopes.append("age_range") }
            if (user.kakaoAccount?.ciNeedsAgreement == true) { scopes.append("account_ci") }
            
            if scopes.count > 0 {
                print("사용자에게 추가 동의를 받아야 합니다.")

                // OpenID Connect 사용 시
                // scope 목록에 "openid" 문자열을 추가하고 요청해야 함
                // 해당 문자열을 포함하지 않은 경우, ID 토큰이 재발급되지 않음
                // scopes.append("openid")
                
                //scope 목록을 전달하여 카카오 로그인 요청
                UserApi.shared.loginWithKakaoAccount(scopes: scopes) { (_, error) in
                    if let error = error {
                        print(error)
                    }
                    else {
                        UserApi.shared.me() { (user, error) in
                            if let error = error {
                                print(error)
                            }
                            else {
                                print("me() success.")
                                
                                //do something
                                _ = user
                            }
                        }
                    }
                }
            }
            else {
                print("사용자의 추가 동의가 필요하지 않습니다.")
            }
        }
    }
}
// Class member property
let disposeBag = DisposeBag()

UserApi.shared.rx.me()
    .map({ (user) -> User in

        //필요한 scope을 아래의 예제코드를 참고해서 추가한다.
        //아래 예제는 모든 스콥을 나열한것.
        var scopes = [String]()
        
        if (user.kakaoAccount?.profileNeedsAgreement == true) { scopes.append("profile") }
        if (user.kakaoAccount?.emailNeedsAgreement == true) { scopes.append("account_email") }
        if (user.kakaoAccount?.birthdayNeedsAgreement == true) { scopes.append("birthday") }
        if (user.kakaoAccount?.birthyearNeedsAgreement == true) { scopes.append("birthyear") }
        if (user.kakaoAccount?.genderNeedsAgreement == true) { scopes.append("gender") }
        if (user.kakaoAccount?.phoneNumberNeedsAgreement == true) { scopes.append("phone_number") }
        if (user.kakaoAccount?.ageRangeNeedsAgreement == true) { scopes.append("age_range") }
        if (user.kakaoAccount?.ciNeedsAgreement == true) { scopes.append("account_ci") }
        
        if (scopes.count > 0) {
            print("사용자에게 추가 동의를 받아야 합니다.")

            // OpenID Connect 사용 시
            // scope 목록에 "openid" 문자열을 추가하고 요청해야 함
            // 해당 문자열을 포함하지 않은 경우, ID 토큰이 재발급되지 않음
            // scopes.append("openid")
            
            // scope 목록을 전달하여 SdkError 처리
            throw SdkError(scopes:scopes)
        }
        else {
            print("사용자의 추가 동의가 필요하지 않습니다.")

            return user
        }
    })
    .retry(when: Auth.shared.rx.incrementalAuthorizationRequired())
    .subscribe(onSuccess:{ ( user ) in
        print("me() success.")

        //do something
        _ = user
        
    }, onFailure: {error in
        print(error)
    })
    .disposed(by: disposeBag)
참고: ReactiveX iOS SDK의 추가 동의 요청

ReactiveX iOS SDK 사용 중 사용자의 추가 동의가 필요한 경우, 위 예제와 같이 SdkError로 해당 동의 항목 정보를 전달합니다. 이후 retryWhen 오퍼레이터에 의해 incrementalAuthorizationRequired() 메서드가 호출되며, 전달된 동의 항목에 대해 사용자에게 추가 동의를 받을 수 있습니다.

동의 내역 확인하기

기본 정보

사전 설정 카카오 로그인 레퍼런스
플랫폼 등록
카카오 로그인 활성화
동의 항목
필요 iOS SDK
scopes()
ReactiveX iOS SDK
scopes()

사용자가 동의한 동의 항목의 상세 정보 목록을 조회합니다. [내 애플리케이션] > [카카오 로그인] > [동의 항목]에 설정된 동의 항목의 목록과 사용자가 동의한 동의 항목의 상세 정보를 반환합니다. 사용자가 기존에 동의했던 동의 항목이라면 현재 앱에 사용하도록 설정돼 있지 않아도 응답에 포함됩니다.

UserApiscopes() API를 호출합니다. 요청 성공 시 응답은 scopeInfo 객체로 각 동의 항목의 상세 정보와 사용자 동의 여부를 포함합니다. 응답 상세 정보는 REST API 가이드 및 레퍼런스를 참고합니다.

Swift
RxSwift
UserApi.shared.scopes() { (scopeInfo, error) in
    if let error = error {
        self?.errorHandler(error: error)
    }
    else {
        self?.success(scopeInfo)
        
        //do something
        _ = scopeInfo
    }
}
// Class member property
let disposeBag = DisposeBag()

UserApi.shared.rx.scopes()
    .subscribe(onSuccess:{ (scopeInfo) in
        self.success(scopeInfo)
        
        //do something
        _ = scopeInfo
                                    
    }, onFailure: {error in
        self.errorHandler(error: error)
    })
    .disposed(by: self.disposeBag)

특정 동의 항목의 동의 내역만 확인하려면 scopes 파라미터로 동의 항목의 ID를 지정하여 요청할 수 있으며, [내 애플리케이션] > [카카오 로그인] > [동의 항목]의 ID를 참고합니다. 동의 항목 ID를 지정한 경우, 성공 응답은 지정된 동의 항목의 정보만 포함합니다.

Swift
RxSwift
UserApi.shared.scopes(scopes: ["account_email","gender"]) { (scopeInfo, error) in
    if let error = error {
        self?.errorHandler(error: error)
    }
    else {
        self?.success(scopeInfo)
        
        //do something
        _ = scopeInfo
    }
}
// Class member property
let disposeBag = DisposeBag()

UserApi.shared.rx.scopes(scopes: ["account_email","gender"])
    .subscribe(onSuccess:{ (scopeInfo) in
        self.success(scopeInfo)
        
        //do something
        _ = scopeInfo
                                    
    }, onError: {error in
        self.errorHandler(error: error)
    })
    .disposed(by: self.disposeBag)

동의 철회하기

기본 정보

사전 설정 카카오 로그인 레퍼런스
플랫폼 등록
카카오 로그인 활성화
동의 항목
필요 iOS SDK
revokeScopes()
ReactiveX iOS SDK
revokeScopes()

사용자가 동의한 항목에 대해 동의를 철회합니다. 동의 내역 확인하기 API를 통해 조회한 동의 항목 정보 중 동의 철회 가능 여부(revocable) 값이 true인 동의 항목만 철회 가능합니다. 동의 철회가 불가능한 동의 항목을 대상으로 요청한 경우 에러 응답을 받습니다.

UserApirevokeScopes()를 호출합니다. 철회할 동의 항목의 ID는 scopes 값으로 지정하며, [내 애플리케이션] > [카카오 로그인] > [동의 항목]의 ID를 참고합니다.

요청 성공 시 응답은 scopeInfo 객체로, 동의 철회를 반영한 후의 각 동의 항목 상세 정보 및 사용자 동의 내역을 포함합니다. 응답 상세 정보는 REST API 가이드 및 레퍼런스를 참고합니다.

Swift
RxSwift
UserApi.shared.revokeScopes(scopes: ["account_email","gender"]) { (scopeInfo, error) in
    if let error = error {
        self?.errorHandler(error: error)
    }
    else {
        self?.success(scopeInfo)
        
        //do something
        _ = scopeInfo
    }
}
// Class member property
let disposeBag = DisposeBag()

UserApi.shared.rx.revokeScopes(scopes: ["account_email","gender"])
    .subscribe(onSuccess:{ (scopeInfo) in
        self.success(scopeInfo)
        
        //do something
        _ = scopeInfo
                                    
    }, onFailure: {error in
        self.errorHandler(error: error)
    })
    .disposed(by: self.disposeBag)

고급: 연결하기

기본 정보

사전 설정 카카오 로그인 권한 레퍼런스
플랫폼 등록
카카오 로그인 활성화
필요 필요:
수동 연결 설정 권한
iOS SDK
signup()
ReactiveX iOS SDK
signup()

주의: 자동 연결 사용 여부 확인

연결하기는 자동 연결을 사용하지 않는 앱에서만 사용하는 API입니다. 사용 전 REST API 개발 가이드를 통해 사용 여부와 주의사항을 확인해야 합니다.

연결하기는 자동 연결을 [사용 안함]으로 설정한 앱에서 앱과 사용자를 수동으로 연결하는 기능입니다. 현재 로그인한 사용자가 연결하기를 통해 앱과 연결되어야 하는지 확인하려면 사용자 정보 가져오기 응답의 hasSignedUp 값을 확인하여 다음과 같이 처리합니다.

  • true: 이미 사용자와 앱이 연결되어 있으므로 다시 연결하기를 호출하지 않습니다.
  • false: 사용자와 앱이 연결되지 않은 상태이므로 signup()을 호출해 사용자와 앱을 연결해야 합니다.
  • nil: 자동 연결을 사용 중인 앱이므로 연결하기가 불필요합니다.

사용자의 hasSignedUp 값이 false이고, 서비스에서의 가입 준비가 끝나 앱과 연결하려면 signup()을 호출합니다. properties 파라미터로 사용자 프로퍼티 저장을 함께 요청할 수 있습니다. properties 파라미터의 구성 방법은 사용자 정보 저장하기를 참고합니다.

Swift
RxSwift
UserApi.shared.signup { (userId, error) in
    if let error = error {
        print(error)
    }
    else {
        print("signup() success.")
    }
}
// Class member property
let disposeBag = DisposeBag()

UserApi.shared.rx.signup()
    .subscribe (onSuccess:{ (userId) in
        print("signup() success.")        
    }, onFailure: {error in
        print(error)
    })
    .disposed(by: disposeBag)

요청 성공 시 별도의 사용자 정보가 제공되지 않으므로, 사용자 정보 가져오기 요청을 통해 다시 한 번 hasSignedUp 값을 확인해야 합니다.

Legacy

카카오 로그인의 Legacy Kakao SDK for iOS(이하 Legacy iOS SDK) 개발 가이드는 다음 링크에서 확인할 수 있습니다. 추후 Legacy iOS SDK에 대한 지원이 중단될 수 있으므로, 가급적 빠른 시일 내에 최신 버전 iOS SDK로 변경할 것을 권장합니다.

더보기