HTTP Requests-요청

Request 엑세스 하기

의존성 주입을 통해서 현재 HTTP request의 인스턴스를 획득하기 위해서는 컨트롤러 메소드에서 Illuminate\Http\Request 클래스를 타입힌트해야 합니다. 유입된 request의 인스턴스는 서비스 컨테이너에 의해서 자동으로 주입될 것입니다.

<?php

namespace App\Http\Controllers;

use Illuminate\Http\Request;

class UserController extends Controller
{
    /**
     * Store a new user.
     *
     * @param  Request  $request
     * @return Response
     */
    public function store(Request $request)
    {
        $name = $request->input('name');

        //
    }
}

의존성 주입 & 라우트 파라미터

만약 컨트롤러 메소드에서 라우트 파라미터로 부터 입력값을 받아야 한다면, 다른 의존성을 지정한 뒤에 라우트 파라미터를 나열해야 합니다. 예를 들어 라우트는 다음과 같이 정의될 수 있습니다:

Route::put('user/{id}', 'UserController@update');

다음과 같이 컨트롤러 메소드를 정의하면 Illuminate\Http\Request를 타입힌트하여 라우트 파라미터 id에 접근할 수 있습니다:

<?php

namespace App\Http\Controllers;

use Illuminate\Http\Request;

class UserController extends Controller
{
    /**
     * Update the specified user.
     *
     * @param  Request  $request
     * @param  string  $id
     * @return Response
     */
    public function update(Request $request, $id)
    {
        //
    }
}

라우트 클로저를 통해서 Request 엑세스하기

또한 라우트 클로저에서도 Illuminate\Http\Request 클래스를 타입힌트 할 수 있습니다. 서비스 컨테이너는 클로저가 실행될 때 자동으로 유입된 request 를 주입할 것입니다:

use Illuminate\Http\Request;

Route::get('/', function (Request $request) {
    //
});

Request 경로 & 메소드

Illuminate\Http\Request 인스턴스는 애플리케이션의 HTTP request를 검사할 수 있는 다양한 메소드를 제공하며 Symfony\Component\HttpFoundation\Request 클래스를 상속 받고 있습니다. 몇가지 가장 중요한 메소드를 알아보겠습니다:

Request 경로 조회하기

path 메소드는 request의 경로정보를 반환합니다. 따라서 들어오는 request가 http://domain.com/foo/bar를 대상으로 한다면 path 메소드는 foo/bar를 반환합니다:

$uri = $request->path();

is 메소드는 들어오는 request가 특정 패턴에 상응한다는 것을 확인할 수 있게 해줍니다. 이 메소드를 활용할 때 * 기호를 와일드카드로 쓸 수 있습니다:

if ($request->is('admin/*')) {
    //
}

Request URI 조회하기

유입되는 request 의 전체 URL을 조회하기 위해서 url 또는 fullUrl 메소드를 사용할 수 있습니다. url 메소드는 쿼리 스트링 없는 URL을, fullUrl 은 쿼리 스트링을 포함한 URL을 반환합니다:

// Without Query String...
$url = $request->url();

// With Query String...
$url = $request->fullUrl();

Request HTTP 메소드(verb) 조회하기

method 메소드는 request에 대해 HTTP 메소드를 반환합니다. HTTP 메소드가 특정 문자열에 대응하는 것을 확인하기 위해 isMethod 메소드를 사용할 수 있습니다:

$method = $request->method();

if ($request->isMethod('post')) {
    //
}

PSR-7 Requests

PSR-7 표준은 요청과 응답을 포함한 HTTP 메세지들에 대한 인터페이스를 지정합니다. 라라벨의 request 대신 PSR-7 요청의 인스턴스를 획득하기 위해서는 우선 몇 개의 라이브러리를 설치해야 합니다. 라라벨은 Symfony HTTP Message Bridge 컴포넌트를 사용하여 일반적인 라라벨의 request-요청과 response-응답을 PSR-7에 맞는 구현체로 변환합니다:

composer require symfony/psr-http-message-bridge
composer require zendframework/zend-diactoros

이 라이브러리들을 설치하였다면 라우트 클로저나 컨트롤러 메소드에 request를 타입힌트하여 PSR-7 request를 얻을 수 있습니다:

use Psr\Http\Message\ServerRequestInterface;

Route::get('/', function (ServerRequestInterface $request) {
    //
});

{tip} 라우트나 컨트롤러에서 반환된 PSR-7 response 인스턴스는 자동으로 라라벨 response 인스턴스로 변환되어 프레임워크에 표시될 것입니다.

입력값 Trim 처리 & 일반화처리

