티스토리 뷰
Flutter는 간단하고 효율적인 HTTP 패키지를 사용하여 RESTful API와 통신할 수 있는 강력한 기능을 제공합니다. 이번 포스팅에서는 Flutter를 이용해 데이터를 업데이트하는 방법을 알아보겠습니다. 특히 HTTP PUT
및 PATCH
요청을 활용하여 서버에 데이터를 업데이트하는 과정을 상세히 다룰 것입니다.
참고. Update data over the internet
Flutter에서 데이터 업데이트의 기본 원리
Flutter에서 데이터를 업데이트하려면 다음과 같은 절차를 따릅니다:
- HTTP 요청을 통해 서버와 통신
- 요청 헤더와 본문 구성
- 서버의 응답 처리 및 상태 코드 확인
- UI 업데이트
이 과정은 비동기적으로 이루어지며, http
패키지를 사용하여 간단하게 구현할 수 있습니다.
1. HTTP 패키지 설치 및 설정
HTTP 요청을 보내기 위해 http
패키지를 설치해야 합니다. Flutter 프로젝트의 pubspec.yaml
파일에 다음을 추가하세요:
dependencies:
http: ^0.15.0
이후 패키지를 가져옵니다:
import 'package:http/http.dart' as http;
2. PUT 요청과 PATCH 요청의 차이
- PUT 요청: 객체 전체를 교체합니다. 서버에 보낸 데이터로 기존 데이터를 완전히 대체하려는 경우 사용합니다.
- PATCH 요청: 특정 필드만 수정합니다. 일부 데이터만 업데이트하려는 경우 유용합니다.
예를 들어, 사용자 정보 업데이트를 살펴보겠습니다.
3. Flutter에서 PUT 요청 구현
다음은 Flutter에서 PUT 요청을 사용하여 데이터를 업데이트하는 코드 예제입니다:
Future<void> updateData(String id, Map<String, String> updatedData) async {
final url = Uri.parse('https://example.com/items/$id');
final response = await http.put(
url,
headers: {
'Content-Type': 'application/json',
},
body: jsonEncode(updatedData),
);
if (response.statusCode == 200) {
print('Data updated successfully!');
} else {
print('Failed to update data: ${response.reasonPhrase}');
}
}
주요 설명:
Uri.parse
: 요청할 URL을 정의합니다.http.put
: PUT 요청을 보냅니다.headers
: 요청의 메타데이터를 포함합니다.body
: 업데이트할 데이터를 JSON으로 직렬화합니다.
4. Flutter에서 PATCH 요청 구현
PATCH 요청은 데이터의 특정 필드를 업데이트할 때 유용합니다. 다음은 코드 예제입니다:
Future<void> patchData(String id, Map<String, dynamic> partialUpdate) async {
final url = Uri.parse('https://example.com/items/$id');
final response = await http.patch(
url,
headers: {
'Content-Type': 'application/json',
},
body: jsonEncode(partialUpdate),
);
if (response.statusCode == 200) {
print('Data partially updated!');
} else {
print('Failed to update data: ${response.reasonPhrase}');
}
}
주요 설명:
http.patch
: PATCH 요청을 보냅니다.- 부분 업데이트를 위해 필요한 필드만
partialUpdate
에 포함합니다.
5. 서버 응답 처리 및 UI 갱신
서버 응답의 상태 코드를 확인하여 업데이트 결과를 처리합니다. 성공적으로 데이터를 업데이트한 후에는 Flutter의 상태 관리 방법(예: setState
또는 Provider
)을 사용하여 UI를 새로 고칠 수 있습니다.
setState(() {
items[index] = updatedItem;
});
데이터 업데이트 시 유의사항
- 예외 처리: 네트워크 실패나 서버 오류에 대비하여 예외를 처리해야 합니다.
- 권한 인증: 데이터 업데이트 요청 시 API 키 또는 토큰 인증이 필요할 수 있습니다.
- 데이터 유효성 검사: 서버에 전송하기 전에 데이터가 올바른지 확인하세요.
실전 팁: 디버깅 및 테스트
- Postman 또는 cURL을 사용하여 서버 API를 테스트하고 올바른 응답을 확인하세요.
- Flutter DevTools를 활용하여 요청 및 응답 로그를 분석하세요.
결론
Flutter에서 HTTP 요청을 사용하여 데이터를 업데이트하는 것은 RESTful API와 통신하는 데 필수적인 기술입니다. 이번 포스팅에서 설명한 PUT 및 PATCH 요청의 차이와 구현 방법을 활용하면, 더욱 강력하고 유연한 네트워크 애플리케이션을 개발할 수 있습니다.
import 'dart:async';
import 'dart:convert';
import 'package:flutter/material.dart';
import 'package:http/http.dart' as http;
Future<Album> fetchAlbum() async {
final response = await http.get(
Uri.parse('https://jsonplaceholder.typicode.com/albums/1'),
);
if (response.statusCode == 200) {
// If the server did return a 200 OK response,
// then parse the JSON.
return Album.fromJson(jsonDecode(response.body) as Map<String, dynamic>);
} else {
// If the server did not return a 200 OK response,
// then throw an exception.
throw Exception('Failed to load album');
}
}
Future<Album> updateAlbum(String title) async {
final response = await http.put(
Uri.parse('https://jsonplaceholder.typicode.com/albums/1'),
headers: <String, String>{
'Content-Type': 'application/json; charset=UTF-8',
},
body: jsonEncode(<String, String>{
'title': title,
}),
);
if (response.statusCode == 200) {
// If the server did return a 200 OK response,
// then parse the JSON.
return Album.fromJson(jsonDecode(response.body) as Map<String, dynamic>);
} else {
// If the server did not return a 200 OK response,
// then throw an exception.
throw Exception('Failed to update album.');
}
}
class Album {
final int id;
final String title;
const Album({required this.id, required this.title});
factory Album.fromJson(Map<String, dynamic> json) {
return switch (json) {
{
'id': int id,
'title': String title,
} =>
Album(
id: id,
title: title,
),
_ => throw const FormatException('Failed to load album.'),
};
}
}
void main() {
runApp(const MyApp());
}
class MyApp extends StatefulWidget {
const MyApp({super.key});
@override
State<MyApp> createState() {
return _MyAppState();
}
}
class _MyAppState extends State<MyApp> {
final TextEditingController _controller = TextEditingController();
late Future<Album> _futureAlbum;
@override
void initState() {
super.initState();
_futureAlbum = fetchAlbum();
}
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Update Data Example',
theme: ThemeData(
colorScheme: ColorScheme.fromSeed(seedColor: Colors.deepPurple),
),
home: Scaffold(
appBar: AppBar(
title: const Text('Update Data Example'),
),
body: Container(
alignment: Alignment.center,
padding: const EdgeInsets.all(8),
child: FutureBuilder<Album>(
future: _futureAlbum,
builder: (context, snapshot) {
if (snapshot.connectionState == ConnectionState.done) {
if (snapshot.hasData) {
return Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Text(snapshot.data!.title),
TextField(
controller: _controller,
decoration: const InputDecoration(
hintText: 'Enter Title',
),
),
ElevatedButton(
onPressed: () {
setState(() {
_futureAlbum = updateAlbum(_controller.text);
});
},
child: const Text('Update Data'),
),
],
);
} else if (snapshot.hasError) {
return Text('${snapshot.error}');
}
}
return const CircularProgressIndicator();
},
),
),
),
);
}
}
'Flutter Cookbook' 카테고리의 다른 글
Flutter에서 WebSocket 사용법: 실시간 데이터 통신의 핵심 (1) | 2024.12.06 |
---|---|
Flutter로 HTTP DELETE 요청 보내기: 데이터 삭제의 기본 원리와 구현 방법 (1) | 2024.12.05 |
Flutter로 데이터 전송하기: 간단하고 명확한 가이드 (0) | 2024.12.03 |
Flutter에서 인증된 요청 처리하기: 단계별 가이드 (0) | 2024.12.02 |
Flutter로 인터넷에서 데이터 가져오기: 완벽 가이드 (2) | 2024.12.01 |