업그레이드 가이드

번역일: 2026년 6월 25일

업그레이드 가이드

영향도 높은 변경사항

영향도 보통인 변경사항

영향도 낮은 변경사항

10.x에서 11.0으로 업그레이드

예상 소요 시간: 약 15분

NOTE

이 문서는 모든 잠재적 브레이킹 체인지를 다루려 하지만, 일부 변경사항은 프레임워크의 특수한 영역에 해당하여 실제로 영향을 받는 경우가 적을 수 있습니다. 업그레이드 작업을 자동화하고 싶다면 Laravel Shift를 활용해 보세요.

의존성 업데이트

영향도: 높음

PHP 8.2.0 이상 필요

Laravel 11은 PHP 8.2.0 이상을 요구합니다.

curl 7.34.0 이상 필요

Laravel의 HTTP 클라이언트는 이제 curl 7.34.0 이상을 요구합니다.

Composer 의존성

composer.json 파일에서 아래 의존성을 업데이트하세요:

  • laravel/framework^11.0으로
  • nunomaduro/collision^8.1
  • 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으로 (설치된 경우)

Cashier Stripe, Passport, Sanctum, Spark Stripe, Telescope 중 하나라도 사용하고 있다면, 이제 각 패키지가 자체 마이그레이션 디렉토리에서 마이그레이션을 자동으로 불러오지 않습니다. 따라서 아래 명령어로 마이그레이션 파일을 애플리케이션으로 퍼블리시해야 합니다:

php artisan vendor:publish --tag=cashier-migrationsphp artisan vendor:publish --tag=passport-migrationsphp artisan vendor:publish --tag=sanctum-migrationsphp artisan vendor:publish --tag=spark-migrationsphp artisan vendor:publish --tag=telescope-migrations

각 패키지의 업그레이드 가이드도 반드시 확인하여 추가적인 브레이킹 체인지가 없는지 점검하세요:

Laravel 인스톨러를 전역으로 설치해 사용 중이라면 Composer로 업데이트하세요:

composer global require laravel/installer:^5.6

마지막으로, 이전에 doctrine/dbalcomposer.json에 직접 추가했다면 제거해도 됩니다. Laravel 11은 이 패키지에 더 이상 의존하지 않습니다.

애플리케이션 구조

Laravel 11은 기본 파일 수를 줄인 새로운 애플리케이션 구조를 도입했습니다. 서비스 프로바이더, 미들웨어, 설정 파일이 기존보다 적습니다.

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

인증

비밀번호 재해싱

영향도: 낮음

Laravel 11은 인증 시, 해싱 알고리즘의 "작업 계수(work factor)"가 마지막 해싱 이후 변경된 경우 사용자 비밀번호를 자동으로 재해싱합니다.

일반적으로 이 변경이 애플리케이션에 문제를 일으키지는 않습니다. 다만 User 모델의 비밀번호 필드명이 password가 아닌 경우, 모델의 authPasswordName 프로퍼티로 필드명을 명시해야 합니다:

protected $authPasswordName = 'custom_password_field';

재해싱 기능을 완전히 비활성화하려면 config/hashing.php에 다음 옵션을 추가하세요:

'rehash_on_login' => false,

`UserProvider` 컨트랙트

영향도: 낮음

Illuminate\Contracts\Auth\UserProvider 컨트랙트에 rehashPasswordIfRequired 메서드가 추가되었습니다. 이 메서드는 애플리케이션의 해싱 알고리즘 작업 계수가 변경되었을 때 사용자 비밀번호를 재해싱하고 저장하는 역할을 합니다.

이 인터페이스를 직접 구현하는 클래스가 있다면 아래 메서드를 추가해야 합니다. 참고 구현은 Illuminate\Auth\EloquentUserProvider 클래스를 확인하세요:

public function rehashPasswordIfRequired(Authenticatable $user, array $credentials, bool $force = false);

`Authenticatable` 컨트랙트

영향도: 낮음

Illuminate\Contracts\Auth\Authenticatable 컨트랙트에 getAuthPasswordName 메서드가 추가되었습니다. 이 메서드는 인증 엔터티의 비밀번호 컬럼명을 반환합니다.

이 인터페이스를 직접 구현하는 클래스가 있다면 아래 메서드를 추가하세요:

public function getAuthPasswordName() { return 'password'; }

Laravel 기본 User 모델은 Illuminate\Auth\Authenticatable 트레이트를 통해 이 메서드를 자동으로 제공받습니다.

