Skip to content

HTTP 응답

응답 생성

문자열 및 배열

모든 라우트 및 컨트롤러는 사용자 브라우저로 다시 전송될 응답을 반환해야 합니다. 라라벨은 응답을 반환하는 여러 가지 다른 방법을 제공합니다. 가장 기본적인 응답은 라우트 또는 컨트롤러에서 문자열을 반환하는 것입니다. 프레임워크는 문자열을 전체 HTTP 응답으로 자동 변환합니다.

Route::get('/', function () {
return 'Hello World';
});

라우트 및 컨트롤러에서 문자열을 반환하는 것 외에도 배열을 반환할 수도 있습니다. 프레임워크는 배열을 JSON 응답으로 자동 변환합니다.

Route::get('/', function () {
return [1, 2, 3];
});
lightbulb

라우트 또는 컨트롤러에서 Eloquent 컬렉션을 반환할 수도 있다는 것을 알고 계셨나요? 이는 자동으로 JSON으로 변환됩니다. 한번 해보세요!

응답 객체

일반적으로 라우트 액션에서 간단한 문자열이나 배열만 반환하지는 않습니다. 대신 전체 Illuminate\Http\Response 인스턴스 또는 를 반환합니다.

전체 Response 인스턴스를 반환하면 응답의 HTTP 상태 코드 및 헤더를 사용자 정의할 수 있습니다. Response 인스턴스는 Symfony\Component\HttpFoundation\Response 클래스에서 상속되며, HTTP 응답을 구축하기 위한 다양한 메서드를 제공합니다.

Route::get('/home', function () {
return response('Hello World', 200)
->header('Content-Type', 'text/plain');
});

Eloquent 모델 및 컬렉션

Eloquent ORM 모델 및 컬렉션을 라우트 및 컨트롤러에서 직접 반환할 수도 있습니다. 이렇게 하면 라라벨은 모델의 숨겨진 속성을 준수하면서 모델 및 컬렉션을 JSON 응답으로 자동 변환합니다.

use App\Models\User;
 
Route::get('/user/{user}', function (User $user) {
return $user;
});

응답에 헤더 첨부

대부분의 응답 메서드는 체인 가능하여 응답 인스턴스를 유연하게 구성할 수 있습니다. 예를 들어 header 메서드를 사용하여 응답을 사용자에게 다시 보내기 전에 응답에 일련의 헤더를 추가할 수 있습니다.

return response($content)
->header('Content-Type', $type)
->header('X-Header-One', 'Header Value')
->header('X-Header-Two', 'Header Value');

또는 withHeaders 메서드를 사용하여 응답에 추가할 헤더 배열을 지정할 수 있습니다.

return response($content)
->withHeaders([
'Content-Type' => $type,
'X-Header-One' => 'Header Value',
'X-Header-Two' => 'Header Value',
]);

캐시 제어 미들웨어

라라벨에는 라우트 그룹에 대한 Cache-Control 헤더를 빠르게 설정하는 데 사용할 수 있는 cache.headers 미들웨어가 포함되어 있습니다. 지시어는 해당 캐시 제어 지시어의 "스네이크 케이스"에 해당하는 값을 사용하여 제공해야 하며 세미콜론으로 구분해야 합니다. 지시어 목록에 etag가 지정된 경우 응답 콘텐츠의 MD5 해시가 ETag 식별자로 자동 설정됩니다.

Route::middleware('cache.headers:public;max_age=2628000;etag')->group(function () {
Route::get('/privacy', function () {
// ...
});
 
Route::get('/terms', function () {
// ...
});
});

응답에 쿠키 첨부

cookie 메서드를 사용하여 나가는 Illuminate\Http\Response 인스턴스에 쿠키를 첨부할 수 있습니다. 이 메서드에 이름, 값, 쿠키가 유효한 것으로 간주되어야 하는 시간(분)을 전달해야 합니다.

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 메서드는 쿠키 인스턴스를 만드는 데 필요한 인수를 허용합니다. 이러한 쿠키는 브라우저로 전송되기 전에 나가는 응답에 첨부됩니다.

