본문으로 건너뛰기
버전: 9.x

Upgrade Guide

High Impact Changes

Medium Impact Changes

Upgrading To 9.0 From 8.x

Estimated Upgrade Time: 30 Minutes

가능한 모든 중요한 변경 사항(breaking change)을 문서화하려고 노력했으나, 일부 변경 사항은 프레임워크의 잘 사용하지 않는 부분에 영향을 줄 수 있으므로 실제로는 일부만이 여러분의 애플리케이션에 영향을 줄 수 있습니다. 시간을 절약하고 싶다면, Laravel Shift를 활용하여 업그레이드 작업을 자동화할 수 있습니다.

Updating Dependencies

영향 가능성: 높음

PHP 8.0.2 Required

Laravel은 이제 PHP 8.0.2 이상 버전이 필요합니다.

Composer Dependencies

애플리케이션의 composer.json 파일에서 다음 의존성들을 업데이트해야 합니다.

  • laravel/framework^9.0으로
  • nunomaduro/collision^6.1

또한, 애플리케이션의 composer.json 파일에서 facade/ignition"spatie/laravel-ignition": "^1.0"으로, 그리고(사용 중이라면) pusher/pusher-php-server"pusher/pusher-php-server": "^5.0"으로 교체해 주시기 바랍니다.

추가적으로, 아래와 같은 Laravel 9.x 지원을 위해 새로운 주요 버전(major release)이 배포된 1차 제공 패키지들이 있습니다. 해당 패키지들을 사용 중이라면, 업그레이드 전 각 패키지의 업그레이드 가이드를 참고해 주세요.

마지막으로, 애플리케이션에서 사용하는 기타 써드파티 패키지들의 버전도 확인하여 Laravel 9 지원 버전이 맞는지 검토하시기 바랍니다.

PHP Return Types

PHP는 이제 offsetGet, offsetSet 등과 같은 일부 메서드에서 반환 타입 명시를 점진적으로 요구하고 있습니다. 이에 따라 Laravel 9에서도 해당 메서드들에 반환 타입이 추가되었습니다. 일반적으로 사용자 코드에는 영향을 주지 않으나, 만약 Laravel의 코어 클래스를 확장(extends)하여 해당 메서드를 오버라이딩하고 있다면, 동일한 반환 타입 명시를 코드에 추가해야 합니다.

  • count(): int
  • getIterator(): Traversable
  • getSize(): int
  • jsonSerialize(): array
  • offsetExists($key): bool
  • offsetGet($key): mixed
  • offsetSet($key, $value): void
  • offsetUnset($key): void

또한, PHP의 SessionHandlerInterface를 구현하는 메서드에도 반환 타입이 추가되었습니다. 일반 애플리케이션이나 패키지 코드에는 영향을 주지 않겠지만, 혹시 오버라이딩 중인 경우에만 아래 타입을 반영해야 합니다.

  • open($savePath, $sessionName): bool
  • close(): bool
  • read($sessionId): string|false
  • write($sessionId, $data): bool
  • destroy($sessionId): bool
  • gc($lifetime): int

Application

The Application Contract

영향 가능성: 낮음

Illuminate\Contracts\Foundation\Application 인터페이스의 storagePath 메서드는 $path 인수를 받도록 변경되었습니다. 이 인터페이스를 직접 구현하고 있다면, 구현체도 아래와 같이 변경해야 합니다.

public function storagePath($path = '');

마찬가지로, Illuminate\Foundation\Application 클래스의 langPath 메서드도 $path 인수를 받도록 변경되었습니다.

public function langPath($path = '');

Exception Handler ignore Method

영향 가능성: 낮음

예외 핸들러의 ignore 메서드는 이제 protected가 아니라 public으로 선언되어야 합니다. 이 메서드는 기본 애플리케이션 스켈레톤에는 포함되어 있지 않지만, 직접 구현한 경우 public 가시성으로 변경해 주세요.

public function ignore(string $class);

Exception Handler Contract Binding

영향 가능성: 아주 낮음

기존에는 Laravel의 기본 예외 핸들러를 오버라이드할 때, \App\Exceptions\Handler::class 타입으로 서비스 컨테이너에 바인딩하였습니다. 이제는 \Illuminate\Contracts\Debug\ExceptionHandler::class 타입으로 바인딩해야 합니다.

Blade

Lazy Collections & The $loop Variable

영향 가능성: 낮음

Blade 템플릿 내에서 LazyCollection 인스턴스를 반복(iterate)할 때, 더 이상 $loop 변수를 사용할 수 없습니다. 이 변수에 접근하면 전체 LazyCollection이 메모리로 로드되어, 원래의 lazy 처리 목적이 사라지기 때문입니다.

Checked / Disabled / Selected Blade Directives

영향 가능성: 낮음

새로운 @checked, @disabled, @selected Blade 디렉티브는 동일한 이름의 Vue 이벤트와 충돌할 수 있습니다. 충돌을 피하려면 디렉티브 앞에 @@를 붙여 이스케이프 해주세요: @@selected.

Collections

The Enumerable Contract

영향 가능성: 낮음

Illuminate\Support\Enumerable 인터페이스에 sole 메서드가 추가되었습니다. 이 인터페이스를 직접 구현하는 경우, 반드시 해당 메서드를 추가해주세요.

public function sole($key = null, $operator = null, $value = null);

The reduceWithKeys Method

reduceWithKeys 메서드는 삭제되었습니다. reduce 메서드가 동일한 기능을 제공하므로, 기존 코드에서 reduceWithKeys 대신 reduce를 호출하도록 교체해 주시면 됩니다.

The reduceMany Method

reduceMany 메서드가 reduceSpread로 이름이 바뀌었습니다. 비슷한 역할의 다른 메서드들과 네이밍 일관성을 맞추기 위함입니다.

Container

The Container Contract

영향 가능성: 아주 낮음

Illuminate\Contracts\Container\Container 인터페이스에 scoped, scopedIf라는 메서드가 추가되었습니다. 만약 이 컨트랙트를 직접 구현 중이라면, 해당 메서드들도 추가해주셔야 합니다.

The ContextualBindingBuilder Contract

영향 가능성: 아주 낮음

Illuminate\Contracts\Container\ContextualBindingBuilder 인터페이스에 giveConfig라는 메서드가 추가되었습니다. 직접 구현한다면 아래와 같이 메서드를 추가해주세요.

public function giveConfig($key, $default = null);

Database

Postgres "Schema" Configuration

영향 가능성: 중간

애플리케이션의 config/database.php에서 Postgres 연결의 검색 경로(search path)를 설정하는 schema 옵션의 이름이 search_path로 변경되었습니다.

Schema Builder registerCustomDoctrineType Method

영향 가능성: 낮음

Illuminate\Database\Schema\Builder 클래스의 registerCustomDoctrineType 메서드는 제거되었습니다. 대신, DB 파사드의 registerDoctrineType 메서드를 사용하거나, config/database.php의 설정 파일에서 커스텀 Doctrine 타입을 등록할 수 있습니다.

Eloquent

Custom Casts & null

영향 가능성: 중간

기존 Laravel에서는 커스텀 cast 클래스의 set 메서드는 해당 속성(attribute)에 null이 할당될 때 호출되지 않았습니다. 그러나 이 동작은 Laravel 공식문서의 설명과 일치하지 않았습니다. Laravel 9.x부터는 set 메서드가 항상 호출되며, 이때 $value 인자는 null이 전달될 수 있습니다. 따라서 커스텀 cast 클래스를 작성할 때 null 값을 올바르게 처리하도록 주의해야 합니다.

/**
* Prepare the given value for storage.
*
* @param \Illuminate\Database\Eloquent\Model $model
* @param string $key
* @param AddressModel $value
* @param array $attributes
* @return array
*/
public function set($model, $key, $value, $attributes)
{
if (! $value instanceof AddressModel) {
throw new InvalidArgumentException('The given value is not an Address instance.');
}

return [
'address_line_one' => $value->lineOne,
'address_line_two' => $value->lineTwo,
];
}

Belongs To Many firstOrNew, firstOrCreate, and updateOrCreate Methods

영향 가능성: 중간

belongsToMany 관계의 firstOrNew, firstOrCreate, updateOrCreate 메서드는 첫 번째 인수로 속성 배열을 받습니다. 기존 Laravel에서는 이 배열을 연결 테이블(피벗 테이블)과 비교하여 기존 레코드를 확인했습니다.

그러나 이 동작은 예상치 못한 것이었고 일반적으로 원하는 동작이 아니었습니다. 이제부터는 이 메서드들이 속성 배열을 관계된 모델 테이블과 비교합니다.

$user->roles()->updateOrCreate([
'name' => 'Administrator',
]);

또한, firstOrCreate 메서드는 두 번째 인수로 $values 배열을 받을 수 있게 되었습니다. 해당 모델이 존재하지 않을 때 모델 생성 시 첫 번째 인수($attributes)와 두 번째 인수 값이 병합되어 사용됩니다. 이 방식은 다른 관계에서의 firstOrCreate와 일관성을 맞추기 위함입니다.

$user->roles()->firstOrCreate([
'name' => 'Administrator',
], [
'created_by' => $user->id,
]);

The touch Method

영향 가능성: 낮음

touch 메서드는 이제 업데이트할 속성명을 인수로 받을 수 있습니다. 만약 이 메서드를 오버라이딩하고 있었다면 시그니처를 아래와 같이 바꿔야 합니다.

public function touch($attribute = null);

Encryption

The Encrypter Contract

영향 가능성: 낮음

Illuminate\Contracts\Encryption\Encrypter 인터페이스에 getKey 메서드가 추가되었습니다. 해당 인터페이스를 직접 구현 중이라면 다음과 같이 메서드를 추가하세요.

public function getKey();

Facades

The getFacadeAccessor Method

영향 가능성: 낮음

getFacadeAccessor 메서드는 반드시 컨테이너 바인딩 키(문자열)를 반환해야 합니다. 이전 버전에서는 객체 인스턴스를 반환해도 동작했지만, 이제는 지원되지 않습니다. 커스텀 파사드를 직접 작성했다면, 반환값이 반드시 문자열인지 확인해야 합니다.

/**
* Get the registered name of the component.
*
* @return string
*/
protected static function getFacadeAccessor()
{
return Example::class;
}

Filesystem

The FILESYSTEM_DRIVER Environment Variable

영향 가능성: 낮음

FILESYSTEM_DRIVER 환경 변수명이 FILESYSTEM_DISK로 변경되어 더 정확한 의미를 표현합니다. 이 변경은 Laravel 기본 스켈레톤에만 영향을 미치며, 원한다면 자신의 애플리케이션 환경 변수도 동일하게 바꿀 수 있습니다.

The "Cloud" Disk

영향 가능성: 낮음

cloud 디스크 설정 옵션은 2020년 11월부터 기본 애플리케이션 스켈레톤에서 삭제되었습니다. 만약 애플리케이션에서 cloud 디스크를 사용하고 있다면, 해당 설정을 계속 유지하셔야 합니다.

Flysystem 3.x

영향 가능성: 높음

Laravel 9.x는 Flysystem 1.x에서 3.x로 업그레이드되었습니다. Storage 파사드가 제공하는 파일 조작 메서드들은 모두 Flysystem을 기반으로 하므로, 아래 변경점들에 주의하여 코드를 점검해 주시기 바랍니다.

Driver Prerequisites

S3, FTP, SFTP 드라이버를 사용하려면 Composer로 아래 패키지를 설치해야 합니다.

  • Amazon S3: composer require -W league/flysystem-aws-s3-v3 "^3.0"
  • FTP: composer require league/flysystem-ftp "^3.0"
  • SFTP: composer require league/flysystem-sftp-v3 "^3.0"

Overwriting Existing Files

put, write, writeStream 등 파일 저장 계열 메서드는 이제 기존 파일을 기본적으로 덮어씁니다. 기존 파일을 덮어쓰기 싫다면 직접 파일 존재 여부를 체크 후 쓰기 작업을 수행해야 합니다.

Write Exceptions

put, write, writeStream 등의 쓰기 작업이 실패할 때 더 이상 예외가 발생하지 않고, false를 반환합니다. 기존처럼 예외 발생을 원한다면 디스크 설정 배열에 throw 옵션을 추가하세요.

'public' => [
'driver' => 'local',
// ...
'throw' => true,
],

Reading Missing Files

존재하지 않는 파일을 읽으려고 하면 예외(Illuminate\Contracts\Filesystem\FileNotFoundException) 대신 null이 반환됩니다.

Deleting Missing Files

존재하지 않는 파일을 delete할 때, 이제는 항상 true를 반환합니다.

Cached Adapters

Flysystem 3.x부터는 캐시 어댑터 기능이 지원되지 않습니다. 따라서 Laravel과 설정 파일에서도 관련된 옵션(예: 디스크 설정 내 cache 키)은 제거할 수 있습니다.

Custom Filesystems

커스텀 파일 시스템 드라이버를 등록하는 방식에 약간의 변경이 있습니다. 직접 커스텀 드라이버를 구현하거나, 해당 기능을 가진 패키지를 사용하는 경우 아래 가이드를 참고하여 코드 및 의존성을 수정해 주세요.

Laravel 8.x에서의 예시:

use Illuminate\Support\Facades\Storage;
use League\Flysystem\Filesystem;
use Spatie\Dropbox\Client as DropboxClient;
use Spatie\FlysystemDropbox\DropboxAdapter;

Storage::extend('dropbox', function ($app, $config) {
$client = new DropboxClient(
$config['authorization_token']
);

return new Filesystem(new DropboxAdapter($client));
});

Laravel 9.x에서는 Storage::extend 콜백에서 반드시 Illuminate\Filesystem\FilesystemAdapter 인스턴스를 직접 반환해야 합니다.

use Illuminate\Filesystem\FilesystemAdapter;
use Illuminate\Support\Facades\Storage;
use League\Flysystem\Filesystem;
use Spatie\Dropbox\Client as DropboxClient;
use Spatie\FlysystemDropbox\DropboxAdapter;

Storage::extend('dropbox', function ($app, $config) {
$adapter = new DropboxAdapter(
new DropboxClient($config['authorization_token'])
);

return new FilesystemAdapter(
new Filesystem($adapter, $config),
$adapter,
$config
);
});

SFTP Private-Public Key Passphrase

애플리케이션에서 Flysystem의 SFTP 어댑터와 개인-공개 키 인증을 사용한다면, 프라이빗 키를 복호화할 때 쓰는 password 설정 항목의 이름이 passphrase로 변경되었습니다.

Helpers

The data_get Helper & Iterable Objects

영향 가능성: 아주 낮음

data_get 헬퍼는 기존엔 배열과 Collection 인스턴스에서만 중첩 데이터 접근이 가능했습니다. 이제는 모든 이터러블 객체에서 중첩 데이터에 접근할 수 있습니다.

The str Helper

영향 가능성: 아주 낮음

Laravel 9.x에 글로벌 str helper function가 추가되었습니다. 만약 애플리케이션에서 동일한 이름의 글로벌 str 헬퍼를 정의해두었다면, Laravel 자체의 str 헬퍼와 충돌하지 않도록 이름을 변경하거나 제거해야 합니다.

The when / unless Methods

영향 가능성: 중간

whenunless 메서드는 프레임워크 전반 다양한 클래스에서 조건부 동작을 위해 제공됩니다. 이 메서드의 첫 번째 인수의 불리언 값이 true 또는 false일 때만 해당 함수를 실행합니다.

$collection->when(true, function ($collection) {
$collection->merge([1, 2, 3]);
});

따라서 기존 Laravel에서는 when이나 unless 메서드에 클로저를 전달하면, 클로저 객체(또는 다른 모든 객체)에 대한 느슨한 비교(loose comparison)가 항상 true로 평가되기 때문에 조건부 동작이 항상 실행되었습니다. 개발자들은 클로저의 결과값이 조건부 동작 실행 여부를 결정하는 불리언 값으로 사용되기를 기대했기 때문에, 이는 종종 예상치 못한 결과로 이어졌습니다.

그래서 Laravel 9.x에서는 when 또는 unless 메서드에 전달된 클로저가 실제로 실행되고, 그 반환값이 whenunless 메서드에서 사용되는 불리언 값으로 간주됩니다.

$collection->when(function ($collection) {
// This closure is executed...
return false;
}, function ($collection) {
// Not executed since first closure returned "false"...
$collection->merge([1, 2, 3]);
});

HTTP Client

Default Timeout

영향 가능성: 중간

HTTP client에 기본 타임아웃이 30초로 설정되었습니다. 즉, 서버가 30초 내로 응답하지 않으면 예외가 발생합니다. 이전에는 별도 제한이 없어 요청이 무한정 "멈춤" 상태가 되는 경우가 있었습니다.

더 긴 타임아웃이 필요하다면 timeout 메서드로 개별 요청마다 지정 가능합니다.

$response = Http::timeout(120)->get(/* ... */);

HTTP Fake & Middleware

영향 가능성: 낮음

기존에는 HTTP client가 "faked"될 때 Guzzle HTTP 미들웨어가 실행되지 않았지만, 9.x에서는 faked 상태에서도 Guzzle 미들웨어가 실행됩니다.

HTTP Fake & Dependency Injection

영향 가능성: 낮음

이전에는 Http::fake() 호출 후에도 생성자(inject) 등을 통해 주입된 Illuminate\Http\Client\Factory 인스턴스에는 영향을 주지 않았지만, Laravel 9.x에서는 Http::fake()의존성 주입된 클라이언트에도 fake 응답이 동작하도록 보장합니다. 이는 다른 파사드 및 fake 객체와 일관성을 맞춘 동작입니다.

Symfony Mailer

영향 가능성: 높음

Laravel 9.x의 가장 큰 변화 중 하나는, 2021년 12월 이후로 유지보수가 중단된 SwiftMailer 대신 Symfony Mailer로 전환되었다는 점입니다. 이 변화는 최대한 사용자 입장에서 매끄럽게 진행되도록 노력했으나, 아래 내용을 꼼꼼히 확인하여 호환성 문제를 예방하시길 권장합니다.

Driver Prerequisites

Mailgun 전송 방식을 계속 사용하려면 symfony/mailgun-mailersymfony/http-client Composer 패키지를 설치해야 합니다.

composer require symfony/mailgun-mailer symfony/http-client

wildbit/swiftmailer-postmark Composer 패키지는 제거해야 하며, 대신 symfony/postmark-mailersymfony/http-client Composer 패키지를 설치해야 합니다.

composer require symfony/postmark-mailer symfony/http-client

Updated Return Types

Illuminate\Mail\Mailersend, html, raw, plain 메서드는 이제 void가 아니라 Illuminate\Mail\SentMessage 인스턴스를 반환합니다. 이 객체에는 getSymfonySentMessage 메서드 또는 다이내믹 메서드로 접근할 수 있는 Symfony\Component\Mailer\SentMessage 인스턴스가 포함되어 있습니다.

Renamed "Swift" Methods

SwiftMailer와 관련된 다양한 메서드들은 Symfony Mailer 네이밍으로 변경되었습니다. 예를 들어, withSwiftMessagewithSymfonyMessage로 이름이 바뀌었습니다.

// Laravel 8.x...
$this->withSwiftMessage(function ($message) {
$message->getHeaders()->addTextHeader(
'Custom-Header', 'Header Value'
);
});

// Laravel 9.x...
use Symfony\Component\Mime\Email;

$this->withSymfonyMessage(function (Email $message) {
$message->getHeaders()->addTextHeader(
'Custom-Header', 'Header Value'
);
});

모든 가능한 Symfony\Component\Mime\Email 객체의 인터랙션을 위해 Symfony Mailer documentation를 반드시 확인하세요.

아래는 이름이 변경된 주요 메서드 목록입니다. 대부분 SwiftMailer 혹은 Symfony Mailer와 직접 연동하는 저수준 메서드이므로, 일반적인 Laravel 애플리케이션은 크게 영향 없을 수 있습니다.

Message::getSwiftMessage();
Message::getSymfonyMessage();

Mailable::withSwiftMessage($callback);
Mailable::withSymfonyMessage($callback);

MailMessage::withSwiftMessage($callback);
MailMessage::withSymfonyMessage($callback);

Mailer::getSwiftMailer();
Mailer::getSymfonyTransport();

Mailer::setSwiftMailer($swift);
Mailer::setSymfonyTransport(TransportInterface $transport);

MailManager::createTransport($config);
MailManager::createSymfonyTransport($config);

Proxied Illuminate\Mail\Message Methods

이전에는 Illuminate\Mail\Message 클래스가 정의되지 않은(missing) 메서드를 내부의 Swift_Message 인스턴스에 프락시 하였으나, 이제는 정의되지 않은 메서드를 Symfony\Component\Mime\Email 인스턴스에 프락시합니다. 따라서 이전에 정의되지 않은 메서드가 SwiftMailer로 프락시되는 방식에 의존하던 코드가 있다면, 그에 대응하는 Symfony Mailer 메서드로 수정해야 합니다.

다시 말하지만, 이 메서드들은 Laravel 공식 문서에 기재되어 있지 않으므로 많은 애플리케이션에서는 사용하지 않을 수 있습니다.

// Laravel 8.x...
$message
->setFrom('[email protected]')
->setTo('[email protected]')
->setSubject('Order Shipped')
->setBody('<h1>HTML</h1>', 'text/html')
->addPart('Plain Text', 'text/plain');

// Laravel 9.x...
$message
->subject('Order Shipped')
->html('<h1>HTML</h1>')
->text('Plain Text');

Generated Messages IDs

SwiftMailer는 생성되는 메시지 ID에 사용되는 도메인을 설정할 수 있도록 mime.idgenerator.idright 옵션을 제공했으나, Symfony Mailer에서는 해당 기능을 지원하지 않습니다. 대신, 메시지 ID는 자동으로 발신자(sender) 정보를 기반으로 생성됩니다.

MessageSent Event Changes

Illuminate\Mail\Events\MessageSent 이벤트의 message 속성에는 이제 Swift_Message 대신 Symfony\Component\Mime\Email 인스턴스가 저장됩니다. 이 객체는 메일 전송 이전의 이메일을 나타냅니다.

또한, MessageSent 이벤트에 새로 추가된 sent 속성에는 Illuminate\Mail\SentMessage 인스턴스가 저장되어, 보낸 이메일의 Message ID 등 추가 정보도 확인할 수 있습니다.

Forced Reconnections

메일러가 데몬 프로세스 등에서 동작할 때 트랜스포트의 강제 재연결이 더 이상 불가능합니다. 대신, Symfony Mailer가 자동으로 재연결을 시도하고, 실패하면 예외를 발생시킵니다.

SMTP Stream Options

SMTP 트랜스포트의 스트림 관련 옵션 설정이 더 이상 지원되지 않습니다. 지원되는 옵션만 설정 파일에 직접 명시해주어야 합니다. 예를 들어, TLS 피어 검증 비활성화는 아래와 같이 설정할 수 있습니다.

'smtp' => [
// Laravel 8.x...
'stream' => [
'ssl' => [
'verify_peer' => false,
],
],

// Laravel 9.x...
'verify_peer' => false,
],

자세한 옵션은 Symfony Mailer documentation를 참고하세요.

위 예시(SSL 검증 비활성화)는 보안상 안전하지 않으므로, "중간자 공격" 위험이 있으니 실사용 시 권장하지 않습니다.

SMTP auth_mode

mail 설정 파일에서 SMTP의 auth_mode를 명시적으로 지정할 필요가 없어졌습니다. 인증 방식은 Symfony Mailer가 SMTP 서버와 자동으로 협상합니다.

Failed Recipients

이제 메일 전송 후 실패한 수신자 목록을 조회할 수 없습니다. 만약 메시지 전송이 실패하면 Symfony\Component\Mailer\Exception\TransportExceptionInterface 예외가 발생합니다. 실패한 이메일을 확인하려면, 메일 전송 전 수신자 이메일 주소의 유효성을 반드시 검증하는 것을 권장합니다.

Packages

The lang Directory

영향 가능성: 중간

새로운 Laravel 애플리케이션에서는 resources/lang 디렉터리가 루트 프로젝트 디렉터리(lang)로 옮겨졌습니다. 패키지에서 언어 파일을 배포하는 경우, 하드코딩된 경로 대신 반드시 app()->langPath() 메서드를 사용해 새로운 경로에 파일을 배포하도록 수정해야 합니다.

Queue

The opis/closure Library

영향 가능성: 낮음

Laravel의 opis/closure 의존성이 laravel/serializable-closure로 대체되었습니다. 애플리케이션에서 opis/closure 라이브러리를 직접 다루지 않는 한 기존 코드를 그대로 사용하는 대부분의 경우 특별한 문제는 없습니다. 단, 직접 opis/closure 라이브러리를 직접적으로 사용하거나, 기존에 deprecated된 Illuminate\Queue\SerializableClosureFactory 또는 Illuminate\Queue\SerializableClosure 클래스를 사용 중이라면, Laravel Serializable Closure로 전환해 주셔야 합니다.

The Failed Job Provider flush Method

영향 가능성: 낮음

Illuminate\Queue\Failed\FailedJobProviderInterface 인터페이스의 flush 메서드는 이제 $hours 인수를 받아, 실패한 작업을 queue:flush 명령으로 삭제할 때 해당 작업이 **몇 시간 이상 된 것인지(시간 단위)**를 지정할 수 있습니다. FailedJobProviderInterface를 직접 구현 중이라면 아래와 같이 시그니처를 변경해 주세요.

public function flush($hours = null);

Session

The getSession Method

영향 가능성: 낮음

Laravel의 Illuminate\Http\Request 클래스가 확장한 Symfony\Component\HttpFoundaton\Request 클래스에는 현재 세션 스토리지를 가져오는 getSession 메서드가 존재합니다. 이는 Laravel 공식 문서에는 언급되지 않으며, 대부분의 사용자는 Laravel 자체의 session 메서드를 사용할 것입니다.

이제 getSession 메서드는 Illuminate\Session\Store 또는 null을 반환하는 대신, Symfony\Component\HttpFoundation\Session\SessionInterface 구현체를 반환하거나, 더 정확히는 getSessionSessionInterface 구현체를 반환합니다. 세션이 없을 경우에는 \Symfony\Component\HttpFoundation\Exception\SessionNotFoundException 예외를 던집니다.

Testing

The assertDeleted Method

영향 가능성: 중간

모든 assertDeleted 호출을 assertModelMissing으로 바꿔야 합니다.

Trusted Proxies

영향 가능성: 낮음

Laravel 8 프로젝트의 코드를 새 Laravel 9 애플리케이션 스켈레톤으로 이전하는 경우, 신뢰된 프록시 미들웨어를 업데이트해야 할 수 있습니다.

app/Http/Middleware/TrustProxies.php 파일에서 use Fideloper\Proxy\TrustProxies as Middlewareuse Illuminate\Http\Middleware\TrustProxies as Middleware로 변경하세요.

다음으로, app/Http/Middleware/TrustProxies.php에서 $headers 프로퍼티 정의를 아래와 같이 수정해야 합니다.

// Before...
protected $headers = Request::HEADER_X_FORWARDED_ALL;

// After...
protected $headers =
Request::HEADER_X_FORWARDED_FOR |
Request::HEADER_X_FORWARDED_HOST |
Request::HEADER_X_FORWARDED_PORT |
Request::HEADER_X_FORWARDED_PROTO |
Request::HEADER_X_FORWARDED_AWS_ELB;

마지막으로, 아래 명령어로 fideloper/proxy Composer 의존성을 제거할 수 있습니다.

composer remove fideloper/proxy

Validation

Form Request validated Method

영향 가능성: 낮음

폼 리퀘스트에서 제공하는 validated 메서드는 이제 $key, $default 인수를 받을 수 있게 되었습니다. 직접 오버라이딩하는 경우 시그니처를 아래와 같이 수정해야 합니다.

public function validated($key = null, $default = null)

The password Rule

영향 가능성: 중간

입력값이 현재 인증된 사용자의 비밀번호와 일치하는지 검사하는 password 규칙의 이름이 **current_password**로 변경되었습니다.

Unvalidated Array Keys

영향 가능성: 중간

기존 Laravel에서는 validator가 반환하는 "validated" 데이터에서 검증되지 않은 배열 키를 제외하도록 직접 지시해야 했으며, 특히 허용 키 목록을 지정하지 않은 array 규칙과 함께 사용할 때 그러했습니다.

그러나 Laravel 9.x에서는 array 규칙으로 허용 키를 지정하지 않은 경우에도 검증되지 않은 배열 키는 항상 "validated" 데이터에서 제외됩니다. 일반적으로 이 동작이 가장 기대되는 동작이며, 이전의 excludeUnvalidatedArrayKeys 메서드는 하위 호환성을 유지하기 위한 임시 조치로 Laravel 8.x에만 추가되었던 것입니다.

권장하지는 않지만, 애플리케이션의 서비스 프로바이더 중 하나의 boot 메서드에서 새로운 includeUnvalidatedArrayKeys 메서드를 호출하면 이전 Laravel 8.x 동작 방식을 선택적으로 사용할 수 있습니다.

use Illuminate\Support\Facades\Validator;

/**
* Register any application services.
*
* @return void
*/
public function boot()
{
Validator::includeUnvalidatedArrayKeys();
}

Miscellaneous

laravel/laravel GitHub repository의 변경점도 확인해보시길 바랍니다. 이들 중 다수는 필수 항목은 아니지만, 필요에 따라 애플리케이션의 설정 파일이나 주석 등도 동기화할 수 있습니다. GitHub comparison tool를 이용하면 어떤 변경 사항이 있는지 한눈에 비교할 수 있습니다.