`AuthenticationException` 클래스

영향도: 매우 낮음

Illuminate\Auth\AuthenticationExceptionredirectTo 메서드가 이제 첫 번째 인수로 Illuminate\Http\Request 인스턴스를 요구합니다. 이 예외를 직접 처리하고 redirectTo 메서드를 호출하는 코드가 있다면 수정하세요:

if ($e instanceof AuthenticationException) { $path = $e->redirectTo($request); }

회원가입 시 이메일 인증 알림

영향도: 매우 낮음

SendEmailVerificationNotification 리스너가 애플리케이션의 EventServiceProvider에 등록되어 있지 않으면 Registered 이벤트에 자동으로 등록됩니다. 만약 이 자동 등록을 원하지 않는다면 EventServiceProvider에 빈 configureEmailVerification 메서드를 정의하세요:

protected function configureEmailVerification() { // ... }

캐시

캐시 키 접두사

영향도: 매우 낮음

이전에는 DynamoDB, Memcached, Redis 캐시 스토어에서 캐시 키 접두사를 설정하면 Laravel이 접두사 뒤에 자동으로 :를 붙였습니다. Laravel 11부터는 :를 자동으로 추가하지 않습니다. 기존 방식을 유지하려면 접두사 설정값에 직접 :를 추가하세요.

컬렉션

`Enumerable` 컨트랙트

영향도: 낮음

Illuminate\Support\Enumerable 컨트랙트의 dump 메서드가 가변 인수(...$args)를 받도록 변경되었습니다. 이 인터페이스를 직접 구현하고 있다면 메서드 시그니처를 수정하세요:

public function dump(...$args);

데이터베이스

SQLite 3.26.0 이상 필요

영향도: 높음

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

Eloquent 모델 `casts` 메서드

영향도: 낮음

기본 Eloquent 모델 클래스에 이제 casts 메서드가 정의됩니다. 애플리케이션의 모델에 casts라는 이름의 관계(relationship)가 정의되어 있다면 기본 클래스의 casts 메서드와 충돌할 수 있습니다.

컬럼 수정

영향도: 높음

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

예를 들어, 아래처럼 unsigned, default, comment를 가진 votes 컬럼을 생성하는 마이그레이션이 있다고 가정합니다:

Schema::create('users', function (Blueprint $table) { $table->integer('votes')->unsigned()->default(1)->comment('The vote count'); });

이후 해당 컬럼을 nullable로 변경하는 마이그레이션을 작성할 때, Laravel 10에서는 기존 속성이 유지되었지만 Laravel 11에서는 명시적으로 선언하지 않은 속성은 제거됩니다:

// Laravel 11에서는 아래와 같이 기존 속성도 함께 명시해야 합니다. Schema::table('users', function (Blueprint $table) { $table->integer('votes') ->unsigned() ->default(1) ->comment('The vote count') ->nullable() ->change(); });

change 메서드는 인덱스에는 영향을 주지 않습니다. 컬럼 수정 시 인덱스를 추가하거나 제거하려면 인덱스 수정자를 명시적으로 사용하세요:

// 인덱스 추가 $table->bigIncrements('id')->primary()->change(); // 인덱스 제거 $table->char('postal_code', 10)->unique(false)->change();

기존 마이그레이션을 모두 수정하기 어렵다면, 마이그레이션 스쿼시를 활용하세요:

php artisan schema:dump

스쿼시 후에는 Laravel이 스키마 파일을 기준으로 데이터베이스를 마이그레이션한 뒤 미처리 마이그레이션을 실행합니다.

부동소수점 타입

영향도: 높음

doublefloat 마이그레이션 컬럼 타입이 데이터베이스 전반에 걸쳐 일관성 있게 동작하도록 재작성되었습니다.

double 컬럼 타입은 이제 전체 자릿수와 소수점 자릿수 없이 표준 SQL 문법에 따른 DOUBLE 컬럼을 생성합니다. 기존에 전달하던 $total, $places 인수는 제거하세요:

$table->double('amount');

float 컬럼 타입은 이제 $total, $places 인수 없이 FLOAT 컬럼을 생성하며, 선택적으로 $precision을 지정해 4바이트 단정밀도 또는 8바이트 배정밀도 컬럼을 선택할 수 있습니다:

$table->float('amount', precision: 53);

unsignedDecimal, unsignedDouble, unsignedFloat 메서드는 제거되었습니다. MySQL에서 이 타입들의 unsigned 속성이 deprecated되었고 다른 데이터베이스에서도 표준화되지 않았기 때문입니다. 계속 사용해야 한다면 unsigned() 메서드를 체이닝하세요:

$table->decimal('amount', total: 8, places: 2)->unsigned(); $table->double('amount')->unsigned(); $table->float('amount', precision: 53)->unsigned();

MariaDB 전용 드라이버

영향도: 매우 낮음

Laravel 11은 MariaDB 데이터베이스 전용 드라이버를 추가했습니다. 기존에는 MySQL 드라이버가 그대로 사용되었습니다.

MariaDB를 사용한다면 향후 MariaDB 전용 기능을 활용하기 위해 연결 설정의 드라이버를 변경할 수 있습니다:

'driver' => 'mariadb',
'url' => env('DB_URL'),
'host' => env('DB_HOST', '127.0.0.1'),
'port' => env('DB_PORT', '3306'),
// ...

현재 새 MariaDB 드라이버는 MySQL 드라이버와 거의 동일하게 동작하지만, 한 가지 차이점이 있습니다: uuid 스키마 빌더 메서드가 char(36) 대신 네이티브 UUID 컬럼을 생성합니다.

기존 마이그레이션에서 uuid 메서드를 사용 중이고 mariadb 드라이버로 전환한다면, 예기치 않은 동작을 방지하기 위해 char로 변경하는 것을 고려하세요:

Schema::table('users', function (Blueprint $table) { $table->char('uuid', 36); // ... });

공간 타입(Spatial Types)

영향도: 낮음

데이터베이스 마이그레이션의 공간 컬럼 타입이 전체 데이터베이스에서 일관성 있게 동작하도록 재작성되었습니다. 기존의 point, lineString, polygon, geometryCollection, multiPoint, multiLineString, multiPolygon, multiPolygonZ 메서드 대신 geometry 또는 geography 메서드를 사용하세요:

$table->geometry('shapes'); $table->geography('coordinates');

MySQL, MariaDB, PostgreSQL에서 저장 타입이나 공간 참조 시스템 식별자를 명시적으로 지정하려면 subtypesrid를 전달하세요:

$table->geometry('dimension', subtype: 'polygon', srid: 0); $table->geography('latitude', subtype: 'point', srid: 4326);

PostgreSQL 문법의 isGeometry, projection 컬럼 수정자는 제거되었습니다.

Doctrine DBAL 제거

영향도: 낮음

아래에 나열된 Doctrine DBAL 관련 클래스와 메서드가 모두 제거되었습니다. Laravel은 더 이상 이 패키지에 의존하지 않으며, 커스텀 Doctrine 타입을 등록하지 않아도 다양한 컬럼 타입을 생성 및 변경할 수 있습니다:

  • Illuminate\Database\Schema\Builder::$alwaysUsesNativeSchemaOperationsIfPossible 클래스 프로퍼티
  • Illuminate\Database\Schema\Builder::useNativeSchemaOperationsIfPossible() 메서드
  • Illuminate\Database\Connection::usingNativeSchemaOperations() 메서드
  • Illuminate\Database\Connection::isDoctrineAvailable() 메서드
  • Illuminate\Database\Connection::getDoctrineConnection() 메서드
  • Illuminate\Database\Connection::getDoctrineSchemaManager() 메서드
  • Illuminate\Database\Connection::getDoctrineColumn() 메서드
  • Illuminate\Database\Connection::registerDoctrineType() 메서드
  • Illuminate\Database\DatabaseManager::registerDoctrineType() 메서드
  • Illuminate\Database\PDO 디렉토리
  • Illuminate\Database\DBAL\TimestampType 클래스
  • Illuminate\Database\Schema\Grammars\ChangeColumn 클래스
  • Illuminate\Database\Schema\Grammars\RenameColumn 클래스
  • Illuminate\Database\Schema\Grammars\Grammar::getDoctrineTableDiff() 메서드

database 설정 파일의 dbal.types를 통해 커스텀 Doctrine 타입을 등록하는 것도 더 이상 필요하지 않습니다.

데이터베이스 테이블 정보를 조회할 때는 Laravel의 네이티브 스키마 메서드(Schema::getTables(), Schema::getColumns(), Schema::getIndexes(), Schema::getForeignKeys() 등)를 사용하세요.

Deprecated 스키마 메서드

영향도: 매우 낮음

Doctrine 기반의 Schema::getAllTables(), Schema::getAllViews(), Schema::getAllTypes() 메서드가 제거되었습니다. 대신 네이티브 메서드인 Schema::getTables(), Schema::getViews(), Schema::getTypes()를 사용하세요.

PostgreSQL과 SQL Server에서는 세 부분으로 구성된 참조(예: database.schema.table)가 지원되지 않습니다. 데이터베이스를 명시적으로 지정하려면 connection()을 사용하세요:

Schema::connection('database')->hasTable('schema.table');

스키마 빌더 `getColumnType()` 메서드

영향도: 매우 낮음

Schema::getColumnType() 메서드는 이제 Doctrine DBAL 동등 타입이 아닌, 실제 컬럼 타입을 반환합니다.

데이터베이스 연결 인터페이스

영향도: 매우 낮음

Illuminate\Database\ConnectionInterface 인터페이스에 scalar 메서드가 추가되었습니다. 이 인터페이스를 직접 구현하는 클래스가 있다면 해당 메서드를 추가하세요:

public function scalar($query, $bindings = [], $useReadPdo = true);

날짜

Carbon 3

영향도: 보통

Laravel 11은 Carbon 2와 Carbon 3을 모두 지원합니다. Carbon은 Laravel 생태계 전반에서 날짜 처리에 널리 사용되는 라이브러리입니다. Carbon 3으로 업그레이드할 경우 diffIn* 메서드가 부동소수점 숫자를 반환하며, 시간의 방향을 나타내기 위해 음수 값을 반환할 수 있습니다. 이는 Carbon 2와 크게 다른 점이므로 Carbon의 변경 로그마이그레이션 문서를 반드시 확인하세요.

메일

`Mailer` 컨트랙트

영향도: 매우 낮음

Illuminate\Contracts\Mail\Mailer 컨트랙트에 sendNow 메서드가 추가되었습니다. 이 컨트랙트를 직접 구현하는 클래스가 있다면 해당 메서드를 추가하세요:

public function sendNow($mailable, array $data = [], $callback = null);

패키지

서비스 프로바이더 퍼블리싱

영향도: 매우 낮음

애플리케이션의 app/Providers 디렉토리에 서비스 프로바이더를 직접 퍼블리시하고, config/app.phpproviders 배열에 등록하는 방식의 Laravel 패키지를 작성한 경우, 새로운 ServiceProvider::addProviderToBootstrapFile 메서드를 사용하도록 패키지를 업데이트해야 합니다.

Laravel 11 신규 애플리케이션에서는 config/app.phpproviders 배열이 존재하지 않으므로, 이 메서드는 서비스 프로바이더를 bootstrap/providers.php 파일에 자동으로 추가합니다:

use Illuminate\Support\ServiceProvider; ServiceProvider::addProviderToBootstrapFile(Provider::class);

`BatchRepository` 인터페이스

영향도: 매우 낮음

Illuminate\Bus\BatchRepository 인터페이스에 rollBack 메서드가 추가되었습니다. 이 인터페이스를 직접 구현하는 경우 해당 메서드를 추가하세요:

public function rollBack();

데이터베이스 트랜잭션 내 동기 Job

영향도: 매우 낮음

이전에는 동기 Job(sync 큐 드라이버 사용)이 큐 연결의 after_commit 설정이나 Job의 afterCommit 메서드 호출 여부와 관계없이 즉시 실행되었습니다.

Laravel 11부터 동기 큐 Job도 큐 연결 또는 Job의 "after commit" 설정을 따릅니다.

요청 제한(Rate Limiting)

초 단위 요청 제한

영향도: 보통

Laravel 11은 분 단위에서 초 단위 요청 제한을 지원합니다. 이와 관련하여 아래의 브레이킹 체인지가 있습니다.

GlobalLimit 클래스의 생성자는 이제 분 대신 초를 받습니다. 이 클래스는 문서화되어 있지 않으므로 일반적으로 사용되지 않지만, 직접 사용했다면 수정하세요:

new GlobalLimit($attempts, 2 * 60);

Limit 클래스의 생성자도 이제 분 대신 초를 받습니다. Limit::perMinute, Limit::perSecond 같은 정적 생성자를 통해 사용하는 경우에는 영향이 없지만, 생성자를 직접 호출했다면 초 단위로 변경하세요:

new Limit($key, $attempts, 2 * 60);

Limit 클래스의 decayMinutes 프로퍼티가 decaySeconds로 이름이 바뀌었으며, 이제

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

번역일: 2026년 6월 25일