클라이언트

[iOS] UserDefaults 동작 방식과 보안

애기공룡훈련병 2025. 2. 15. 17:28
반응형

UserDefaults는 iOS 개발에서 간단한 데이터를 저장하고 불러오는 데 자주 사용되는 API이다. 그러나 보안상의 이슈가 있을 수 있어, 적절한 사용법과 보안 대책을 고려해야 한다. 이번 글에서는 UserDefaults의 동작 방식과 보안 관련 사항을 자세히 살펴본다.

1. UserDefaults란?

UserDefaults는 앱 내에서 Key-Value 형태로 데이터를 저장할 수 있는 간단한 저장소이다. 설정 값, 사용자 선호도, 앱 상태 등을 저장하는 데 주로 사용된다.

1.1 주요 특징

  • 간단한 Key-Value 저장 방식
  • 앱이 삭제되기 전까지 데이터 유지
  • 앱이 재시작되더라도 데이터 유지
  • plist 파일을 사용하여 데이터 저장
  • 보안이 강하지 않으므로 민감한 데이터 저장에 부적절

1.2 지원하는 데이터 타입

UserDefaults는 다음과 같은 기본 데이터 타입을 지원한다.

  • String
  • Int
  • Double
  • Bool
  • Array
  • Dictionary
  • Data

2. UserDefaults의 동작 방식

UserDefaults는 내부적으로 plist 파일을 이용하여 데이터를 저장한다. 해당 파일은 Library/Preferences 디렉터리에 위치하며, 앱이 접근할 때마다 이 파일을 읽거나 쓴다.

2.1 데이터 저장 방식

let defaults = UserDefaults.standard
defaults.set("Hello, World!", forKey: "greeting")
defaults.set(25, forKey: "age")
defaults.synchronize()

이렇게 저장된 데이터는 앱이 다시 실행될 때도 유지된다.

2.2 데이터 불러오기

let defaults = UserDefaults.standard
let greeting = defaults.string(forKey: "greeting")
let age = defaults.integer(forKey: "age")

2.3 데이터 삭제

defaults.removeObject(forKey: "greeting")

3. UserDefaults의 보안 문제

UserDefaults는 보안이 강하지 않은 저장 방식이다. 주요 보안 문제는 다음과 같다.

3.1 평문 저장

UserDefaults는 데이터를 암호화하지 않고 평문으로 저장한다. 따라서 탈옥된 기기나 백업 파일을 통해 데이터가 쉽게 유출될 수 있다.

3.2 디버깅 도구를 통한 접근

개발자는 NSUserDefaults 파일을 직접 접근하여 내용을 확인할 수 있다.

plutil -p Library/Preferences/com.yourapp.bundleid.plist

이 방법을 사용하면 저장된 데이터를 쉽게 확인할 수 있다.

3.3 MITM 공격 가능성

UserDefaults에 저장된 데이터가 네트워크 전송에 사용될 경우, 중간자 공격(MITM)을 통해 가로챌 가능성이 있다.

4. UserDefaults 보안 강화 방법

보안 문제를 최소화하기 위해 다음과 같은 방법을 적용할 수 있다.

4.1 Keychain 사용

민감한 데이터(예: 로그인 정보, API Key 등)는 UserDefaults 대신 Keychain에 저장해야 한다.

import Security

let keychainQuery: [String: Any] = [
    kSecClass as String: kSecClassGenericPassword,
    kSecAttrAccount as String: "userToken",
    kSecValueData as String: "your_secure_token".data(using: .utf8)!
]
SecItemAdd(keychainQuery as CFDictionary, nil)

4.2 UserDefaults 데이터 암호화

UserDefaults에 저장하기 전에 데이터를 암호화하는 것이 보안에 도움이 된다.

import CryptoKit

func encryptData(_ text: String) -> Data? {
    let key = SymmetricKey(size: .bits256)
    let sealedBox = try? AES.GCM.seal(text.data(using: .utf8)!, using: key)
    return sealedBox?.combined
}

암호화된 데이터를 UserDefaults에 저장하면 외부 접근을 방지할 수 있다.

4.3 App Transport Security (ATS) 활용

네트워크 전송 시 UserDefaults 데이터를 포함하는 경우, HTTPS를 강제하는 ATS를 활성화해야 한다.

<key>NSAppTransportSecurity</key>
<dict>
    <key>NSAllowsArbitraryLoads</key>
    <false/>
</dict>

4.4 UserDefaults 접근 제한

UserDefaults에 접근하는 코드를 최소화하고, 필요할 때만 데이터를 저장/읽도록 한다. 또한, 앱이 백그라운드로 전환될 때 민감한 데이터를 삭제하는 것도 보안 강화에 도움이 된다.

func applicationDidEnterBackground(_ application: UIApplication) {
    let defaults = UserDefaults.standard
    defaults.removeObject(forKey: "sensitiveData")
}

5. 결론

UserDefaults는 간단한 데이터를 저장하는 데 유용하지만, 보안이 취약하기 때문에 신중하게 사용해야 한다. 민감한 정보는 Keychain을 활용하고, 암호화를 적용하는 등의 방법으로 보안을 강화하는 것이 중요하다. 또한, 앱이 네트워크를 통해 데이터를 주고받을 때는 HTTPS를 강제하고, 백그라운드 전환 시 민감한 데이터를 삭제하는 등의 조치를 취하는 것이 필요하다.

반응형