비교적 간단한 데이터라면 Firebase와 연동해서 데이터를 불러올 수 있겠지만, Firebase는 Array 내부에 새로운 Array를 추가하지 못 해 복잡한 데이터를 구축할 수 없다는 단점이 있습니다. 하지만, 저희의 프로젝트에서는 레시피 상세 데이터 내부에 절차나 재료 등 여러 Array를 구축할 필요가 있기 때문에, 필연적으로 따로 데이터베이스를 구축해야 했습니다. 따라서, Flutter 내부에서 Json 형식의 데이터를 파싱할 수 있는 방법을 조사하였습니다.
Json을 파싱하기 위해서는 우선 API와 http 통신을 할 필요가 있습니다. 따라서, 앱의 pubspec.yaml 파일의 dependencies에 최신 버전의 http 패키지를 추가해줍니다.
dependencies:
http: ^<최신 버전>
그리고 레시피 등의 데이터를 가져와야 하기 때문에, http get 방식으로 통신해주기 위해 http.get() 메소드를 사용해 API 주소로 DB에서 데이터를 가져올 것입니다. 따라서, 먼저 아까 추가한 http 패키지를 import해주는 데, 여기에 as http라는 키워드를 추가하여 get()이나 post() 등의 통신에 필요한 메소드들을 사용할 때 앞에 http라는 프리픽스를 붙여줘 더 명확하게 할 수 있습니다. 다만 이 http를 앞에 붙이지 않으면 에러가 발생하게 됩니다.
여기서 async라는 키워드를 붙인 이유는, http 통신을 위한 메소드인 get()과 post()가 await 키워드를 포함하고 있기 때문에 비동기로 동작하기 때문입니다. 비동기는 요청과 응답이 동시에 이루어지지 않는 프로그래밍 방식으로, http 통신을 요청한 후 응답이 오지 않아도 다른 작업을 계속해서 요청해야 하기 때문에 async 키워드가 포함되었습니다.
import 'package:http/http.dart' as http;
Future<List<Recipe>?> fetchRecipe(http.Client client) async {
final response = await client.get(Uri.parse('${API 주소}'));
return ...
}
다음으로, 레시피 관련 데이터를 담을 클래스가 필요합니다. 클래스를 정의하고, Json 객체를 통해 레시피를 좀 더 쉽게 생성하기 위하여 factory의 fromJson 메소드 또한 정의해줍니다.
class Recipe {
final int recipe_id;
final String recipe_title;
...
Recipe({
required this.recipe_id,
required this.recipe_title,
...
});
factory Recipe.fromJson(Map<String, dynamic> json) {
return Recipe(
recipe_id: json['recipe_id'],
recipe_title: json['recipe_title'],
...
);
}
}
이제 fetchRecipe 메소드가 Future<List<Recipe>>를 return할 수 있도록 parseRecipes 메소드를 정의합니다.
우선, 통신을 통해 받아온 데이터를 처리하기 위해 parseRecipes 메소드에는 데이터 매개변수가 필요하게 되는데, 여기에는 아까 http get 방식으로 API와 통신해서 받은 데이터가 들어갈 것입니다. 하지만, 그냥 사용한다면 한글이 깨져 오류가 발생하기 때문에, utf8.decode()라는 메소드를 사용합니다. utf8을 사용할 때에는 dart:convert를 import해줘야 합니다. 이 메소드를 사용하면 통신을 통해 받아온 데이터를 String의 형태로 저장하게 됩니다.