기본적으로 라라벨은 애플리케이션의 글로벌 미들웨어 스택에 TrimStrings 그리고 ConvertEmptyStringsToNull 미들웨어를 포함하고 있습니다. 이 미들웨어는 App\Http\Kernel 클래스의 미들웨어 스택에 나열되어 있습니다. 이 미들웨어는 request-요청에 유입되는 모든 문자 필드들을 자동으로 trim 처리하고, 빈 문자필드는 null로 변환합니다. 따라서 라우트와 컨트롤러에서 이러한 일반화 문제를 걱정할 필요가 없습니다.

이 동작을 비활성화 시키려면, App\Http\Kernel 클래스의 $middleware 속성에서 두 미들웨어를 제거하면 됩니다.

입력값 조회하기

모든 입력값 조회하기

all 메소드를 사용하여 모든 입력데이터를 배열 로 조회할 수 있습니다.

$input = $request->all();

입력값 조회하기

몇 개의 단순한 메소드들을 사용하면 어떤 HTTP verb 가 request 에 사용되었는지에 대한 걱정없이 Illuminate\Http\Request 인스턴스에서 모든 사용자 입력에 접근할 수 있습니다. HTTP verb에 관계없이 input 메서드는 사용자 입력을 조회하는데 사용됩니다:

$name = $request->input('name');

input 메소드에 두번째 인자로 기본값을 전달할 수 있습니다. Request에 요청된 입력 값이 존재하지 않는다면 기본값이 반환됩니다:

$name = $request->input('name', 'Sally');

배열 입력을 가진 폼에서 동작할 때에는, 배열에 접근하기 위하여 "점" 표기법을 사용할 수 있습니다:

$name = $request->input('products.0.name');

$names = $request->input('products.*.name');

쿼리 스트링에서 입력값 조회하기

input 메소드가 요청-request 전체의 payload(쿼리 스트링을 포함하여)에서 값을 조회한다면, query 메소드는 쿼리 스트링에서만 값을 조회합니다:

$name = $request->query('name');

찾고자 하는 데이터가 존재하지 않을 때를 위해서 메소드의 두번째 인자로 기본값을 전달할 수 있습니다:

$name = $request->query('name', 'Helen');

query 메소드를 호출할 때 아무런 인자를 전달하지 않는다면, 전체 쿼리 스트링의 값들을 배열 형태로 반환합니다:

$query = $request->query();

동적 속성을 통한 입력값 조회하기

Illuminate\Http\Request 인스턴스의 동적 속성을 사용하여 사용자 입력에 엑세스할 수도 있습니다. 예를 들어 애플리케이션의 form 중에 하나가 name 필드를 가지고 있다면, 다음과 같이 필드의 값에 엑세스 할 수 있습니다:

$name = $request->name;

동적 속성을 사용할 때, 라라벨은 먼저 request payload 안에 있는 파라미터의 값을 찾습니다. 만약 값이 없다면 라라벨은 라우트 파라미터 안에 있는 필드를 찾을 것입니다.

JSON 입력 값 조회하기

애플리케이션에 JSON 요청이 전달되어 Content-Type 헤더 속성이 application/json 으로 지정되어 있다면 input 메소드를 통해서 JSON 데이터에 접근할 수 있습니다. 또한 "점" 문법을 통해서 JSON 배열에 접근할 수도 있습니다.

$name = $request->input('user.name');

입력 데이터의 한 부분 조회하기

입력 데이터의 일부분만 조회하기 위해서 onlyexcept 메소드를 사용할 수 있습니다. 이 두 메소드 모두 하나의 배열 또는 동적인 인자의 목록을 받아 들입니다:

$input = $request->only(['username', 'password']);

$input = $request->only('username', 'password');

$input = $request->except(['credit_card']);

$input = $request->except('credit_card');

{tip} only 메소드는 유입되는 request-요청에서 입력한 키 / 값 쌍을 반환합니다. 그렇지만 현재 request 에서 존재하지 않는 키/값은 반환하지 않습니다.

$input = $request->intersect(['username', 'password']);

입력값이 존재하는지 확인하기

Request에 어떤 값이 존재하는지 확인하기 위해서 has 메소드를 사용해야 합니다. has 메소드는 현재 request 에서 값이 존재할 때 true를 반환합니다:

if ($request->has('name')) {
    //
}

has 메소드에 배열이 주어지면, 지정된 모든 값이 존재하는지 확인하게 됩니다:

if ($request->has(['name', 'email'])) {
    //
}

주어진 변수값이 현재 request 에 존재하고 비어 있지 않은 것을 확인하려면 filled 메소드를 사용하면 됩니다:

if ($request->filled('name')) {
    //
}

이전 입력값 확인하기

