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

# Laravel 11 이후의 애플리케이션 구조

> Laravel 11에서 도입된 Slim Application Skeleton의 전모와, Application::configure()에서 ApplicationBuilder까지의 내부 구현을 해설합니다.

## Laravel 10 이전과의 비교

Laravel 11에서는 "Slim Application Skeleton"으로서, 애플리케이션 구조가 대폭 쇄신되었습니다. 최대의 변화는, 설정의 분산을 없애고 `bootstrap/app.php` 한 곳으로 집약한 것입니다.

| 항목        | Laravel 10 이전                | Laravel 11 이후                 |
| --------- | ---------------------------- | ----------------------------- |
| HTTP 커널   | `app/Http/Kernel.php`        | 폐지(프레임워크 내에 통합)               |
| 콘솔 커널     | `app/Console/Kernel.php`     | 폐지(`routes/console.php`로 이관)  |
| 예외 핸들러    | `app/Exceptions/Handler.php` | 폐지(`bootstrap/app.php`에 집약)   |
| 서비스 프로바이더 | 5파일                          | `AppServiceProvider.php` 1파일  |
| 라우트 파일    | `web.php` / `api.php`가 기본    | `web.php`만 기본, `api.php`는 옵트인 |
| 부트스트랩     | 설정이 여러 파일에 분산                | `bootstrap/app.php`에 집약       |
| 기본 DB     | MySQL/PostgreSQL             | SQLite                        |

<Info>
  이 변경은 **신규 프로젝트용**입니다. 기존의 Laravel 10 애플리케이션을 업그레이드해도, 오래된 구조는 그대로 동작합니다.
</Info>

## 새로운 디렉토리·파일 구성

### 스켈레톤의 디렉토리 구성

```
laravel-app/
├── app/
│   ├── Http/
│   │   └── Controllers/
│   ├── Models/
│   │   └── User.php
│   └── Providers/
│       └── AppServiceProvider.php
├── bootstrap/
│   ├── app.php          ← アプリケーション設定の中心
│   ├── cache/
│   └── providers.php    ← サービスプロバイダー一覧
├── config/
├── database/
├── public/
│   └── index.php        ← エントリーポイント
├── resources/
├── routes/
│   ├── web.php          ← Webルート（デフォルト）
│   └── console.php      ← Artisanコマンドとスケジュール
├── storage/
└── tests/
```

### `bootstrap/app.php` — 앱 설정의 중심

```php theme={null}
<?php

use Illuminate\Foundation\Application;
use Illuminate\Foundation\Configuration\Exceptions;
use Illuminate\Foundation\Configuration\Middleware;

return Application::configure(basePath: dirname(__DIR__))
    ->withRouting(
        web: __DIR__.'/../routes/web.php',
        commands: __DIR__.'/../routes/console.php',
        health: '/up',
    )
    ->withMiddleware(function (Middleware $middleware): void {
        //
    })
    ->withExceptions(function (Exceptions $exceptions): void {
        //
    })->create();
```

이 파일 하나로, 라우팅·미들웨어·예외 핸들링을 설정할 수 있습니다. Laravel 10 이전에서는 `app/Http/Kernel.php`·`app/Console/Kernel.php`·`app/Exceptions/Handler.php`의 3파일에 분산되어 있던 설정이, 여기에 집약되어 있습니다.

### `bootstrap/providers.php` — 서비스 프로바이더 목록

```php theme={null}
<?php

use App\Providers\AppServiceProvider;

return [
    AppServiceProvider::class,
];
```

이 파일은 서비스 프로바이더의 등록처입니다. Laravel 10에서는 `config/app.php`의 `providers` 배열에 기술하고 있었지만, `bootstrap/providers.php`로 분리되었습니다. Laravel 11의 기본으로는 `AppServiceProvider`만입니다.

<Tip>
  `composer require`로 패키지를 설치하면, 그 패키지가 `bootstrap/providers.php`를 자동 갱신하는 경우가 있습니다. `config/app.php`는 참조되지 않게 된 것은 아니지만, 신규 등록은 `bootstrap/providers.php`가 권장 장소가 되었습니다.
</Tip>

### `routes/` 디렉토리의 변경

```
routes/
├── web.php      ← Webルート（デフォルトで読み込まれる）
└── console.php  ← Artisanコマンドとスケジュールを定義する
```

`api.php`와 `channels.php`는 기본으로는 존재하지 않습니다. 필요에 따라 Artisan 커맨드로 생성합니다.

