카테고리 없음

[ios] 하이브리드앱 자동로그인 구현하기.

modori@ 2025. 10. 23. 23:44

오늘은 하이브리드 앱에 자동로그인을 구현해볼려고 합니다.

 

하이브리드 앱은 웹 기술을 기반으로 네이티브 앱의 기능을 함께 활용하는 구조이기 때문에, 자동로그인 기능을 구현할 때도 네이티브와 웹뷰(WebView) 사이의 인증 상태 동기화가 핵심입니다.

 

웹의 인증 상태를 네이티브에 저장하기위해 userdefault에 토큰을 저장, 조회하는 함수를 만들어줍니다.

UserDefaults 는 IOS 앱에서 데이터를 영구적으로 저장하고 불러오는 데 사용하는 간단한 로컬 저장소입니다.

 

class UserDataUtils {
    class func setLoginToken(_ token: String) {
        UserDefaults.standard.set(token, forKey: "loginToken")
    }

    class func getLoginToken() -> String {
        return UserDefaults.standard.string(forKey: "loginToken") ?? ""
    }
}

 

로그인 페이지에서 token을 인증하게되면 앱 실행  -> 로그인페이지 -> 웹뷰 로 이동해 사용자에게 "자동로그인이 되긴 한건가?" 라는 인식을 심어줄 수 있기 때문에 splash screen에서 token 인증 후, 인증에 성공하면 token set 후 웹뷰로 이동하는 로직으로 구현하도록 하겠습니다.

 

splash screen controller

override func viewDidAppear(_ animated: Bool) {
    super.viewDidAppear(animated)
    
    DispatchQueue.main.asyncAfter(deadline: .now() + 1.0) {
        let savedToken = UserDataUtils.getLoginToken()
        if !savedToken.isEmpty {
            self.tokenLogin()
        } else {
            self.redirectLoginPage()
        }
    }
}

private func tokenLogin() {
    let token = UserDataUtils.getLoginToken()
    AuthAPI.validateToken(token) { isLogin, userInfo in
        DispatchQueue.main.async {
            if isLogin {
                self.redirectMainPage(with: token)
            } else {
                self.redirectLoginPage()
            }
        }
    }
}

 

viewWillAppear는 해당 뷰(view)가 화면에 완전히 나타난 후에 호출되는 생명주기 메서드중 하나입니다.
해당 메서드를 통해 splash iamge를 먼저 화면에 띄운 후, tokenLogin()함수를 통해 해당 token이 유효한지를 검사합니다.

 

 

 

하이브리드 앱이기 때문에

redirectMainPage()

를 통해서 받은 token을 웹에서 사용하기 위해 저희가 사용할 webview의 cookies에 set해주어야합니다.

private func redirectMainPage(with token: String) {
    guard let webVC = UIStoryboard(name: "Main", bundle: nil)
        .instantiateViewController(withIdentifier: "WebViewController") as? WebViewController else { return }
    
    webVC.token = token
    webVC.url_Str = targetURL("https://example.com")

    navigationController?.pushViewController(webVC, animated: true)
}

 

 

webView controller

이제 웹뷰에 진입했을 때, 해당 토큰을 사용해야겠죠?

WKWebView는 기본적으로 쿠키를 공유하지 않기 때문에, 토큰을 웹뷰 내 쿠키로 설정해야 합니다.

이를 위해 WKHTTPCookieStore를 사용합니다.

override func viewDidLoad() {
    super.viewDidLoad()
    setupCookieAndLoad()
}

private func setupCookieAndLoad() {
    guard let token = token,
          let url = URL(string: url_Str ?? "") else { return }

    let cookie = HTTPCookie(properties: [
        .domain: url.host ?? "",
        .path: "/",
        .name: "loginToken",
        .value: token,
        .secure: "TRUE",
        .expires: NSDate(timeIntervalSinceNow: 31536000)
    ])
    
    if let cookie = cookie {
        WKWebsiteDataStore.default().httpCookieStore.setCookie(cookie) { [weak self] in
            self?.webView.load(URLRequest(url: url))
        }
    } else {
        webView.load(URLRequest(url: url))
    }
}

 

이 과정을 통해 네이티브에서 인증된 토큰이 웹뷰 내의 쿠키로 동기화되어, 동일한 로그인 세션을 유지할 수 있습니다.
즉, 사용자는 웹 로그인 페이지를 거치지 않고도 바로 서비스 페이지로 접근 가능해집니다.

 

이후에는 웹뷰 내부에서 토큰 변경이나 만료 검증이 발생했을 때 다시 네이티브 측에 반영해야 합니다.
이를 위해 웹뷰 내에서 쿠키를 읽어와 UserDefaults의 토큰과 비교하는 로직을 유지합니다.

 

이렇게 웹뷰 하이브리드앱의 자동로그인을 구현해보았습니다.

 

회고

구현 후, 알게된 것이지만 UserDefaults는 iOS 내에서 간편하게 데이터를 저장하고 불러오는 대신, 데이터를 평문으로 저장하므로 OS 탈취나 탈옥 환경에서는 민감한 정보가 쉽게 노출될 위험이 크다고합니다.
따라서 로그인 토큰과 같은 중요한 인증 정보 저장에 사용하기에는 적합하지 않음을 알게 되었습니다.
키체인은 iOS가 제공하는 암호화된 보안 저장소로, AES-256 암호화와 디바이스 잠금 상태와 연동해 강력한 보호 기능을 제공하기때문에 물리적 탈취 및 기기 비밀번호 탈취 시에도 어느 정도 보안성을 지킬 수 있습니다. 

 

이후 리랙토링을 통해 키체인으로 변경을 진행할 예정입니다.!