Flutter로 애플리케이션을 개발할 때, REST API를 활용한 데이터 통신은 매우 중요합니다.
이번 포스팅에서는 Flutter에서 인기 있는 HTTP 통신 패키지인 Dio를 사용하여 서버와 데이터를 주고받는 방법을 단계별로 살펴보겠습니다.
💡 학습 목표
1. Dio 패키지를 설치하고 기본 사용법 익히기
2. REST API로 데이터 가져오기
3. JSON 데이터를 Dart 객체로 변환하기
1. Dio 패키지 설치하기
dio install | Dart package
A powerful HTTP networking package, supports Interceptors, Aborting and canceling a request, Custom adapters, Transformers, etc.
pub.dev
Dio는 강력하고 유연한 HTTP 클라이언트 패키지로, Flutter에서 쉽게 설치하고 사용할 수 있습니다.
pub.dev 사이트에서 dio 패키지를 디펜던시 코드를 가져와서 pubspec.yaml 파일에 의존성을 추가하고 pub get을 실행하여 패키지를 설치했습니다.
dependencies:
flutter:
sdk: flutter
dio: ^5.7.0
2. Dio로 간단한 GET 요청 보내기
Dio를 사용하여 서버에서 데이터를 가져오는 간단한 예제를 만들어봅니다.
전체 코드 구조
- Dio 객체: HTTP 요청을 처리하는 클라이언트.
- _fetchTodos 메서드: 서버에서 데이터를 가져오는 비동기 함수.
- try-catch 문: 예외 처리를 통해 안정성을 높임.
import 'package:dio/dio.dart';
import 'package:flutter/material.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
const MyApp({super.key});
@override
Widget build(BuildContext context) {
return MaterialApp(
debugShowCheckedModeBanner: false,
home: SafeArea(
child: Scaffold(
body: HomePage(),
),
),
);
}
}
class HomePage extends StatefulWidget {
const HomePage({super.key});
@override
State<HomePage> createState() => _HomePageState();
}
class _HomePageState extends State<HomePage> {
// 통신을 담당하는 클라언트 측 객체를 가져오자
Dio _dio = Dio();
@override
void initState() {
super.initState();
// 객체 실행시 한번 호출 메서드
_fetchTodos();
}
@override
Widget build(BuildContext context) {
return const Placeholder();
}
// 통신을 담당하는 메서드를 만들어 보자.
_fetchTodos() async {
// https://jsonplaceholder.typicode.com/todos/1
// 통신을 담당하는 코드를 기본적으로 예외처리을 꼭 넣자
try {
Response response =
await _dio.get('https://jsonplaceholder.typicode.com/todos/1');
print('HTTP status code : ${response.statusCode}');
print('서버측 전달한 데이터 : ${response.data}');
print(
'json 통신 후 dart 에서는 어떤 타입으로 변경 되었을까? : ${response.data.runtimeType}');
// Map 타입에 값을 출력하는 방법
print('-----------------------------------------------');
print('data-> title 값 확인 : ${response.data['title']}');
} catch (e) {
print('실행 시점 예외가 발생 했어요');
print(e.toString());
}
}
}
테스트 데이터는 아래의 링크에서 받아와 사용했습니다.
JSONPlaceholder - Free Fake REST API
{JSON} Placeholder Free fake and reliable API for testing and prototyping. Powered by JSON Server + LowDB. Serving ~3 billion requests each month.
jsonplaceholder.typicode.com
3. JSON 데이터를 Dart 객체로 변환하기
서버에서 받은 JSON 데이터를 Dart 객체로 변환하여 사용하면 더 간편합니다. 이를 위해 모델 클래스를 생성합니다.
- Todo 모델 클래스 만들기
class Todo {
int? userId;
int? id;
String? title;
bool? completed;
Todo({
required this.userId,
required this.id,
required this.title,
required this.completed,
});
// JSON 데이터를 Dart 객체로 변환하는 생성자
Todo.fromJson(Map<String, dynamic> json)
: userId = json['userId'],
id = json['id'],
title = json['title'],
completed = json['completed'];
@override
String toString() {
return 'Todo{userId: $userId, id: $id, title: $title, completed: $completed}';
}
}
- JSON 데이터를 객체로 변환하기
- _fetchTodos 메서드에서 가져온 데이터를 Todo 객체로 변환합니다.
Future<void> _fetchTodos() async {
try {
Response response =
await _dio.get('https://jsonplaceholder.typicode.com/todos/1');
print('HTTP 상태 코드: ${response.statusCode}');
print('서버 데이터: ${response.data}');
// JSON 데이터를 Dart 객체로 변환
Todo todo = Todo.fromJson(response.data);
print('변환된 Todo 객체: $todo');
} catch (e) {
print('에러 발생: $e');
}
}
4. 예외 처리와 데이터 출력
Dio는 HTTP 요청 실패, 네트워크 연결 문제 등 다양한 예외를 처리할 수 있습니다.
try-catch 블록을 사용하여 안정적인 네트워크 통신을 구현했습니다.
try {
Response response =
await _dio.get('https://jsonplaceholder.typicode.com/todos/1');
print('서버 데이터: ${response.data}');
} catch (e) {
print('에러 발생: $e');
}
실행결과
HTTP 상태 코드: 200
서버 데이터: {userId: 1, id: 1, title: delectus aut autem, completed: false}
변환된 Todo 객체: Todo{userId: 1, id: 1, title: delectus aut autem, completed: false}
전체 코드
import 'package:dio/dio.dart';
import 'package:flutter/material.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
const MyApp({super.key});
@override
Widget build(BuildContext context) {
return MaterialApp(
debugShowCheckedModeBanner: false,
home: SafeArea(
child: Scaffold(
body: HomePage(),
),
),
);
}
}
class HomePage extends StatefulWidget {
const HomePage({super.key});
@override
State<HomePage> createState() => _HomePageState();
}
class _HomePageState extends State<HomePage> {
// 통신을 담당하는 클라언트 측 객체를 가져오자
Dio _dio = Dio();
@override
void initState() {
super.initState();
// 객체 실행시 한번 호출 메서드
_fetchTodos();
}
@override
Widget build(BuildContext context) {
return const Placeholder();
}
// 통신을 담당하는 메서드를 만들어 보자.
_fetchTodos() async {
// https://jsonplaceholder.typicode.com/todos/1
// 통신을 담당하는 코드를 기본적으로 예외처리을 꼭 넣자
try {
Response response =
await _dio.get('https://jsonplaceholder.typicode.com/todos/1');
print('HTTP status code : ${response.statusCode}');
print('서버측 전달한 데이터 : ${response.data}');
print(
'json 통신 후 dart 에서는 어떤 타입으로 변경 되었을까? : ${response.data.runtimeType}');
// Map 타입에 값을 출력하는 방법
print('-----------------------------------------------');
Todo todo1 = Todo.fromJson(response.data);
print("todo1 : ${todo1}");
print('-----------------------------------------------');
// Map 으로 들어온 데이터를 Todo 객체를 생성해서 상태 값을 담아 보시오
} catch (e) {
print('실행 시점 예외가 발생 했어요');
print(e.toString());
}
}
}
// dart
class Todo {
int? userId;
int? id;
String? title;
bool? completed;
Todo(
{required this.userId,
required this.id,
required this.title,
required this.completed});
// dart 생성자 -> 명명된 생성자
Todo.fromJson(Map<String, dynamic> json)
: userId = json['userId'],
id = json['id'],
title = json['title'],
completed = json['completed'];
@override
String toString() {
return 'Todo{userId: $userId, id: $id, title: $title, completed: $completed}';
}
}
이번 포스팅에서는 Flutter에서 Dio 패키지를 활용하여 REST API와 통신하는 방법을 배웠습니다.
Dio는 강력한 HTTP 클라이언트로, Flutter에서 효율적인 네트워크 요청을 처리할 수 있다고 합니다.
다음에도 Flutter 관련된 유용한 포스팅으로 돌아오도록 할게요~ 감사합니다.
'Flutter' 카테고리의 다른 글
[Flutter] Callback 함수 - 자식 위젯 이벤트 처리 (1) | 2025.01.15 |
---|---|
[Flutter] 연습하기 5 - Flutter shopping cart app (0) | 2025.01.14 |
[Flutter] 연습하기 4 - Flutter login app (0) | 2025.01.13 |
[Flutter] 플러터 Stack 위젯 (0) | 2025.01.10 |
[Flutter] 연습하기3 - Flutter profile app (0) | 2025.01.10 |