```shell theme={null}
# APIルートを追加する（api.php + Sanctumをインストール）
php artisan install:api

# ブロードキャストを追加する（channels.php + Reverb などをインストール）
php artisan install:broadcasting
```

`routes/console.php`에서는 스케줄도 정의할 수 있습니다.

```php theme={null}
<?php

use Illuminate\Foundation\Inspiring;
use Illuminate\Support\Facades\Artisan;
use Illuminate\Support\Facades\Schedule;

Artisan::command('inspire', function () {
    $this->comment(Inspiring::quote());
})->purpose('Display an inspiring quote');

Schedule::command('emails:send')->daily();
```

### 폐지된 파일

<AccordionGroup>
  <Accordion title="app/Http/Kernel.php의 폐지">
    HTTP 커널은 프레임워크 내의 `Illuminate\Foundation\Http\Kernel`에 통합되었습니다. 미들웨어의 커스터마이즈는 `bootstrap/app.php`의 `withMiddleware()`에서 합니다.

    ```php theme={null}
    // Laravel 10 以前: app/Http/Kernel.php
    protected $middleware = [
        \Illuminate\Http\Middleware\TrustProxies::class,
        // ...
    ];

    protected $middlewareGroups = [
        'web' => [
            \App\Http\Middleware\EncryptCookies::class,
            // ...
        ],
    ];
    ```

    ```php theme={null}
    // Laravel 11 以降: bootstrap/app.php
    ->withMiddleware(function (Middleware $middleware) {
        $middleware->web(append: [
            EnsureUserIsSubscribed::class,
        ]);

        $middleware->validateCsrfTokens(except: ['stripe/*']);
    })
    ```
  </Accordion>

  <Accordion title="app/Console/Kernel.php의 폐지">
    콘솔 커널의 2개의 역할이 분리되었습니다. Artisan 커맨드는 `app/Console/Commands/`에 두어 자동 검출되고, 스케줄은 `routes/console.php`에 기술합니다.

    ```php theme={null}
    // Laravel 10 以前: app/Console/Kernel.php
    protected function schedule(Schedule $schedule): void
    {
        $schedule->command('emails:send')->daily();
    }
    ```

    ```php theme={null}
    // Laravel 11 以降: routes/console.php
    use Illuminate\Support\Facades\Schedule;

    Schedule::command('emails:send')->daily();
    ```
  </Accordion>

  <Accordion title="app/Exceptions/Handler.php의 폐지">
    예외 핸들러는 프레임워크 내의 `Illuminate\Foundation\Exceptions\Handler`에 통합되었습니다. 커스터마이즈는 `bootstrap/app.php`의 `withExceptions()`에서 합니다.

    ```php theme={null}
    // Laravel 10 以前: app/Exceptions/Handler.php
    public function register(): void
    {
        $this->reportable(function (InvalidOrderException $e) {
            // ...
        });
    }
    ```

    ```php theme={null}
    // Laravel 11 以降: bootstrap/app.php
    ->withExceptions(function (Exceptions $exceptions) {
        $exceptions->report(function (InvalidOrderException $e) {
            // ...
        });
    })
    ```
  </Accordion>
</AccordionGroup>

## `Application::configure()`의 구조

### 프레임워크 내부에서의 구현

`Application::configure()`는 `Illuminate\Foundation\Application`의 정적 메서드입니다.

```php theme={null}
// Illuminate\Foundation\Application より
public static function configure(?string $basePath = null)
{
    $basePath = match (true) {
        is_string($basePath) => $basePath,
        default => static::inferBasePath(),
    };

    return (new Configuration\ApplicationBuilder(new static($basePath)))
        ->withKernels()
        ->withEvents()
        ->withCommands()
        ->withProviders();
}
```

이 메서드는 다음의 처리를 합니다.

1. `basePath`에서 애플리케이션의 루트 디렉토리를 결정한다
2. `Application` 인스턴스를 생성한다
3. `ApplicationBuilder`로 래핑하고, 기본 설정을 적용한다
4. `ApplicationBuilder` 인스턴스를 반환한다

중요한 것은, `configure()` 내에서 **이미 `withKernels()` / `withEvents()` / `withCommands()` / `withProviders()`가 호출되고 있다**는 점입니다. `bootstrap/app.php`에서 이것들을 다시 호출할 필요는 없습니다.

### 메서드 체인으로 설정을 하는 흐름

