> ## 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 10에서 11로의 업그레이드

> Laravel 10에서 11로의 업그레이드 절차와 주요 변경점 설명

## 시작하며

Laravel 11은 2024년 3월에 릴리스되었습니다. 이 가이드에서는 Laravel 10.x에서 11.x로의 업그레이드 절차를 설명합니다.

<Info>
  업그레이드에 필요한 예상 시간은 **약 15분**입니다. 다만 파괴적 변경이 애플리케이션에 미치는 영향은 규모나 사용하고 있는 기능에 따라 다릅니다.
</Info>

### Laravel Shift를 사용한 자동 업그레이드

[Laravel Shift](https://laravelshift.com/)를 사용하여 업그레이드를 자동화할 수도 있습니다. Shift는 애플리케이션의 의존관계나 설정 파일을 자동으로 갱신해 줍니다.

***

## 영향도별 변경점

### 영향도: 높음

* 의존관계 갱신
* 애플리케이션 구조의 변경
* 부동소수점형의 변경
* 컬럼 변경 시 속성 보존
* SQLite 최소 버전
* Sanctum 갱신

### 영향도: 중간

* Carbon 3
* 패스워드의 재해시
* 초 단위 레이트 리밋
* Spatie Once 패키지

### 영향도: 낮음

* Doctrine DBAL 삭제
* Eloquent 모델의 `casts` 메서드
* 공간형의 변경
* `Enumerable` 컨트랙트
* `UserProvider` 컨트랙트
* `Authenticatable` 컨트랙트

***

## 업그레이드 절차

### 의존관계 갱신

**영향도: 높음**

`composer.json`의 이하 의존관계를 갱신해 주세요.

```json theme={null}
{
  "require": {
    "laravel/framework": "^11.0",
    "nunomaduro/collision": "^8.1"
  }
}
```

패키지를 사용하고 있는 경우에는 함께 갱신해 주세요.

```json theme={null}
{
  "require": {
    "laravel/breeze": "^2.0",
    "laravel/cashier": "^15.0",
    "laravel/dusk": "^8.0",
    "laravel/jetstream": "^5.0",
    "laravel/octane": "^2.3",
    "laravel/passport": "^12.0",
    "laravel/sanctum": "^4.0",
    "laravel/scout": "^10.0",
    "laravel/spark-stripe": "^5.0",
    "laravel/telescope": "^5.0",
    "livewire/livewire": "^3.4",
    "inertiajs/inertia-laravel": "^1.0"
  }
}
```

갱신 후, 이하 명령으로 의존관계를 설치합니다.

```shell theme={null}
composer update
```

Cashier Stripe, Passport, Sanctum, Spark Stripe, Telescope를 사용하고 있는 경우에는 마이그레이션을 애플리케이션에 퍼블리시할 필요가 있습니다.

```shell theme={null}
php artisan vendor:publish --tag=cashier-migrations
php artisan vendor:publish --tag=passport-migrations
php artisan vendor:publish --tag=sanctum-migrations
php artisan vendor:publish --tag=spark-migrations
php artisan vendor:publish --tag=telescope-migrations
```

Laravel 인스톨러를 사용하고 있는 경우에는 함께 갱신해 주세요.

```shell theme={null}
composer global require laravel/installer:^5.6
```

이전에 `doctrine/dbal`을 수동으로 추가하고 있었던 경우에는 삭제할 수 있습니다. Laravel 11에서는 이 패키지로의 의존이 없어졌습니다.

***

## PHP 버전 요구사항

**영향도: 높음**

Laravel 11에서는 **PHP 8.2.0 이상**이 필요합니다. 또한 Laravel의 HTTP 클라이언트에는 **curl 7.34.0 이상**이 필요합니다.

***

## 애플리케이션 구조의 변경

**영향도: 높음**

Laravel 11에서는 기본 애플리케이션 구조가 간소화되었습니다. 서비스 프로바이더, 미들웨어, 설정 파일의 수가 대폭 삭감되어 있습니다.

다만, Laravel 10의 애플리케이션을 Laravel 11로 업그레이드할 때, 애플리케이션 구조의 마이그레이션을 시도하는 것은 **권장하지 않습니다**. Laravel 11은 Laravel 10의 애플리케이션 구조도 지원하도록 설계되어 있습니다.

주요 구조적 변경점:

* `bootstrap/app.php`에서 미들웨어, 예외 핸들러, 라우팅을 직접 설정하도록 변경
* `app/Http/Kernel.php`가 폐지되고 `bootstrap/app.php`에 통합
* 기본 서비스 프로바이더 수가 삭감되어 `bootstrap/providers.php`에서 관리
* `config/` 디렉터리의 파일 수가 삭감 (필요에 따라 `php artisan config:publish`로 공개 가능)

***

## 파괴적 변경 (Breaking Changes)

### 인증

#### 패스워드 재해시

**영향도: 중간**

Laravel 11에서는 인증 시 해시 알고리즘의 "워크 팩터"가 변경되어 있는 경우 자동으로 패스워드를 재해시합니다.

`User` 모델의 패스워드 필드 이름이 `password` 이외인 경우, 모델의 `authPasswordName` 프로퍼티로 지정해 주세요.

```php theme={null}
class User extends Authenticatable
{
    protected $authPasswordName = 'custom_password_field';
}
```

이 기능을 무효화하려면, `config/hashing.php`에 이하를 추가해 주세요.

```php theme={null}
'rehash_on_login' => false,
```

#### `UserProvider` 컨트랙트

**영향도: 낮음**

`Illuminate\Contracts\Auth\UserProvider` 컨트랙트에 `rehashPasswordIfRequired` 메서드가 추가되었습니다. 이 인터페이스를 구현하고 있는 클래스가 있는 경우에는 메서드를 추가해 주세요.

```php theme={null}
public function rehashPasswordIfRequired(Authenticatable $user, array $credentials, bool $force = false);
```

#### `Authenticatable` 컨트랙트

**영향도: 낮음**

`Illuminate\Contracts\Auth\Authenticatable` 컨트랙트에 `getAuthPasswordName` 메서드가 추가되었습니다. 이 인터페이스를 구현하고 있는 클래스가 있는 경우에는 메서드를 추가해 주세요.

```php theme={null}
public function getAuthPasswordName()
{
    return 'password';
}
```

***

### 데이터베이스

#### SQLite 최소 버전

**영향도: 높음**

SQLite를 사용하고 있는 경우에는 **SQLite 3.26.0 이상**이 필요합니다.

또한 Laravel 11의 신규 프로젝트에서는 기본 데이터베이스 드라이버가 SQLite로 변경되었습니다.

#### 컬럼 변경 시의 속성 보존

**영향도: 높음**

컬럼을 변경할 때, 변경 후에도 유지하고 싶은 모든 수식자를 명시적으로 지정해야 합니다. 지정되지 않은 속성은 삭제됩니다.

```php theme={null}
// Laravel 10에서는 unsigned, default, comment가 유지되었음
Schema::table('users', function (Blueprint $table) {
    $table->integer('votes')->nullable()->change();
});

// Laravel 11에서는 명시적으로 모든 속성을 지정해야 함
Schema::table('users', function (Blueprint $table) {
    $table->integer('votes')
        ->unsigned()
        ->default(1)
        ->comment('The vote count')
        ->nullable()
        ->change();
});
```

기존 마이그레이션을 모두 갱신하고 싶지 않은 경우에는, 마이그레이션을 스쿼시해 주세요.

```shell theme={null}
php artisan schema:dump
```

#### 부동소수점형의 변경

**영향도: 높음**

`double`과 `float`의 마이그레이션 컬럼 타입이 전 데이터베이스에서 통일되었습니다.

```php theme={null}
// double: 합계 자릿수 · 소수점 이하 자릿수의 인자가 불필요해짐
$table->double('amount');

// float: 정밀도를 지정하는 임의 인자만
$table->float('amount', precision: 53);
```

`unsignedDecimal`, `unsignedDouble`, `unsignedFloat` 메서드는 삭제되었습니다. 계속해서 `unsigned` 속성을 사용하는 경우에는 메서드 체인으로 지정해 주세요.

```php theme={null}
$table->decimal('amount', total: 8, places: 2)->unsigned();
$table->double('amount')->unsigned();
$table->float('amount', precision: 53)->unsigned();
```

#### Eloquent 모델의 `casts` 메서드

**영향도: 낮음**

기저 Eloquent 모델 클래스에 `casts` 메서드가 정의되었습니다. 애플리케이션의 모델에서 `casts`라는 릴레이션을 정의하고 있는 경우에는 이름이 경합하므로 변경이 필요합니다.

#### MariaDB 전용 드라이버

**영향도: 매우 낮음**

Laravel 11에서는 MariaDB용 전용 데이터베이스 드라이버가 추가되었습니다. MariaDB에 접속하는 경우에는 설정에서 `mariadb` 드라이버를 사용할 수 있습니다.

```php theme={null}
'driver' => 'mariadb',
```

#### 공간형의 변경

**영향도: 낮음**

공간 컬럼 타입이 전 데이터베이스에서 통일되었습니다. `point`, `lineString`, `polygon` 등의 메서드 대신에 `geometry` 또는 `geography`를 사용해 주세요.

```php theme={null}
$table->geometry('shapes');
$table->geography('coordinates');
```

타입이나 공간 참조 시스템을 명시적으로 지정하는 경우에는 `subtype`과 `srid`를 전달해 주세요.

```php theme={null}
$table->geometry('dimension', subtype: 'polygon', srid: 0);
$table->geography('latitude', subtype: 'point', srid: 4326);
```

#### Doctrine DBAL 삭제

**영향도: 낮음**

Laravel은 Doctrine DBAL로의 의존을 없앴습니다. 이하의 클래스나 메서드가 삭제되었습니다.

* `Schema\Builder::useNativeSchemaOperationsIfPossible()`
* `Connection::getDoctrineConnection()`
* `Connection::getDoctrineSchemaManager()`
* `Connection::registerDoctrineType()`
* `DatabaseManager::registerDoctrineType()`
* `Schema\Grammars\ChangeColumn` 클래스
* `Schema\Grammars\RenameColumn` 클래스

데이터베이스 검사에는 `Schema::getTables()`, `Schema::getColumns()`, `Schema::getIndexes()`, `Schema::getForeignKeys()` 등의 새로운 네이티브 메서드를 사용해 주세요.

***

### 날짜

#### Carbon 3

**영향도: 중간**

Laravel 11은 Carbon 2와 Carbon 3 양쪽을 지원합니다. Carbon 3으로 업그레이드할 경우, `diffIn*` 메서드가 부동소수점 수를 반환하게 되고, 음수 값으로 시간의 방향을 나타내는 것에 주의해 주세요.

***

### 레이트 리밋

#### 초 단위 레이트 리밋

**영향도: 중간**

Laravel 11에서는 분 단위가 아니라 초 단위의 레이트 리밋이 지원되었습니다. `GlobalLimit`, `Limit` 클래스의 생성자가 초 단위를 받도록 되었습니다.

```php theme={null}
// 변경 전 (분 단위)
new GlobalLimit($attempts, 2); // 2분

// 변경 후 (초 단위)
new GlobalLimit($attempts, 2 * 60); // 120초
```

`Limit` 클래스의 `decayMinutes` 프로퍼티는 `decaySeconds`로 개명되어 초 단위가 되었습니다.

`ThrottlesExceptions`와 `ThrottlesExceptionsWithRedis`의 생성자도 초 단위를 받도록 되었습니다.

```php theme={null}
new ThrottlesExceptions($attempts, 2 * 60);
new ThrottlesExceptionsWithRedis($attempts, 2 * 60);
```

***

### 패키지

#### 서비스 프로바이더의 퍼블리시

**영향도: 매우 낮음**

Laravel 11의 신규 애플리케이션에는 `config/app.php`의 `providers` 배열이 없습니다. 패키지에서 서비스 프로바이더를 퍼블리시하고 있는 경우에는 `ServiceProvider::addProviderToBootstrapFile` 메서드를 사용해 주세요.

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

ServiceProvider::addProviderToBootstrapFile(Provider::class);
```

***

### Sanctum

#### Sanctum 업데이트

**영향도: 높음**

Laravel 11은 Sanctum 3.x를 지원하지 않습니다. `composer.json`의 Sanctum 의존관계를 `^4.0`으로 갱신해 주세요.

Sanctum 4.0은 마이그레이션을 자동으로 로드하지 않게 되었습니다. 이하 명령으로 퍼블리시해 주세요.

```shell theme={null}
php artisan vendor:publish --tag=sanctum-migrations
```

또한 `config/sanctum.php`의 미들웨어 설정을 갱신해 주세요.

```php theme={null}
'middleware' => [
    'authenticate_session' => Laravel\Sanctum\Http\Middleware\AuthenticateSession::class,
    'encrypt_cookies' => Illuminate\Cookie\Middleware\EncryptCookies::class,
    'validate_csrf_token' => Illuminate\Foundation\Http\Middleware\ValidateCsrfToken::class,
],
```

***

### Spatie Once 패키지

**영향도: 중간**

Laravel 11은 독자적인 [`once` 함수](https://laravel.com/docs/11.x/helpers#method-once)를 제공하도록 되었습니다. `spatie/once` 패키지를 사용하고 있는 경우에는 경합을 피하기 위해 `composer.json`에서 삭제해 주세요.

***

## 정리

Laravel 11은 큰 구조 변경을 포함하는 버전이지만, Laravel 10의 애플리케이션 구조는 그대로 동작하므로, 단계적으로 마이그레이션할 수 있습니다.

| 변경점                      | 영향도 | 대응                                 |
| ------------------------ | --- | ---------------------------------- |
| `composer.json`의 의존관계 갱신 | 높음  | `laravel/framework ^11.0`으로 변경     |
| PHP 8.2 필수               | 높음  | PHP 버전 확인                          |
| 컬럼 변경 시의 속성 보존           | 높음  | `change()` 사용 부분 확인                |
| 부동소수점형의 변경               | 높음  | `double`/`float` 컬럼의 정의 확인         |
| SQLite 3.26.0+ 필수        | 높음  | SQLite 버전 확인                       |
| Sanctum `^4.0`           | 높음  | 마이그레이션을 퍼블리시                       |
| Carbon 3                 | 중간  | `diffIn*` 메서드의 반환 값 확인             |
| 초 단위 레이트 리밋              | 중간  | `decayMinutes`를 `decaySeconds`로 변경 |
| Doctrine DBAL 삭제         | 낮음  | 네이티브 스키마 메서드로 이관                   |

***

## 참고 자료

* [공식 업그레이드 가이드 (영어)](https://laravel.com/docs/11.x/upgrade)
* [laravel/laravel 리포지토리의 차분 (10.x → 11.x)](https://github.com/laravel/laravel/compare/10.x...11.x)
* [Laravel Shift](https://laravelshift.com) — 업그레이드를 자동화하는 커뮤니티 서비스
* [Carbon 3 변경 로그](https://github.com/briannesbitt/Carbon/releases/tag/3.0.0)


## Related topics

- [Laravel 9에서 10으로의 업그레이드](/ko/blog/upgrade-9-to-10.md)
- [Laravel 11에서 12로의 업그레이드 가이드](/ko/blog/upgrade-11-to-12.md)
- [Laravel 12에서 13으로의 업그레이드 가이드](/ko/blog/upgrade-12-to-13.md)
- [Laravel 8에서 9로의 업그레이드](/ko/blog/upgrade-8-to-9.md)
- [구 구조에서 새 구조로의 이관 가이드](/ko/advanced/app-structure-migration.md)
