> ## Documentation Index
> Fetch the complete documentation index at: https://kawax.biz/llms.txt
> Use this file to discover all available pages before exploring further.

# URL 생성

> Laravel의 url() 헬퍼, 이름 지정 라우트 URL, 서명된 URL, 컨트롤러 액션 URL 생성 방법을 설명합니다.

## 소개

Laravel은 애플리케이션의 URL을 생성하기 위한 몇 가지 헬퍼를 제공합니다.
이 헬퍼들은 템플릿이나 API 응답에서 링크를 구축할 때, 또는 애플리케이션의 다른 곳으로 리다이렉트 응답을 생성할 때 특히 편리합니다.

## 기본 사용법

### URL 생성

`url` 헬퍼를 사용해 임의의 URL을 생성할 수 있습니다.
생성된 URL은 애플리케이션이 처리하고 있는 현재 요청의 스킴(HTTP 또는 HTTPS)과 호스트를 자동으로 사용합니다.

```php theme={null}
$post = App\Models\Post::find(1);

echo url("/posts/{$post->id}");

// http://example.com/posts/1
```

쿼리 문자열 파라미터를 포함하는 URL을 생성하려면 `query` 메서드를 사용합니다.

```php theme={null}
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
```

경로에 이미 존재하는 쿼리 문자열 파라미터를 지정하면 기존 값이 덮어써집니다.

```php theme={null}
echo url()->query('/posts?sort=latest', ['sort' => 'oldest']);

// http://example.com/posts?sort=oldest
```

배열 값도 쿼리 파라미터로 전달할 수 있습니다. 이 값들은 적절히 키가 부여되어 생성된 URL에 인코딩됩니다.

```php theme={null}
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에 관한 정보에 접근할 수 있습니다.

```php theme={null}
// 쿼리 문자열 없는 현재 URL
echo url()->current();

// 쿼리 문자열을 포함하는 현재 URL
echo url()->full();
```

이 메서드들은 `URL` [파사드](./facades)에서도 접근할 수 있습니다.

```php theme={null}
use Illuminate\Support\Facades\URL;

echo URL::current();
```

### 직전 URL 가져오기

사용자가 방문했던 직전의 URL을 알고 싶은 경우가 있습니다. `url` 헬퍼의 `previous` 메서드나 `previousPath` 메서드로 가져올 수 있습니다.

```php theme={null}
// 직전 요청의 완전한 URL
echo url()->previous();

// 직전 요청의 경로
echo url()->previousPath();
```

세션을 경유해 직전 URL을 가져올 수도 있습니다.

```php theme={null}
use Illuminate\Http\Request;

Route::post('/users', function (Request $request) {
    $previousUri = $request->session()->previousUri();

    // ...
});
```

직전에 방문한 URL의 라우트 이름을 세션을 경유해 가져올 수도 있습니다.

```php theme={null}
$previousRoute = $request->session()->previousRoute();
```

## 이름 지정 라우트의 URL

`route` 헬퍼는 [이름 지정 라우트](./routing#named-routes)로의 URL을 생성하는 데 사용할 수 있습니다.
이름 지정 라우트를 사용하면 라우트에 정의된 실제 URL에 의존하지 않고 URL을 생성할 수 있습니다.
따라서 라우트의 URL이 변경되어도 `route` 함수의 호출을 변경할 필요가 없습니다.

```php theme={null}
Route::get('/post/{post}', function (Post $post) {
    // ...
})->name('post.show');
```

이 라우트에 대한 URL을 생성하려면 다음과 같이 합니다.

```php theme={null}
echo route('post.show', ['post' => 1]);

// http://example.com/post/1
```

여러 파라미터를 가진 라우트에도 대응하고 있습니다.

```php theme={null}
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의 쿼리 문자열에 추가됩니다.

```php theme={null}
echo route('post.show', ['post' => 1, 'search' => 'rocket']);

// http://example.com/post/1?search=rocket
```

