본문 바로가기

URL 생성

업데이트됨

번역일: 2026년 10월 22일

이 페이지는 원문이 업데이트되어 번역이 갱신되었습니다.

원문 수정
2026년 10월 17일
번역 갱신
2026년 10월 22일

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 인코딩되어 생성된 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을 가져올 수 있습니다.

// 이전 요청의 전체 URL을 가져옵니다... echo url()->previous(); // 이전 요청의 경로를 가져옵니다... 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을 만들려면 다음과 같이 route 헬퍼를 사용합니다.

echo route('post.show', ['post' => 1]); // http://example.com/post/1

물론 route 헬퍼는 파라미터가 여러 개인 라우트의 URL도 만들 수 있습니다.

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

라우트 정의의 파라미터와 대응하지 않는 배열 요소는 URL의 쿼리 문자열로 추가됩니다.

echo route('post.show', ['post' => 1, 'search' => 'rocket']); // http://example.com/post/1?search=rocket

Eloquent 모델

URL을 만들 때는 Eloquent 모델의 라우트 키(보통 기본 키)를 사용하는 경우가 많습니다. 그래서 파라미터 값으로 Eloquent 모델을 그대로 전달할 수 있으며, route 헬퍼가 모델의 라우트 키를 자동으로 추출합니다.

echo route('post.show', ['post' => $post]);

서명된 URL

Laravel에서는 이름이 지정된 라우트에 대해 "서명된(signed)" URL을 손쉽게 만들 수 있습니다. 서명된 URL은 쿼리 문자열 끝에 "서명" 해시가 붙으며, Laravel은 이 해시를 통해 URL이 생성된 이후 변조되지 않았음을 검증할 수 있습니다. 서명된 URL은 누구나 접근할 수 있는 공개 라우트이면서도 URL 조작을 막을 최소한의 보호 장치가 필요한 경우에 특히 유용합니다.

예를 들어 고객에게 이메일로 보내는 공개 "수신 거부(unsubscribe)" 링크를 서명된 URL로 구현할 수 있습니다. 이름이 지정된 라우트에 대한 서명된 URL은 URL 파사드의 signedRoute 메서드로 만듭니다.

use Illuminate\Support\Facades\URL; return URL::signedRoute('unsubscribe', ['user' => 1]);

signedRoute 메서드에 absolute 인자를 지정하면 서명된 URL의 해시 계산에서 도메인을 제외할 수 있습니다.

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] );

서명된 라우트 요청 검증하기

들어온 요청에 유효한 서명이 있는지 확인하려면, 수신한 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');

WARNING

서명은 URL의 경로와 쿼리 문자열만을 대상으로 합니다. 폼이나 JSON 요청 본문 같은 그 밖의 요청 입력값은 서명되지 않으므로 사용자가 마음대로 수정할 수 있습니다. Laravel은 이러한 입력 소스를 하나로 병합하고, 요청 본문이 쿼리 문자열보다 우선하도록 처리합니다. 따라서 input, all, 동적 요청 프로퍼티처럼 query 이외의 방법으로 입력값을 가져오면, 서명되지 않은 값이 서명된 쿼리 문자열 값을 덮어쓴 채 반환될 수 있습니다. 그러므로 서명된 값은 항상 $request->query('email')처럼 query 메서드로 가져와야 합니다. 이는 GET 요청에도 해당됩니다. 특별히 조작된 GET 요청에도 JSON 요청 본문이 포함될 수 있기 때문입니다.

유효하지 않은 서명 라우트에 응답하기

만료된 서명된 URL에 접근하면 403 HTTP 상태 코드에 해당하는 기본 오류 페이지가 표시됩니다. 이 동작을 바꾸고 싶다면 애플리케이션의 bootstrap/app.php 파일에서 InvalidSignatureException 예외에 대한 커스텀 "render" 클로저를 정의하면 됩니다.

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를 객체로 만들고 조작할 수 있는 편리한 fluent 인터페이스를 제공합니다. 이 클래스는 내부적으로 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 { /** * Handle an incoming request. * * @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 파일에서 priority 관련 미들웨어 메서드를 사용하면 됩니다.

->withMiddleware(function (Middleware $middleware): void { $middleware->prependToPriorityList( before: \Illuminate\Routing\Middleware\SubstituteBindings::class, prepend: \App\Http\Middleware\SetDefaultLocaleForUrls::class, ); })

이 문서는 Laravel 공식 문서(MIT)를 한국 개발자를 위해 번역·재구성한 것입니다.

번역일: 2026년 10월 22일