한 문장 요약
Apple / Google 로그인 핸들러와 “동일한 추상화 레벨”을 유지하면서,
Kakao SDK의 특성을 Swift Concurrency에 맞게 감싸는 것
이게 설계의 핵심이야.
2️⃣ 설계 기준 ① — “Handler 패턴” 유지
이미 네 프로젝트에 존재하는 구조
이미 이런 패턴을 쓰고 있어:
AuthService
├─ AppleAuthHandler
├─ GoogleAuthHandler
└─ (KakaoAuthHandler ← 여기에 추가)
이 구조의 장점은 명확:
- AuthService는 로그인 전략을 선택만 함
- 각 Handler는 자기 SDK만 책임
- ViewModel은 AuthService만 의존
👉 그래서 Kakao도 무조건 Handler로 들어가야 함
3️⃣ 설계 기준 ② — “책임을 accessToken까지로 제한”
KakaoAuthHandler의 책임 범위
KakaoAuthHandler
└─ Kakao SDK 사용
└─ 사용자 인증
└─ accessToken 반환 (여기까지)
❌ 하지 않는 것:
- Firebase 로그인
- 서버 통신
- Custom Token 처리
근거 (아키텍처 원칙)
이건 Clean Architecture / SRP(Single Responsibility Principle) 그대로야.
“Kakao SDK가 바뀌면, KakaoAuthHandler만 바뀌어야 한다.”
만약 KakaoAuthHandler 안에서:
- Firebase Functions 호출
- Firebase Auth 로그인까지 해버리면?
👉 Kakao SDK 변경 + Firebase 변경이 한 클래스에 섞임
이건 실무에서 바로 리젝 사유야.
4️⃣ 설계 기준 ③ — async/await로 통일
Kakao SDK의 원래 API
Kakao SDK는 콜백 기반이야:
UserApi.shared.loginWithKakaoTalk { oauthToken, error in
...
}
하지만 프로젝트는 이미:
- Swift Concurrency 사용
- Apple / Google 로그인도 async 기반
그래서 우리는 이걸 이렇게 감쌌지:
try await withCheckedThrowingContinuation { continuation in
...
}
이 패턴의 근거 자료
🔗 Apple 공식 문서
- Adopting Swift Concurrency
- Wrapping Callback-Based APIs
Apple이 직접 권장하는 방식
“기존 callback API를 async/await로 감싸라”
5️⃣ 설계 기준 ④ — “카카오톡 / 계정 로그인 분기”
Kakao 공식 가이드의 핵심
Kakao는 공식적으로 말해:
“카카오톡이 설치되어 있으면 카카오톡 로그인 사용을 권장”
그래서 SDK도 아예 이 API를 제공해:
UserApi.isKakaoTalkLoginAvailable()
이걸 무시하고:
- 항상 account 로그인만 쓰거나
- 항상 talk 로그인만 쓰는 건
👉 공식 가이드 위반
그래서 login()의 흐름은 이렇게 설계됨:
func login() async throws -> String {
if UserApi.isKakaoTalkLoginAvailable() {
return try await loginWithKakaoTalk()
} else {
return try await loginWithKakaoAccount()
}
}
📌 이 구조는 카카오 공식 샘플 코드의 구조를 그대로 유지하면서
Swift Concurrency만 얹은 형태야.
6️⃣ “근거 자료” 정리 (네가 요청한 부분)
아래는 실제로 참고 가능한 근거들이야.
① Kakao iOS SDK 공식 문서
- Kakao iOS SDK – Login
- UserApi.shared.loginWithKakaoTalk
- UserApi.shared.loginWithKakaoAccount
👉 우리가 쓴 API는 전부 공식 문서에 있는 것
https://developers.kakao.com/docs/latest/ko/kakaologin/ios
Kakao Developers
카카오 API를 활용하여 다양한 어플리케이션을 개발해 보세요. 카카오 로그인, 메시지 보내기, 친구 API, 인공지능 API 등을 제공합니다.
developers.kakao.com
② Apple 공식 Swift Concurrency 문서
- Using Async/Await
- withCheckedThrowingContinuation (https://developer.apple.com/documentation/swift/withcheckedthrowingcontinuation(isolation:function:_:))
👉 callback → async 변환 방식의 정석
③ Firebase / Google / Apple 로그인과의 “레벨 맞추기”
이건 특정 문서라기보다 실무 관례야.
- AppleAuthHandler → 인증 토큰 반환
- GoogleAuthHandler → 인증 토큰 반환
- KakaoAuthHandler → accessToken 반환
👉 “소셜 로그인 Handler는 토큰까지만”
이건 실무에서 거의 암묵적인 룰
import Foundation
// MARK: - KakaoAuthProviding
/// Kakao 로그인을 담당하는 인터페이스입니다.
///
/// AuthService는 이 Protocol에만 의존하며,
/// Kakao SDK의 실제 구현 디테일은 알 필요가 없습니다.
protocol KakaoAuthProviding {
/// 카카오 로그인을 수행합니다.
///
/// - Returns: Kakao accessToken
/// - Throws: 로그인 실패 시 에러
func login() async throws -> String
}
----------------------------------------------------------------
import Foundation
import KakaoSDKAuth
import KakaoSDKUser
// MARK: - KakaoAuthHandler
/// Kakao SDK를 사용해 실제 로그인 로직을 수행하는 구현체입니다.
///
/// 책임:
/// 1. 카카오톡 설치 여부 판단
/// 2. 카카오톡 / 카카오계정 로그인 분기
/// 3. 로그인 성공 시 accessToken 반환
///
/// ❗️Firebase, 서버 통신(Custom Token)은 여기서 다루지 않습니다.
final class KakaoAuthHandler: KakaoAuthProviding {
// MARK: - Public
/// Kakao 로그인 진입점
///
/// 카카오톡 설치 여부에 따라
/// - 설치 O → 카카오톡 로그인
/// - 설치 X → 카카오 계정 로그인
func login() async throws -> String {
if UserApi.isKakaoTalkLoginAvailable() {
return try await loginWithKakaoTalk()
} else {
return try await loginWithKakaoAccount()
}
}
}
// MARK: - Private Login Methods
private extension KakaoAuthHandler {
/// 카카오톡 로그인
///
/// Kakao SDK의 callback 기반 API를
/// Swift async/await 스타일로 래핑합니다.
func loginWithKakaoTalk() async throws -> String {
try await withCheckedThrowingContinuation { continuation in
UserApi.shared.loginWithKakaoTalk { oauthToken, error in
// 1️⃣ Kakao SDK 에러 발생
if let error = error {
continuation.resume(throwing: error)
return
}
// 2️⃣ accessToken 추출 실패
guard let accessToken = oauthToken?.accessToken else {
continuation.resume(throwing: KakaoAuthError.failedToGetToken)
return
}
// 3️⃣ 로그인 성공 → accessToken 반환
continuation.resume(returning: accessToken)
}
}
}
/// 카카오 계정 로그인 (웹 로그인)
///
/// 카카오톡이 설치되어 있지 않은 경우 사용됩니다.
func loginWithKakaoAccount() async throws -> String {
try await withCheckedThrowingContinuation { continuation in
UserApi.shared.loginWithKakaoAccount { oauthToken, error in
// 1️⃣ Kakao SDK 에러 발생
if let error = error {
continuation.resume(throwing: error)
return
}
// 2️⃣ accessToken 추출 실패
guard let accessToken = oauthToken?.accessToken else {
continuation.resume(throwing: KakaoAuthError.failedToGetToken)
return
}
// 3️⃣ 로그인 성공 → accessToken 반환
continuation.resume(returning: accessToken)
}
}
}
}
// MARK: - KakaoAuthError
/// Kakao 로그인 과정에서 발생할 수 있는 에러 정의
enum KakaoAuthError: Error {
/// accessToken을 정상적으로 얻지 못한 경우
case failedToGetToken
}'PulseBoard' 카테고리의 다른 글
| 🤔 카카오, 네이버 로그인 - accessToken 처리 방향 (0) | 2025.12.26 |
|---|---|
| ▶️ index.js 파일 설치기 (버전 이슈 해결 포함) (0) | 2025.12.26 |
| 🚀 axios 설치와 역할 - 서버에서 토큰 검증이 필요한 이유! (0) | 2025.12.26 |
| Firebase Cloud Functions index.js 완전 해설 (0) | 2025.12.25 |
| Firebase Authentication의 OpenID Connect를 쓰지 않고Cloud Functions + Custom Token으로 Kakao 로그인을 구현한 이유 (1) | 2025.12.25 |