728x90
SMALL
https://firebase.google.com/docs/auth/ios/google-signin?hl=ko
Apple 플랫폼에서 Google 로그인을 사용하여 인증 | Firebase Authentication
의견 보내기 Apple 플랫폼에서 Google 로그인을 사용하여 인증 컬렉션을 사용해 정리하기 내 환경설정을 기준으로 콘텐츠를 저장하고 분류하세요. Google 로그인을 앱에 통합하여 사용자가 Google 계
firebase.google.com
Firebase 공식 튜토리얼 구조 요약
공식 문서(Google Sign-In SDK 기준)의 핵심 흐름은 다음과 같다.
📌 튜토리얼의 기본 흐름
- GIDSignIn.sharedInstance.signIn
- Google 사용자 인증 성공
- ID Token + Access Token 획득
- GoogleAuthProvider.credential(...)
- Auth.auth().signIn(with: credential)
여기서 가장 중요한 개념 하나
❗ “Google 로그인” ≠ “Firebase 로그인”
이게 진짜 핵심이야.
- Google 로그인
- Google이 “이 사용자가 누구인지” 증명
- 결과물: ID Token, Access Token
- Firebase 로그인
- Firebase가 “이 Google 사용자를 우리 앱 사용자로 받아들임”
- 입력값: AuthCredential
👉 GoogleAuthProvider.credential(...)
이 메서드는 두 세계를 연결하는 어댑터 역할이야.
📌 특징
- ViewController 안에서 모든 로직 처리
- 로그인 UI / 토큰 처리 / Firebase 연동이 한 파일에 결합
- “동작 예제”로는 충분하지만
- 테스트
- 확장
- 유지보수
에는 한계가 있음
1️⃣ 튜토리얼 코드 ① URL Scheme 처리
📌 Firebase 튜토리얼 코드
func scene(
_ scene: UIScene,
openURLContexts URLContexts: Set<UIOpenURLContext>
) {
return GIDSignIn.sharedInstance.handle(url)
}
🔍 이 코드의 역할
- Google 로그인은 외부 브라우저 / Google 앱을 사용
- 인증이 끝나면 앱으로 다시 돌아오며 URL 콜백 발생
- 해당 URL을 Google Sign-In SDK에게 전달해야 로그인 완료
⚠️ 중요한 점
- 이 코드는 “로그인 로직”이 아님
- 앱 전역 설정 레벨(SceneDelegate) 책임
👉 따라서 이 부분은 리팩토링 대상이 아님
👉 GoogleAuthHandler로 옮기지 않는다
2️⃣ 튜토리얼 코드 ② Client ID 설정
📌 Firebase 튜토리얼 코드
guard let clientID = FirebaseApp.app()?.options.clientID else { return }
let config = GIDConfiguration(clientID: clientID)
GIDSignIn.sharedInstance.configuration = config
🔍 이 코드의 역할
- Firebase 프로젝트에 연결된 Google OAuth Client ID 획득
- Google Sign-In SDK에 인증 정보 주입
⚠️ 최신 SDK에서의 변화
- 최신 GoogleSignIn SDK에서는
👉 configuration을 명시적으로 설정하지 않아도 됨 - GoogleService-Info.plist를 통해 자동 설정
✅ 우리가 한 선택
// 최신 SDK는 configuration 설정 불필요
GIDSignIn.sharedInstance.signIn(withPresenting: ...)
👉 튜토리얼 코드 중 “환경 설정” 부분은 제거
3️⃣ 튜토리얼 코드 ③ Google 로그인 시작
📌 Firebase 튜토리얼 코드
GIDSignIn.sharedInstance.signIn(withPresenting: viewController) { result, error in
🔍 이 코드의 역할
- Google 로그인 UI 표시
- 사용자가 계정 선택 / 인증 진행
🧠 문제점
- 보통 이 코드는 ViewController 내부에 위치
- UI + Auth 로직이 결합됨
4️⃣ 튜토리얼 코드 ④ Token 추출
📌 Firebase 튜토리얼 코드
guard let user = result?.user,
let idToken = user.idToken?.tokenString
else {
return
}
🔍 이 코드의 역할
- Google 인증 성공 후
- ID Token
- Access Token
획득
👉 Firebase Auth로 넘어가기 위한 재료
5️⃣ 튜토리얼 코드 ⑤ Firebase Auth 연동
📌 Firebase 튜토리얼 코드
let credential = GoogleAuthProvider.credential(
withIDToken: idToken,
accessToken: user.accessToken.tokenString
)
self.signIn(with: credential)
🔍 이 코드의 역할
- Google 인증 정보 → Firebase 인증 정보로 변환
- Firebase Auth에 로그인 요청
🔄 이제, 이 코드를 어떻게 리팩토링했는가?
6️⃣ 책임 분리의 시작: GoogleAuthHandler
🎯 리팩토링 기준
“Google 로그인 전체 흐름을 하나의 객체가 책임진다”
📦 튜토리얼 → GoogleAuthHandler 대응 관계
| 튜토리얼 위치 | 역할 | 리팩토링 후 |
| SceneDelegate | URL 콜백 처리 | 유지 (전역 설정) |
| ViewController | signIn 호출 | GoogleAuthHandler |
| ViewController | 토큰 처리 | GoogleAuthHandler |
| ViewController | Firebase 연동 | GoogleAuthHandler |
7️⃣ GoogleAuthHandler 구현 핵심
// MARK: - GoogleAuthHandler
/// Google 로그인 전담 핸들러
///
/// Google Sign-In SDK를 통해 인증을 수행하고,
/// 획득한 인증 정보를 Firebase Auth와 연동하는 책임을 가집니다.
final class GoogleAuthHandler {
// MARK: - Login
/// Google 로그인 플로우를 시작합니다.
///
/// - Parameters:
/// - presentingViewController: Google 로그인 UI를 표시할 ViewController
/// - completion: 로그인 성공 / 실패 결과
func startLogin(
presentingViewController: UIViewController,
completion: @escaping (Result<Void, Error>) -> Void
) {
// 최신 GoogleSignIn SDK는 configuration을 직접 전달하지 않음
GIDSignIn.sharedInstance.signIn(
withPresenting: presentingViewController
) { result, error in
if let error {
completion(.failure(error))
return
}
guard
let user = result?.user,
let idToken = user.idToken?.tokenString
else {
completion(.failure(AuthError.invalidCredential))
return
}
let credential = GoogleAuthProvider.credential(
withIDToken: idToken,
accessToken: user.accessToken.tokenString
)
// Firebase Auth와 연동
Auth.auth().signIn(with: credential) { _, error in
if let error {
completion(.failure(error))
} else {
completion(.success(()))
}
}
}
}
}
🔍 무엇이 달라졌나?
- 튜토리얼 로직 100% 동일
- 단, 위치와 책임만 변경
- ViewController는:
- UI 트리거
- 결과 수신
만 담당
8️⃣ AuthService.swift
login 함수 내에 case .google 구현
final class AuthService: AuthProviding {
// MARK: - Properties
/// Apple 로그인 전담 핸들러
private let appleHandler = AppleAuthHandler()
/// Google 로그인 전담 핸들러
private let googleHandler = GoogleAuthHandler()
/// Firebase Auth 상태 리스너 핸들
private var authStateHandle: AuthStateDidChangeListenerHandle?
// MARK: - Auth State
var currentUserUID: String? {
Auth.auth().currentUser?.uid
}
func observeAuthState(_ handler: @escaping (String?) -> Void) {
// Firebase Auth 상태 감시
authStateHandle = Auth.auth().addStateDidChangeListener { _, user in
let uid = user?.uid
handler(uid)
}
}
// MARK: - Login
func login(
with provider: SocialLoginProvider,
from presentationContext: ASAuthorizationControllerPresentationContextProviding,
completion: @escaping (Result<Void, Error>) -> Void
) {
// 어떤 로그인 방식을 쓸지 분기
// Google, Kakao, Naver 추가할 때, handler 만들어 case 추가
switch provider {
case .apple:
appleHandler.startLogin(
presentationContext: presentationContext,
completion: completion
)
// ✅ google 로그인
case .google:
guard let viewController = presentationContext as? UIViewController else {
completion(.failure(AuthError.invalidCredential))
return
}
googleHandler.startLogin(
presentingViewController: viewController,
completion: completion
)
case .kakao,
.naver:
completion(.failure(AuthError.unsupportedProvider))
}
}
728x90
LIST
'PulseBoard' 카테고리의 다른 글
| 카카오 OpenID Connect를 써도 Firebase Custom Token이 필요한 이유 (0) | 2025.12.24 |
|---|---|
| 🔐 카카오 로그인은 왜 Firebase Email/Password로 쓰면 안 될까? (0) | 2025.12.24 |
| 🤔 Firebase Apple 로그인 튜토리얼 코드 → 우리가 만든 구조 (1) | 2025.12.22 |
| UIKit + Firebase Apple 로그인, MVVM & Coordinator로 설계하기 (0) | 2025.12.22 |
| 🤔 Firebase - Apple Login 하기 (Firebase Authentication, Apple Developer 설정) (0) | 2025.12.22 |