카카오로그인 구현

유재우·2022년 10월 10일
0

iOS Developer의 길!

목록 보기
3/15

1. 앱 등록

우선 카카오 디벨로퍼사이트에 접속하여 내 애플리케이션을 클릭하고 앱등록을 한다.


애플리케이션 추가하기를 클릭하고 사용할 플랫폼에 맞게 생성해준다.


번들 ID를 프로젝트랑 통일 시켜준다.


2. 패키지 다운받기

이후 카카오 디벨로퍼 사이트에 다시 접속하여 시작하기 카테고리를 선택하고 자신에게 맞는 플랫폼을 클릭해준다.


Swift와 RxSwift 중 상황에 맞는 Repository URL을 복사해준다.


프로젝트로 넘어와 PackageDependencies로 들어가 +를 눌러준다.


우측 상단에 검색창에 방금 복사한 URL을 붙여넣기하고 Dependency Rule이 Branch -> master인 것을 확인하고 Add to Project가 현재 프로젝트인 것을 확인하고 Add Package를 클릭한다.




여기서 필요한 패키지만 선택하여 설치를 해준다.



설치 된 모습


3. 설정


Info.plist를 Source Code로 열어준다.


소스코드에서 최상위 <dict>안에 밑에 소스코드를 복사해서 붙여넣기 해준다.

<key>LSApplicationQueriesSchemes</key>
  <array>
      <!-- 카카오톡으로 로그인 -->
      <string>kakaokompassauth</string>
      <!-- 카카오톡 공유 -->
      <string>kakaolink</string>
  </array>

성공적으로 LSApplicationQueriesSchemes이 추가가 된 모습


info창에 맨 밑에 있는 URL Types에 + 버튼을 눌러 추가해준다.


다시 내 애플리케이션에 있는 프로젝트의 요약 정보 카테고리에 들어가 네이티브 앱키의 앱키를 복사해준다.


URL Schemes칸에 방금 복사한 앱키를 kakao를 앞에 써주고 붙여넣기 해준다.

하지만 이 앱키 부분은 소스코드를 공유 시 보이기 때문에, 보안 작업이 필요합니다.

우선 Configuration Settings File을 생성해줍니다.


다음과 같이 작성해준다.

KAKAO_NATIVE_APP_KEY = <- YOUR APP KEY

이 후에 다시 info창에 URL Schemes 칸을 수정해줍니다.

kakao${KAKAO_NATIVE_APP_KEY}

다시 info.plist에 KAKAO_NATIVE_APP_KEY를 추가하고 String형으로 ${KAKAO_NATIVE_APP_KEY}값을 저장해둡니다.


마지막으로 프로젝트의 Info에 가서 Configurations에 있는 Debug/Release에 있는 None을 방금 생성한 Config파일로 설정해 줍니다.


설정한 모습


config 파일이 GitHub에 올라가지 못하게 gitignore파일에 밑에 코드를 복사해서 붙여넣는다.

*.xcconfig

이런 식으로 Native App Key를 환경변수로 만들어서 사용하게 되면 편하게 관리할 수 있고, 외부에 노출을 막을 수 있다.


4. 초기화


MyApplication 파일을 만들어 밑에 코드를 붙여 넣는다.

import RxKakaoSDKCommon
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey : Any]? = nil) -> Bool {
        // 메인번들에 있는 카카오 앱키 불러오기
        let kakaoAppKey = Bundle.main.infoDictionary?["KAKAO_NATIVE_APP_KEY"] ?? ""
        // kakao SDK 초기화
        RxKakaoSDK.initSDK(appKey: kakaoAppKey as! String)
        return true
    }

프로젝트 이름으로 되있는 Swift파일에 밑에 코드를 위의 사진과 같은 위치에 붙여 넣는다.

@UIApplicationDelegateAdaptor var appDelegate : MyAppDelegate

MySceneDelegate 파일을 만들고 밑에 코드를 붙여 넣는다.

import Foundation
import UIKit
import RxKakaoSDKAuth
import KakaoSDKAuth
class MySceneDelegate: 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)
            }
        }
    }
}


MyAppDelegate와 MySceneDelegate를 이어주는 함수를 MyAppDelegate 파일에 작성해준다.

func application(_ app: UIApplication, open url: URL, options: [UIApplication.OpenURLOptionsKey : Any] = [:]) -> Bool {
            if (AuthApi.isKakaoTalkLoginUrl(url)) {
                return AuthController.rx.handleOpenUrl(url: url)
            }
            return false
        }
    // appDelegate 에서 sceneDelegate 연결 하기
        func application(_ application: UIApplication, configurationForConnecting connectingSceneSession: UISceneSession, options: UIScene.ConnectionOptions) -> UISceneConfiguration {
            let sceneConfigutation = UISceneConfiguration(name: nil, sessionRole: connectingSceneSession.role)
            sceneConfigutation.delegateClass = MySceneDelegate.self
            return sceneConfigutation
        }

5. 카카오 로그인

내 어플리케이션에 카카오 로그인 항목에 들어가 활성화 시켜주고 Redirect URI를 설정해준다.


