118호. 라라벨 7.0 신기능 - HTTP 클라이언트 free

2020-04-01

모두들 그 동안 잘 지내셨나요? 코로나 때문에 다들 힘드실 것 같아요 ㅠ


아직 완전히 끝낸 건 아니지만 번역 작업이 어느 정도 진행되서 다시 1일 1식 라라벨을 재개합니다! 너무 오래 기다리셨어요 ㅠㅠ


앞으로도 꾸준히 성실하게 라라벨을 사용하는데 도움이 되는 글을 하루 한 편씩 전달해드리도록 하겠습니다. 저 말고도 함께 1일 1식 라라벨 컨텐츠를 만들 분들이 함께 하니 기대해주세요.


오늘 준비한 내용은 라라벨 7에 새로 추가된 HTTP 클라이언트입니다. 재밋게 봐주세요!


라라벨 7.0 신기능 - HTTP 클라이언트


라라벨 HTTP 클라이언트는 Guzzle HTTP 클라이언트를 기반으로 하되 자주 쓰는 기능만 추리고, 더 사용하기 편하게 만든 도구입니다. 주로 외부 애플리케이션에 HTTP 요청을 보낼 때 사용합니다.


Guzzle HTTP 클라이언트에 의존하기 때문에 컴포저로 애플리케이션에 Guzzle HTTP 클라이언트를 설치해야 사용할 수 있습니다.


저 처럼 어차피 외부에 요청을 보내기 위해 Guzzle을 설치해서 썼던 사람이라면 왠만한 건 라라벨 HTTP 클라이언트로 처리하고 복잡한 기능이 필요하면 Guzzle을 사용하는 식으로 활용하면 될 것 같습니다. Guzzle이 아닌 다른 HTTP 클라이언트를 사용하고 있었다면 기존에 쓰던 것을 유지할 지 갈아탈 지 한 번쯤 검토해보는 것도 좋을 것 같네요.


Guzzle과 간단한 비교


사용법은 공식 문서에 잘 안내되어 있으니 따로 설명할 필요는 없을 것 같습니다. 써볼까? 싶은 분들은 꼭 공식 문서를 한 번 읽어보시길 권해드려요. 이 글에서는 기존에 사용하던 도구인 Guzzle에 비해 얼마나 편해졌는지를 위주로 정리해보도록 하겠습니다.


퍼사드


// Guzzle

$client = new GuzzleHttp\Client();
$res = $client->get('https://laravel.com');

// 라라벨 HTTP
$response = Http::get('https://laravel.com');

퍼사드를 이용해서 인스턴스화 하는 단계를 줄일 수 있습니다. 별 것 아닙니다만. :)


데이터 접근


라라벨 HTTP 클라이언트의 get 메서드가 반환하는 Illuminate\Http\Client\Response는 ArrayAccess 인터페이스를 구현하고 있어서 JSON 응답 데이터에 접근하기가 Guzzle에 비해 편리합니다.


// Guzzle
$client = new GuzzleHttp\Client();
$res = $client->get('http://test.com/users/1');
return $response->json()['name'];

// 라라벨 HTTP
return Http::get('http://test.com/users/1')['name'];

데이터 첨부



application/x-www-form-urlencoded 컨텐트 타입으로 데이터를 전송하고 싶은 경우, Guzzle은 ‘form_parmas’에 배열로 데이터를 담아 전송하면 되고, 라라벨 HTTP는 asForm() 메서드를 사용하면 됩니다.


// Guzzle
$client = new \GuzzleHttp\Client();
$response = $client->request('POST', 'http://test.com/users', [
'form_params' => [
'name' => 'Sara',
'role' => 'Privacy Consultant',
]
]);

// 라라벨 HTTP
$response = Http::asForm()->post('http://test.com/users', [
'name' => 'Sara',
'role' => 'Privacy Consultant',
]);

파일 전송


Guzzle과 라라벨 HTTP 모두 문자열과 스트림으로 파일을 전달할 수 있습니다. Guzzle로 파일을 전송할 때는 ‘multipart’에 배열로 데이터를 담아 전송하면 되고, 라라벨 HTTP는 attach() 메서드를 사용하면 됩니다.


