PHP 개발자들이 자주 쓰는 삼항 연산자(ternary operator)는 사실 꽤 장황하고 읽기 어렵다. 특히 변수가 null인지 확인하고 기본값을 할당할 때마다 isset() ? $var : $default 같은 코드를 반복하면서 코드가 금방 복잡해진다. 다만 PHP 7.0 이상에서 제공하는 Null Coalescing Operator(??)와 Spaceship Operator(<=>)를 정확히 이해하고 활용하는 개발자는 많지 않다. 이번에는 이 두 연산자가 정확히 뭔지, 왜 필요한지, 어떻게 쓰는지 실무 예제와 함께 완벽하게 정리해서 소개하겠다.

 

1단계: Null Coalescing Operator(??)란?

Null Coalescing Operator(??)는 변수가 null인지 확인하고 null이면 다른 값을 사용하도록 하는 간단한 문법이다. isset()과 비슷하지만 훨씬 간결하다.

기본 문법:

$result = $variable ?? $default;

이것은 다음과 같이 작동한다:

  • $variable이 null이 아니면 → $variable 반환
  • $variable이 null이면 → $default 반환
  • $variable이 정의되지 않았으면 → $default 반환 (Notice 에러 없음)

✗ 이전 방식 (장황함):

$user_name = isset($_GET['name']) ? $_GET['name'] : 'Guest';
$email = isset($userData['email']) ? $userData['email'] : 'no-email@example.com';

✓ Null Coalescing Operator 사용:

$user_name = $_GET['name'] ?? 'Guest';
$email = $userData['email'] ?? 'no-email@example.com';

결과 및 이점:

  • 코드가 35% 더 짧다
  • 읽기 쉽고 의도가 명확하다
  • Notice 에러가 발생하지 않는다 (정의되지 않은 변수 접근 안전)

 

2단계: 연쇄 Null Coalescing (Multiple Fallbacks)

여러 개의 기본값을 순차적으로 확인해야 할 때 ?? 를 연쇄적으로 사용할 수 있다.

✓ 올바른 사용:

$config = [
    'host' => null,
    'user' => 'admin'
];

// 여러 대체값 중 첫 번째 null이 아닌 값 선택
$hostname = $config['host'] ?? $config['user'] ?? 'localhost';
// 결과: 'admin' (host는 null, user는 'admin'이므로)

$port = $config['port'] ?? $_ENV['DB_PORT'] ?? 3306;
// 결과: 3306 (모두 null이므로 기본값)

결과 및 활용:

  • 설정값 우선순위를 명확하게 표현
  • 여러 소스(배열, 환경변수, 기본값)에서 순차적으로 확인
  • if 블록 없이 한 줄로 처리

 

3단계: Spaceship Operator (<=>) - 비교 연산자

Spaceship Operator(<=>)는 두 값을 비교해서 대소 관계를 정수로 반환한다. 정렬이나 대소 비교가 필요할 때 매우 유용하다.

기본 문법과 반환값:

$a <=> $b

// 반환값:
// -1 : $a < $b (a가 더 작음)
//  0 : $a == $b (같음)
//  1 : $a > $b (a가 더 큼)

✗ 이전 방식 (복잡함):

function compare_numbers($a, $b) {
    if ($a < $b) {
        return -1;
    } elseif ($a == $b) {
        return 0;
    } else {
        return 1;
    }
}

$result = compare_numbers(5, 10); // -1

✓ Spaceship Operator 사용:

$result = 5 <=> 10; // -1
$result = 5 <=> 5;  // 0
$result = 10 <=> 5; // 1

 

4단계: Spaceship Operator를 이용한 배열 정렬

Spaceship Operator의 진정한 가치는 usort() 같은 커스텀 정렬 함수에서 나타난다.

✗ 이전 방식 (복잡한 콜백):

$users = [
    ['name' => 'Alice', 'age' => 25],
    ['name' => 'Bob', 'age' => 20],
    ['name' => 'Charlie', 'age' => 30]
];

usort($users, function($a, $b) {
    if ($a['age'] < $b['age']) {
        return -1;
    } elseif ($a['age'] == $b['age']) {
        return 0;
    } else {
        return 1;
    }
});

✓ Spaceship Operator 사용:

$users = [
    ['name' => 'Alice', 'age' => 25],
    ['name' => 'Bob', 'age' => 20],
    ['name' => 'Charlie', 'age' => 30]
];

usort($users, function($a, $b) {
    return $a['age'] <=> $b['age'];
});

// 결과 (나이 순 정렬):
// Bob (20), Alice (25), Charlie (30)

여러 기준으로 정렬 (다중 조건):

// 부서로 먼저 정렬, 같은 부서면 나이로 정렬
usort($employees, function($a, $b) {
    $dept_cmp = $a['department'] <=> $b['department'];
    return $dept_cmp !== 0 ? $dept_cmp : $a['age'] <=> $b['age'];
});

 

5단계: 실전 예제 - API 응답 처리

실무에서 자주 마주치는 API 응답 처리 코드를 개선해보자.

✗ 이전 방식:

$api_response = [
    'status' => 'success',
    'data' => [
        'user' => null,
        'timestamp' => null
    ]
];

// 방어적 프로그래밍이 복잡함
$user_id = isset($api_response['data']['user']['id']) ? $api_response['data']['user']['id'] : 'unknown';
$created_at = isset($api_response['data']['timestamp']) ? $api_response['data']['timestamp'] : date('Y-m-d H:i:s');
$api_status = isset($api_response['status']) ? $api_response['status'] : 'pending';

✓ Null Coalescing으로 개선:

$api_response = [
    'status' => 'success',
    'data' => [
        'user' => null,
        'timestamp' => null
    ]
];

$user_id = $api_response['data']['user']['id'] ?? 'unknown';
$created_at = $api_response['data']['timestamp'] ?? date('Y-m-d H:i:s');
$api_status = $api_response['status'] ?? 'pending';

결과 및 장점:

  • 코드 길이 50% 단축
  • null 체크 로직이 명확
  • Notice 경고 없음

 

6단계: 주의사항 및 흔한 실수
상황✗ 잘못된 것✓ 올바른 것
null vs false 구분$flag = $config['enabled'] ?? true;
(false면 true로 설정됨)
$flag = isset($config['enabled']) ? $config['enabled'] : true;
(false 값을 보존)
배열 키 확인$value = $arr['key'] ?? 'default';
(E_NOTICE 발생 가능)
$value = $arr['key'] ?? 'default';
(PHP 7.0+에서는 안전)
Spaceship으로 존재 확인if ($a <=> $b) { }
(0은 false이므로 오류)
if (($a <=> $b) !== 0) { }
(결과가 0이 아니면)

 

7단계: 마무리 - 코드 품질을 높이는 연산자

Null Coalescing Operator(??)와 Spaceship Operator(<=>)는 PHP 7.0 이상에서 제공되는 강력한 도구다. 단순히 문법을 줄이는 것이 아니라 코드의 의도를 명확하게 표현하고 버그를 줄일 수 있다는 점이 핵심이다. 이 두 연산자를 습관적으로 사용하면, 가독성 높은 PHP 코드를 자연스럽게 작성할 수 있을 것이다. 지금 진행 중인 프로젝트에서 삼항 연산자나 복잡한 비교 로직을 찾아 이 글의 예제로 리팩토링해보면, 코드 품질의 눈에 띄는 향상을 체감할 수 있을 것이다.