### Eloquent 모델

Eloquent 모델의 라우트 키(일반적으로 기본 키)를 사용해 URL을 생성하는 경우가 많을 것입니다.
그를 위해 Eloquent 모델을 파라미터 값으로 전달할 수 있습니다. `route` 헬퍼는 모델의 라우트 키를 자동으로 꺼냅니다.

```php theme={null}
echo route('post.show', ['post' => $post]);
```

### 서명된 URL

Laravel에서는 이름 지정 라우트로의 "서명된" URL을 간단하게 만들 수 있습니다.
이 URL들에는 쿼리 문자열에 "서명" 해시가 부가되어, URL이 만들어진 후 변조되지 않았는지를 Laravel이 검증할 수 있습니다.
서명된 URL은 공개적으로 접근 가능하지만 URL 조작에 대한 보호가 필요한 라우트에 특히 편리합니다.

예를 들어 고객에게 이메일로 전송하는 공개 "구독 해지" 링크를 구현하기 위해 서명된 URL을 사용할 수 있습니다.
`URL` 파사드의 `signedRoute` 메서드를 사용해 서명된 URL을 만듭니다.

```php theme={null}
use Illuminate\Support\Facades\URL;

return URL::signedRoute('unsubscribe', ['user' => 1]);
```

`signedRoute` 메서드에 `absolute` 인수를 지정함으로써 서명 URL 해시에서 도메인을 제외할 수 있습니다.

```php theme={null}
return URL::signedRoute('unsubscribe', ['user' => 1], absolute: false);
```

지정한 시간 후에 유효기간이 만료되는 일시적 서명된 URL을 생성하려면 `temporarySignedRoute` 메서드를 사용합니다.
Laravel은 일시적 서명된 URL을 검증할 때 서명된 URL에 인코딩된 유효기간 타임스탬프가 경과하지 않았는지 확인합니다.

```php theme={null}
use Illuminate\Support\Facades\URL;

return URL::temporarySignedRoute(
    'unsubscribe', now()->plus(minutes: 30), ['user' => 1]
);
```

#### 서명된 URL의 검증 플로우

```mermaid theme={null}
sequenceDiagram
    participant App as Laravel 앱
    participant User as 사용자
    participant Mail as 이메일
    App->>App: URL::signedRoute() / temporarySignedRoute()
    App->>Mail: 서명된 URL을 이메일로 전송
    Mail->>User: 이메일 수신
    User->>App: URL을 클릭(GET 요청)
    App->>App: 서명 검증<br>hasValidSignature()
    alt 서명이 유효
        App->>User: 처리 실행(예: 구독 해지)
    else 서명이 무효·만료
        App->>User: 403 오류
    end
```

#### 서명된 라우트 요청의 검증

수신 요청에 유효한 서명이 있는지 확인하려면 `Illuminate\Http\Request` 인스턴스의 `hasValidSignature` 메서드를 호출합니다.

```php theme={null}
use Illuminate\Http\Request;

Route::get('/unsubscribe/{user}', function (Request $request) {
    if (! $request->hasValidSignature()) {
        abort(401);
    }

    // ...
})->name('unsubscribe');
```

특정 쿼리 파라미터를 검증 시에 무시하고 싶은 경우에는 `hasValidSignatureWhileIgnoring` 메서드를 사용합니다.

```php theme={null}
if (! $request->hasValidSignatureWhileIgnoring(['page', 'order'])) {
    abort(401);
}
```

수신 요청 인스턴스를 사용하는 대신, `signed`(`Illuminate\Routing\Middleware\ValidateSignature`) [미들웨어](./middleware)를 라우트에 할당할 수도 있습니다.
수신 요청에 유효한 서명이 없는 경우 미들웨어는 자동으로 `403` HTTP 응답을 반환합니다.

```php theme={null}
Route::post('/unsubscribe/{user}', function (Request $request) {
    // ...
})->name('unsubscribe')->middleware('signed');
```