라라벨은 한 request의 입력을 다음 request 중에도 유지할 수 있도록 해줍니다. 이 기능은 특히 유효성 검사 오류를 감지한 후 폼을 다시 채워 넣을 때 유용합니다. 하지만 라라벨에 포함된 유효성 검사 기능를 이용한다면 몇몇 유효성 검사 기능들이 자동으로 이 기능을 호출하기 때문에 수동으로 이 메소드들을 사용해야 할 가능성은 낮습니다.

입력값을 세션에 임시 저장하기

Illuminate\Http\Request 클래스의 flash 메소드는 현재의 입력들을 세션에 저장하여, 사용자의 다음 request 동안에도 값을 사용할 수 있게 해줍니다:

$request->flash();

flashOnlyflashExcept 메소드를 이용하여 request 데이터의 일부분을 세션에 임시 저장(flash)할 수 있습니다. 이 메소드들은 패스워드와 같은 민감한 정보들을 세션에 포함하지 않도록 하는데 유용합니다:

$request->flashOnly(['username', 'email']);

$request->flashExcept('password');

입력값을 임시저장한 후 리다이렉트하기

대부분 입력값을 세션에 임시 저장 하고 이전 페이지로 리다이렉트 하기를 원하기 때문에, 이를 위해 리다이렉트와 함께 입력값 임시 저장을 메소드 체이닝으로 사용할 수 있습니다.

return redirect('form')->withInput();

return redirect('form')->withInput(
    $request->except('password')
);

이전 입력값 조회하기

이전 request 에서 저장된 입력값을 조회하기 위해서는 Request 인스턴스의 old 메소드를 사용하면 됩니다. old 메소드는 세션에 저장된 입력 데이터를 꺼낼 것입니다:

$username = $request->old('username');

라라벨은 글로벌 old 헬퍼 함수도 제공합니다. 블레이드 템플릿 안에서 지난 입력값을 보여주려면 old 헬퍼 함수를 사용하는 것이 보다 편리합니다. 주어진 필드에 대한 이전 입력값이 존재하지 않는다면, null 이 반환될 것입니다:

<input type="text" name="username" value="{{ old('username') }}">

쿠키

Request 에서 쿠키 조회하기

라라벨 프레임워크에서 생성된 모든 쿠키는 인증 코드와 함께 암호화 됩니다. 이 것은 클라이언트가 변경되었을 때는, 쿠키가 유효하지 않다는 것을 의미합니다. Request에서 쿠키 값을 가져오기 위해서는 Illuminate\Http\Request 인스턴스에서 cookie 메소드를 사용하십시오:

$value = $request->cookie('name');

또한, 쿠키에 엑세스 하기 위해서 Cookie 파사드를 사용할 수 있습니다:

$value = Cookie::get('name');

쿠키를 Response 에 추가하기

외부로 나가는 Illuminate\Http\Response인스턴스에 cookie 메소드를 사용하여 쿠키를 추가할 수 있습니다. 메소드에는 이름과 값 그리고 쿠키가 얼마나 유효한지 결정하는 분단위의 값이 전달되어야 합니다:

return response('Hello World')->cookie(
    'name', 'value', $minutes
);

cookie 메소드는 또한 자주 사용되지 않는 몇가지 인자를 더 받아들입니다. 일반적으로 이 인자들은 PHP의 내장된 setcookie 메소드에 제공되는 인자들과 동일한 목적과 의미가 있습니다:

return response('Hello World')->cookie(
    'name', 'value', $minutes, $path, $domain, $secure, $httpOnly
);

또는, Cookie 파사드를 애플리케이션의 응답에 쿠키를 추가하기 위해서 "queue"할 수 있습니다. queue 메소드는 Cookie 인스턴스나 Cookie 인스턴스를 생성하는데 필요한 인자를 받습니다. 이 쿠키는 응답이 브라우저로 보내지기 전에 추가됩니다:

Cookie::queue(Cookie::make('name', 'value', $minutes));

Cookie::queue('name', 'value', $minutes);

쿠키 인스턴스 생성하기

나중에 response 인스턴스에 넣을 수 있는 Symfony\Component\HttpFoundation\Cookie인스턴스를 생성하려면, 글로벌 cookie 헬퍼 함수를 사용할 수 있습니다. 이 쿠키는 response 인스턴스에 첨부하지 않는 한 클라이언트에게 다시 보내지지 않습니다:

$cookie = cookie('name', 'value', $minutes);

return response('Hello World')->cookie($cookie);

파일처리

업로드된 파일 조회하기

Illuminate\Http\Request 인스턴스에서 file 메소드를 사용하거나 동적 속성을 사용하여 업로드된 파일에 엑세스 할 수 있습니다. file 메소드는 PHP SplFileInfo클래스를 상속한 Illuminate\Http\UploadedFile 클래스의 인스턴스를 반환하고 파일과 상호작용할 수 있는 다양한 메소드를 제공합니다:

$file = $request->file('photo');

$file = $request->photo;

