애플리케이션이 외부 서비스와 상호작용하거나 실시간 데이터를 받아오기 위해서는 API 통합이 필수적입니다. Flutter는 RESTful API와 같은 외부 API에 간단하게 접근할 수 있는 기능을 제공하여 앱이 데이터를 받아오거나 서버로 전송할 수 있게 해줍니다. 이번 글에서는 Flutter에서 HTTP 요청을 사용하여 API를 통합하는 방법을 단계별로 설명하겠습니다.
1. API 통합이란?
API 통합(API Integration)은 애플리케이션이 외부 서버와 통신하여 데이터를 주고받는 과정입니다. Flutter에서는 API 통합을 통해 서버에서 데이터를 불러오거나, 사용자 입력을 서버로 전송할 수 있습니다. 일반적으로 REST API를 사용하여 JSON 형식의 데이터를 주고받으며, 이 과정에서 HTTP 메서드(GET, POST, PUT, DELETE 등)를 사용합니다.
2. Flutter의 HTTP 패키지
Flutter에서 HTTP 요청을 처리하기 위해 기본적으로 http 패키지를 사용합니다. 이 패키지는 간단하고 강력한 HTTP 클라이언트로, API와의 통신을 쉽게 처리할 수 있습니다.
2.1 HTTP 패키지 설치
먼저 pubspec.yaml 파일에 http 패키지를 추가합니다.
dependencies:
http: ^0.13.3
패키지를 설치한 후, flutter pub get 명령어를 실행하여 패키지를 다운로드합니다.
2.2 HTTP 패키지 사용
패키지를 설치한 후, http 라이브러리를 임포트하여 API 요청을 보낼 수 있습니다.
import 'package:http/http.dart' as http;
이제 HTTP 요청을 사용하여 서버와 데이터를 주고받는 방법을 살펴보겠습니다.
3. GET 요청: 데이터 가져오기
GET 요청은 서버로부터 데이터를 가져올 때 사용됩니다. 예를 들어, 뉴스 기사, 사용자 정보 등 외부 데이터를 앱에서 표시할 때 GET 요청을 사용합니다.
3.1 GET 요청 기본 예제
import 'package:flutter/material.dart';
import 'package:http/http.dart' as http;
import 'dart:convert';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
home: HomeScreen(),
);
}
}
class HomeScreen extends StatefulWidget {
@override
_HomeScreenState createState() => _HomeScreenState();
}
class _HomeScreenState extends State<HomeScreen> {
late Future<List<dynamic>> _users;
@override
void initState() {
super.initState();
_users = fetchUsers();
}
Future<List<dynamic>> fetchUsers() async {
final response = await http.get(Uri.parse('https://jsonplaceholder.typicode.com/users'));
if (response.statusCode == 200) {
return jsonDecode(response.body);
} else {
throw Exception('Failed to load users');
}
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text('API Integration Example')),
body: FutureBuilder<List<dynamic>>(
future: _users,
builder: (context, snapshot) {
if (snapshot.hasData) {
return ListView.builder(
itemCount: snapshot.data!.length,
itemBuilder: (context, index) {
return ListTile(
title: Text(snapshot.data![index]['name']),
subtitle: Text(snapshot.data![index]['email']),
);
},
);
} else if (snapshot.hasError) {
return Center(child: Text('Failed to load users'));
}
return Center(child: CircularProgressIndicator());
},
),
);
}
}
위 예제에서는 jsonplaceholder라는 샘플 API에서 사용자 목록을 GET 요청으로 받아와, 리스트에 표시하는 간단한 예제입니다.
- http.get 메서드를 사용하여 GET 요청을 보내고, response.statusCode를 통해 요청이 성공했는지 확인합니다.
- 성공하면 JSON 데이터를 디코딩하여 사용합니다.
- FutureBuilder 위젯을 사용하여 비동기적으로 데이터를 받아와 UI에 표시합니다.
4. POST 요청: 데이터 전송
POST 요청은 서버로 데이터를 전송할 때 사용됩니다. 사용자 입력을 서버에 저장하거나, 양식을 제출할 때 POST 요청을 사용합니다.
4.1 POST 요청 기본 예제
import 'package:flutter/material.dart';
import 'package:http/http.dart' as http;
import 'dart:convert';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
home: PostDataScreen(),
);
}
}
class PostDataScreen extends StatefulWidget {
@override
_PostDataScreenState createState() => _PostDataScreenState();
}
class _PostDataScreenState extends State<PostDataScreen> {
final TextEditingController _nameController = TextEditingController();
final TextEditingController _jobController = TextEditingController();
Future<void> _submitData(String name, String job) async {
final response = await http.post(
Uri.parse('https://reqres.in/api/users'),
headers: <String, String>{
'Content-Type': 'application/json; charset=UTF-8',
},
body: jsonEncode(<String, String>{
'name': name,
'job': job,
}),
);
if (response.statusCode == 201) {
print('Data submitted successfully');
} else {
throw Exception('Failed to submit data');
}
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text('Submit Data')),
body: Padding(
padding: const EdgeInsets.all(16.0),
child: Column(
children: [
TextField(
controller: _nameController,
decoration: InputDecoration(labelText: 'Name'),
),
TextField(
controller: _jobController,
decoration: InputDecoration(labelText: 'Job'),
),
SizedBox(height: 20),
ElevatedButton(
onPressed: () {
_submitData(_nameController.text, _jobController.text);
},
child: Text('Submit'),
),
],
),
),
);
}
}
위 예제에서는 reqres.in이라는 샘플 API를 사용하여 사용자가 입력한 데이터를 서버로 POST 요청을 통해 전송하는 예제입니다.
- http.post 메서드를 사용하여 데이터를 서버로 전송하고, 응답 상태 코드를 확인합니다.
- headers를 통해 서버에 JSON 형식의 데이터를 보낼 것을 명시합니다.
- 데이터는 jsonEncode를 통해 JSON 형식으로 인코딩됩니다.
5. PUT, DELETE 요청: 데이터 수정 및 삭제
Flutter에서 PUT과 DELETE 요청은 데이터 수정을 위해 사용되며, API에서 제공되는 리소스를 업데이트하거나 삭제할 때 사용됩니다.
5.1 PUT 요청
PUT 요청은 기존 데이터를 업데이트하는 데 사용됩니다. 예를 들어, 사용자의 정보를 수정하는 경우를 살펴보겠습니다.
Future<void> updateUser(String id, String name, String job) async {
final response = await http.put(
Uri.parse('https://reqres.in/api/users/$id'),
headers: <String, String>{
'Content-Type': 'application/json; charset=UTF-8',
},
body: jsonEncode(<String, String>{
'name': name,
'job': job,
}),
);
if (response.statusCode == 200) {
print('User updated successfully');
} else {
throw Exception('Failed to update user');
}
}
5.2 DELETE 요청
DELETE 요청은 서버에서 데이터를 삭제하는 데 사용됩니다. 아래는 특정 사용자를 삭제하는 예제입니다.
Future<void> deleteUser(String id) async {
final response = await http.delete(
Uri.parse('https://reqres.in/api/users/$id'),
);
if (response.statusCode == 204) {
print('User deleted successfully');
} else {
throw Exception('Failed to delete user');
}
}
6. API 응답 처리 및 오류 처리
API 요청이 실패하거나 오류가 발생했을 때, 사용자에게 적절한 메시지를 표시하고 오류를 처리하는 것이 중요합니다. 이를 위해 상태 코드를 확인하고, 예외 처리를 통해 오류를 관리할 수 있습니다.
6.1 응답 및 오류 처리 예제
Future<void> fetchData() async {
try {
final response = await http.get(Uri.parse('https://example.com/data'));
if (response.statusCode == 200) {
// 데이터 처리
} else {
throw Exception('Failed to load data');
}
} catch (error) {
print('An error occurred: $error');
}
}
위 예제에서는 try-catch 블록을 사용하여 네트워크 요청 중 발생하는 오류를 처리합니다. 요청이 성공하면 데이터를 처리하고, 실패 시 예외를 발생시켜 오류를 관리합니다.
7. 비동기 프로그래밍 및 FutureBuilder
Flutter에서 API 요청은 비동기적으로 처리됩니다. 비동기 프로그래밍을 위해 async와 await 키워드를 사용하며, 비동기 결과를 UI에 반영하기 위해 FutureBuilder 위젯을 사용합니다.
7.1 FutureBuilder 사용 예제
FutureBuilder(
future: fetchData(),
builder: (context, snapshot) {
if (snapshot.connectionState == ConnectionState.waiting) {
return CircularProgressIndicator();
} else if (snapshot.hasError) {
return Text('Error: ${snapshot.error}');
} else {
return Text('Data: ${snapshot.data}');
}
},
);
FutureBuilder는 비동기 데이터의 상태를 모니터링하여 UI에 반영할 수 있도록 도와줍니다. 데이터가 로딩 중일 때는 로딩 화면을, 데이터가 성공적으로 로드되면 결과를, 오류가 발생하면 에러 메시지를 표시합니다.
결론
Flutter에서 API 통합은 매우 간단하고 직관적으로 구현할 수 있습니다. http 패키지를 사용하여 GET, POST, PUT, DELETE 등의 요청을 통해 서버와 데이터를 주고받을 수 있으며, 비동기 프로그래밍을 활용하여 네트워크 요청을 효율적으로 처리할 수 있습니다. 또한, 오류 처리를 통해 안정적인 네트워크 통신을 구현할 수 있습니다. 이번 글에서 설명한 방법들을 활용하여 Flutter 애플리케이션에서 외부 API와의 통신을 원활하게 통합해보세요.
'Flutter' 카테고리의 다른 글
Flutter의 REST API 사용법 (0) | 2025.03.15 |
---|---|
Flutter의 GraphQL 사용법 (0) | 2025.03.15 |
Flutter의 데이터 동기화(Data Synchronization) 사용법 (0) | 2025.01.28 |
Flutter의 오프라인 데이터 저장 방법 (0) | 2025.01.28 |
Flutter의 네트워크 이미지(Network Image) 사용법 (0) | 2025.01.27 |