본문 바로가기

EXPERIENCE/iOS

[Xcode/iOS] SwiftUI 구글(Google)로그인 구현하고 정보 가져오기

728x90
728x90

 

 

 

 

728x90

 

 

 

저번에 구글로그인 구현하는 글을 작성했는데,

해당 방법은 스토리보드(StoryBoard)를 사용한 방법이었다.

오늘은 SwiftUI를 사용해서 구글 로그인을 진행할 예정이며,

코드 구현 전 기본 세팅은 방법이 동일하기에 이전 글을 참고 하면 된다 :)

 

 

 

 

사전 세팅 방법
 

[Xcode/iOS] Swift 구글(Google)로그인 스토리보드(StoryBoard)로 구현하기

구글, 애플, 카카오, 네이버 각종 소셜로그인을 모두 구현하여 포스팅 해볼 예정이다! 오늘은 첫번째로 구글 로그인을 준비했으며 추후 SwiftUI로 구현한 내용도 업로드할 예정이다 :) 결과화면 Doc

s-o-h-a.tistory.com

 

 

 

 

 

 

결과화면

 

 

 

 

 

 

 

Document
 

iOS 및 macOS용 Google 로그인 시작하기  |  Authentication  |  Google Developers

이 페이지는 Cloud Translation API를 통해 번역되었습니다. Switch to English 의견 보내기 iOS 및 macOS용 Google 로그인 시작하기 컬렉션을 사용해 정리하기 내 환경설정을 기준으로 콘텐츠를 저장하고 분류

developers.google.com

 

 

 

 

 

 

Github
 

GitHub - sohay19/SocialLoginUI: Social Login with. SwiftUI

Social Login with. SwiftUI. Contribute to sohay19/SocialLoginUI development by creating an account on GitHub.

github.com

 

 

 

 

 

 

사전세팅 차이점
pod 'GoogleSignInSwiftSupport'
기존에는 'GoogleSignIn'만 다운하였으나 SwiftUI를 사용할 경우에는 'Google 계정으로 로그인' 버튼의 확장 프로그램인 'GoogleSignInSwiftSupport'도 추가해준다

 

 

 

 

구현하기

 

  • Main.swift
@main
struct SocialLoginUIApp: App {
    var body: some Scene {
        WindowGroup {
            ContentView(userData: UserData(url: nil, name: "", email: ""))
                .onOpenURL { url in
                    GIDSignIn.sharedInstance.handle(url)
                }
        }
    }
}
App 프로토콜을 채택하는 메인 Swift 파일에 GIDSignIn의 handleURL를 호출한다

 

 

  • UserData.swift
struct UserData {
    let url:URL?
    let name:String
    let email:String
    
    init(url: URL?, name: String, email: String) {
        self.url = url
        self.name = name
        self.email = email
    }
}
유저 정보를 담는 구조체로 url은 프로필 이미지 주소이다

 

 

  • ContentView.swift
struct ContentView: View {
    // 로그인 상태
    @State private var isLogined = false
    // 유저 데이터
    @State private var userData:UserData
    // 팝업용
    @State private var isAlert = false
    
    public init(isLogined: Bool = false, userData: UserData) {
        _isLogined = State(initialValue: isLogined)
        _userData = State(initialValue: userData)
    }
    
    var body: some View {
        NavigationStack {
            ZStack {
                GoogleSignInButton(
                    scheme: .light,
                    style: .wide,
                    action: {
                        googleLogin()
                    })
                .frame(width: 300, height: 60, alignment: .center)
            }
            .navigationDestination(isPresented: $isLogined, destination: { MyPageView(userData: $userData) })
        }
        .onAppear(perform: {
            // 로그인 상태 체크
            checkState()
        })
        .alert(LocalizedStringKey("로그인 실패"), isPresented: $isAlert) {
            Text("확인")
        } message: {
            Text("다시 시도해주세요")
        }
    }
}
메인 로그인 화면

