From b6e9b7ddb63227a451c8de77de456914d0986308 Mon Sep 17 00:00:00 2001 From: Jungwoo <108061510+jwson-automation@users.noreply.github.com> Date: Fri, 30 Aug 2024 23:59:48 +0900 Subject: [PATCH 1/4] Delete lib/feature/voiceOutput directory (#88) --- .../voiceOutput/VoiceOutputScreen.dart | 21 ------ .../provider/VoiceOutputProvider.dart | 11 ---- .../voiceOutput/widget/VoiceOutputWidget.dart | 66 ------------------- 3 files changed, 98 deletions(-) delete mode 100644 lib/feature/voiceOutput/VoiceOutputScreen.dart delete mode 100644 lib/feature/voiceOutput/provider/VoiceOutputProvider.dart delete mode 100644 lib/feature/voiceOutput/widget/VoiceOutputWidget.dart diff --git a/lib/feature/voiceOutput/VoiceOutputScreen.dart b/lib/feature/voiceOutput/VoiceOutputScreen.dart deleted file mode 100644 index 148c0afd..00000000 --- a/lib/feature/voiceOutput/VoiceOutputScreen.dart +++ /dev/null @@ -1,21 +0,0 @@ -import './widget/VoiceOutputWidget.dart'; -import 'package:flutter/material.dart'; - -class VoiceOutputScreen extends StatelessWidget { - const VoiceOutputScreen({super.key}); - - @override - Widget build(BuildContext context) { - return Scaffold( - appBar: AppBar(), - body: const Center( - child: Column( - mainAxisAlignment: MainAxisAlignment.center, - children: [ - Expanded(child: VoiceOutputWidget()), - ], - ), - ), - ); - } -} diff --git a/lib/feature/voiceOutput/provider/VoiceOutputProvider.dart b/lib/feature/voiceOutput/provider/VoiceOutputProvider.dart deleted file mode 100644 index 74c11474..00000000 --- a/lib/feature/voiceOutput/provider/VoiceOutputProvider.dart +++ /dev/null @@ -1,11 +0,0 @@ -import 'package:cloud_firestore/cloud_firestore.dart'; -import 'package:flutter_riverpod/flutter_riverpod.dart'; - -final voiceOutputProvider = StreamProvider>((ref) { - final firestore = FirebaseFirestore.instance; - return firestore.collection('textInputs').snapshots().map((snapshot) { - final textInputs = - snapshot.docs.map((doc) => doc['textInput'] as String).toList(); - return textInputs; - }); -}); diff --git a/lib/feature/voiceOutput/widget/VoiceOutputWidget.dart b/lib/feature/voiceOutput/widget/VoiceOutputWidget.dart deleted file mode 100644 index be4e3045..00000000 --- a/lib/feature/voiceOutput/widget/VoiceOutputWidget.dart +++ /dev/null @@ -1,66 +0,0 @@ -import 'package:flutter/material.dart'; -import 'package:flutter_riverpod/flutter_riverpod.dart'; -import '../provider/VoiceOutputProvider.dart'; - -class VoiceOutputWidget extends ConsumerWidget { - const VoiceOutputWidget({super.key}); - - @override - Widget build(BuildContext context, WidgetRef ref) { - final list = ref.watch(voiceOutputProvider); - return list.when( - data: (data) { - return _buildListView(data); - }, - loading: () => const Center(child: CircularProgressIndicator()), - error: (error, stackTrace) { - return Center(child: Text('Error: $error')); - }, - ); - } - - Widget _buildListView(List data) { - return Container( - padding: const EdgeInsets.all(16.0), - child: Column( - mainAxisAlignment: MainAxisAlignment.center, - children: data - .map((text) => Padding( - padding: const EdgeInsets.symmetric(vertical: 8.0), - child: VoiceOutputRow(text: text), - )) - .toList(), - ), - ); - } -} - -class VoiceOutputRow extends StatelessWidget { - final String text; - - const VoiceOutputRow({super.key, required this.text}); - - @override - Widget build(BuildContext context) { - return Padding( - padding: const EdgeInsets.symmetric(horizontal: 16.0), - child: Row( - mainAxisAlignment: MainAxisAlignment.center, - children: [ - Expanded( - child: Text( - text, - style: const TextStyle(fontSize: 18), - textAlign: TextAlign.left, - ), - ), - const SizedBox(width: 8), - ElevatedButton( - onPressed: () {}, - child: const Text("button"), - ), - ], - ), - ); - } -} From 2341206807e7cd2c55aa62ce70be45b5150ef087 Mon Sep 17 00:00:00 2001 From: Jungwoo <108061510+jwson-automation@users.noreply.github.com> Date: Sat, 31 Aug 2024 00:00:03 +0900 Subject: [PATCH 2/4] Delete lib/feature/voiceoutput directory (#89) --- .../voiceoutput/VoiceOutputScreen.dart | 23 ------------- .../provider/VoiceOutputProvider.dart | 11 ------ .../widget/VoiceOutputItemWidget.dart | 31 ----------------- .../widget/VoiceOutputListWidget.dart | 34 ------------------- 4 files changed, 99 deletions(-) delete mode 100644 lib/feature/voiceoutput/VoiceOutputScreen.dart delete mode 100644 lib/feature/voiceoutput/provider/VoiceOutputProvider.dart delete mode 100644 lib/feature/voiceoutput/widget/VoiceOutputItemWidget.dart delete mode 100644 lib/feature/voiceoutput/widget/VoiceOutputListWidget.dart diff --git a/lib/feature/voiceoutput/VoiceOutputScreen.dart b/lib/feature/voiceoutput/VoiceOutputScreen.dart deleted file mode 100644 index 22ff7c82..00000000 --- a/lib/feature/voiceoutput/VoiceOutputScreen.dart +++ /dev/null @@ -1,23 +0,0 @@ -/* -구현 중입니다. -샘플 voiceOutput들을 각각 플레이 버튼과 함께 한 줄에 보여줍니다. -8월 16일 미란 -*/ - -import './widget/VoiceOutputListWidget.dart'; -import 'package:flutter/material.dart'; - -class VoiceOutputScreen extends StatelessWidget { - static const String name = 'VoiceOutput'; - - const VoiceOutputScreen({super.key}); - - @override - Widget build(BuildContext context) { - return const Scaffold( - body: Center( - child: VoiceOutputListWidget(), - ), - ); - } -} \ No newline at end of file diff --git a/lib/feature/voiceoutput/provider/VoiceOutputProvider.dart b/lib/feature/voiceoutput/provider/VoiceOutputProvider.dart deleted file mode 100644 index 74c11474..00000000 --- a/lib/feature/voiceoutput/provider/VoiceOutputProvider.dart +++ /dev/null @@ -1,11 +0,0 @@ -import 'package:cloud_firestore/cloud_firestore.dart'; -import 'package:flutter_riverpod/flutter_riverpod.dart'; - -final voiceOutputProvider = StreamProvider>((ref) { - final firestore = FirebaseFirestore.instance; - return firestore.collection('textInputs').snapshots().map((snapshot) { - final textInputs = - snapshot.docs.map((doc) => doc['textInput'] as String).toList(); - return textInputs; - }); -}); diff --git a/lib/feature/voiceoutput/widget/VoiceOutputItemWidget.dart b/lib/feature/voiceoutput/widget/VoiceOutputItemWidget.dart deleted file mode 100644 index 953fcb62..00000000 --- a/lib/feature/voiceoutput/widget/VoiceOutputItemWidget.dart +++ /dev/null @@ -1,31 +0,0 @@ -import 'package:flutter/material.dart'; - -class VoiceOutputItemWidget extends StatelessWidget { - final String voiceOutput; - - const VoiceOutputItemWidget({super.key, required this.voiceOutput}); - - @override - Widget build(BuildContext context) { - return Padding( - padding: const EdgeInsets.symmetric(horizontal: 30.0, vertical: 15.0), - child: Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - Expanded( - child: Text( - voiceOutput, - style: const TextStyle(fontSize: 18), - textAlign: TextAlign.left, - ), - ), - const SizedBox(width: 16), - ElevatedButton( - onPressed: () {}, - child: const Icon(Icons.play_arrow_rounded), - ), - ], - ), - ); - } -} diff --git a/lib/feature/voiceoutput/widget/VoiceOutputListWidget.dart b/lib/feature/voiceoutput/widget/VoiceOutputListWidget.dart deleted file mode 100644 index d5dfc72c..00000000 --- a/lib/feature/voiceoutput/widget/VoiceOutputListWidget.dart +++ /dev/null @@ -1,34 +0,0 @@ -import 'package:flutter/material.dart'; -import 'package:flutter_riverpod/flutter_riverpod.dart'; -import '../provider/VoiceOutputProvider.dart'; -import './VoiceOutputItemWidget.dart'; - -class VoiceOutputListWidget extends ConsumerWidget { - const VoiceOutputListWidget({super.key}); - - @override - Widget build(BuildContext context, WidgetRef ref) { - final voiceOutputList = ref.watch(voiceOutputProvider); - - return voiceOutputList.when( - data: (voiceOutputs) { - return Center( - child: Padding( - padding: const EdgeInsets.symmetric(vertical: 30.0), - child: ListView.builder( - shrinkWrap: true, - itemCount: voiceOutputs.length, - itemBuilder: (context, index) { - return VoiceOutputItemWidget( - voiceOutput: voiceOutputs[index]); - }), - ), - ); - }, - loading: () => const Center(child: CircularProgressIndicator()), - error: (error, stackTrace) { - return Center(child: Text('Error: $error')); - }, - ); - } -} \ No newline at end of file From 45c20cebb17dff287d6634286797cccac9f3488c Mon Sep 17 00:00:00 2001 From: Jungwoo <108061510+jwson-automation@users.noreply.github.com> Date: Sat, 31 Aug 2024 13:15:26 +0900 Subject: [PATCH 3/4] =?UTF-8?q?=EB=A9=94=EC=9D=B4=ED=81=AC=20=ED=8C=8C?= =?UTF-8?q?=EC=9D=BC=20=EC=88=98=EC=A0=95=20+=20.env=20=ED=8C=8C=EC=9D=BC?= =?UTF-8?q?=20=EC=83=9D=EC=84=B1=20=EC=BB=A4=EB=A7=A8=EB=93=9C=20=EC=B6=94?= =?UTF-8?q?=EA=B0=80=20(#78)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Makefile | 29 +++++++++++++++++++++++------ generate_env.ps1 | 19 +++++++++++++++++++ generate_env.sh | 5 +++++ 3 files changed, 47 insertions(+), 6 deletions(-) create mode 100644 generate_env.ps1 create mode 100644 generate_env.sh diff --git a/Makefile b/Makefile index b5f42344..b196dcb1 100644 --- a/Makefile +++ b/Makefile @@ -1,5 +1,4 @@ ROOT := $(shell git rev-parse --show-toplevel) - # Detect operating system ifeq ($(OS), Windows_NT) DETECTED_OS := Windows @@ -12,10 +11,23 @@ else FLUTTER := $(shell which flutter) endif endif - # Define the default target to call all necessary targets all: init analyze apply format buildRunner +# Define the init target to initialize the project +first : create init analyze buildRunner env +setting : init buildRunner +lint : analyze apply format + +# Define the init target +create: + @echo "Create ios and android floder..." +ifeq ($(DETECTED_OS), Windows) + @flutter create . +else + @$(FLUTTER) create . +endif + # Define the init target init: @echo "Initializing Flutter project..." @@ -24,7 +36,6 @@ ifeq ($(DETECTED_OS), Windows) else @$(FLUTTER) pub get endif - # Define the analyze target analyze: @echo "Analyzing Flutter project..." @@ -33,7 +44,6 @@ ifeq ($(DETECTED_OS), Windows) else -@$(FLUTTER) analyze endif - # Define the apply target apply: @echo "Applying dart fixes..." @@ -42,7 +52,6 @@ ifeq ($(DETECTED_OS), Windows) else @dart fix --apply endif - # Define the apply target format: @echo "format dart fixes..." @@ -51,7 +60,6 @@ ifeq ($(DETECTED_OS), Windows) else @dart format . endif - # Define the buildRunner target buildRunner: @echo "Freezed Running build runner..." @@ -61,3 +69,12 @@ else @$(FLUTTER) pub run build_runner build --delete-conflicting-outputs endif +# Define the env target for Unix-like systems +env: +ifeq ($(DETECTED_OS), Windows) + @echo "Using PowerShell script to create .env file." + @powershell -ExecutionPolicy Bypass -File generate_env.ps1 +else + @echo "Using bash script to create .env file." + @bash generate_env.sh +endif \ No newline at end of file diff --git a/generate_env.ps1 b/generate_env.ps1 new file mode 100644 index 00000000..811f4a9e --- /dev/null +++ b/generate_env.ps1 @@ -0,0 +1,19 @@ +# PowerShell 스크립트로 .env 파일 생성 + +# 현재 작업 중인 디렉터리 경로 가져오기 +$TargetDir = Get-Location + +# .env 파일 내용 +$envContent = @" +# please replace 'your_api_key_here' with your actual API key +GOOGLE_API_KEY=your_api_key_here +GPT_API_KEY=your_api_key_here +# Other environment variables can be added here +"@ + +# .env 파일 생성 +$envFilePath = Join-Path -Path $TargetDir -ChildPath ".env" +Write-Output "Creating .env file at: $envFilePath" + +# UTF-8 인코딩으로 파일 생성 +$envContent | Out-File -FilePath $envFilePath -Encoding utf8 \ No newline at end of file diff --git a/generate_env.sh b/generate_env.sh new file mode 100644 index 00000000..4ab99624 --- /dev/null +++ b/generate_env.sh @@ -0,0 +1,5 @@ +# .env 파일 생성 +echo "# please replace 'your_api_key_here' with your actual API key" > ".env" +echo "GOOGLE_API_KEY=your_api_key_here" >> ".env" +echo "GPT_API_KEY=your_api_key_here" >> ".env" +echo "# Other environment variables can be added here" >> ".env" \ No newline at end of file From 66b3a89eccfc2b8c921c87e978e5499a3010477d Mon Sep 17 00:00:00 2001 From: suojae Date: Sat, 31 Aug 2024 13:19:24 +0900 Subject: [PATCH 4/4] =?UTF-8?q?[Test]=20post,=20users=20=EB=AA=A8=EB=8D=B8?= =?UTF-8?q?=20=ED=86=B5=ED=95=A9=ED=85=8C=EC=8A=A4=ED=8A=B8=20=EC=B6=94?= =?UTF-8?q?=EA=B0=80=20(#14)=20(#80)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Jungwoo <108061510+jwson-automation@users.noreply.github.com> --- integration_test/app_test.dart | 46 ++++++ .../rank/provider/UserRankProvider.dart | 140 +++++++++++------- lib/services/cache/CacheService.dart | 14 +- 3 files changed, 142 insertions(+), 58 deletions(-) diff --git a/integration_test/app_test.dart b/integration_test/app_test.dart index 3d52e195..6718d19b 100644 --- a/integration_test/app_test.dart +++ b/integration_test/app_test.dart @@ -1,5 +1,7 @@ import 'package:blueberry_flutter_template/firebase_options.dart'; import 'package:blueberry_flutter_template/model/PetProfileModel.dart'; +import 'package:blueberry_flutter_template/model/PostModel.dart'; +import 'package:blueberry_flutter_template/model/UserModel.dart'; import 'package:cloud_firestore/cloud_firestore.dart'; import 'package:firebase_core/firebase_core.dart'; import 'package:flutter_test/flutter_test.dart'; @@ -39,5 +41,49 @@ void main() { // Then: 매핑된 데이터 검증 expect(fetchedData, isNotNull, reason: 'fetchedData는 null이 아니어야 합니다.'); }); + + test('user 컬렉션이 있을 때, 첫 번째 문서를 가져와 fromJson 메서드로 매핑하면, 오류 없이 매핑된다', + () async { + UserModel? fetchedData; + + // Given: 컬렉션 이름 설정 + collectionName = 'users'; + + // When: 첫 번째 문서 가져오기 및 fromJson 매핑 + final querySnapshot = + await firestore.collection(collectionName).limit(1).get(); + + if (querySnapshot.docs.isNotEmpty) { + final data = querySnapshot.docs.first.data(); + fetchedData = UserModel.fromJson(data); + } else { + throw Exception('$collectionName 컬렉션 안에 다큐먼트가 존재하지 않습니다'); + } + + // Then: 매핑된 데이터 검증 + expect(fetchedData, isNotNull, reason: 'fetchedData는 null이 아니어야 합니다.'); + }); + + test('posts 컬렉션이 있을 때, 첫 번째 문서를 가져와 fromJson 메서드로 매핑하면, 오류 없이 매핑된다', + () async { + PostModel? fetchedPost; + + // Given: 컬렉션 이름 설정 + collectionName = 'posts'; + + // When: 첫 번째 문서 가져오기 및 fromJson 매핑 + final querySnapshot = + await firestore.collection(collectionName).limit(1).get(); + + if (querySnapshot.docs.isNotEmpty) { + final data = querySnapshot.docs.first.data(); + fetchedPost = PostModel.fromJson(data); + } else { + throw Exception('$collectionName 컬렉션 안에 다큐먼트가 존재하지 않습니다'); + } + + // Then: 매핑된 데이터 검증 + expect(fetchedPost, isNotNull, reason: 'fetchedPost는 null이 아니어야 합니다.'); + }); }); } diff --git a/lib/feature/rank/provider/UserRankProvider.dart b/lib/feature/rank/provider/UserRankProvider.dart index b8731c55..0ea39eef 100644 --- a/lib/feature/rank/provider/UserRankProvider.dart +++ b/lib/feature/rank/provider/UserRankProvider.dart @@ -6,28 +6,21 @@ import 'package:blueberry_flutter_template/utils/AppStrings.dart'; import 'package:cloud_firestore/cloud_firestore.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; +/// User provider - Firestore에서 사용자 데이터를 가져오고 캐싱 처리 final userProvider = FutureProvider>((ref) async { final cacheService = CacheService.instance; - // 한국 시간으로 매일 오전 9시 설정 - final now = DateTime.now().toUtc().add(const Duration(hours: 9)); - final tomorrowMorning = DateTime(now.year, now.month, now.day + 1, 9).toUtc(); - - // 캐시 정책 설정 - final cacheConfig = CacheConfig( - cacheKey: AppStrings.userCacheKey, - expiryTime: tomorrowMorning, // 다음 날 오전 9시까지 유효 - ); + final cacheConfig = _createCacheConfig(); try { - // 캐시된 데이터 가져오기 + // 1. 캐시된 데이터 가져오기 시도 final cachedUsers = await _getCachedUsers(cacheService, cacheConfig); if (cachedUsers != null) return cachedUsers; - // Firestore에서 데이터 가져오기 + // 2. Firestore에서 데이터 가져오기 final users = await _fetchUsersFromFirestore(); - // 캐시에 저장 + // 3. 캐시에 사용자 데이터 저장 await _cacheUsers(cacheService, cacheConfig, users); return users; @@ -36,15 +29,35 @@ final userProvider = FutureProvider>((ref) async { } }); +/// 캐시 구성 생성 함수 +CacheConfig _createCacheConfig() { + // 한국 시간으로 매일 오전 9시 설정 + final now = DateTime.now().toUtc().add(const Duration(hours: 9)); + final tomorrowMorning = DateTime(now.year, now.month, now.day + 1, 9).toUtc(); + + return CacheConfig( + cacheKey: AppStrings.userCacheKey, + expiryTime: tomorrowMorning, // 다음 날 오전 9시까지 유효 + ); +} + +/// 캐시된 사용자 데이터를 가져오는 함수 Future?> _getCachedUsers( - CacheService cacheService, CacheConfig cacheConfig) async { + CacheService cacheService, + CacheConfig cacheConfig, +) async { try { final cachedData = await cacheService.getCachedData(cacheConfig); if (cachedData != null) { - final cachedUsers = (json.decode(cachedData) as List) - .map((item) => UserModel.fromJson(item as Map)) - .toList(); - return cachedUsers; + // 캐시 만료 시간 확인 + final now = DateTime.now().toUtc(); + if (cacheConfig.expiryTime != null && + now.isBefore(cacheConfig.expiryTime!)) { + return _decodeCachedUsers(cachedData); + } else { + // 만료되었으면 캐시 삭제 + await cacheService.deleteCachedData(cacheConfig.cacheKey); + } } } catch (e) { throw Exception('Failed to fetch user cached data'); @@ -52,56 +65,69 @@ Future?> _getCachedUsers( return null; } +/// 캐시된 사용자 데이터를 디코딩하는 함수 +List _decodeCachedUsers(String cachedData) { + final List jsonData = json.decode(cachedData); + return jsonData + .map((item) => UserModel.fromJson(item as Map)) + .toList(); +} + +/// Firestore에서 사용자 데이터를 가져오는 함수 Future> _fetchUsersFromFirestore() async { try { final fireStore = FirebaseFirestore.instance; - final likesSnapshot = await fireStore - .collection('likes') - .orderBy('likedUsers', descending: true) - .get(); - - final likedUserIds = likesSnapshot.docs - .expand((doc) => List.from(doc['likedUsers'])) - .toList(); - - final userDocs = await Future.wait( - likedUserIds - .map((userId) => fireStore.collection('users').doc(userId).get()) - .toList(), - ); - - final users = userDocs.map((doc) { - if (doc.exists) { - final data = doc.data()!; - return UserModel( - userClass: data['userClass'] as String, - userId: doc.id, - name: data['name'] as String, - email: data['email'] as String, - age: data['age'] as int, - isMemberShip: data['isMemberShip'] as bool, - profileImageUrl: data['profilePicture'] as String?, - createdAt: DateTime.parse(data['createdAt'] as String), - socialLogin: data['socialLogin'] as bool, - socialCompany: data['socialCompany'] as String, - mbti: data['mbti'] as String, - fcmToken: data['fcmToken'] as String?, - likeGivens: data["likeGivens"] as List, - ); - } else { - throw Exception('User not found'); - } - }).toList(); + // 'likes' 컬렉션에서 좋아요 순으로 사용자 아이디 가져오기 + final likedUserIds = await _fetchLikedUserIds(fireStore); - return users; + // 'users' 컬렉션에서 해당 사용자 문서들 가져오기 + final userDocs = await _fetchUserDocs(fireStore, likedUserIds); + + return _mapDocsToUsers(userDocs); } catch (e) { throw Exception('Failed to fetch users from Firestore'); } } -Future _cacheUsers(CacheService cacheService, CacheConfig cacheConfig, - List users) async { +/// Firestore에서 'likes' 컬렉션으로부터 사용자 아이디 목록을 가져오는 함수 +Future> _fetchLikedUserIds(FirebaseFirestore fireStore) async { + final likesSnapshot = await fireStore + .collection('likes') + .orderBy('likedUsers', descending: true) + .get(); + + return likesSnapshot.docs + .expand((doc) => List.from(doc['likedUsers'])) + .toList(); +} + +/// Firestore에서 사용자 문서들을 가져오는 함수 +Future> _fetchUserDocs( + FirebaseFirestore fireStore, + List likedUserIds, +) async { + return await Future.wait( + likedUserIds + .map((userId) => fireStore.collection('users').doc(userId).get()) + .toList(), + ); +} + +/// Firestore 문서 목록을 UserModel 객체로 매핑하는 함수 +List _mapDocsToUsers(List userDocs) { + return userDocs.where((doc) => doc.exists).map((doc) { + final data = doc.data() as Map; + return UserModel.fromJson(data); + }).toList(); +} + +/// 사용자 데이터를 캐시에 저장하는 함수 +Future _cacheUsers( + CacheService cacheService, + CacheConfig cacheConfig, + List users, +) async { try { final encodedData = json.encode(users.map((user) => user.toJson()).toList()); diff --git a/lib/services/cache/CacheService.dart b/lib/services/cache/CacheService.dart index b1998dd7..0ab6c7ca 100644 --- a/lib/services/cache/CacheService.dart +++ b/lib/services/cache/CacheService.dart @@ -28,7 +28,7 @@ final class CacheService { return _readFile(fileInfo); } else { // 파일이 오래된 경우 캐시에서 파일을 제거 - await _cacheManager.removeFile(config.cacheKey); + await deleteCachedData(config.cacheKey); } } return null; @@ -49,6 +49,18 @@ final class CacheService { ); } + /// 특정 캐시를 삭제하는 메서드 + /// + /// [cacheKey] : 캐시 키를 기반으로 캐시 데이터를 삭제 + Future deleteCachedData(String cacheKey) async { + await _cacheManager.removeFile(cacheKey); + } + + /// 전체 캐시 데이터를 삭제하는 메서드 + Future clearAllCache() async { + await _cacheManager.emptyCache(); + } + /// 파일 정보를 가져오는 유틸리티 메서드 /// /// [cacheKey] : 캐시에서 파일 정보를 찾기 위한 키