use Illuminate\Support\Facades\Cookie;
 
Cookie::queue('name', 'value', $minutes);

나중에 응답 인스턴스에 첨부할 수 있는 Symfony\Component\HttpFoundation\Cookie 인스턴스를 생성하려면 글로벌 cookie 도우미를 사용하면 됩니다. 이 쿠키는 응답 인스턴스에 첨부되지 않으면 클라이언트로 다시 전송되지 않습니다.

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

쿠키 조기 만료

나가는 응답의 withoutCookie 메서드를 통해 만료시켜 쿠키를 제거할 수 있습니다.

return response('Hello World')->withoutCookie('name');

아직 나가는 응답 인스턴스가 없는 경우 Cookie 파사드의 expire 메서드를 사용하여 쿠키를 만료할 수 있습니다.

Cookie::expire('name');

쿠키 및 암호화

기본적으로 Illuminate\Cookie\Middleware\EncryptCookies 미들웨어 덕분에 라라벨에서 생성된 모든 쿠키는 클라이언트가 수정하거나 읽을 수 없도록 암호화되고 서명됩니다. 애플리케이션에서 생성된 쿠키의 하위 집합에 대한 암호화를 비활성화하려면 애플리케이션의 bootstrap/app.php 파일에서 encryptCookies 메서드를 사용할 수 있습니다.

->withMiddleware(function (Middleware $middleware) {
$middleware->encryptCookies(except: [
'cookie_name',
]);
})

리디렉션

리디렉션 응답은 Illuminate\Http\RedirectResponse 클래스의 인스턴스이며, 사용자를 다른 URL로 리디렉션하는 데 필요한 적절한 헤더를 포함합니다. RedirectResponse 인스턴스를 생성하는 방법에는 여러 가지가 있습니다. 가장 간단한 방법은 글로벌 redirect 도우미를 사용하는 것입니다.

Route::get('/dashboard', function () {
return redirect('/home/dashboard');
});

때로는 제출된 양식이 유효하지 않은 경우와 같이 사용자를 이전 위치로 리디렉션할 수 있습니다. 글로벌 back 도우미 함수를 사용하여 그렇게 할 수 있습니다. 이 기능은 세션을 활용하므로 back 함수를 호출하는 라우트가 web 미들웨어 그룹을 사용하고 있는지 확인하세요.

Route::post('/user/profile', function () {
// 요청을 검증합니다...
 
return back()->withInput();
});

이름 있는 라우트로 리디렉션

매개변수 없이 redirect 도우미를 호출하면 Illuminate\Routing\Redirector의 인스턴스가 반환되어 Redirector 인스턴스에서 모든 메서드를 호출할 수 있습니다. 예를 들어 이름 있는 라우트에 대한 RedirectResponse를 생성하려면 route 메서드를 사용할 수 있습니다.

return redirect()->route('login');

라우트에 매개변수가 있는 경우 route 메서드의 두 번째 인수로 전달할 수 있습니다.

// 다음 URI가 있는 라우트의 경우: /profile/{id}
 
return redirect()->route('profile', ['id' => 1]);

Eloquent 모델을 통해 매개변수 채우기

Eloquent 모델에서 채워지는 "ID" 매개변수가 있는 라우트로 리디렉션하는 경우 모델 자체를 전달할 수 있습니다. ID는 자동으로 추출됩니다.

// 다음 URI가 있는 라우트의 경우: /profile/{id}
 
return redirect()->route('profile', [$user]);

라우트 매개변수에 배치되는 값을 사용자 지정하려면 라우트 매개변수 정의(/profile/{id:slug})에서 열을 지정하거나 Eloquent 모델에서 getRouteKey 메서드를 재정의할 수 있습니다.

/**
* 모델의 라우트 키 값을 가져옵니다.
*/
public function getRouteKey(): mixed
{
return $this->slug;
}

