버전 4.7.0

릴리스 날짜: 2026년 2월 1일

CodeIgniter4 4.7.0 릴리스

주요 내용

  • 최소 PHP 요구 사항이 8.2로 업데이트되었습니다.

  • 성능 향상을 위한 실험적 FrankenPHP 워커 모드 지원이 추가되었습니다.

주요 변경사항

동작 변경사항

유효성 검사 규칙

regex_match 유효성 검사 규칙의 플레이스홀더는 이제 이중 중괄호를 사용해야 합니다. 이전에 regex_match[/^{placeholder}$/]처럼 단일 중괄호를 사용했다면 이중 중괄호 regex_match[/^{{placeholder}}$/]로 업데이트해야 합니다.

이 변경사항은 단일 중괄호(예: {1,3})가 수량자로 사용되는 정규식 구문과의 모호성을 방지하기 위해 도입되었습니다.

BaseModel

insertBatch()updateBatch() 메서드가 이제 updateOnlyChangedallowEmptyInserts 같은 모델 설정을 따릅니다. 이 변경사항은 모든 삽입/업데이트 작업에 걸쳐 일관된 처리를 보장합니다.

기본 키 유효성 검사

insert()insertBatch()(useAutoIncrement가 비활성화된 경우), update(), delete() 메서드가 이제 데이터베이스 쿼리를 실행하기 전에 기본 키 값의 유효성을 검사합니다. 유효하지 않은 기본 키 값은 이제 DatabaseException 대신 InvalidArgumentException을 발생시킵니다.

변경된 내용:

  • 예외 타입: 유효하지 않은 기본 키는 이제 데이터베이스 계층의 일반적인 DatabaseException 대신 구체적인 오류 메시지와 함께 InvalidArgumentException을 발생시킵니다.

  • 유효성 검사 시점:
    • update()delete()의 경우: beforeUpdate/beforeDelete 이벤트 이전, 그리고 데이터베이스 쿼리가 실행되기 전에 유효성 검사가 이루어집니다.

    • insert()insertBatch()(자동 증가가 비활성화된 경우): beforeInsert 이벤트 이후, 데이터베이스 쿼리가 실행되기 전에 유효성 검사가 이루어집니다.

  • 유효하지 않은 값: 다음 값들은 이제 기본 키로 명시적으로 거부됩니다:
    • null (자동 증가가 비활성화된 경우 삽입 시)

    • 0 (정수 0)

    • '0' (문자열 0)

    • '' (빈 문자열)

    • truefalse (불리언)

    • [] (빈 배열)

    • 중첩 배열 (예: [[1, 2]])

    • 위의 유효하지 않은 값 중 하나라도 포함하는 배열

    참고: RawSql 객체는 원시 SQL 표현식을 사용해야 하는 복잡한 시나리오에서 기본 키 값으로 허용됩니다.

이 변경사항은 일반적인 데이터베이스 오류 대신 구체적인 유효성 검사 메시지(예: “Invalid primary key: 0 is not allowed”)를 제공하여 오류 보고를 개선하고 유효하지 않은 쿼리가 데이터베이스에 도달하는 것을 방지합니다.

기본 키에 대해 이러한 값 중 일부를 허용해야 하는 경우, 모델에서 validateID() 메서드를 재정의할 수 있습니다.

Entity

Entity::hasChanged()Entity::syncOriginal() 메서드가 이제 얕은 비교 대신 객체와 배열에 대한 깊은 비교를 수행합니다. 이는 다음을 의미합니다:

  • 객체와 배열은 이제 JSON 인코딩되고 정규화되어 비교되며, 중첩 구조, 객체 속성 및 배열 요소의 변경사항을 감지합니다.

  • 열거형(BackedEnumUnitEnum 모두)은 이제 백킹 값 또는 케이스 이름으로 올바르게 추적됩니다.

  • DateTime 객체(DateTimeInterface)는 타임존 정보를 포함한 ISO 8601 표현을 사용하여 비교됩니다.

  • ArrayObjectArrayIterator 같은 컬렉션(Traversable)은 비교를 위해 배열로 변환됩니다.

  • __toString() 메서드를 가진 값 객체는 속성에 접근할 수 없을 때(비공개 속성을 가진 객체에 대한 폴백) 문자열 표현으로 비교됩니다.

  • 중첩 엔티티(toRawArray() 사용), JsonSerializable 객체 및 toArray() 메서드를 가진 객체는 정확한 변경 감지를 위해 재귀적으로 정규화됩니다.

  • 스칼라 값(문자열, 정수, 부동소수점, 불리언, null)은 모든 엔티티 속성이 스칼라일 때 최적화를 통해 직접 비교를 계속 사용합니다.

