[iOS] 카카오 로그인

김범수·2022년 6월 2일
0

소셜 로그인

목록 보기
2/2

0. Kakao Developers 접속


https://developers.kakao.com

1. Kakao Developer 설정


1-1 앱 아이콘, 앱 이름, 사업자명 기재 후 앱 추가

1-2 번들 ID (필수) 및 앱스토어 id (선택) 입력 후 저장

1-3 카카오 로그인 활성화 (ON)

1-4 왼쪽 메뉴창의 동의 항목 내 필요한 정보 설정

  • 프로필 정보를 제외한 다른 동의 항목의 ‘필수 동의’ 설정이 불가
  • 설정한 동의 항목 내역은 앱의 카카오 로그인 동의 화면에 반영
  • ‘카카오계정으로 정보 수집 후 제공’ 기능에 대한 자세한 안내는 사용자 정보 가이드를 참고
  • 동의 목적은 참고 문구로 카카오 로그인 동의 화면에 나타나지 않으나, 해당 동의 항목 이용 권한 검수에 사용되는 참고 정보

1-5 (선택) Redirect **URI 및 팀 멤버 등록**

  • REST API로 개발한다면 Redirect URI 설정
  • 팀원과 함께 개발한다면 팀 멤버 등록

2. 프로젝트 설정


2-1 Pod 설치

# 전체 추가
pod 'KakaoSDK'
# or
# 카카오 로그인 시 필요 모듈
pod 'KakaoSDKCommon'  # 필수 요소를 담은 공통 모듈
pod 'KakaoSDKAuth'  # 카카오 로그인
pod 'KakaoSDKUser'  # 사용자 관리
# 필요한 모듈 추가
pod 'KakaoSDKTalk'  # 친구, 메시지(카카오톡)
pod 'KakaoSDKStory'  # 카카오스토리 
pod 'KakaoSDKLink'  # 메시지(카카오링크)
pod 'KakaoSDKTemplate'  # 메시지 템플릿 
pod 'KakaoSDKNavi'  # 카카오내비

2-2 **info.plist에 앱 실행 허용 목록(Allowlist) 등록**

2-3 **URL Schemes 설정**

URL Schemes에 항목에 네이티브 앱 키(Native App Key)를 ‘kakao{NATIVE_APP_KEY}’ 형식으로 등록

2-4 AppDelegate or SceneDelegate에 카카오톡에서 서비스 앱으로 돌아왔을 때 카카오 로그인 처리를 정상적으로 완료하기 위해 handleOpenUrl() 추가

import KakaoSDKAuth

func application(_: UIApplication, didFinishLaunchingWithOptions _: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
    sleep(2)
    // Override point for customization after application launch.
    KakaoSDKCommon.KakaoSDK.initSDK(appKey: "NATIVE_APP_KEY")
    return true
}
import KakaoSDKAuth

func scene(_ scene: UIScene, openURLContexts URLContexts: Set<UIOpenURLContext>) {
      if let url = URLContexts.first?.url {
          if (AuthApi.isKakaoTalkLoginUrl(url)) {
              _ = AuthController.handleOpenUrl(url: url)
          }
      }
  }

3. 카카오 로그인 로직


함수가 길어 분리가 필요하지만 사실 내용은 간단합니다

  • 토큰 유무 체크
    • 토큰 O:
      • 유저 정보 요청
    • 토큰 X:
      • 로그인
        • 앱 설치 여부
          • 앱 로그인
          • 웹 로그인