서명된 URL에 도메인이 포함되지 않는 경우에는 `relative` 인수를 미들웨어에 지정합니다.

```php theme={null}
Route::post('/unsubscribe/{user}', function (Request $request) {
    // ...
})->name('unsubscribe')->middleware('signed:relative');
```

#### 무효한 서명된 라우트로의 응답

유효 기간이 만료된 서명된 URL에 접근하면 `403` HTTP 상태 코드의 범용 오류 페이지가 표시됩니다.
애플리케이션의 `bootstrap/app.php` 파일에서 `InvalidSignatureException` 예외의 커스텀 "render" 클로저를 정의함으로써 이 동작을 커스터마이징할 수 있습니다.

```php theme={null}
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을 생성합니다.

```php theme={null}
use App\Http\Controllers\HomeController;

$url = action([HomeController::class, 'index']);
```

컨트롤러 메서드가 라우트 파라미터를 받는 경우, 함수의 두 번째 인수에 라우트 파라미터의 연관 배열을 전달합니다.

```php theme={null}
$url = action([UserController::class, 'profile'], ['id' => 1]);
```

## 플루언트 URI 객체

Laravel의 URI 클래스는 객체를 통해 URI를 생성·조작하기 위한 편리한 플루언트 인터페이스를 제공합니다.

```php theme={null}
use App\Http\Controllers\UserController;
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']);

// 현재 요청 URL에서 URI 인스턴스 생성
$uri = $request->uri();
```

URI 인스턴스를 획득한 후에는 플루언트하게 변경할 수 있습니다.

```php theme={null}
$uri = Uri::of('https://example.com')
    ->withScheme('http')
    ->withHost('test.com')
    ->withPort(8000)
    ->withPath('/users')
    ->withQuery(['page' => 2])
    ->withFragment('section-1');
```

## 기본 URL 파라미터

특정 URL 파라미터에 요청 전체의 기본값을 지정하고 싶은 경우가 있습니다.
예를 들어 많은 라우트에 `{locale}` 파라미터가 정의되어 있다고 합시다.

```php theme={null}
Route::get('/{locale}/posts', function () {
    // ...
})->name('post.index');
```

`route` 헬퍼를 호출할 때마다 `locale`을 전달하는 것은 번거롭습니다.
그래서 `URL::defaults` 메서드를 사용해 현재 요청 중에 항상 적용되는 이 파라미터의 기본값을 정의할 수 있습니다.
이 메서드는 [라우트 미들웨어](./middleware#assigning-middleware-to-routes)에서 호출하면 현재 요청에 접근할 수 있습니다.

```php theme={null}
<?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을 생성할 때 그 값을 전달할 필요가 없어집니다.

<Info>
  URL 기본값의 설정은 Laravel의 암묵적 모델 바인딩 처리를 방해하는 경우가 있습니다.
  URL 기본값을 설정하는 미들웨어를 Laravel 자체의 `SubstituteBindings` 미들웨어보다 먼저 실행되도록 [미들웨어의 우선순위 설정](./middleware#sorting-middleware)을 해 주세요.
  애플리케이션의 `bootstrap/app.php` 파일에서 `priority` 미들웨어 메서드를 사용해 설정할 수 있습니다.

  ```php theme={null}
  ->withMiddleware(function (Middleware $middleware): void {
      $middleware->prependToPriorityList(
          before: \Illuminate\Routing\Middleware\SubstituteBindings::class,
          prepend: \App\Http\Middleware\SetDefaultLocaleForUrls::class,
      );
  })
  ```
</Info>


## Related topics

- [라우팅](/ko/routing.md)
- [Laravel Sail](/ko/sail.md)
- [헬퍼 함수](/ko/helpers.md)
- [Laravel AI SDK](/ko/ai-sdk.md)
- [문자열 조작 (Str 클래스)](/ko/strings.md)
