15일차 과제 링크 👉 15일차 과제
→ 서버가 수행해야 할 동작을 지정하여 요청을 보내는 방법
메소드 | 설명 |
---|---|
GET | 리소스 조회, 주로 데이터를 받을 때 사용 |
POST | 요청 데이터 처리, 주로 데이터 생성할 때 사용 |
PUT | 리소스를 대체 (덮어쓰기), 해당 리소스가 없으면 생성 |
PATCH | 리소스 부분 변경 (PUT이 전체 변경, PATCH는 일부 변경) |
DELETE | 리소스 삭제 |
http 패키지 설치
http: ^0.13.5
등록HTTP 사용할 대상의 URL 정의
Method 선택 (GET, POST)
요청 보내기
요청 응답받기
출력
var url = 'https://sniperfactory.com/sfac/http_test';
var response = await http.get(Uri.parse(url)); // string 형태의 url을 Uri로 바꿈
print(response.statusCode); // 200 : 요청 성공
print(response.body); // {"result":"스나이퍼팩토리 비밀 URL에 접근하시다니."}
[URI와 URL의 차이]
URI
- "Uniform Resource Identifier"의 약자로, 인터넷에서 식별 가능한 리소스를 나타내는 일반적인 용어
- 식별자와 리소스의 위치를 모두 나타낼 수 있음
URL
- "Uniform Resource Locator"의 약자로, 인터넷에서 리소스의 위치를 나타내는 것
- 일반적으로 웹 브라우저에서 입력하는 것과 같이, 프로토콜, 호스트명, 리소스 경로 등을 포함하는 문자열
- 일반적으로 인터넷에서 식별 가능한 리소스를 나타내는 데 사용됨
차이
- URI는 리소스의 위치뿐만 아니라 식별자도 포함할 수 있지만, URL은 리소스의 위치만 포함한다.
- 예를 들어, URI는 ISBN 번호와 같은 고유한 식별자를 사용하여 책을 나타낼 수 있지만, URL은 해당 책이 있는 위치를 식별함
void main() async {
var url = 'https://sniperfactory.com/sfac/http_only_get';
var getResponse = await http.get(Uri.parse(url));
print(getResponse.body); // {"result":"정답입니다! GET 요청만 받는 경우도 정말정말 많습니다."}
var postResponse = await http.post(Uri.parse(url));
print(postResponse.body); // {"error":"GET 요청만 받습니다."}
}
void main() async {
var url = 'https://sniperfactory.com/sfac/http_only_post';
var postResponse = await http.post(Uri.parse(url));
print(postResponse.body); // {"result":"정답입니다! POST 요청만 받는 경우도 정말정말 많습니다."}
var getResponse = await http.get(Uri.parse(url));
print(getResponse.body); // {"error":"POST 요청만 받습니다."}
}
var dio = Dio();
dio.options.baseUrl = url; // baseUrl: 가장 기본이 되는 RouteURL (도메인 최상위 URL)
var dio = Dio();
var getRes = await dio.get('https://sniperfactory.com/sfac/http_only_get');
// var postRes = await dio.post('https://sniperfactory.com/sfac/http_only_get');
print(getRes); // {"result":"정답입니다! POST 요청만 받는 경우도 정말정말 많습니다."}
// print(postRes); // 400: Bad Request
var dio = Dio();
var postRes = await dio.post('https://sniperfactory.com/sfac/http_only_post');
// var getRes = await dio.get('https://sniperfactory.com/sfac/http_only_post');
print(postRes); // {"result":"정답입니다! POST 요청만 받는 경우도 정말정말 많습니다."}
// print(getRes); // 400: Bad Request
var dio = Dio();
var res = await dio.get(
'https://sniperfactory.com/sfac/http_only_chrome_browser',
options: Options(
headers: {
'user-agent': 'Chrome'
// 'user-agent': 'Safari' // 400: Bad Request
}
)
);
print(res); // {"result":"정답입니다! 이런 꿀잼 과제라니"}
var dio = Dio();
var res = await dio.get(
'https://sniperfactory.com/sfac/http_only_jwt_included',
options: Options(
headers: {
// 인증키를 첨부할 수 있는 key 값
'authorization': 'asdfasdf'
}
)
);
print(res); // {"result":"정답입니다! 이런 꿀잼 과제라니"}
import 'package:dio/dio.dart';
import 'package:http/http.dart' as http;
var dio = Dio();
var url = 'https://sniperfactory.com/sfac/http_json_data';
void main() {
getDataUsingDio();
getDataUsingHttp();
}
void getDataUsingHttp() async {
var res = await http.get(Uri.parse(url));
print('Http : $res'); // Instance of 'Future<Response>'
print('Http res.body : ${res.body}'); // {"item":{"name":"스나이퍼팩토리 플러터 과정","description":"스나이퍼팩토리의 플러터 과정입니다! 지금 바로 신청해볼까요?","image":"https://picsum.photos/200/200","price":4000000}}
print('Http res.body.runtimeType : ${res.body.runtimeType}'); // String
}
void getDataUsingDio() async {
var res = await dio.get(url);
print('Dio : $res'); // {"item":{"name":"스나이퍼팩토리 플러터 과정","description":"스나이퍼팩토리의 플러터 과정입니다! 지금 바로 신청해볼까요?","image":"https://picsum.photos/200/200","price":4000000}}
print('Dio res.data : ${res.data}'); // {item: {name: 스나이퍼팩토리 플러터 과정, description: 스나이퍼팩토리의 플러터 과정입니다! 지금 바로 신청해볼까요?, image: https://picsum.photos/200/200, price: 4000000}}
print('Dio res.data.runtimeType : ${res.data.runtimeType}'); // _InternalLinkedHashMap<String, dynamic>
print('Dio res.data item : ${res.data['item']['name']}');
}
[추가 비교]
HTTP
- GET, POST, PUT, DELETE 등 HTTP 메서드를 지원
- 헤더 및 쿼리 매개변수를 설정할 수 있음
- 인증 정보를 설정할 수 있음
- 쿠키를 사용할 수 있음
- 인터셉터를 사용하여 요청과 응답을 수정할 수 있음
- 타임아웃 및 소켓 연결 설정을 지원
- 플러터 앱과 통합된 예외 처리를 제공
Dio
- FormData 및 멀티파트 요청을 지원
- JSON 직렬화 및 역직렬화를 지원
- Interceptor를 사용하여 HTTP 요청과 응답을 수정하고 로깅할 수 있음
- 쿠키 지원
- 자동 취소 기능 제공
- 다운로드 및 업로드 기능을 제공
- 자체 캐시 시스템 지원
- http 패키지는 간단한 HTTP 요청을 처리하기에 적합
- Dio 패키지는 좀 더 복잡한 HTTP 요청 및 응답 처리를 위해 사용됨
작업을 순차적으로 실행하며, 한 작업이 완료될 때까지 다음 작업을 수행할 수 없음
[동기의 장점과 단점]
장점
- 코드가 간단하며, 순차적으로 실행됨
- 에러가 발생했을 때 디버깅하기 쉽다
- 결과가 도착할 때까지 대기하므로 동기적인 방식은 동시성 제어 문제를 해결할 수 있다
단점
- 대기 시간이 발생하면 블로킹(blocking)이 발생하여 시스템 전체의 처리 속도가 느려짐
- 대규모 사용자가 있는 시스템에서는 처리 속도가 매우 느려질 수 있음
- 서버 측의 자원을 많이 차지할 수 있다
한 작업이 끝날 때까지 기다리지 않고 다른 작업을 수행할 수 있는 방식
[비동기의 장점과 단점]
장점
- 비동기적 방식이 대부분의 경우 더 빠름
- 작업이 완료되는 동안 대기할 필요가 없으므로 다른 작업을 수행할 수 있음
- 다수의 작업이 동시에 수행될 수 있다
단점
- 비동기적인 방식은 설계가 복잡함
- 에러 처리가 어려울 수 있음
- 결과가 순서대로 도착하지 않을 수 있으므로 일부 알고리즘에서는 사용할 수 없다
[예시]
I/O 작업을 수행할 때 파일을 읽거나 네트워크를 통해 데이터를 받아오는 등의 작업은 시간이 오래 걸리기 때문에 동기적으로 수행하면 애플리케이션이 블로킹되어 다른 작업을 수행할 수 없음.
비동기적으로 수행하면 I/O 작업이 수행되는 동안 다른 작업을 수행할 수 있으므로 애플리케이션의 성능을 향상시킬 수 있다
async
await
void main() async {
print('로그인을 시도합니다.');
await Future.delayed(Duration(seconds: 3));
print('로그인에 성공했습니다');
print('반갑소');
}
로그인을 시도합니다.
(3초 뒤)
로그인에 성공했습니다
반갑소
then
void main() async {
print('로그인을 시도합니다.');
Future.delayed(Duration(seconds: 3)).then((res) {
print(res);
print('로그인에 성공했습니다');
});
print('반갑소');
}
로그인을 시도합니다.
반갑소
(3초 뒤)
null
로그인에 성공했습니다
var message = '';
Text(message);
Future<String> getData() async {
var dio = Dio();
var res = await dio.get('https://sniperfactory.com/sfac/http_test');
return res.data['result'];
}
void handleOnPressed() async {
message = await getData();
}
TextButton(
onPressed: () {
handleOnPressed();
}
child: Text('데이터 가져오기'),
)
차가운 챗선생......