이전에는 참조 비교만 수행되었기 때문에 객체 속성이나 객체를 포함한 배열을 변경해도 변경사항으로 감지되지 않았습니다. 이제 객체나 배열의 내부 상태에 대한 모든 수정이 올바르게 감지됩니다. 이전의 얕은 비교 동작에 의존했다면 코드를 업데이트해야 합니다.

Entity::toRawArray() 메서드가 이제 $recursive 매개변수가 true일 때 엔티티 배열을 올바르게 변환합니다. 이전에는 배열을 포함하는 속성이 재귀적으로 처리되지 않았습니다. 배열이 변환되지 않는 이전 동작에 의존하고 있었다면 코드를 업데이트해야 합니다.

Entity와 DataCaster

이전에는 타입 캐스팅이 설정되지 않은 경우(빈 $casts = [] 배열)에도 DataCaster 객체가 항상 초기화되었습니다.

DataCaster는 이제 필요에 따라 생성되며 타입 캐스팅이 설정되지 않은 경우 null이 됩니다. 이 변경사항은 일반적인 사용에는 영향을 주지 않지만, 개발자는 일부 경우에 $dataCaster가 nullable일 수 있음을 인지해야 합니다.

암호화 핸들러

OpenSSLHandlerSodiumHandler는 이제 $params 인자를 통해 암호화/복호화 매개변수가 전달될 때 핸들러의 $key 속성을 더 이상 수정하지 않습니다. $params를 통해 전달된 키는 이제 로컬 변수로 사용되어 핸들러의 상태가 변경되지 않습니다.

변경된 내용:

  • 이전에는 $params를 통해 encrypt() 또는 decrypt()에 키를 전달하면 핸들러의 내부 $key 속성이 영구적으로 수정되었습니다.

  • 이제 핸들러의 $key 속성은 Config\Encryption을 통한 핸들러 생성 시에만 설정됩니다. $params를 통해 키를 전달하면 핸들러의 상태를 수정하지 않고 임시 로컬 변수로 사용됩니다.

  • SodiumHandler::encrypt()는 이제 sodium_memzero($this->key)를 더 이상 호출하지 않습니다. 이전에는 이 함수가 첫 번째 사용 후 암호화 키를 파괴하여 핸들러의 재사용을 방지했습니다.

영향:

영향을 받는 경우: $params를 통해 encrypt() 또는 decrypt()에 키를 전달하고 이후 작업을 위해 해당 키가 유지될 것으로 기대한 경우에만 영향을 받습니다. 대부분의 사용자는 영향을 받지 않습니다:

  • 영향 없음: 각 작업마다 항상 $params를 통해 키를 전달하는 경우

  • 영향 없음: $params를 사용하지 않고 항상 Config\Encryption을 통해 키를 설정하는 경우

  • 영향 있음: $params를 통해 한 번 키를 전달하고 그 키가 기억될 것으로 기대한 경우

영향을 받는 경우, $params 부작용에 의존하는 대신 Config\Encryption을 통해 키를 올바르게 설정하거나 서비스에 사용자 정의 설정을 전달하세요.

영향받는 코드 예시:

$config      = config('Encryption');
$config->key = 'your-encryption-key';
$handler     = service('encrypter', $config);
$handler->encrypt($data, 'temporary-key');
// Old: $handler->key is now 'temporary-key'
// New: $handler->key remains unchanged ('your-encryption-key')

$handler->encrypt($moreData);
// Old: Would use 'temporary-key'
// New: Uses default key ('your-encryption-key')

마이그레이션:

다른 암호화 키를 영구적으로 사용하려면 서비스를 생성할 때 사용자 정의 설정을 전달하세요:

$config      = config('Encryption');
$config->key = 'your-custom-encryption-key';

// Get a new handler instance with the custom config (not shared)
$handler = service('encrypter', $config, false);

인터페이스 변경사항