hasFile 메소드를 사용하면 request에 파일을 가지고 있는지 확인할 수 있습니다:

if ($request->hasFile('photo')) {
    //
}

성공적으로 업로드 되었는지 확인하기

파일이 현재 존재하는지 확인하는데 더하여, isValid 메소드를 사용하여 업로드된 파일에 아무런 문제가 없는지 확인할 수 있습니다:

if ($request->file('photo')->isValid()) {
    //
}

파일 경로 & 확장자

UploadedFile 클래스는 파일의 전체 경로와 확장자에 엑세스 할 수 있는 메소드를 가지고 있습니다. extension 메소드는 그 내용에 따라 파일의 확장자를 추측하려고 시도합니다. 이 확장자는 클라이언트가 제공 한 확장자와는 다를 수 있습니다:

$path = $request->photo->path();

$extension = $request->photo->extension();

기타 파일 관련 메소드들

UploadedFile 인스턴스에 다양한 다른 메소드들이 제공되어 있습니다. 이 메소드들에 대해 더 많은 정보를 얻으려면 클래스의 API documentation을 확인해보십시오.

업로드된 파일 저장하기

업로드된 파일을 저장하려면, 일반적으로 설정된 파일시스템중 하나를 사용합니다. UploadedFile 클래스는 업로드된 파일을 로컬 파일 시스템이나 아마존 S3 와 같은 클라우드 스토리지 디스크 중에 하나로 이동 시킬 수 있는 store 메소드를 가지고 있습니다.

store 메소드는 파일 시스템에 구성된 루트 디렉토리로 부터 파일이 어디에 저장되어야 할지에 대한 경로를 전달 받습니다. 파일의 이름은 자동으로 고유한 ID로 생성되므로 이 경로에는 파일 이름을 포함하지 않아야 합니다.

store 메소드는 선택적으로 파일이 저장되는데 사용될 디스크 이름을 두번째 인자로 전달 받습니다. 메소드는 디스크의 루트를 기준으로 파일의 경로를 반환합니다:

$path = $request->photo->store('images');

$path = $request->photo->store('images', 's3');

파일 이름이 자동으로 생성되지 않기를 원한다면, 경로와, 파일이름 그리고 디스크 이름을 인자로 받아 들이는 storeAs 메소드를 사용할 수 있습니다:

$path = $request->photo->storeAs('images', 'filename.jpg');

$path = $request->photo->storeAs('images', 'filename.jpg', 's3');

신뢰할 수 있는 프록시 설정하기

TLS / SSL 인증서가 적용된 로드 밸런서 뒤에서 애플리케이션을 실행할 때 애플리케이션에서 HTTPS 링크가 생성되지 않는 경우가 있습니다. 일반적으로 이는 애플리케이션이 포트 80의 로드 밸런서에서 전송되는 트래픽뒤에 위치해서, HTTPS 링크를 생성해야 한다는 것을 알지 못하기 때문입니다.

이 문제를 해결하기 위해서, 라라벨 애플리케이션에는 App\Http\Middleware\TrustProxies 미들웨어를 사용하여 손쉽게 애플리케이션에서 신뢰할 수 있는 로드밸런서 또는 프록시를 설정할 수 있습니다. 신뢰할 수 있는 프록시들은 이 미들웨어의 $proxies 속성 배열에 지정해놓으면 됩니다. 신뢰할 수 있는 프록시를 구성하는 것 이외에도 신뢰해야 하는 프록시 헤더를 설정 할 수 있습니다:

<?php

namespace App\Http\Middleware;

use Illuminate\Http\Request;
use Fideloper\Proxy\TrustProxies as Middleware;

class TrustProxies extends Middleware
{
    /**
     * The trusted proxies for this application.
     *
     * @var array
     */
    protected $proxies = [
        '192.168.1.1',
        '192.168.1.2',
    ];

    /**
     * The headers that should be used to detect proxies.
     *
     * @var string
     */
    protected $headers = Request::HEADER_X_FORWARDED_ALL;
}

{팁} 만약 여러분이 AWS Elastic 로드 발란싱을 사용하고 있다면, 여러분의 $headers 값은 Request::HEADER_X_FORWARDED_AWS_ELB이 되어야 합니다. $headers에 사용될 수 있는 상수에 대한 다른 정보는, Symfony 문서의 trusting proxies를 참고하십시오.

모든 프록시 신뢰하기

아마존 AWS 또는 다른 "클라우드" 로드밸런서를 사용하는 경우에는, 실제 로드밸런서의 IP를 알 수가 없습니다. 이 경우, 모든 프록시를 신뢰할 수 있도록 하기 위해서 * 를 사용할 수 있습니다:

/**
 * The trusted proxies for this application.
 *
 * @var array
 */
protected $proxies = '*';