프로젝트

Flutter 프로젝트 페이징 처리

TMJeti 2025. 4. 29. 12:50

프로젝트 하다가 어떤 곳은 정보가 너무 없고 반경이 똑같으면 계속 같은 장소만 나오는 게 이상해서 디버깅 출력해보니 이런 문제가 있었다... 알고보니 Firestore의 REST API 기본 응답은 최대 100개 문서만 반환한다고 한다.

 

모든 장소 문서들을 가져오기 위해 페이징 처리를 해보도록 한다! 

 

# travel_results_screen.dart

Future<void> fetchPlacesAndAskGpt() async {
    List<Map<String, dynamic>> allPlaces = [];
    String? nextPageToken;

    final centerLat = location['lat'] ?? 0.0;
    final centerLng = location['lng'] ?? 0.0;
    final radiusKm = location['radius_km']?.toDouble() ?? 10.0;

    do{
      final queryParameters = {
      'key': firebaseApiKey,
      if (nextPageToken != null) 'pageToken': nextPageToken,
      };
      final url = Uri.https(
      'firestore.googleapis.com',
      '/v1/projects/$firebaseProjectId/databases/(default)/documents/places',
      queryParameters,
      );
      final response = await http.get(url);
    if (response.statusCode != 200) {
      setState(() {
        gptAnswer = '❌ Firestore 불러오기 실패';
        isLoading = false;
      });
      return;
    }

 

 final jsonData = jsonDecode(utf8.decode(response.bodyBytes));
      final documents = jsonData['documents'] ?? [];
      debugPrint("📦 Firestore에서 받은 장소 문서 수: ${documents.length}");

      for (final doc in documents) {
      final fields = doc['fields'];
      final name = fields['pname']?['stringValue'] ?? '이름 없음';
      final lat = double.tryParse(fields['location']?['mapValue']?['fields']?['lat']?['doubleValue']?.toString() ?? '') ?? 0.0;
      final lng = double.tryParse(fields['location']?['mapValue']?['fields']?['lng']?['doubleValue']?.toString() ?? '') ?? 0.0;
      final distance = calculateDistance(centerLat, centerLng, lat, lng);

      if (distance <= radiusKm) {
        final ptags = fields['ptags']?['arrayValue']?['values'];
        final tagList = ptags is List ? ptags.map((e) => e['stringValue'] as String).toList() : [];
        final address = fields['address']?['stringValue'] ?? '주소 없음';

        allPlaces.add({
          'name': name,
          'address': address,
          'tags': tagList,
          'lat': lat,
          'lng': lng,
        });
      }
    }
    nextPageToken = jsonData['nextPageToken'];
    } while (nextPageToken != null);

    debugPrint("📦 총 수집된 장소 수: ${allPlaces.length}");