```php theme={null}
Application::configure(basePath: dirname(__DIR__))  // ApplicationBuilder を返す
    ->withRouting(...)       // ルーティングを設定し $this を返す
    ->withMiddleware(...)    // ミドルウェアを設定し $this を返す
    ->withExceptions(...)    // 例外ハンドリングを設定し $this を返す
    ->create();              // Application インスタンスを返す
```

`create()`의 호출로 `ApplicationBuilder`에서 `Application` 인스턴스가 꺼내지고, `bootstrap/app.php`가 `return`하는 것은 이 `Application` 인스턴스입니다.

## 요청에서 앱 기동까지의 흐름

```mermaid theme={null}
flowchart TD
    A["public/index.php<br>진입점"] --> B["bootstrap/app.php<br>를 require 하여 Application 취득"]
    B --> C["Application::configure()<br>ApplicationBuilder 생성"]
    C --> D["withKernels()<br>HTTP/Console 커널을 등록"]
    D --> E["withEvents()<br>이벤트 디스커버리를 설정"]
    E --> F["withCommands()<br>Artisan 커맨드의 경로를 설정"]
    F --> G["withProviders()<br>bootstrap/providers.php 를 로드"]
    G --> H["withRouting()<br>라우팅을 설정"]
    H --> I["withMiddleware()<br>미들웨어를 설정"]
    I --> J["withExceptions()<br>예외 핸들링을 설정"]
    J --> K["create()<br>Application 인스턴스를 반환"]
    K --> L["HTTP Kernel 이 요청을 처리<br>미들웨어 → 라우터 → 컨트롤러"]
    L --> M["응답을 반환"]
```

`public/index.php`가 진입점이 되어, `bootstrap/app.php`를 로드하여 `Application`을 취득합니다. 그 후, HTTP Kernel이 요청을 미들웨어의 파이프라인에 통과시키고, 라우터가 컨트롤러에 디스패치합니다.

## `ApplicationBuilder`의 주요 메서드 심층 분석

### `withRouting()` — 라우팅 등록의 내부 처리

```php theme={null}
public function withRouting(
    ?Closure $using = null,
    array|string|null $web = null,
    array|string|null $api = null,
    ?string $commands = null,
    ?string $channels = null,
    ?string $pages = null,
    ?string $health = null,
    string $apiPrefix = 'api',
    ?callable $then = null
)
```

내부에서는 `AppRouteServiceProvider::loadRoutesUsing()`에 콜백을 등록하고, 애플리케이션의 booting 시에 `AppRouteServiceProvider`를 등록합니다.

```php theme={null}
// withRouting() の内部処理（簡略版）
protected function buildRoutingCallback(...)
{
    return function () use ($web, $api, $pages, $health, $apiPrefix, $then) {
        if (is_string($api) || is_array($api)) {
            Route::middleware('api')->prefix($apiPrefix)->group($api);
        }

        if (is_string($health)) {
            Route::get($health, function () {
                Event::dispatch(new DiagnosingHealth);
                return response(View::file(...), status: 200);
            });
        }

        if (is_string($web) || is_array($web)) {
            Route::middleware('web')->group($web);
        }

        if (is_callable($then)) {
            $then($this->app);
        }
    };
}
```

**포인트:**