func kakaoSignin() -> Single<Result<AuthModel, APIError>> {
	return Single.create { single in
	    if AuthApi.hasToken() { // 기존 access token 토큰 존재 여부 체크
	        UserApi.shared.accessTokenInfo { _, error in // access token 토큰 요청
	            if error != nil { // access token 토큰 만료 시
	                if UserApi.isKakaoTalkLoginAvailable() { // 앱 로그인: 카톡 어플 O
	                    UserApi.shared.loginWithKakaoTalk { _, error in
	                        if error != nil { // 로그인 실패
	                            single(.success(.failure(APIError(statusCode: -1, description: error.debugDescription))))
	                        } else { // 로그인 성공, userId 발급
	                            UserApi.shared.me(completion: { user, error in
	                                guard let user = user,
	                                      let id = user.id
	                                else {
	                                    single(.success(.failure(APIError(statusCode: -1, description: error.debugDescription))))
	                                    return
	                                }
	                                let auth = AuthModel(type: .kakao,
	                                                     identyfier: String(id),
	                                                     email: user.kakaoAccount?.email,
	                                                     name: user.kakaoAccount?.name)
	                                single(.success(.success(auth)))
	                            })
	                        }
	                    }
	                } else { // 웹 로그인: 카톡 어플 X
	                    UserApi.shared.loginWithKakaoAccount { _, error in
	                        if error != nil { // 로그인 실패
	                            single(.success(.failure(APIError(statusCode: -1, description: error.debugDescription))))
	                        } else { // 로그인 성공, userId 발급
	                            UserApi.shared.me(completion: { user, error in
	                                guard let user = user,
	                                      let id = user.id
	                                else {
	                                    single(.success(.failure(APIError(statusCode: -1, description: error.debugDescription))))
	                                    return
	                                }
	                                let auth = AuthModel(type: .kakao,
	                                                     identyfier: String(id),
	                                                     email: user.kakaoAccount?.email,
	                                                     name: user.kakaoAccount?.name)
	                                single(.success(.success(auth)))
	                            })
	                        }
	                    }
	                }
              } else { // 토큰 유효 시, userId 발급
                  UserApi.shared.me(completion: { user, error in
                      guard let user = user,
                            let id = user.id
                      else {
                          single(.success(.failure(APIError(statusCode: -1, description: error.debugDescription))))
                          return
                      }
                      let auth = AuthModel(type: .kakao,
                                           identyfier: String(id),
                                           email: user.kakaoAccount?.email,
                                           name: user.kakaoAccount?.name)
                      single(.success(.success(auth)))
                  })
              }
          }
      } else { // 토큰 없을 시
          if UserApi.isKakaoTalkLoginAvailable() { // 간편 로그인: 카톡 어플 있을 시
              UserApi.shared.loginWithKakaoTalk { _, error in
                  if error != nil { // 로그인 실패
                      single(.success(.failure(APIError(statusCode: -1, description: error.debugDescription))))
                  } else { // 로그인 성공, userId 발급
                      UserApi.shared.me(completion: { user, error in
                          guard let user = user,
                                let id = user.id
                          else {
                              single(.success(.failure(APIError(statusCode: -1, description: error.debugDescription))))
                              return
                          }
                          let auth = AuthModel(type: .kakao,
                                               identyfier: String(id),
                                               email: user.kakaoAccount?.email,
                                               name: user.kakaoAccount?.name)
                          single(.success(.success(auth)))
                      })
                  }
              }
          } else { // 카톡 어플 없을 시
              UserApi.shared.loginWithKakaoAccount { _, error in
                  if error != nil {
                      single(.success(.failure(APIError(statusCode: -1, description: error.debugDescription))))
                  } else { // 로그인 성공, userId 발급
                      UserApi.shared.me(completion: { user, error in
                          guard let user = user,
                                let id = user.id
                          else {
                              single(.success(.failure(APIError(statusCode: -1, description: error.debugDescription))))
                              return
                          }
                          let auth = AuthModel(type: .kakao,
                                               identyfier: String(id),
                                               email: user.kakaoAccount?.email,
                                               name: user.kakaoAccount?.name)
                          single(.success(.success(auth)))
                      })
                  }
              }
          }
      }
      return Disposables.create()
  }
}
profile
iOS Developer

0개의 댓글