참고: 이 인터페이스를 처음부터 구현한 클래스가 있다면, 호환성을 보장하기 위해 새 메서드를 포함하도록 구현을 업데이트해야 합니다.

  • Cache: CacheInterface에 이제 deleteMatching() 메서드가 포함됩니다.

  • Cache: CacheInterface에 이제 remember() 메서드가 포함됩니다. 모든 내장 캐시 핸들러는 BaseHandler를 통해 이 메서드를 상속하므로 변경이 필요하지 않습니다.

  • Database: QueryInterface에 이제 getOriginalQuery() 메서드가 포함됩니다.

  • Images: ImageHandlerInterface에 새 메서드 clearMetadata()가 포함됩니다.

메서드 시그니처 변경사항

  • BaseModel: cleanValidationRules() 메서드의 $row 매개변수 타입이 ?array $row = null에서 array $row로 변경되었습니다.

  • PageCache: PageCache 필터 생성자가 이제 선택적 Cache 설정 매개변수를 허용합니다: __construct(?Cache $config = null). 이를 통해 테스트 목적의 의존성 주입이 가능합니다. 기술적으로 자체 생성자로 PageCache 클래스를 확장하는 경우 주요 변경사항이지만, 매개변수에 기본값이 있으므로 대부분의 사용자에게는 영향을 주지 않습니다.

  • 스택 추적에서 민감한 정보를 숨기기 위해 다양한 메서드에 SensitiveParameter 속성이 추가되었습니다. 영향을 받는 메서드는 다음과 같습니다:
    • CodeIgniter\Encryption\EncrypterInterface::encrypt()

    • CodeIgniter\Encryption\EncrypterInterface::decrypt()

    • CodeIgniter\Encryption\Handlers\OpenSSLHandler::encrypt()

    • CodeIgniter\Encryption\Handlers\OpenSSLHandler::decrypt()

    • CodeIgniter\Encryption\Handlers\SodiumHandler::encrypt()

    • CodeIgniter\Encryption\Handlers\SodiumHandler::decrypt()

    • CodeIgniter\HTTP\CURLRequest::setAuth()

    • CodeIgniter\HTTP\URI::setUserInfo()

    • CodeIgniter\Security\Security::derandomize()

  • 타입이 누락된 CacheInterface 메서드에 네이티브 타입이 추가되었습니다. 다음 메서드가 업데이트되었습니다:
    • initialize()

    • save()

    • delete()

    • increment()

    • decrement()

    • clean()

    • getCacheInfo()

    • getMetaData()

  • CodeIgniter\Database\QueryInterface 메서드에 네이티브 매개변수 및 반환 타입이 추가되었습니다:
    • setQuery(string $sql, mixed $binds = null, bool $setEscape = true): self

    • getQuery(): string

    • setDuration(float $start, ?float $end = null): self

    • setError(int $code, string $error): self

    • swapPrefix(string $orig, string $swap): self

  • CodeIgniter\Debug\Toolbar 메서드에 네이티브 반환 타입이 추가되었습니다:
    • prepare(): void

    • respond(): void

  • 이전에 #[ReturnTypeWillChange] 속성을 가졌던 메서드들이 네이티브 반환 타입을 포함하도록 업데이트되었습니다:
    • CodeIgniter\Cookie\Cookie::offsetGet($offset): bool|int|string

    • CodeIgniter\Entity\Entity::jsonSerialize(): array

    • CodeIgniter\Files\File::getSize(): false|int

    • CodeIgniter\I18n\TimeLegacy::setTimestamp($timestamp): static

    • CodeIgniter\I18n\TimeTrait::createFromFormat($format, $time, $timezone = null): static

    • CodeIgniter\I18n\TimeTrait::setTimezone($timezone): static

    • CodeIgniter\Session\Handlers\Database\PostgreHandler::gc($max_lifetime): false|int

    • CodeIgniter\Session\Handlers\ArrayHandler::read($id): string

    • CodeIgniter\Session\Handlers\ArrayHandler::gc($max_lifetime): int

    • CodeIgniter\Session\Handlers\DatabaseHandler::read($id): false|string

    • CodeIgniter\Session\Handlers\DatabaseHandler::gc($max_lifetime): false|int

    • CodeIgniter\Session\Handlers\FileHandler::read($id): false|string

    • CodeIgniter\Session\Handlers\FileHandler::gc($max_lifetime): false|int

    • CodeIgniter\Session\Handlers\MemcachedHandler::read($id): false|string

    • CodeIgniter\Session\Handlers\MemcachedHandler::gc($max_lifetime): int

    • CodeIgniter\Session\Handlers\RedisHandler::read($id): false|string

    • CodeIgniter\Session\Handlers\RedisHandler::gc($max_lifetime): int

