URL 생성
업데이트됨번역일: 2026년 6월 20일
이 페이지는 원문이 업데이트되어 번역이 갱신되었습니다.
- 원문 수정
- 2026년 6월 20일
- 번역 갱신
- 2026년 6월 20일
URL 생성
소개
Laravel은 애플리케이션 내에서 URL을 생성할 때 유용한 여러 헬퍼를 제공합니다. 이 헬퍼들은 템플릿이나 API 응답에서 링크를 만들 때, 또는 애플리케이션의 다른 영역으로 리다이렉트 응답을 생성할 때 특히 도움이 됩니다.
기본 사용법
URL 생성하기
url 헬퍼를 사용하면 애플리케이션의 임의 URL을 생성할 수 있습니다. 생성된 URL은 현재 처리 중인 요청의 스킴(HTTP 또는 HTTPS)과 호스트를 자동으로 사용합니다.
$post = App\Models\Post::find(1);
echo url("/posts/{$post->id}");
// http://example.com/posts/1쿼리 스트링 파라미터를 포함한 URL을 생성하려면 query 메서드를 사용하세요.
echo url()->query('/posts', ['search' => 'Laravel']);
// https://example.com/posts?search=Laravel
echo url()->query('/posts?sort=latest', ['search' => 'Laravel']);
// http://example.com/posts?sort=latest&search=Laravel경로에 이미 존재하는 쿼리 스트링 파라미터와 동일한 키를 전달하면, 기존 값이 덮어씌워집니다.
echo url()->query('/posts?sort=latest', ['sort' => 'oldest']);
// http://example.com/posts?sort=oldest배열 값도 쿼리 파라미터로 전달할 수 있습니다. 이 경우 키와 값이 올바르게 인코딩된 URL이 생성됩니다.
echo $url = url()->query('/posts', ['columns' => ['title', 'body']]);
// http://example.com/posts?columns%5B0%5D=title&columns%5B1%5D=body
echo urldecode($url);
// http://example.com/posts?columns[0]=title&columns[1]=body현재 URL 접근하기
url 헬퍼에 경로를 전달하지 않으면 Illuminate\Routing\UrlGenerator 인스턴스가 반환되며, 이를 통해 현재 URL 정보를 조회할 수 있습니다.
// 쿼리 스트링을 제외한 현재 URL
echo url()->current();
// 쿼리 스트링을 포함한 현재 URL
echo url()->full();이 메서드들은 URL 파사드를 통해서도 동일하게 사용할 수 있습니다.
use Illuminate\Support\Facades\URL;
echo URL::current();이전 URL 접근하기
사용자가 이전에 방문했던 URL을 알아야 할 경우, url 헬퍼의 previous 및 previousPath 메서드를 사용하세요.
// 이전 요청의 전체 URL
echo url()->previous();
// 이전 요청의 경로(path)만
echo url()->previousPath();또는 세션을 통해 이전 URL을 Fluent URI 인스턴스로 가져올 수도 있습니다.
use Illuminate\Http\Request;
Route::post('/users', function (Request $request) {
$previousUri = $request->session()->previousUri();
// ...
});이전에 방문한 URL의 라우트 이름도 세션을 통해 조회할 수 있습니다.
$previousRoute = $request->session()->previousRoute();이름 있는 라우트 URL
route 헬퍼를 사용하면 이름 있는 라우트의 URL을 생성할 수 있습니다. 이름 있는 라우트를 사용하면 실제 URL 경로가 아닌 라우트 이름을 기준으로 URL을 생성하기 때문에, 나중에 URL이 변경되더라도 route 함수를 호출하는 코드를 수정할 필요가 없습니다.
예를 들어, 다음과 같은 라우트가 있다고 가정해 봅시다.
Route::get('/post/{post}', function (Post $post) {
// ...
})->name('post.show');이 라우트의 URL은 다음과 같이 생성합니다.
echo route('post.show', ['post' => 1]);
// http://example.com/post/1여러 파라미터를 가진 라우트도 동일하게 처리할 수 있습니다.
Route::get('/post/{post}/comment/{comment}', function (Post $post, Comment $comment) {
// ...
})->name('comment.show');
echo route('comment.show', ['post' => 1, 'comment' => 3]);
// http://example.com/post/1/comment/3라우트 정의에 없는 추가 파라미터는 자동으로 쿼리 스트링에 추가됩니다.
echo route('post.show', ['post' => 1, 'search' => 'rocket']);
// http://example.com/post/1?search=rocketEloquent 모델
URL을 생성할 때 Eloquent 모델을 파라미터로 직접 전달할 수 있습니다. route 헬퍼는 모델의 라우트 키(기본적으로 기본 키)를 자동으로 추출해 사용합니다.
echo route('post.show', ['post' => $post]);서명된 URL
Laravel은 이름 있는 라우트에 대해 "서명된(signed)" URL을 쉽게 생성할 수 있습니다. 서명된 URL은 쿼리 스트링에 signature 해시가 추가되어, URL이 생성된 이후 변조되지 않았음을 Laravel이 검증할 수 있게 해줍니다.
서명된 URL은 공개적으로 접근 가능하지만 URL 조작을 방지해야 하는 경우에 유용합니다. 예를 들어, 이메일로 발송하는 수신 거부(unsubscribe) 링크나 인증 링크에 적합합니다.
URL 파사드의 signedRoute 메서드로 서명된 URL을 생성합니다.
use Illuminate\Support\Facades\URL;
return URL::signedRoute('unsubscribe', ['user' => 1]);서명 해시에서 도메인을 제외하려면 absolute 인수를 false로 전달하세요.
return URL::signedRoute('unsubscribe', ['user' => 1], absolute: false);일정 시간이 지나면 만료되는 임시 서명 URL이 필요하다면 temporarySignedRoute 메서드를 사용하세요. Laravel은 임시 서명 URL을 검증할 때 URL에 인코딩된 만료 타임스탬프도 함께 확인합니다.
use Illuminate\Support\Facades\URL;
return URL::temporarySignedRoute(
'unsubscribe', now()->plus(minutes: 30), ['user' => 1]
);서명된 URL 요청 검증하기
들어온 요청에 유효한 서명이 있는지 확인하려면 Illuminate\Http\Request 인스턴스의 hasValidSignature 메서드를 호출하세요.
use Illuminate\Http\Request;
Route::get('/unsubscribe/{user}', function (Request $request) {
if (! $request->hasValidSignature()) {
abort(401);
}
// ...
})->name('unsubscribe');클라이언트 측 페이지네이션처럼 프론트엔드에서 서명된 URL에 파라미터를 추가해야 하는 경우, hasValidSignatureWhileIgnoring 메서드로 검증 시 무시할 파라미터를 지정할 수 있습니다. 단, 무시된 파라미터는 누구나 수정할 수 있다는 점에 유의하세요.
if (! $request->hasValidSignatureWhileIgnoring(['page', 'order'])) {
abort(401);
}요청 인스턴스를 직접 사용하는 대신, 라우트에 signed 미들웨어(Illuminate\Routing\Middleware\ValidateSignature)를 지정할 수도 있습니다. 유효한 서명이 없는 요청은 미들웨어가 자동으로 403 HTTP 응답을 반환합니다.
Route::post('/unsubscribe/{user}', function (Request $request) {
// ...
})->name('unsubscribe')->middleware('signed');서명된 URL의 해시에 도메인이 포함되지 않은 경우, 미들웨어에 relative 인수를 전달하세요.
Route::post('/unsubscribe/{user}', function (Request $request) {
// ...
})->name('unsubscribe')->middleware('signed:relative');유효하지 않은 서명 URL에 대한 응답 커스터마이징
만료된 서명 URL에 접근하면 기본적으로 403 HTTP 상태 코드의 일반 에러 페이지가 표시됩니다. 이 동작을 커스터마이징하려면 bootstrap/app.php 파일에서 InvalidSignatureException 예외에 대한 커스텀 렌더 클로저를 정의하세요.
use Illuminate\Routing\Exceptions\InvalidSignatureException;
->withExceptions(function (Exceptions $exceptions): void {
$exceptions->render(function (InvalidSignatureException $e) {
return response()->view('errors.link-expired', status: 403);
});
})컨트롤러 액션 URL
action 함수를 사용하면 특정 컨트롤러 액션에 대한 URL을 생성할 수 있습니다.
use App\Http\Controllers\HomeController;
$url = action([HomeController::class, 'index']);컨트롤러 메서드가 라우트 파라미터를 받는 경우, 두 번째 인수로 파라미터 배열을 전달하세요.
$url = action([UserController::class, 'profile'], ['id' => 1]);Fluent URI 객체
Laravel의 Uri 클래스는 URI를 객체 방식으로 편리하게 생성하고 조작할 수 있는 유연한 인터페이스를 제공합니다. 내부적으로 League URI 패키지를 감싸며, Laravel의 라우팅 시스템과도 자연스럽게 통합됩니다.
정적 메서드를 통해 Uri 인스턴스를 간단하게 생성할 수 있습니다.
use App\Http\Controllers\UserController;
use App\Http\Controllers\InvokableController;
use Illuminate\Support\Uri;
// 문자열로부터 URI 인스턴스 생성
$uri = Uri::of('https://example.com/path');
// 경로, 이름 있는 라우트, 컨트롤러 액션 등으로 URI 생성
$uri = Uri::to('/dashboard');
$uri = Uri::route('users.show', ['user' => 1]);
$uri = Uri::signedRoute('users.show', ['user' => 1]);
$uri = Uri::temporarySignedRoute('user.index', now()->plus(minutes: 5));
$uri = Uri::action([UserController::class, 'index']);
$uri = Uri::action(InvokableController::class);
// 현재 요청 URL로부터 URI 인스턴스 생성
$uri = $request->uri();
// 이전 요청 URL로부터 URI 인스턴스 생성
$uri = $request->session()->previousUri();URI 인스턴스를 생성한 후에는 메서드 체이닝으로 유연하게 수정할 수 있습니다.
$uri = Uri::of('https://example.com')
->withScheme('http')
->withHost('test.com')
->withPort(8000)
->withPath('/users')
->withQuery(['page' => 2])
->withFragment('section-1');Fluent URI 객체에 대한 더 자세한 내용은 URI 문서를 참고하세요.
기본값 설정
일부 애플리케이션에서는 특정 URL 파라미터에 대해 요청 전반에 걸친 기본값을 지정하고 싶을 수 있습니다. 예를 들어 많은 라우트가 {locale} 파라미터를 포함하는 경우를 생각해 보세요.
Route::get('/{locale}/posts', function () {
// ...
})->name('post.index');route 헬퍼를 호출할 때마다 locale을 매번 전달하는 것은 번거롭습니다. 이럴 때 URL::defaults 메서드로 현재 요청 동안 항상 적용될 기본값을 정의할 수 있습니다. 현재 요청에 접근하기 위해 라우트 미들웨어 안에서 이 메서드를 호출하는 것이 좋습니다.
<?php
namespace App\Http\Middleware;
use Closure;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\URL;
use Symfony\Component\HttpFoundation\Response;
class SetDefaultLocaleForUrls
{
/**
* 요청을 처리합니다.
*
* @param \Closure(\Illuminate\Http\Request): (\Symfony\Component\HttpFoundation\Response) $next
*/
public function handle(Request $request, Closure $next): Response
{
URL::defaults(['locale' => $request->user()->locale]);
return $next($request);
}
}locale 파라미터의 기본값이 설정된 이후에는 route 헬퍼로 URL을 생성할 때 해당 값을 별도로 전달하지 않아도 됩니다.
URL 기본값과 미들웨어 우선순위
URL 기본값 설정은 Laravel의 암시적 모델 바인딩 처리와 충돌할 수 있습니다. 따라서 URL 기본값을 설정하는 미들웨어는 Laravel 자체의 SubstituteBindings 미들웨어보다 먼저 실행되도록 우선순위를 지정해야 합니다. bootstrap/app.php 파일에서 prependToPriorityList 메서드를 사용하세요.
->withMiddleware(function (Middleware $middleware): void {
$middleware->prependToPriorityList(
before: \Illuminate\Routing\Middleware\SubstituteBindings::class,
prepend: \App\Http\Middleware\SetDefaultLocaleForUrls::class,
);
})