[swift] Swift에서 키체인을 사용하여 로그인 세션 유실 방지하기

앱의 로그인 세션이 유실되거나 만료될때마다 사용자는 매번 로그인을 다시 해야하는 번거로움을 겪게 됩니다. 이러한 문제를 해결하기 위해 Swift에서는 키체인(Keychain)을 사용할 수 있습니다. 키체인은 암호화된 형태로 데이터를 안전하게 저장할 수 있는 기능을 제공합니다.

키체인에 데이터 저장하기

먼저, 키체인에 사용자의 로그인 세션 정보를 저장하는 방법을 알아보겠습니다. 아래와 같이 KeychainService 클래스를 만들어 키체인과 관련된 메소드를 구현합니다.

import Foundation
import Security

class KeychainService {
    
    static func saveSessionToken(_ token: String) {
        guard let data = token.data(using: .utf8) else { return }
        
        let query: [String: Any] = [
            kSecClass as String: kSecClassGenericPassword,
            kSecAttrAccount as String: "SessionToken",
            kSecValueData as String: data,
            kSecAttrAccessible as String: kSecAttrAccessibleAfterFirstUnlock
        ]
        
        SecItemDelete(query as CFDictionary)
        SecItemAdd(query as CFDictionary, nil)
    }
    
    static func getSessionToken() -> String? {
        let query: [String: Any] = [
            kSecClass as String: kSecClassGenericPassword,
            kSecAttrAccount as String: "SessionToken",
            kSecReturnData as String: true,
            kSecMatchLimit as String: kSecMatchLimitOne
        ]
        
        var result: AnyObject?
        let status = SecItemCopyMatching(query as CFDictionary, &result)
        
        if status == noErr, let data = result as? Data {
            return String(data: data, encoding: .utf8)
        } else {
            return nil
        }
    }
    
    static func deleteSessionToken() {
        let query: [String: Any] = [
            kSecClass as String: kSecClassGenericPassword,
            kSecAttrAccount as String: "SessionToken"
        ]
        
        SecItemDelete(query as CFDictionary)
    }
    
}

위의 코드는 KeychainService 클래스에 saveSessionToken, getSessionToken, 그리고 deleteSessionToken 메소드를 구현하였습니다.

saveSessionToken 메소드는 주어진 토큰을 데이터로 변환하여 키체인에 저장합니다. 저장될 데이터의 정보는 kSecClass, kSecAttrAccount, kSecValueData, kSecAttrAccessible 등으로 구성되고, SecItemAdd 함수를 사용하여 키체인에 데이터를 추가합니다.

getSessionToken 메소드는 키체인에서 저장된 세션 토큰을 가져옵니다. kSecMatchLimitOne 설정을 통해 하나의 데이터만 반환되도록 하며, SecItemCopyMatching 함수를 사용하여 데이터를 검색합니다.

deleteSessionToken 메소드는 키체인에서 저장된 세션 토큰을 삭제합니다.

로그인 세션 관리하기

이제 실제로 로그인 세션을 관리하는 예제 코드를 살펴보겠습니다. 아래와 같이 LoginManager 클래스를 만들어 로그인과 로그아웃을 담당하는 메소드를 구현합니다.

class LoginManager {
    
    static func login(withToken token: String) {
        // Login API 호출 및 성공 시 토큰 저장
        KeychainService.saveSessionToken(token)
    }
    
    static func logout() {
        // 로그아웃 처리 및 토큰 삭제
        KeychainService.deleteSessionToken()
    }
    
    static func checkSession() -> Bool {
        // 세션 체크 로직
        if let token = KeychainService.getSessionToken() {
            // 세션 유효성 확인
            return true
        } else {
            return false
        }
    }
    
}

위의 코드는 LoginManager 클래스에 login, logout, checkSession 메소드를 구현하였습니다.

login 메소드는 로그인 API를 호출하여 성공 시 받아온 토큰을 키체인에 저장합니다.

logout 메소드는 로그아웃 처리를 수행하고, 키체인에서 세션 토큰을 삭제합니다.

checkSession 메소드는 현재 세션의 유효성을 확인합니다. 키체인에서 세션 토큰을 가져와서 유효하다면 true를, 그렇지 않다면 false를 반환합니다.

사용 예제

이제 위에서 작성한 코드를 사용하여 로그인 세션을 관리해보겠습니다.

// 로그인
LoginManager.login(withToken: "user123")

// 세션 체크
if LoginManager.checkSession() {
    // 로그인 세션이 유효한 경우
    print("로그인 상태입니다.")
} else {
    // 로그인 세션이 유효하지 않은 경우
    print("로그인되어있지 않습니다.")
}

// 로그아웃
LoginManager.logout()

위의 예제에서는 LoginManager 클래스를 사용하여 로그인, 세션 체크, 그리고 로그아웃을 수행합니다. login 메소드에서는 임의로 user123라는 토큰을 사용하여 로그인 세션을 생성하고, checkSession 메소드를 이용하여 현재 세션의 유효성을 확인합니다. 마지막으로 logout 메소드를 호출하여 세션을 종료합니다.

결론

이렇게 키체인을 사용하여 Swift 앱에서 로그인 세션을 유실 방지하는 방법을 알아보았습니다. 키체인은 보안을 강화하고 사용자의 편의성을 높일 수 있는 중요한 요소입니다. 앱의 세션 관리와 보안을 위해 키체인을 적절히 활용하면 사용자 경험을 향상시킬 수 있습니다.

참고 자료