속성 시그니처 변경사항

  • Entity: CodeIgniter\Entity\Entity::$dataCaster 보호된 속성 타입이 DataCaster에서 ?DataCaster(nullable)로 변경되었습니다.

제거된 사용 중단 항목

  • BaseModel: 사용 중단된 메서드 transformDataRowToArray()가 제거되었습니다.

  • Cache: CodeIgniter\Cache\CacheInterface::getMetaData()의 사용 중단된 반환 타입 falsenull 타입으로 대체되었습니다.

  • CodeIgniter: 사용 중단된 CodeIgniter\CodeIgniter::resolvePlatformExtensions()이 제거되었습니다.

  • Entity: 사용 중단된 CodeIgniter\Entity\Entity::setAttributes()이 제거되었습니다. 대신 CodeIgniter\Entity\Entity::injectRawData()를 사용하세요.

  • IncomingRequest: 사용 중단된 메서드가 제거되었습니다:
    • CodeIgniter\HTTP\IncomingRequest\detectURI()

    • CodeIgniter\HTTP\IncomingRequest\detectPath()

    • CodeIgniter\HTTP\IncomingRequest\parseRequestURI()

    • CodeIgniter\HTTP\IncomingRequest\parseQueryString()

  • IncomingRequest: CodeIgniter\HTTP\IncomingRequest::setPath()에서 사용 중단된 $config 매개변수가 제거되었으며, 메서드 가시성이 public에서 private으로 변경되었습니다.

  • Session: CodeIgniter\Session\Session의 사용 중단된 속성이 제거되었습니다:
    • CodeIgniter\Session\Session::$sessionDriverName

    • CodeIgniter\Session\Session::$sessionCookieName

    • CodeIgniter\Session\Session::$sessionExpiration

    • CodeIgniter\Session\Session::$sessionSavePath

    • CodeIgniter\Session\Session::$sessionMatchIP

    • CodeIgniter\Session\Session::$sessionTimeToUpdate

    • CodeIgniter\Session\Session::$sessionRegenerateDestroy

  • Session: 사용 중단된 메서드 CodeIgniter\Session\Session::stop()이 제거되었습니다.

  • Text Helper: random_string() 함수에서 사용 중단된 타입 basic, md5, sha1이 제거되었습니다.

개선사항