- isLogined : 로그인 상태 체크를 위한 변수(T-로그인, F-로그아웃)
- isAlert : 팝업 호출 여부를 확인하기 위한 변수(T-팝업 열림, F-팝업 닫힘)
- GoogleSignInButton() : 구글에서 제공된 로그인 버튼
- NavigationStack, navigationDestination : 마이페이지로 이동을 위한 네비게이션
- onAppear() : 화면이 보여질 때 수행할 내용
- alert() : 로그인 실패 시, 팝업 호출

 

{
    // 상태 체크
    func checkState() {
        GIDSignIn.sharedInstance.restorePreviousSignIn { user, error in
            if error != nil || user == nil {
                // 로그아웃 상태
                print("Not Sign In")
            } else {
                // 로그인 상태
                guard let profile = user?.profile else { return }
                let data = UserData(url: profile.imageURL(withDimension: 180), name: profile.name, email: profile.email)
                userData = data
                isLogined = true
                print(isLogined)
            }
        }
    }
    // 구글 로그인
    func googleLogin() {
        // rootViewController
        guard let presentingViewController = (UIApplication.shared.connectedScenes.first as? UIWindowScene)?.windows.first?.rootViewController else { return }
        // 로그인 진행
        GIDSignIn.sharedInstance.signIn(withPresenting: presentingViewController) { signInResult, error in
            guard let result = signInResult else {
                isAlert = true
                return
            }
            guard let profile = result.user.profile else { return }
            let data = UserData(url: profile.imageURL(withDimension: 180), name: profile.name, email: profile.email)
            userData = data
            isLogined = true
        }
    }
}
    
struct ContentView_Previews: PreviewProvider {
    static var previews: some View {
        ContentView(userData: UserData(url: nil, name: "", email: ""))
    }
}
- checkState() : 로그인 여부를 체크하여 isLogined를 변경하고 유저 정보를 저장함
- googleLogin() : 구글 로그인을 진행하고 유저 정보를 저장함

 

 

  • MyPageView.swift
struct MyPageView: View {
    // 화면 종료
    @Environment(\.dismiss) private var dismiss
    // 유저 데이터 바인딩
    @Binding var userData:UserData
    
    var body: some View {
        VStack (spacing: 30) {
            // 프로필
            AsyncImage(url: userData.url)
                .imageScale(.small)
                .frame(width: 180, height: 180, alignment: .center)
                .padding(EdgeInsets(top: 60, leading: 0, bottom: 0, trailing: 0))
            // 이름
            Text(userData.name)
            // 이메일
            Text(userData.email)
            
            Spacer()
            
            HStack {
                // 로그아웃 버튼
                Button {
                    logout()
                } label: {
                    Text("로그아웃")
                }
                .frame(width: 60, height: 33, alignment: .bottom)
                .padding(EdgeInsets(top: 0, leading: 30, bottom: 30, trailing: 0))
            }
            .frame(maxWidth: .infinity, alignment: .leading)
        }
        .frame(minWidth: 0, maxWidth: .infinity, minHeight: 0, maxHeight: .infinity)
        // 뒤로 가기 버튼 숨김
        .navigationBarBackButtonHidden(true)
    }
    // 로그아웃
    func logout() {
        GIDSignIn.sharedInstance.signOut()
        // 메인으로 돌아가기
        dismiss()
    }
}

struct MyPageView_Previews: PreviewProvider {
    static var previews: some View {
        MyPageView(userData: .constant(UserData(url: nil, name: "이름", email: "이메일")))
    }
}
마이페이지 화면

- dismiss() : 현재 화면을 닫음
- logout() : 로그아웃 후 메인으로 돌아감

 

 

 

 

 

 

다음번엔 애플, 카카오 로그인을 진행해서 포스팅하고자 한다.

SwiftUI 연습을 위해 앞으로 기능 구현과 같은 간단한 내용의 포스팅은 SwiftUI로 제작하여 진행하려한다.

이렇게 하면 조금은 더 빨리 익숙해질 수 있지 않을까... ㅜㅜ

 

 

 

 

 

 

 

 

 

728x90
728x90