평범한 이야기들

[TIL] PHP Laravel - 요청,응답,미들웨어 본문

평범한 개발 이야기/Laravel

[TIL] PHP Laravel - 요청,응답,미들웨어

songsariya 2021. 3. 5. 18:41
728x90

라라벨 요청 생명주기

라라벨은 들어오는 모든 요청을 즉시 일루미네이트 요청 객체로 변경

 

 

애플리케이션 부트스트랩하기

Apache의 .htaccess 파일이나 Nginx의 서버 설정을 통해 URL에 상관없이 public/index.php 로 보내게 함

index.php 에서는 3가지 주요 기능이 존재

  1. 컴포저가 관리하는 모든 의존성을 등록해주는 컴포저 오토로드 파일을 호출
  2. 애플리케이션 컨테이너를 만들고 서비스를 등록하는 부트스트랩 실행
  3. 커널 인스턴스를 만들고 현재 사용자의 웹 요청을 반영하는 요청 객체의 인스턴스를 만들어 커널이 처리하도록 넘겨줌

라라벨의 커널

  • 사용자의 요청을 받아 미들웨어에 전달, 예외 발생하면 알맞은 응답을 처리
  • 라우터로 전달해 등록된 라우터와 연결된 로직 처리
  • 클로저나 컨트롤러에서 반환되는 최종 응답을 클라이언트(주로 브라우저)에 전달
  • http, console 커널 2개 존재, 각 커널은 handle() 메서드를 가짐, 일루미네이트 요청 객체를 받고 응답 객체를 반환함

 

서비스 프로바이더

서비스 프로바이더는 애플리케이션의 핵심 기능을 다양한 부분으로 구분하여 부트스트랩하는 데 필요한 로직을 캡슐화한 클래스

ex) AuthServiceProvider는 라라벨 인증 시스템에 필요한 부트스트래핑 작업, RouteServiceProvider 는 라우팅 시스템에 필요한 부트스트래핑 작업

서비스 프로바이더는 boot(), register() 두가지 주요 메서드를 가짐, DeferrableProvider 인터페이스( 5.8 이상 ), $defer 속성( 5.7 이하 ) 를 사용 할 수 있음

register() : 서비스 프로바이더 부트스트래핑 되는 과정에서 제일 먼저 호출, 프로바이더가 제공하고자 하는 클래스의 인스턴스 생성 방법을 컨테이너에 등록하는 역활(바인딩을 등록한다),

boot() : 모든 서비스 프로바이더가 컨테이너에 바인딩 등록을 마친 뒤에 호출되는 메서드, 이벤트 리스너를 바인딩하거나 라우트를 정의하는 등 부트스트래핑이 완료된 애플리케이션에서 추가적으로 필요한 작업들을 boot() 에 담아서 처리 할 수 있음

서비스 프로바이더의 등록을 지연하고 싶으면 5.8 버전 이상에서는 DeferrableProvider 인터페이스를 구현, 5.7 이하에서는 protected $defer 속성에 true 값을 설정 그 후 서비스 프로바이더에 프로바이더가 제공하는 바인딩 목록을 반환하는 provides() 메서드 추가



요청 객체

라라벨에서 사용자의 요청을 나타내는 Illuminate\Http\Request 클래스는 심포니의 HttpFoundation\Request 클래스를 상속받아 라라벨 용으로 만듬

하나의 HTTP 요청에 관련된 모든 정보를 모아 하나의 객체로 표현, 손쉽게 조회하는 편리한 메서드 제공

 

라라벨에서 요청 객체 얻기

요청이 있을 때마다 내부적으로 요청 객체를 생성

  1. 컨테이너가 처리하는 생성자나 메서드에 요청 클래스를 타입힌트 하는 방법
  2. request() 글로벌 헬퍼 를 사용하는 방법
  3. 글로벌 메서드인 app() 를 사용하는 방법 (정규화된 클래스명, 단축 키워드 둘다 가능)
// 첫번째 방법
class PersonController extends Controller
{
    public function index(Request $request)
    {
        $allInput = $request->all();
    }
}

// 두번째 방법
$request = request();
$allInput = $request->all();
//또는
$allInput = request->all();