라이브러리

  • API Transformers: 이 새로운 기능은 API 응답을 위한 데이터 변환을 구조화된 방식으로 제공합니다. 자세한 내용은 API 트랜스포머를 참조하세요.

  • CLI: CLI 커맨드에서 운영 체제 신호를 통합 처리하기 위한 SignalTrait이 추가되었습니다.

  • Cache: Predis 핸들러에 asyncpersistent 설정 항목이 추가되었습니다.

  • Cache: Redis 핸들러에 persistent 설정 항목이 추가되었습니다.

  • Cache: ResponseCache에 HTTP 상태 지원이 추가되었습니다.

  • Cache: PageCache 필터로 캐시할 수 있는 HTTP 상태 코드를 제어하는 Config\Cache::$cacheStatusCodes가 추가되었습니다. 기본값은 [](하위 호환성을 위한 모든 상태 코드)입니다. 성공적인 응답만 캐시하려면 권장 값인 [200]을 사용하세요. 자세한 내용은 $cacheStatusCodes 설정을 참조하세요.

  • Cache: APCu 캐싱 드라이버가 추가되었습니다.

  • CURLRequest: 기본 공유 연결을 변경하는 shareConnection 설정 항목이 추가되었습니다.

  • CURLRequest: 기본 DNS 캐시 시간 초과를 변경하는 dns_cache_timeout 옵션이 추가되었습니다.

  • CURLRequest: 요청 새로운 연결을 활성화/비활성화하는 fresh_connect 옵션이 추가되었습니다.

  • DataConverter: 데이터베이스와 엔티티를 위한 EnumCast 캐스터가 추가되었습니다.

  • Email: SMTP 인증 방법을 선택하는 지원이 추가되었습니다. Config\Email::$SMTPAuthMethod 옵션으로 변경할 수 있습니다.

  • Encryption: 암호화 키 교체를 지원하는 Config\Encryption::$previousKeys 설정 옵션이 추가되었습니다. 현재 키로 복호화에 실패하면 시스템이 자동으로 이전 키로 폴백하여, 이전에 암호화된 데이터에 대한 접근을 잃지 않고 암호화 키를 교체할 수 있습니다.

  • Image: ImageMagickHandler가 PHP imagick 확장에만 의존하도록 재작성되었습니다.

  • Image: 개인 정보 보호를 위해 이미지 메타데이터를 제거하는 ImageMagickHandler::clearMetadata() 메서드가 추가되었습니다.

  • ResponseTrait: 페이지네이션된 API 응답을 단순화하는 paginate 메서드가 추가되었습니다. 자세한 내용은 ResponseTrait::paginate()를 참조하세요.

  • Session: RedisHandlerpersistent 설정 항목이 추가되었습니다.

  • Session: PersistsConnection 트레이트를 통해 Redis 및 Memcached 세션 핸들러에 연결 지속성이 추가되어 요청 간 연결을 재사용함으로써 워커 모드에서 성능이 향상됩니다.

  • Time: Time::addCalendarMonths()Time::subCalendarMonths() 메서드가 추가되었습니다.

  • Time: 편의 메서드 Time::isPast()Time::isFuture()가 추가되었습니다. 자세한 내용은 isPastisFuture를 참조하세요.

  • Toolbar: 프레임워크의 Response 객체 대신 네이티브 PHP 헤더를 사용하는 서드파티 라이브러리(예: Dompdf)에서 생성된 응답에 디버그 툴바가 잘못 주입되는 문제가 수정되었습니다.

  • UserAgents: 새로운 검색 엔진 및 서비스 크롤러로 인식되는 robots 목록이 확장되었습니다.

  • View: app/Views/overrides 디렉토리 내에 일치하는 파일 구조를 배치하여 네임스페이스가 지정된 뷰(예: 모듈/패키지)를 재정의하는 기능이 추가되었습니다. 자세한 내용은 네임스페이스 뷰 재정의를 참조하세요.

커맨드

  • FrankenPHP 워커 모드 파일(Caddyfile 및 워커 진입점)을 생성하는 php spark worker:install 커맨드가 추가되었습니다.

  • 워커 모드 파일을 제거하는 php spark worker:uninstall 커맨드가 추가되었습니다.

데이터베이스

  • BaseConnection: 데이터베이스 연결이 아직 활성 상태인지 확인하는 ping() 메서드가 추가되었습니다. OCI8은 SELECT 1 FROM DUAL을, 다른 드라이버는 SELECT 1을 사용합니다.

  • BaseConnection: reconnect() 메서드가 이제 재연결 전에 ping()을 사용하여 연결이 활성 상태인지 확인합니다. 이전에는 일부 드라이버가 항상 무조건 닫고 재연결했으며, OCI8의 reconnect()는 아무 동작도 하지 않았습니다.

  • Exception Logging: 모든 DB 드라이버가 이제 데이터베이스 예외를 균일하게 로깅합니다. 이전에는 각 드라이버마다 자체 로그 형식이 있었습니다.

마이그레이션

  • MigrationRunner: 다중 프로세스 환경에서 동시 마이그레이션을 방지하기 위한 분산 잠금 지원이 추가되었습니다. Config\Migrations::$lock = true로 활성화합니다.

HTTP

콘텐츠 보안 정책

  • script-srcstyle-src 지시문이 이제 소스 표현식으로 SHA-256, SHA-384, SHA-512 다이제스트를 사용할 수 있습니다.

  • 새로운 CSP Level 3 키워드 지원이 추가되었습니다:
    • 'strict-dynamic'

    • 'unsafe-hashes'

    • 'report-sample'

    • 'unsafe-allow-redirects'

    • 'wasm-unsafe-eval'

    • 'trusted-types-eval'

    • 'report-sha256'

    • 'report-sha384'

    • 'report-sha512'

  • 다음 CSP Level 3 지시문 지원이 추가되었습니다:
    • report-to

    • script-src-elem

    • script-src-attr

    • style-src-elem

    • style-src-attr

    • worker-src

    app/Config/ContentSecurityPolicy.php의 CSP 설정을 업데이트하여 이 새로운 지시문을 포함하세요.