* `api` 라우트는 `api` 미들웨어 그룹과 `/api` 프리픽스가 자동적으로 적용된다
* `health`에 문자열을 전달하면 헬스 체크 엔드포인트(기본 `/up`)가 자동 등록된다
* `health`의 경로는 유지보수 모드 중에도 제외된다(`PreventRequestsDuringMaintenance::except()`로 설정)
* `web`보다 먼저 `api`가 등록되는 것에 주의. 같은 경로에 대해 Web과 API의 라우트를 정의하면, API 라우트가 우선된다
* `pages`에 문자열을 전달하면 [Laravel Folio](https://github.com/laravel/folio)의 라우팅이 활성화된다

### `withMiddleware()` — 미들웨어 커스터마이즈

```php theme={null}
public function withMiddleware(?callable $callback = null)
{
    $this->app->afterResolving(HttpKernel::class, function ($kernel) use ($callback) {
        $middleware = (new Middleware)
            ->redirectGuestsTo(fn () => route('login'));

        if (! is_null($callback)) {
            $callback($middleware);
        }

        $kernel->setGlobalMiddleware($middleware->getGlobalMiddleware());
        $kernel->setMiddlewareGroups($middleware->getMiddlewareGroups());
        $kernel->setMiddlewareAliases($middleware->getMiddlewareAliases());
        // ...
    });

    return $this;
}
```

`withMiddleware()`는 `HttpKernel`이 해결된 **후**에 콜백을 실행합니다. 이것은 `afterResolving()` 훅을 사용하고 있기 때문입니다. 콜백에 전달되는 `Middleware` 오브젝트에는 풍부한 커스터마이즈 메서드가 있습니다.

```php theme={null}
->withMiddleware(function (Middleware $middleware) {
    // グローバルミドルウェアを追加
    $middleware->append(MyGlobalMiddleware::class);

    // web グループにミドルウェアを追加
    $middleware->web(append: [EnsureUserIsSubscribed::class]);

    // api グループのミドルウェアを置き換え
    $middleware->api(replace: [
        OldMiddleware::class => NewMiddleware::class,
    ]);

    // CSRF 除外パスを設定
    $middleware->validateCsrfTokens(except: ['stripe/*', 'webhook/*']);

    // 未認証ユーザーのリダイレクト先を変更
    $middleware->redirectGuestsTo('/custom-login');

    // ミドルウェアの優先順位を設定
    $middleware->priority([
        \Illuminate\Session\Middleware\StartSession::class,
        \Illuminate\View\Middleware\ShareErrorsFromSession::class,
    ]);
})
```

### `withExceptions()` — 예외 핸들링의 설정

```php theme={null}
public function withExceptions(?callable $using = null)
{
    $this->app->singleton(
        \Illuminate\Contracts\Debug\ExceptionHandler::class,
        \Illuminate\Foundation\Exceptions\Handler::class
    );

    if ($using !== null) {
        $this->app->afterResolving(
            \Illuminate\Foundation\Exceptions\Handler::class,
            fn ($handler) => $using(new Exceptions($handler)),
        );
    }

    return $this;
}
```

`withExceptions()`는 프레임워크의 `Handler` 클래스를 싱글톤으로서 등록한 뒤, 콜백을 `afterResolving()`으로 설정합니다. 콜백에는 `Exceptions` 래퍼 오브젝트가 전달됩니다.

```php theme={null}
->withExceptions(function (Exceptions $exceptions) {
    // 特定の例外をレポートしない
    $exceptions->dontReport(MissedFlightException::class);

    // 特定の例外をカスタムレポート
    $exceptions->report(function (InvalidOrderException $e) {
        // Slack に通知など
    });

    // 特定の例外のHTTPレスポンスをカスタマイズ
    $exceptions->render(function (NotFoundHttpException $e, Request $request) {
        if ($request->is('api/*')) {
            return response()->json(['message' => 'Not Found'], 404);
        }
    });

    // スロットリング（同じ例外を連続でレポートしない）
    $exceptions->throttle(function (Throwable $e) {
        return Limit::perMinute(20);
    });
})
```

### `withProviders()` — 서비스 프로바이더 등록

```php theme={null}
public function withProviders(array $providers = [], bool $withBootstrapProviders = true)
{
    RegisterProviders::merge(
        $providers,
        $withBootstrapProviders
            ? $this->app->getBootstrapProvidersPath()
            : null
    );

    return $this;
}
```

`withProviders()`는 `Application::configure()` 내에서 기본 호출되므로, `bootstrap/providers.php`는 자동적으로 로드됩니다. 추가 프로바이더를 전달하고 싶은 경우에는 `bootstrap/app.php`에서 명시적으로 호출할 필요가 있습니다.

```php theme={null}
Application::configure(basePath: dirname(__DIR__))
    ->withProviders([
        // デフォルトのbootstrap/providers.phpに加えてプロバイダーを追加する
        App\Providers\CustomServiceProvider::class,
    ])
    ->withRouting(...)
    ->create();
```

<Warning>
  `withBootstrapProviders: false`를 전달하면 `bootstrap/providers.php`가 로드되지 않게 됩니다. 특별한 이유가 없는 한 생략해 주세요.
</Warning>

### 기타의 주요 메서드

| 메서드                                  | 설명                                                |
| ------------------------------------ | ------------------------------------------------- |
| `withKernels()`                      | HTTP / Console 커널을 싱글톤 등록한다. `configure()`가 자동 호출 |
| `withEvents()`                       | 이벤트 디스커버리를 활성화한다. `configure()`가 자동 호출            |
| `withCommands(array $commands)`      | Artisan 커맨드 클래스 또는 디렉토리를 추가 등록한다                  |
| `withSchedule(callable $callback)`   | 스케줄을 `bootstrap/app.php`에서 정의한다                   |
| `withBroadcasting(string $channels)` | 브로드캐스트 채널 파일을 등록한다                                |
| `withBindings(array $bindings)`      | 컨테이너 바인딩을 등록한다                                    |
| `withSingletons(array $singletons)`  | 싱글톤 바인딩을 등록한다                                     |
| `registered(callable $callback)`     | 서비스 프로바이더 등록 후에 실행되는 콜백을 추가한다                     |
| `booting(callable $callback)`        | booting 시에 실행되는 콜백을 추가한다                          |
| `booted(callable $callback)`         | booted 시에 실행되는 콜백을 추가한다                           |
| `create()`                           | `Application` 인스턴스를 반환한다                          |

## 설계 의도: 왜 이렇게 되어 있는가

### "코드 퍼스트"의 설정

Laravel 10 이전의 `app/Http/Kernel.php`에는 배열로 미들웨어를 열거하는 스타일이 사용되고 있었습니다. 이것은 설정 파일에 가까운 쓰는 법으로, PHP의 타입 시스템이나 IDE의 서포트를 얻기 어렵다는 결점이 있었습니다.

Laravel 11에서는 `withMiddleware(function (Middleware $middleware) { ... })`라는 콜백 스타일로 바뀌었습니다. 이에 의해 타입 자동 완성이 통하고, 조건 분기나 루프 등의 로직을 사용한 동적인 설정이 자연스럽게 쓸 수 있게 됩니다.

### "규약보다 설정"에서 "명시적인 설정"으로

`api.php`를 옵트인으로 한 것은, API 라우트를 사용하지 않는 애플리케이션에서도 `api` 미들웨어 그룹이 항상 로드되어 있던 것을 해소하기 위함입니다. 사용하지 않는 기능은 기본으로 존재하지 않는다, 는 방침입니다.

### `afterResolving()` 훅의 활용

`withMiddleware()`나 `withExceptions()`에서 `afterResolving()`을 사용하고 있는 것은, 설정의 순서 문제를 피하기 위함입니다. `ApplicationBuilder`의 메서드는 애플리케이션이 완전히 기동하기 전에 호출되지만, 실제의 처리(커널에의 설정 적용)는 커널이 최초에 해결되었을 때 지연 실행됩니다.

## 커스터마이즈의 실전 예

### API와 Web을 공존시킨다

```php theme={null}
return Application::configure(basePath: dirname(__DIR__))
    ->withRouting(
        web: __DIR__.'/../routes/web.php',
        api: __DIR__.'/../routes/api.php',
        commands: __DIR__.'/../routes/console.php',
        health: '/up',
        apiPrefix: 'api/v1',  // デフォルトの /api から変更
    )
    ->withMiddleware(function (Middleware $middleware): void {
        //
    })
    ->withExceptions(function (Exceptions $exceptions): void {
        //
    })->create();
```

### 미들웨어의 커스터마이즈

```php theme={null}
->withMiddleware(function (Middleware $middleware) {
    // Webルートに認証チェックミドルウェアを追加
    $middleware->web(append: [
        \App\Http\Middleware\EnsureEmailIsVerified::class,
    ]);

    // APIルートで特定のミドルウェアを除外
    $middleware->api(remove: [
        \Illuminate\Session\Middleware\StartSession::class,
    ]);

    // Webhook エンドポイントを CSRF から除外
    $middleware->validateCsrfTokens(except: [
        'webhook/*',
        'stripe/webhook',
    ]);

    // 特定のミドルウェアにエイリアスを設定
    $middleware->alias([
        'subscribed' => \App\Http\Middleware\EnsureUserIsSubscribed::class,
    ]);
})
```

### 스케줄을 `bootstrap/app.php`에 집약한다

스케줄은 `routes/console.php`에 쓸 수도 있지만, `withSchedule()`을 사용하면 `bootstrap/app.php`로 정리할 수 있습니다.

```php theme={null}
use Illuminate\Console\Scheduling\Schedule;

return Application::configure(basePath: dirname(__DIR__))
    ->withRouting(
        web: __DIR__.'/../routes/web.php',
        commands: __DIR__.'/../routes/console.php',
        health: '/up',
    )
    ->withSchedule(function (Schedule $schedule) {
        $schedule->command('emails:send')->daily();
        $schedule->command('reports:generate')->weeklyOn(1, '8:00');
        $schedule->job(new PruneOldRecords)->daily();
    })
    ->withMiddleware(function (Middleware $middleware): void {
        //
    })
    ->withExceptions(function (Exceptions $exceptions): void {
        //
    })->create();
```

### 예외 핸들링의 커스터마이즈

```php theme={null}
->withExceptions(function (Exceptions $exceptions) {
    // APIリクエストには常にJSONで返す
    $exceptions->render(function (Throwable $e, Request $request) {
        if ($request->is('api/*') || $request->wantsJson()) {
            $status = match (true) {
                $e instanceof NotFoundHttpException => 404,
                $e instanceof AuthenticationException => 401,
                $e instanceof AuthorizationException => 403,
                $e instanceof ValidationException => 422,
                default => 500,
            };

            return response()->json([
                'message' => $e->getMessage(),
            ], $status);
        }
    });

    // 本番環境のみSlackに通知
    if (app()->isProduction()) {
        $exceptions->report(function (Throwable $e) {
            app(SlackNotifier::class)->notify($e);
        })->stop();
    }
})
```

### 컨테이너 바인딩을 `bootstrap/app.php`에서 관리한다

소규모의 애플리케이션이라면, 심플한 바인딩을 `AppServiceProvider`가 아닌 `bootstrap/app.php`에 쓸 수도 있습니다.

```php theme={null}
return Application::configure(basePath: dirname(__DIR__))
    ->withRouting(...)
    ->withSingletons([
        \App\Contracts\PaymentGateway::class => \App\Services\StripeGateway::class,
        \App\Contracts\MailService::class => \App\Services\SendgridMailService::class,
    ])
    ->withMiddleware(...)
    ->withExceptions(...)
    ->create();
```

## Laravel의 기동 처리의 순번

Laravel 애플리케이션의 기동 시, 서비스 프로바이더와 Application의 훅은 이하의 순번으로 실행됩니다.

1. 모든 ServiceProvider의 `register()` 실행
2. Application의 `registered()`
3. Application의 `booting()`
4. 모든 ServiceProvider의 `boot()` 실행
5. Application의 `booted()`

`AppServiceProvider`에 다음 코드를 추가하면 실행 순을 확인할 수 있습니다.

```php theme={null}
class AppServiceProvider extends ServiceProvider
{
    public function register(): void
    {
        info('1. AppServiceProvider register');

        $this->booting(function () {
            info('4. AppServiceProvider booting');
        });

        $this->booted(function () {
            info('5. AppServiceProvider booted');
        });

        $this->app->registered(function () {
            info('2. app registered');
        });

        $this->app->booting(function () {
            info('3. app booting');
        });

        $this->app->booted(function () {
            info('6. AppServiceProvider@register app booted');
        });
    }

    public function boot(): void
    {
        $this->app->booted(function () {
            info('7. AppServiceProvider@boot app booted');
        });
    }
}
```

`ApplicationBuilder`의 `registered()`, `booting()`, `booted()`는 Application에 콜백을 등록할 뿐인 메서드입니다. 일반적으로는 사용할 필요가 없지만, 기동 준비가 완료된 Kernel에 대해 `booted()`에서 변경을 가하는 등의 특수한 조작이 가능합니다.

```php theme={null}
// bootstrap/app.php

use Illuminate\Contracts\Http\Kernel;

return Application::configure(basePath: dirname(__DIR__))
    ->withRouting(...)
    ->withMiddleware(...)
    ->withExceptions(...)
    ->booted(function (Application $app) {
        $kernel = $app->make(Kernel::class);

        //

        $app->instance(Kernel::class, $kernel);
    })
    ->create();
```

## 다음 단계

<Card title="서비스 컨테이너" icon="box" href="/ko/service-container">
  `ApplicationBuilder`가 내부에서 사용하고 있는 서비스 컨테이너의 구조를 이해합니다.
</Card>

<Card title="새 앱 구조 FAQ" icon="circle-question" href="/ko/advanced/app-structure-faq">
  새로운 애플리케이션 구조에 관한 자주 있는 의문과 답변을 정리하고 있습니다.
</Card>


## Related topics

- [Laravel 10에서 11로의 업그레이드](/ko/blog/upgrade-10-to-11.md)
- [설치](/ko/installation.md)
- [Laravel 11 이후의 새 앱 구조 FAQ](/ko/advanced/app-structure-faq.md)
- [구 구조에서 새 구조로의 이관 가이드](/ko/advanced/app-structure-migration.md)
- [디렉터리 구조](/ko/directory-structure.md)