컨트롤러 액션으로 리디렉션

컨트롤러 액션으로 리디렉션을 생성할 수도 있습니다. 이렇게 하려면 컨트롤러 및 액션 이름을 action 메서드에 전달합니다.

use App\Http\Controllers\UserController;
 
return redirect()->action([UserController::class, 'index']);

컨트롤러 라우트에 매개변수가 필요한 경우 action 메서드의 두 번째 인수로 전달할 수 있습니다.

return redirect()->action(
[UserController::class, 'profile'], ['id' => 1]
);

외부 도메인으로 리디렉션

애플리케이션 외부의 도메인으로 리디렉션해야 할 수도 있습니다. 추가 URL 인코딩, 유효성 검사 또는 확인 없이 RedirectResponse를 생성하는 away 메서드를 호출하여 그렇게 할 수 있습니다.

return redirect()->away('https://www.google.com');

플래시된 세션 데이터와 함께 리디렉션

새 URL로 리디렉션하고 세션에 데이터 플래시는 일반적으로 동시에 수행됩니다. 일반적으로 성공 메시지를 세션에 플래시할 때 작업을 성공적으로 수행한 후에 수행됩니다. 편의를 위해 RedirectResponse 인스턴스를 만들고 단일 유연한 메서드 체인으로 세션에 데이터를 플래시할 수 있습니다.

Route::post('/user/profile', function () {
// ...
 
return redirect('/dashboard')->with('status', '프로필이 업데이트되었습니다!');
});

사용자를 리디렉션한 후 세션에서 플래시된 메시지를 표시할 수 있습니다. 예를 들어, Blade 구문을 사용하는 경우:

@if (session('status'))
<div class="alert alert-success">
{{ session('status') }}
</div>
@endif

입력과 함께 리디렉션

RedirectResponse 인스턴스에서 제공하는 withInput 메서드를 사용하여 사용자를 새 위치로 리디렉션하기 전에 현재 요청의 입력 데이터를 세션에 플래시할 수 있습니다. 일반적으로 사용자가 유효성 검사 오류가 발생한 경우에 수행됩니다. 입력이 세션에 플래시되면 다음 요청 중에 간단히 검색하여 양식을 다시 채울 수 있습니다.

return back()->withInput();

기타 응답 유형

response 도우미를 사용하여 다른 유형의 응답 인스턴스를 생성할 수 있습니다. response 도우미가 인수 없이 호출되면 Illuminate\Contracts\Routing\ResponseFactory 계약의 구현이 반환됩니다. 이 계약은 응답 생성을 위한 몇 가지 유용한 메서드를 제공합니다.

뷰 응답

응답의 상태 및 헤더를 제어해야 하지만 응답의 콘텐츠로 를 반환해야 하는 경우 view 메서드를 사용해야 합니다.

return response()
->view('hello', $data, 200)
->header('Content-Type', $type);

물론 사용자 지정 HTTP 상태 코드 또는 사용자 지정 헤더를 전달할 필요가 없는 경우 글로벌 view 도우미 함수를 사용할 수 있습니다.

JSON 응답

json 메서드는 Content-Type 헤더를 application/json으로 자동 설정하고, json_encode PHP 함수를 사용하여 지정된 배열을 JSON으로 변환합니다.

return response()->json([
'name' => 'Abigail',
'state' => 'CA',
]);

JSONP 응답을 만들려면 json 메서드를 withCallback 메서드와 함께 사용할 수 있습니다.

return response()
->json(['name' => 'Abigail', 'state' => 'CA'])
->withCallback($request->input('callback'));

파일 다운로드

download 메서드를 사용하여 사용자 브라우저가 지정된 경로에 있는 파일을 강제로 다운로드하도록 하는 응답을 생성할 수 있습니다. download 메서드는 메서드의 두 번째 인수로 파일 이름을 허용하며, 이는 파일을 다운로드하는 사용자가 보는 파일 이름을 결정합니다. 마지막으로 메서드의 세 번째 인수로 HTTP 헤더 배열을 전달할 수 있습니다.

