Dico

isset vs empty 그리고 유사 연산자

   코드를 작성할 때 조건문과 마찬가지로 많이 활용하는 PHP 내장 함수 중 하나는 boolean 타입으로 전환할 수 있는 empty()입니다. 변수 선언 여부와 함께 value가 null이 아닌지 확인하는 isset()보다 상대적으로 범용적으로 쓰일 수 있는 empty()를 많이 사용합니다. 조건에 맞지 않을 경우 조기 종료(early exit)를 위해 사용하기도 하고, 변수에 기본값(default value)를 선언하기 위해 씁니다.

public function getArticle(int $ArticleNumber): ?Article
{
	// early exit
	if (empty(ArticleNumber)) {
		return null;
	}

	// code...

	return $article;
}

public function getPageNumber(): int
{
	if (!empty($this->page)) {
		return $this->page;
	}
	return 1; // default value
}

// or

public function getPageNumber(): int
{
	return !empty($this->page) ? $this->page : 1; // default value
}

   보통 위와 같이 함수를 사용하며, 상황에 따라 isset()이나 적절한 방법을 찾아 boolean 타입으로 전환합니다. 이를 표로 정리하여 살펴보면 다음과 같습니다.

$conditionisset($condition)is_null($condition)empty($condition)!!$condition
$condition;falsetruetrueUndefined variable
$condition = null;falsetruetruefalse
$condition = '';truefalsetruefalse
$condition = 'string';truefalsefalsetrue
$condition = '0';truefalsetruefalse
$condition = 0;truefalsetruefalse
$condition = 1;truefalsefalsetrue
$condition = [];truefalsetruefalse
$condition = [1];truefalsefalsetrue

   물론 이정도는 PHP를 한다는 사람이라면 누구나도 알고 있을 내용입니다. 여러 책에서도 앞 장에 등장하며, PHP Docs에도 잘 나와있습니다. 이번에 하고 싶은 이야기는 비교적 최근에 등장한 ?? 연산자와 오래전부터 존재한 ?: 연산자입니다.

   PHP 7.0에서 등장한 ?? 연산자는 과연 isset()과 동일한 결과값을 줄까요, !empty()와 동일한 결과값을 줄까요? 관심 깊게 살펴보지 않았다면 모르는 분들도 계실겁니다. 여기서 힌트는 ?? 연산자를 'null 병합 연산자'로 부른다는 사실입니다.

$message = null;
echo $message ?? 'not message'; // 'not message'

$message = '';
echo $message ?? 'not message'; // ''

$message = 'hello world';
echo $message ?? 'not message'; // 'hello world'

   ?? 연산자의 반환은 isset() 함수와 동일합니다. 따라서 !empty()와 같은 결과를 기대하고 쓴다면 프로그래밍 시 오류를 발생시킬 수 있습니다. 만약 !empty()와 동일한 결과를 얻고 싶은데, !empty()를 쓰고 싶지 않다면 PHP 5.3부터 존재한 ?: 연산자를 사용해야 합니다.

$message = null;
echo !empty($message) ? $message : 'not message'; // 'not message'
echo $message ?: 'not message'; // 'not message'

$message = '';
echo !empty($message) ? $message : 'not message'; // 'not message'
echo $message ?: 'not message'; // 'not message'

$message = 'hello world';
echo !empty($message) ? $message : 'not message'; // 'hello world'
echo $message ?: 'not message'; // 'hello world'

   ?: 연산자는 삼항연산자의 약어로 !!와 동일한 결과를 반환합니다. 여러 변수를 초기화할 때 유용하게 활용할 수 있지만, 개발 성향에 따라 호불호가 갈리기도 합니다. !!를 명시적으로 적는게 가독성이 더 높다는 분들도 있고, 반복적인 !!를 줄여 타이핑에 대한 피로도를 줄이자는 분들도 있습니다. 주변 개발자들에게 물어보았을 때는 경력에 따라 의견이 갈렸습니다.

   이 두 연산자는 호불호가 갈림에도 불구하고 PSR(PHP Standard Recommendation)과 같은 대표적인 PHP 표준 권고안에 규약 되어 있지 않습니다. 따라서 협업을 위한다면 추가적인 Convention을 통하여 개발자 간 합의가 필요해보입니다. 개발에 있어 중요한건 나의 의견이 아니라 협업을 위한 우리의 규칙입니다.