// Guzzle 문자열 이용
$client = new \GuzzleHttp\Client();
$response = $client->request('POST', 'http://httpbin.org/post', [
'multipart' => [
[
'name' => 'field_name',
'contents' => 'abc'
'filename' => 'filename.txt',
]
]
]);

// 라라벨 HTTP 문자열 이용
$response = Http::attach(
'attachment', file_get_contents('photo.jpg'), 'photo.jpg'
)->post('http://test.com/attachments');

// Guzzle 스트림 이용
$client = new \GuzzleHttp\Client();
$response = $client->request('POST', 'http://httpbin.org/post', [
'multipart' => [
[
'name' => 'file_name',
'contents' => fopen('/path/to/file', 'r'),
'filename' => 'filename.txt',
],
]
]);

// 라라벨 HTTP 스트림 이용
$photo = fopen('photo.jpg', 'r');

$response = Http::attach(
'attachment', $photo, 'photo.jpg'
)->post('http://test.com/attachments');

인증


// Guzzle 기본
$response = $client->request('GET', '/get', ['auth' => ['username', 'password']]);

// Guzzle 다이제스트
$response = $client->request('GET', '/get', [
'auth' => ['username', 'password', 'digest']
]);

// Guzzle Bearer
$response = $client->request('GET', '/get', [
'headers' => [
'Authorization' => 'Bearer' . $token,
'Accept' => 'application/json',
]
]);
// 라라벨 HTTP 기본
$response = Http::withBasicAuth('taylor@laravel.com', 'secret')->post(...);

// 라라벨 HTTP 다이제스트
$response = Http::withDigestAuth('taylor@laravel.com', 'secret')->post(...);

// 라라벨 HTTP Bearer
$response = Http::withToken('token')->post(...);

재시도


Guzzle은 내장된 RetryMiddleware를 사용하거나, caseyamcl/guzzle_retry_middleware 같은 외부 패키지를 사용해서 재시도를 설정할 수 있습니다. 언뜻 보기에 라라벨 HTTP 보다 편하게 설정할 수 있는 것 처럼 보이진 않네요.


// 라라벨 HTTP
$response = Http::retry(3, 100)->post(...);

에러 처리


Guzzle은 외부 서버에서 에러가 발생해도 예외를 던지지만, 라라벨 HTTP는 그렇지 않습니다. 이건 어떤 방식이 더 편리한건지 잘 모르겠네요.


테스트


기존에는 응답을 속이기 위해 직접 모킹해야 했습니다. 라라벨 HTTP는 테스트에 활용할 수 있는 여러 편의 기능을 제공합니다. 이 부분에 대해서는 라라벨 HTTP가 압승인 듯 합니다. 간단히 비교하면 아래와 같습니다. 더 많은 기능이 있으니 관심있으시면 공식 메뉴얼을 참고하세요.


// Guzzle
$mock = $this->mock(Client::class);
$mock->shouldReceive('send')
->andReturn(new Response(
$status = 200,
$headers = [],
['foo' => 'bar']
));

// 라라벨 HTTP
Http::fake([
// 깃헙 엔드포인트용 JSON 응답 스텁...
'github.com/*' => Http::response(['foo' => 'bar'], 200, ['Headers']),

// 구글 엔드포인트용 문자열 응답 스텁...
'google.com/*' => Http::response('Hello World', 200, ['Headers']),
]);

마치며


기존에 Guzzle(또는 다른 HTTP 클라이언트 패키지)를 사용하는 것에 비해 어떤 면에서 편리해졌을까 하는 궁금증으로 글을 시작했습니다. 하나씩 정리해보니 확실히 더 편리해보이네요. 서두에 말씀드린 것 처럼 어차피 라라벨 HTTP 클라이언트를 사용하기 위해선 Guzzle을 설치해야 하기 때문에, 좀 더 손쉽게 사용할 수 있는 HTTP 클라이언트를 우선 이용하고 이것으로 해결되지 않는 상황은 Guzzle로 해결하면 어떨까 싶습니다.


이현석

메쉬 코리아 개발자. 바쁜 팀장님 대신 알려주는 신입 PHP 개발자 안내서를 쓰고, 클린 아키텍처 인 PHP를 번역했습니다. 2020년에 출간될 Laravel Up & Running 2nd Edition을 번역하고 있습니다.