return response()->download($pathToFile);
 
return response()->download($pathToFile, $name, $headers);
exclamation

파일 다운로드를 관리하는 Symfony HttpFoundation은 다운로드되는 파일에 ASCII 파일 이름이 필요합니다.

파일 응답

file 메서드를 사용하여 다운로드를 시작하는 대신 이미지 또는 PDF와 같은 파일을 사용자 브라우저에 직접 표시할 수 있습니다. 이 메서드는 파일의 절대 경로를 첫 번째 인수로 허용하고 헤더 배열을 두 번째 인수로 허용합니다.

return response()->file($pathToFile);
 
return response()->file($pathToFile, $headers);

스트리밍된 응답

생성되는 대로 클라이언트로 데이터를 스트리밍하면 특히 매우 큰 응답의 경우 메모리 사용량을 크게 줄이고 성능을 향상시킬 수 있습니다. 스트리밍된 응답을 사용하면 서버가 전송을 완료하기 전에 클라이언트가 데이터 처리를 시작할 수 있습니다.

function streamedContent(): Generator {
yield '안녕하세요, ';
yield '세계!';
}
 
Route::get('/stream', function () {
return response()->stream(function (): void {
foreach (streamedContent() as $chunk) {
echo $chunk;
ob_flush();
flush();
sleep(2); // 청크 사이의 지연을 시뮬레이션합니다...
}
}, 200, ['X-Accel-Buffering' => 'no']);
});
lightbulb

내부적으로 라라벨은 PHP의 출력 버퍼링 기능을 활용합니다. 위 예에서 볼 수 있듯이 ob_flushflush 함수를 사용하여 버퍼링된 콘텐츠를 클라이언트로 푸시해야 합니다.

스트리밍된 JSON 응답

JSON 데이터를 점진적으로 스트리밍해야 하는 경우 streamJson 메서드를 활용할 수 있습니다. 이 메서드는 JavaScript에서 쉽게 구문 분석할 수 있는 형식으로 브라우저에 점진적으로 전송해야 하는 대규모 데이터 세트에 특히 유용합니다.

use App\Models\User;
 
Route::get('/users.json', function () {
return response()->streamJson([
'users' => User::cursor(),
]);
});

스트리밍된 다운로드

때로는 주어진 작업의 문자열 응답을 디스크에 작업 내용을 쓸 필요 없이 다운로드 가능한 응답으로 변환할 수 있습니다. 이 시나리오에서는 streamDownload 메서드를 사용할 수 있습니다. 이 메서드는 콜백, 파일 이름 및 선택적 헤더 배열을 인수로 허용합니다.

use App\Services\GitHub;
 
return response()->streamDownload(function () {
echo GitHub::api('repo')
->contents()
->readme('laravel', 'laravel')['contents'];
}, 'laravel-readme.md');

응답 매크로

다양한 라우트 및 컨트롤러에서 재사용할 수 있는 사용자 지정 응답을 정의하려면 Response 파사드에서 macro 메서드를 사용할 수 있습니다. 일반적으로 App\Providers\AppServiceProvider 서비스 공급자와 같은 애플리케이션의 서비스 공급자 중 하나의 boot 메서드에서 이 메서드를 호출해야 합니다.

<?php
 
namespace App\Providers;
 
use Illuminate\Support\Facades\Response;
use Illuminate\Support\ServiceProvider;
 
class AppServiceProvider extends ServiceProvider
{
/**
* 모든 애플리케이션 서비스를 부트스트랩합니다.
*/
public function boot(): void
{
Response::macro('caps', function (string $value) {
return Response::make(strtoupper($value));
});
}
}

macro 함수는 첫 번째 인수로 이름, 두 번째 인수로 클로저를 허용합니다. 매크로의 클로저는 ResponseFactory 구현 또는 response 도우미에서 매크로 이름을 호출할 때 실행됩니다.

return response()->caps('foo');