이 후에 동의항목에서 프로젝트에 사용할 항목을 설정해준다.


6. 카카오 앱 설치 여부 확인

KakaoAuthVM 파일을 새로 만들고 카카오 앱 설치 여부를 확인하고 없으면 WebView를 이용하여 로그인 할수 있게하는 코드를 작성해준다.

import Foundation
import RxSwift
import Combine
import RxKakaoSDKAuth
import RxKakaoSDKUser
import KakaoSDKUser
class KakaoAuthVM: ObservableObject {
    // Class member property
    let disposeBag = DisposeBag()
    func handleKakaoLogin() {
        // 카카오톡 설치 여부 확인
        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)
        } else { // 카카오톡이 설치가 안되어 있을 경우
            // 카카오 계정으로 로그인 하기 - 웹뷰를 열러서 로그인 하기
            UserApi.shared.loginWithKakaoAccount {(oauthToken, error) in
                if let error = error {
                    print(error)
                }
                else {
                    print("loginWithKakaoAccount() success.")
                    //do something
                    _ = oauthToken
                }
            }
        }
    }
}

7. 로그아웃

우선 KakaoAuthVM 파일에 가서 밑에 코드를 붙여넣는다.

// Class member property
let disposeBag = DisposeBag()
UserApi.shared.rx.logout()
    .subscribe(onCompleted:{
        print("logout() success.")
    }, onError: {error in
        print(error)
    })
    .disposed(by: disposeBag)


위의 함수를 async await 함수로 변경해준다.

func handleKakaoLogout() async -> Bool {
        await withCheckedContinuation{ continuation in
            UserApi.shared.rx.logout()
                .subscribe(onCompleted:{
                    print("logout() success.")
                    continuation.resume(returning: true)
                }, onError: {error in
                    print(error)
                    continuation.resume(returning: false)
                })
                .disposed(by: disposeBag)
        }
    }

로그아웃/로그인 상태를 알 수 있는 변수를 설정해주고 그에 관련된 함수를 KakaoAuthVM에 선언한다.


LoginButton 파일에 가서 로그아웃 버튼을 만들어준다.

Button(action: {
                kakoAuthVM.KakaoLogout()
            }, label: {
                Text("카카오 로그아웃")
            })

로그인 여부에 따라 값이 바뀌는 함수를 선언해주고 버튼 액션에 위와 같이 코드를 선언한다.

let loginStatusInfo : (Bool) -> String = { isLogedIn in
        return isLogedIn ? "로그인 상태" : "로그아웃 상태"
    }
    ...
Button(action: {
                kakoAuthVM.KakaoLogout()
            }, label: {
                Text("카카오 로그아웃")
            })
            Text(loginStatusInfo(kakoAuthVM.isLogedIn)) 
            // 로그인 상태를 보여주는 텍스트

위에서 작성했던 handleKakaoLogin() 함수를 위와같이 함수를 나누어 모두 async await 처리를 해준다.
handleKakaoLogin() 함수

func handleLoginWithKakaoTalkApp() async -> Bool {
        await withCheckedContinuation{ continuation in
            UserApi.shared.rx.loginWithKakaoTalk()
                .subscribe(onNext:{ (oauthToken) in
                    print("loginWithKakaoTalk() success.")
                    continuation.resume(returning: true)
                    //do something
                    _ = oauthToken
                }, onError: {error in
                    print(error)
                    continuation.resume(returning: false)
                })
                .disposed(by: disposeBag)
        }
    }
    func handleWithKakaoAccount() async -> Bool{
        await withCheckedContinuation{ continuation in
            // 카카오 계정으로 로그인 하기 - 웹뷰를 열러서 로그인 하기
            UserApi.shared.loginWithKakaoAccount {(oauthToken, error) in
                if let error = error {
                    print(error)
                    continuation.resume(returning: false)
                }
                else {
                    print("loginWithKakaoAccount() success.")
                    continuation.resume(returning: true)
                    //do something
                    _ = oauthToken
                }
            }
        }
    }
    func handleKakaoLogin() {
        Task{
            // 카카오톡 설치 여부 확인
            if (UserApi.isKakaoTalkLoginAvailable()) {
                isLogedIn = await handleLoginWithKakaoTalkApp()
            } else { // 카카오톡이 설치가 안되어 있을 경우
                isLogedIn = await handleWithKakaoAccount()
            }
        }
    }

마지막으로 Task{}가 있는 함수 에 @MainActor를 선언해준다.

8. 실행 화면

카카오 로그인 버튼 클릭 전


카카오 앱이 없을 시 이런 식으로 웹 사이트로 연다고 알림창이 뜸


전에 동의항목 설정한 항목만 물어보는 화면


로그인을 한번 하고 껐다가 다시 버튼을 클릭 했을때 뜨는 화면


로그도 정상적으로 받아오는 콘솔창 화면


로그아웃이 성공적으로 되는 콘솔창


참고한 유튜브 링크(개발하는 정대리)를 보고 RxSwift는 살짝 코드가 달라 직접 정리해 봤다.

profile
끝없이 탐구하는 iOS 개발자 유재우입니다!

0개의 댓글