PHP 8의 새로운 내장 예외, ValueError란?
PHP 8에는 새로운 내장 예외인 ValueError가 도입되었습니다. 함수에 전달한 값이 타입 자체는 유효하지만 해당 연산에 사용할 수 없는 값일 때 PHP가 이 예외를 던집니다(throw). 이전 버전의 PHP에서는 이런 상황에서 단순히 Warning 경고만 출력되었지만, PHP 8부터는 ValueError가 발생하여 문제를 훨씬 명확하게 알려줍니다.
개념을 정리하면 다음과 같습니다.
- TypeError: 인자의 타입 자체가 잘못된 경우 발생
- ValueError: 타입은 올바르지만 값이 유효하지 않은 경우 발생
예제 1: 유효하지 않은 값으로 인한 ValueError
<?php
declare(strict_types=1);
array_rand([1,2,3], 0);
json_decode('{}', true, -1);
?>
출력 결과:
Fatal error: Uncaught ValueError: array_rand(): Argument #2 ($num) must be between 1 and the number of elements in the array
위 코드에서 array_rand()의 두 번째 인자로 0을 전달했습니다. 정수(int)라는 타입 자체는 유효하지만, "배열에서 뽑을 요소 개수"라는 용도로는 허용되지 않는 값이므로 PHP 8은 ValueError를 던집니다. 마찬가지로 json_decode()의 세 번째 인자(재귀 깊이)에 음수(-1)를 전달하면 json_decode(): Argument #3 ($depth) must be greater than 0 오류가 발생합니다.
예제 2: 타입은 유효하지만 결과가 false인 경우
<?php
$x = strpos("h", "hello", 16);
var_dump($x);
?>
출력 결과:
bool(false)
이 예제에서는 모든 인자의 타입(string, int)이 올바르기 때문에 ValueError가 발생하지 않습니다. 대신 strpos()는 지정된 오프셋 이후에서 문자열을 찾지 못하고 단순히 false를 반환합니다. 즉, 전달된 값의 타입이 유효한지 여부와 함수의 실행 결과는 서로 별개의 문제라는 점을 이해하는 것이 중요합니다.
try-catch로 ValueError 처리하기
ValueError는 일반적인 예외이므로 try-catch 블록을 사용해 우아하게 처리할 수 있습니다.
<?php
try {
array_rand([1,2,3], 0);
} catch (ValueError $e) {
echo 'ValueError 발생: ' . $e->getMessage();
}
?>
이처럼 PHP 8의 ValueError를 활용하면 런타임에 함수에 전달된 값이 연산에 적합한지 명확하게 검증할 수 있으며, 문제가 있는 값을 사전에 감지해 안전하게 처리할 수 있습니다. 기존의 모호한 Warning 메시지 대신 구체적인 예외 정보를 제공하므로, 디버깅과 코드 품질 관리 측면에서 큰 이점을 얻을 수 있습니다.