쉬운 목차
ToggleFlutter 앱 개발: flutter_secure_storage로 민감한 정보 저장하기
Flutter 앱 개발을 하면서, 사용자 인증 정보나 토큰과 같은 민감한 데이터를 안전하게 저장하려면 보안이 중요한 요소로 작용합니다. 이를 위해 많은 개발자들이 flutter_secure_storage
패키지를 활용합니다.
이 글에서 flutter_secure_storage
패키지가 무엇이고 어떻게 쓰는지 정리해봤습니다.
flutter_secure_storage 란?
flutter_secure_storage
는 Flutter 애플리케이션에서 민감한 데이터를 안전하게 저장할 수 있도록 설계된 패키지입니다. 이 패키지는 다음과 같은 기능을 제공합니다:
- iOS: 키체인(Keychain)을 활용하여 데이터를 암호화 및 저장
- Android: Keystore를 이용해 암호화된 데이터 저장
- Web: LocalStorage나 IndexedDB를 활용한 데이터 저장
이 패키지는 플랫폼별 보안 메커니즘을 활용하여 데이터 보안을 강화하며, 특히 인증 토큰, API 키, 비밀번호 등 민감한 데이터를 다룰 때 유용합니다.
Flutter 앱 개발 시 flutter_secure_storage 패키지를 사용하는 이유?
flutter_secure_storage
를 사용하는 몇 가지 주요 이유입니다:
- 보안성:
단순한 SharedPreferences나 일반 로컬 스토리지가 아닌, 각 플랫폼의 고유 보안 API를 활용하여 데이터를 암호화합니다. - 사용 편의성:
데이터 저장 및 읽기 작업이 간단한 API 호출로 이루어져, 개발 생산성을 높일 수 있습니다. - 플랫폼 독립성:
Flutter 앱의 핵심 철학에 맞춰 다양한 플랫폼에서 일관된 방식으로 데이터를 다룰 수 있습니다. - 개발자 커뮤니티와 문서 지원:
인기 패키지 중 하나로, 문제가 발생했을 때 관련 자료를 찾기 쉽습니다.
flutter_secure_storage의 장단점
장점:
- 보안성: 암호화를 기본으로 지원하여 민감한 데이터 보호에 적합
- 다중 플랫폼 지원: iOS, Android, Web 환경에서 모두 사용 가능
- 사용의 간편함: 초기 설정이 간단하고 코드 작성이 직관적
단점:
- 웹 환경 보안: Web에서 사용하는 LocalStorage는 플랫폼에 따라 완전한 보안이 보장되지 않을 수 있음
- 플랫폼 의존적 문제: 플랫폼별 보안 메커니즘 차이로 인해 예상치 못한 동작이 발생할 수 있음
- 디버깅 제한: 암호화된 데이터를 직접 확인하기 어려움
그렇다면 flutter_secure_storage에 저장된 값은 어떻게 확인할 수 있을까요?
flutter_secure_storage에 저장된 값을 보는 디버깅 방법
Flutter 앱에서 암호화된 데이터를 디버깅하려면, 데이터 저장 및 호출 과정을 추적하는 몇 가지 방법을 사용할 수 있습니다:
- 디버깅 로그 사용:
데이터를 저장하거나 읽기 전에 암호화되기 전의 데이터를 로그로 출력해 확인합니다.
- 플랫폼별 도구 활용:
- iOS: Xcode의 Keychain Access를 사용해 키체인 데이터를 확인
- Android: Android Studio에서 Device File Explorer를 사용해 Keystore 파일 조회
- 임시 해제:
개발 단계에서만 데이터를 암호화하지 않고 저장하여 내용을 쉽게 확인.
(주의: 반드시 개발 모드에서만 사용해야 하며, 프로덕션에서 금지)
flutter_secure_storage 사용 방법
1. 패키지 설치
flutter_secure_storage
를 사용하려면 먼저 패키지를 프로젝트에 추가해야 합니다.
참고 링크
pubspec.yaml
에 추가dependencies: flutter_secure_storage: ^9.2.2
flutter pub get
패키지 설치
2. 기본 사용법
flutter_secure_storage
가져오기import 'package:flutter_secure_storage/flutter_secure_storage.dart';'
- 인스턴스 생성: 인스턴스를 생성하여 데이터를 저장하거나 읽을 수 있습니다.
final storage = FlutterSecureStorage();
- 데이터 저장: 키-값 쌍으로 데이터를 저장합니다.
await storage.write(key: 'authToken', value: 'your_secure_token');
- 데이터 읽기 저장된 데이터를 읽습니다. 키에 해당하는 값이 없으면
null
을 반환합니다.String? token = await storage.read(key: 'authToken'); print('Token: $token');
- 모든 데이터 읽기 저장된 모든 데이터를 Map 형태로 읽어옵니다.
Map<String, String> allData = await storage.readAll(); print('All Data: $allData');
- 데이터 삭제 특정 키에 해당하는 데이터를 삭제하거나 전체 데이터를 삭제할 수 있습니다.
// 특정 키 삭제 await storage.delete(key: 'authToken'); // 전체 데이터 삭제 await storage.deleteAll();
- 키 존재 여부 확인 데이터가 존재하는지 확인합니다.
bool exists = await storage.containsKey(key: 'authToken'); print('Exists: $exists');
Platform Exception...The specified item already exists in the keychain.. 에러
Unhandled Exception: PlatformException(Unexpected security result code, Code: -25299, Message: The specified item already exists in the keychain., -25299, null) 에러 발생
저는 어떤 값이 변할때 기존에 storage에 저장된 값에 새로 업데이트 되기를 원했습니다.
그런데 아래와 같은 에러가 발생하면서 storage에 새로운 값 저장이 잘 되지 않는 버그가 생겼습니다.
Unhandled Exception: PlatformException(Unexpected security result code, Code: -25299, Message: The specified item already exists in the keychain., -25299, null)
에러 해결
아래와 같이 기존 데이터를 지우고 새로 저장하는 방식으로 해결했습니다.
await storage.delete(key: 'key'); await storage.write(key:key, value: value);
추가 설정
// AS-IS final storage = FlutterSecureStorage(); // TO-BE final storage = FlutterSecureStorage( iOptions: IOSOptions(accessibility: KeychainAccessibility.first_unlock), aOptions: AndroidOptions(encryptedSharedPreferences: true), );
iOptions, aOptions는 각각 ios와 android 플랫폼에서 데이터를 안전하게 저장하기 위해 사용되는 설정입니다.
iOS: Keychain에 데이터를 저장하며, 기기가 처음으로 잠금 해제된 이후에는 데이터를 사용할 수 있습니다.
Android: EncryptedSharedPreferences를 사용해 데이터를 암호화한 상태로 저장합니다.
- iOptions – accessibility 옵션: Keychain 데이터에 접근할 수 있는 시점을 지정합니다.
- KeychainAccessibility.first_unlock:
- 기기가 재부팅된 후 최초로 잠금이 해제되었을 때 Keychain 데이터에 접근이 가능합니다.
- 보안과 편의성 간의 균형을 맞춘 옵션입니다.
- 앱이 백그라운드에서 실행 중인 경우에도 Keychain에 접근 가능.
- KeychainAccessibility.unlocked:
- 기기가 현재 잠금 해제된 상태에서만 Keychain 데이터에 접근할 수 있습니다.
- 보안이 가장 높은 설정 중 하나이며, 앱이 백그라운드에서 실행 중인 경우에는 접근할 수 없습니다.
- KeychainAccessibility.always:
- 기기가 잠겨 있어도 언제나 Keychain 데이터에 접근할 수 있습니다.
- 편의성은 높지만 보안 수준이 낮습니다.
- 민감한 데이터를 저장하기에는 적합하지 않습니다.
- aOptions – encryptedSharedPreferences
- true: 데이터를 Android EncryptedSharedPreferences에 저장합니다.
- 이 설정은 Android 6.0 (API 23) 이상에서 지원되며, 데이터는 암호화되어 저장됩니다.
- EncryptedSharedPreferences는 앱에 대해 강력한 보안을 제공합니다.
- 기본적으로 AES-256 암호화를 사용합니다.
- false: 데이터를 일반 SharedPreferences에 저장합니다.
- 이 경우 데이터는 암호화 되지 않습니다.
- true: 데이터를 Android EncryptedSharedPreferences에 저장합니다.
- KeychainAccessibility.first_unlock: