업그레이드 가이드
번역일: 2026년 6월 20일
업그레이드 가이드
영향도 높음
영향도 중간
영향도 낮음
- Carbon 3
- Concurrency 결과 인덱스 매핑
- 컨테이너 클래스 의존성 해결
- 이미지 유효성 검사에서 SVG 제외
- 로컬 파일시스템 디스크 기본 루트 경로
- 멀티 스키마 데이터베이스 검사
- 중첩 배열 요청 병합
11.x에서 12.0으로 업그레이드
예상 소요 시간: 5분
NOTE
모든 브레이킹 체인지를 문서화하려고 노력했지만, 일부 변경 사항은 프레임워크의 잘 사용되지 않는 부분에 해당하므로 실제로 영향을 받는 경우는 많지 않습니다. 업그레이드 작업을 자동화하고 싶다면 Laravel Shift를 활용해 보세요.
의존성 업데이트
영향도: 높음
composer.json 파일에서 아래 패키지 버전을 업데이트하세요.
laravel/framework를^12.0으로phpunit/phpunit를^11.0으로pestphp/pest를^3.0으로
Carbon 3
영향도: 낮음
Laravel 12부터 Carbon 2.x 지원이 제거되었습니다. 모든 Laravel 12 애플리케이션은 Carbon 3.x를 사용해야 합니다.
Laravel 인스톨러 업데이트
영향도: 높음
Laravel 인스톨러 CLI를 사용해 새 프로젝트를 생성하는 경우, Laravel 12.x 및 새 Laravel 스타터 킷과 호환되도록 인스톨러를 업데이트해야 합니다.
composer global require로 설치한 경우 다음 명령으로 업데이트할 수 있습니다.
composer global update laravel/installerphp.new를 통해 PHP와 Laravel을 설치했다면, 운영체제에 맞는 설치 명령을 다시 실행하면 최신 버전의 PHP와 인스톨러가 설치됩니다.
macOS
/bin/bash -c "$(curl -fsSL https://php.new/install/mac/8.4)"Windows PowerShell
# 관리자 권한으로 실행하세요...
Set-ExecutionPolicy Bypass -Scope Process -Force; [System.Net.ServicePointManager]::SecurityProtocol = [System.Net.ServicePointManager]::SecurityProtocol -bor 3072; iex ((New-Object System.Net.WebClient).DownloadString('https://php.new/install/windows/8.4'))Linux
/bin/bash -c "$(curl -fsSL https://php.new/install/linux/8.4)"Laravel Herd에 내장된 인스톨러를 사용하고 있다면, Herd 자체를 최신 버전으로 업데이트하세요.
인증
`DatabaseTokenRepository` 생성자 시그니처 변경
영향도: 매우 낮음
Illuminate\Auth\Passwords\DatabaseTokenRepository 클래스의 생성자에서 $expires 파라미터의 단위가 분(minute) 에서 초(second) 로 변경되었습니다. 해당 클래스를 직접 인스턴스화하는 코드가 있다면 값을 조정해야 합니다.
Concurrency
Concurrency 결과 인덱스 매핑
영향도: 낮음
Concurrency::run 메서드에 연관 배열(associative array)을 전달하면, 이제 결과도 동일한 키를 유지한 채 반환됩니다.
$result = Concurrency::run([
'task-1' => fn () => 1 + 1,
'task-2' => fn () => 2 + 2,
]);
// ['task-1' => 2, 'task-2' => 4]이전에는 키가 보존되지 않고 순서 기반의 숫자 인덱스로 반환되었으므로, 결과를 키로 참조하는 코드가 있다면 확인이 필요합니다.
컨테이너
컨테이너 클래스 의존성 해결
영향도: 낮음
의존성 주입 컨테이너가 클래스 인스턴스를 생성할 때, 이제 생성자 파라미터의 기본값을 그대로 존중합니다. 이전에는 기본값이 있어도 컨테이너가 해당 타입을 주입하려 시도했지만, 12.x부터는 기본값이 그대로 사용됩니다.
class Example
{
public function __construct(public ?Carbon $date = null) {}
}
$example = resolve(Example::class);
// Laravel <= 11.x: Carbon 인스턴스가 주입됨
$example->date instanceof Carbon;
// Laravel >= 12.x: 기본값인 null이 사용됨
$example->date === null;컨테이너가 Carbon 인스턴스를 자동으로 주입해 주는 동작에 의존하고 있었다면, 명시적으로 바인딩을 등록하거나 코드를 수정해야 합니다.
데이터베이스
멀티 스키마 데이터베이스 검사
영향도: 낮음
Schema::getTables(), Schema::getViews(), Schema::getTypes() 메서드가 이제 기본적으로 모든 스키마의 결과를 반환합니다. 특정 스키마만 조회하려면 schema 인자를 전달하세요.
// 모든 스키마의 테이블 조회
$tables = Schema::getTables();
// 'main' 스키마의 테이블만 조회
$tables = Schema::getTables(schema: 'main');
// 'main'과 'blog' 스키마의 테이블 조회
$tables = Schema::getTables(schema: ['main', 'blog']);Schema::getTableListing() 메서드는 이제 기본적으로 스키마 이름이 포함된 형태(스키마.테이블)로 테이블 목록을 반환합니다. schemaQualified 인자로 동작을 제어할 수 있습니다.
$tables = Schema::getTableListing();
// ['main.migrations', 'main.users', 'blog.posts']
$tables = Schema::getTableListing(schema: 'main');
// ['main.migrations', 'main.users']
$tables = Schema::getTableListing(schema: 'main', schemaQualified: false);
// ['migrations', 'users']db:table 및 db:show Artisan 명령도 MySQL, MariaDB, SQLite에서 PostgreSQL, SQL Server와 동일하게 모든 스키마의 결과를 출력합니다.
데이터베이스 클래스 생성자 시그니처 변경
영향도: 매우 낮음
Laravel 12에서는 일부 저수준 데이터베이스 클래스의 생성자가 Illuminate\Database\Connection 인스턴스를 직접 요구하도록 변경되었습니다.
이 변경 사항은 주로 데이터베이스 관련 패키지 개발자에게 해당하며, 일반 애플리케이션 개발에는 거의 영향을 미치지 않습니다.
Illuminate\Database\Schema\Blueprint
Blueprint 생성자의 첫 번째 인자로 Connection 인스턴스가 필요하게 되었습니다. Blueprint를 직접 인스턴스화하는 코드가 있다면 수정이 필요합니다.
Illuminate\Database\Grammar
Grammar 생성자도 Connection 인스턴스를 요구합니다. 이전에는 생성 후 setConnection() 메서드로 연결을 설정했지만, 이 메서드는 Laravel 12에서 제거되었습니다.
// Laravel <= 11.x
$grammar = new MySqlGrammar;
$grammar->setConnection($connection);
// Laravel >= 12.x
$grammar = new MySqlGrammar($connection);또한 아래 API들이 제거되거나 더 이상 사용되지 않습니다(deprecated).
Blueprint::getPrefix()메서드 — deprecatedConnection::withTablePrefix()메서드 — 제거됨Grammar::getTablePrefix()및setTablePrefix()메서드 — deprecatedGrammar::setConnection()메서드 — 제거됨
테이블 접두사(prefix)가 필요한 경우에는 데이터베이스 연결 객체에서 직접 가져오세요.
$prefix = $connection->getTablePrefix();커스텀 데이터베이스 드라이버, 스키마 빌더, 또는 Grammar 구현체를 관리하고 있다면 생성자 시그니처를 반드시 검토하세요.
Eloquent
모델과 UUIDv7
영향도: 중간
HasUuids 트레이트가 이제 UUID 버전 7(시간 순서가 보장되는 UUID) 형식의 값을 반환합니다. 기존처럼 UUIDv4를 계속 사용하고 싶다면 HasVersion4Uuids 트레이트로 교체하세요.
use Illuminate\Database\Eloquent\Concerns\HasUuids; //use Illuminate\Database\Eloquent\Concerns\HasVersion4Uuids as HasUuids; //기존에 HasVersion7Uuids 트레이트를 직접 사용하고 있었다면, 해당 트레이트가 제거되었으므로 HasUuids로 교체하면 동일한 동작이 유지됩니다.
NOTE
UUIDv7은 생성 시각 기반으로 정렬이 가능하여 데이터베이스 인덱스 성능에 유리합니다. 기존 UUIDv4 기반 데이터가 저장된 테이블이 있다면, 트레이트 변경 후 기존 데이터와의 혼용 여부를 반드시 검토하세요.
요청(Request)
중첩 배열 요청 병합
영향도: 낮음
$request->mergeIfMissing() 메서드가 이제 "dot" 표기법을 사용한 중첩 배열 병합을 지원합니다.
$request->mergeIfMissing([
'user.last_name' => '김',
]);이전에는 'user.last_name'이라는 키 이름 자체가 최상위 키로 추가되었지만, 이제는 user 배열 안의 last_name 키로 병합됩니다. "dot" 키 이름을 그대로 최상위 키로 사용하는 코드가 있다면 수정이 필요합니다.
라우팅
라우트 우선순위
영향도: 낮음
동일한 이름을 가진 라우트가 여러 개 등록된 경우의 동작이 캐시된 라우팅과 캐시되지 않은 라우팅 사이에서 통일되었습니다. 이제 캐시되지 않은 라우팅에서도 마지막에 등록된 라우트가 아닌 첫 번째로 등록된 라우트가 매칭됩니다.
스토리지
로컬 파일시스템 디스크 기본 루트 경로
영향도: 낮음
filesystems 설정 파일에 local 디스크를 명시적으로 정의하지 않은 경우, Laravel 12부터는 로컬 디스크의 루트 경로가 storage/app/private으로 기본 설정됩니다. 이전에는 storage/app이 기본값이었습니다.
따라서 Storage::disk('local')을 호출하면 storage/app/private 경로를 기준으로 파일을 읽고 씁니다. 이전 동작을 유지하려면 config/filesystems.php에 local 디스크를 직접 정의하고 원하는 루트 경로를 지정하세요.
유효성 검사
이미지 유효성 검사에서 SVG 제외
영향도: 낮음
image 유효성 검사 규칙이 이제 기본적으로 SVG 파일을 허용하지 않습니다. SVG를 허용해야 한다면 명시적으로 옵션을 추가하세요.
use Illuminate\Validation\Rules\File;
// 문자열 방식
'photo' => 'required|image:allow_svg'
// 객체 방식
'photo' => ['required', File::image(allowSvg: true)],NOTE
SVG는 XML 기반 포맷으로 스크립트를 포함할 수 있어 XSS 등 보안 위협이 될 수 있습니다. 사용자 업로드 파일에 SVG를 허용할 때는 별도의 보안 처리를 함께 적용하는 것을 권장합니다.
기타
laravel/laravel GitHub 저장소의 변경 사항도 함께 확인해 보세요. 필수 변경 사항은 아니지만, 설정 파일이나 기타 스캐폴딩 파일을 최신 상태로 동기화해 두면 좋습니다. GitHub 비교 도구를 사용하면 11.x와 12.x 사이의 변경 내용을 한눈에 확인하고 필요한 부분만 선택적으로 반영할 수 있습니다.