기타

  • Controller Attributes: 컨트롤러 클래스와 메서드에 필터 및 기타 메타데이터를 정의하기 위한 PHP 속성(Attributes) 지원이 추가되었습니다. 자세한 내용은 컨트롤러 속성를 참조하세요.

메시지 변경사항

  • Email.invalidSMTPAuthMethod, Email.failureSMTPAuthMethod, CLI.signals.noPcntlExtension, CLI.signals.noPosixExtension, CLI.signals.failedSignal이 추가되었습니다.

  • Email.failedSMTPLoginImage.libPathInvalid가 사용 중단되었습니다.

  • Session.missingDatabaseTable이 변경되었습니다.

변경사항

  • Boot: 일회성 워커 초기화를 위한 Boot::bootWorker() 메서드가 추가되었습니다.

  • CodeIgniter: 워커 요청 간 요청별 상태를 초기화하는 CodeIgniter::resetForWorkerMode() 메서드가 추가되었습니다.

  • Config: 워커 모드 설정(영구 서비스, 가비지 컬렉션)을 위한 app/Config/WorkerMode.php가 추가되었습니다.

  • Cookie: CookieInterface::EXPIRES_FORMAT이 RFC 7231의 권장 형식을 따르기 위해 D, d M Y H:i:s T로 변경되었습니다.

  • DatabaseConfig: 워커 모드에서 데이터베이스 연결 관리를 위한 Config::reconnectForWorkerMode()Config::cleanupForWorkerMode() 메서드가 추가되었습니다.

  • Events: Events::cleanupForWorkerMode() 메서드가 추가되었습니다.

  • Format: Config\Format::$jsonEncodeDepth를 통해 json_encode() 최대 깊이를 설정하는 지원이 추가되었습니다.

  • Paths: Paths::$envDirectory 속성을 통해 .env 파일의 위치를 변경하는 지원이 추가되었습니다.

  • Services: Services::resetForWorkerMode()Services::reconnectCacheForWorkerMode() 메서드가 추가되었습니다.

  • Toolbar: app/Config/Toolbar.php$disableOnHeaders 속성이 추가되었습니다.

  • Toolbar: 디버그 툴바 수집기를 초기화하는 Toolbar::reset() 메서드가 추가되었습니다.

사용 중단

  • ContentSecurityPolicy:
    • CodeIgniter\HTTP\ContentSecurityPolicy::$nonces 속성이 사용 중단되었습니다. 사용된 적이 없습니다.

  • Encryption:
    • CodeIgniter\Encryption\Handlers\SodiumHandler::parseParams() 메서드가 사용 중단되었습니다. 매개변수는 이제 encrypt()decrypt() 메서드에서 직접 처리됩니다.

  • Image:
    • Config\Image::libraryPath 설정 속성이 사용 중단되었습니다. 더 이상 사용되지 않습니다.

    • CodeIgniter\Images\Exceptions\ImageException::forInvalidImageLibraryPath 예외 메서드가 사용 중단되었습니다. 더 이상 사용되지 않습니다.

버그 수정

  • Cookie: CookieInterface::SAMESITE_STRICT, CookieInterface::SAMESITE_LAX, CookieInterface::SAMESITE_NONE 상수가 이제 프레임워크의 나머지 부분과 일관성을 위해 ucfirst 스타일로 작성됩니다.

  • Cache: WincacheHandler::increment()WincacheHandler::decrement()mixed 대신 bool을 반환하도록 변경되었습니다.

  • Entity: CodeIgniter\Entity\Entity::toArray() 호출 시 초기값을 복원하는 대신 항상 $_cast 값이 true로 변경되던 문제가 수정되었습니다.

  • Toolbar: 디버그 툴바가 활성화된 페이지에서 AJAX 유사 요청(HTMX, Turbo, Unpoly 등)을 수행할 때 최대 콜 스택 크기 초과 충돌이 발생하는 문제가 수정되었습니다.

수정된 버그의 전체 목록은 저장소의 CHANGELOG.md를 참조하세요.