// 세번째 방법 
$request = app(Illuminate\Http\Reqeust::class);
$request = app('request);

 

기본정보 얻기 (가장많이 사용하는 것)

all() : 모든 입력을 배열로 반환

input(필드명) : 필드명에 해당되는 값 반환

only(필드명|[필드명배열]) : 지정된 필드명에 해당하는 사용자의 입력을 배열로 반환

except(필드명|[필드명배열]) : 지정된 필드명을 제외하고 사용자의 입력을 배열로 반환

exists(필드명) : 필드명에 해당하는 입력이 있는지 boolean 값 반환 (has() 는 exists의 별칭)

filled(필드명) : 필드명에 해당하는 입력이 있고, 값이 비어 있지 않은지 boolean 값 반환

json() : 페이지에 전달된 json이 있으면 parameterBag을 반환

json(키명) : 페이지에 전달된 json에서 주어진 키에 해당하는 값을 반환

 

사용자와 요청 상태 (많이 사용하는 것)

method() : 라우트에 접근하기 위해 사용된 메서드(POST, GET, DELETE) 를 반환

path() : 페이지에 도달하기 위해 사용한 경로 ( www.도메인.com/abc/def 일때 abc/def 를 반환)

url() : 페이지에 도달하기 위해 사용한 URL(도메인 포함)

is() : Str::is()를 사용해서 현재 페이지 요청이 주어진 문자열을 포함하는지 여부를 반환

ip() : 사용자의 IP 주소를 반환

header() : 헤더를 배열로 반환

server() : $_SERVER에 저장된 변수의 배열을 반환 (변수명을 넘겨주면 해당 값만 반환)

secure() : 페이지를 https로 불러왔는지 boolean 값으로 반환

wantsJson() : 요청이 Accept 헤더에 /json 콘텐츠 타입을 가지고 있는지 boolean 값으로 반환

isJson() : 요청이 Content-Type 헤더에 /json 콘텐츠 타입을 가지고 있는지 boolean 값으로 반환

accepts() : 요청이 주어진 콘텐츠 타입을 받아들이지는지를 boolean 값으로 반환

 

파일

file() : 모든 업로드된 파일을 배열로 반환 (키를 넘겨주면 키에 해당하는 파일만 반환)

allFiles() : 모든 업로드된 파일을 배열로 반환

hasFile() : 특정 키에 해당하는 파일이 업로드됐는지 boolean 값으로 반환

처리 방법은 추후에 확인

 

세션과 데이터 유지

flash() : 현재 요청의 사용자 입력을 플래시 (세션에 저장하되 다음 요청 이후 자동제거) 함

flashOnly() : 현재 요청의 사용자 입력 중 배열로 넘긴 키에 해당 하는 일부만 플래시함

flashExcept() : 현재 요청의 사용자 입력 중 배열로 넘긴 키에 해당하는 일부를 제외하고 플래시 함

old() : 이전에 플래시한 모든 사용자 입력 값을 배열로 반환 (키 지정 가능)

flush() : 이전에 플래시한 모든 사용자 입력을 제거

cookie() : 요청에서 모든 쿠키를 조회 (키 지정 가능)

hasCookie() : 키에 해당하는 쿠키가 있는지 boolean 값으로 반환

주로 사용자 입력 값의 유효성 검증이 실패한 경우에 사용



응답 객체

애플리케이션이 최종 사용자에게 전달하는 응답을 객체로 표현한 것

헤더, 쿠키, 콘텐츠, 그 외에 최종 사용자의 브라우저가 페이지를 만드는 데 사용하는 모든 정보를 포함

라우트에서 반환되는 모든 응답 객체는 HTTP 응답으로 반환

// 간단한 응답
Route::get('route', function() {
    return new Illuminate\Http\Response('Hello!');
});

//글로벌 함수 이용
Route::get('route', function() {
    return response('Hello!');
});

응답 객체를 만들고 콘텐츠 데이터를 넣어 반환

Route::get('route', function(){
    return response('Error!', 400)->header('X-Header-Name','header-value')
                                                                ->cookie('cookie-name','cookie-value');
});

 

맞품형 응답 타입

뷰 응답

글로벌 헬퍼인 view() 사용

Route::get('/', function(XmlGetterService $xml){
    $data = $xml->get();
    return response()
                    ->view('xml-structure', $data)
                    ->header('Content-Type','text/xml');
});

다운로드 응답

// 파일명, 저장될 때 사용할 이름, 헤더 배열
return response()->download('file.csv', 'export.csv', ['header' => 'value']);

// 다운로드 후 원본 파일 삭제 deleteFileAfterSend() 메서드 호출
return response()->download('file.csv', 'export.csv')->deleteFileAfterSend();

파일 응답

파일을 브라우저에서 보여준다는 것 제외하고 다운로드 응답과 비슷

// 파일명, 헤더 배열
return response()->file("./invoices/hello.pdf", ['header' => 'value']);

JSON 응답

json 응답은 데이터를 json_encode() 내장 함수를 사용하여 json으로 변환하고 헤더의 Contect-Type을 application/json 으로 설정

return reponse()->json(Contact::all());

리다이렉트 응답

다른페이지나 이전페이지로 다시 접속하게 함 보통 redirect() 헬퍼를 사용할 수 있는데 흔치 않지만 response() 헬퍼를 사용해서 리다이렉트 응답을 생성할 수도 있음

return redirect('account/payment');

커스텀 응답 매크로

매크로를 이용해 고유한 응답 타입을 만들 수 있음

//json() 과 동일하게 myJson 으로 커스텀 응답 매크로 만들기
class AppServiceProvider
{
    public function boot()
    {
        Response::macro("myJson", function ($contecnt) {
            return response(json_encode($content))->withHeaders(['Content-type' => 'application/json']);
        });
    }
}

// 사용법
return response()->myJson(['name' => 'Lisa Soo']);



라라벨과 미들웨어

대부분의 프레임워크에서 이 패턴을 구현하고 있음 (아마 AOP 개념과 같아보임)

미들웨어 자신이 확인 할 수 있는 정보로 요청을 조회해서 추가적인 작업을 한 후 핵심 로직을 실행 그리고 응답하기 전 미들웨어를 통과하면서 또 추가작업을 진행 할 수 있음 (그림 참조)

 

커스텀 미들웨어 만들기

// 미들웨어 생성
~ php artisan make:middleware BanIpMethod
// 기본 형태
class BanIpMethod
{
    public function handle($request, Closure $next)
    {

        // 미들웨어 요청 로직
        if($request->ip() == "192.168.1.1") {
            return response('금지된 IP 접근', 403);
        }

        // 다음 미들웨어에 전달
        $response =  $next($request);

        // 응답전에 처리
        $response->cookie('visited-our-site', true);

        // 미들웨어 종료
        return $response;
    }
}

 

미들웨어 등록

미들웨어 클래스를 작성하고 등록을 해주어야 사용할 수 있음

글로벌 미들웨어 등록

app/Http/Kernel.php 에 $middleware 배열에 추가

라우트 미들웨어 등록

app/Http/Kernel.php 에 $routeMiddleware 배열에 추가

이 미들웨어를 라우트 정의에 사용할 수 있음

Route::get('contacts', 'ContactController@index')->middleware('ban-delete');

Route::prefix('api')->middleware('ban-delete')->group(function (){
    // API 관련 모든 라우트
});

미들웨어 그룹 사용하기

미들웨어 그룹은 특정 상황에서 함께 사용하기 좋은 미들웨어를 미리 모아둔 것

 

미들웨어에 파라미터 넘기기

미들웨어에서 파라미터를 필요로 하는 경우 사용

// member, owner 값을 넝기는 방법
Route::get('company', function() {
    return view('company.admin');
})->middleware('auth:owner');

// 파라미터를 받는 라우트 미들웨어 정의
public function handle($request, $next, $role)
{
    if(auth()->check() && auth()->user()->hasRole($role)) {
        return $next($request);
    }

    return redirect('login');
}

// 2개 이상 넘길때 쉼표(,)로 구분
Route::get('company', function() {
    return view('company.admin');
})->middleware('auth:owner,view');



신뢰할 수 있는 프록시

라라벨에는 신뢰할 수 있는 프록시 기능이 내장되어있음

App\Http\Middleware\TrustProxies 미들웨어의 $proxies 배열에 신뢰할 수 있는 로드 밸런서나 프록시의 IP 를 추가하고 모든 X_FORWAREDED 헤더를 적용할 것인가 아니면 일부만 적용 할 것인가 결정 가능

//TrustProxies

// 신뢰할 수 있는 프록시
protected $proxies = [
    '192.168.1.1',
    '192.168.1.2',
];

//프록시를 감지하는 데 사용하는 헤더
protected $headers = Request::HEADER_X_FORWARED_ALL;
728x90
Comments