PHP 개발을 하다 보면 정말 자주 마주치는 에러가 있다. 바로 Warning: Undefined array key 메시지다. 특히 PHP 8.0 이상에서는 이전의 'Undefined index' 에러가 더 엄격하게 변했는데, 대부분의 개발자들은 이 에러가 정확히 뭔지, 왜 나타나는지, 어떻게 막아야 하는지 제대로 이해 못한 채 @(suppress) 연산자를 붙이거나 무작정 isset()을 감싸곤 한다.

이번에는 이 에러의 정확한 원인이 뭔지, 언제 생기는지, 그리고 실무에서 바로 적용할 수 있는 여러 가지 해결 방법을 완벽하게 정리해서 소개하겠다.

 

1단계: Warning: Undefined array key 에러 이해하기

이 에러는 배열에 존재하지 않는 키(key)에 접근하려고 할 때 발생한다. PHP 7.x 시대에는 'Undefined index'라는 경고(Warning)였지만, PHP 8.0부터는 더 명확하게 'Undefined array key'로 표기되며, 설정에 따라 Notice나 Warning으로 처리된다.

핵심은 이거다: 배열의 키가 존재하는지 먼저 확인하지 않고 접근하면 이 에러가 난다.

예를 들어, 폼 데이터나 외부 API 응답, 데이터베이스 쿼리 결과처럼 예측 불가능한 데이터를 다룰 때 특히 자주 나타난다. 사용자가 특정 필드를 입력하지 않았거나, API 응답 구조가 바뀌었거나, 데이터베이스에 컬럼이 없을 수 있기 때문이다.

 

2단계: 상세 해결 방법 5가지

 

방법 1: isset() 함수로 확인 (가장 기본)

✗ 잘못된 코드 (에러 발생)

<?php
$data = ['name' => 'John', 'email' => 'john@example.com'];
echo $data['phone']; // Warning: Undefined array key "phone"
?>

✓ 올바른 코드

<?php
$data = ['name' => 'John', 'email' => 'john@example.com'];

if (isset($data['phone'])) {
    echo $data['phone'];
} else {
    echo '전화번호 정보 없음';
}
?>

설명: isset()은 키가 존재하고 NULL이 아닌지 확인한다. 조건부로 접근하면 에러를 완벽하게 막을 수 있다.

 

방법 2: array_key_exists() 함수 (NULL 값도 감지)

✗ 잘못된 경우

<?php
$data = ['name' => 'John', 'phone' => null];

if (isset($data['phone'])) { // isset은 NULL을 감지 못함
    echo "전화: " . $data['phone'];
} else {
    echo '전화번호 없음'; // 이 부분 출력됨
}
?>

✓ 올바른 코드

<?php
$data = ['name' => 'John', 'phone' => null];

if (array_key_exists('phone', $data)) {
    echo "전화: " . ($data['phone'] ?? '정보 없음');
} else {
    echo '전화번호 필드 자체가 없음';
}
?>

설명: array_key_exists()는 키의 존재 여부만 확인하므로, 값이 NULL이어도 감지한다. 데이터 구조가 명확할 때 유용하다.

 

방법 3: Null Coalescing 연산자 ??: (가장 간결)

✗ 잘못된 코드

<?php
$_GET = ['search' => ''];
$query = $_GET['keyword']; // Warning: Undefined array key "keyword"
?>

✓ 올바른 코드

<?php
$_GET = ['search' => ''];
$query = $_GET['keyword'] ?? '검색어 없음';
echo $query; // '검색어 없음'
?>

설명: ?? 연산자는 왼쪽 값이 존재하지 않으면 오른쪽 기본값을 반환한다. PHP 7.0 이상에서만 작동하지만, 코드가 깔끔하다.

 

방법 4: Null Coalescing Assignment 연산자 ??= (PHP 7.4+)

✓ 올바른 코드

<?php
$config = ['host' => 'localhost'];
$config['port'] ??= 3306; // port가 없으면 3306 할당
$config['user'] ??= 'root'; // user가 없으면 'root' 할당

var_dump($config);
// Array ( [host] => localhost [port] => 3306 [user] => root )
?>

설명: ??= 는 키가 없거나 NULL일 때만 값을 할당한다. 설정값 초기화할 때 매우 유용하다.

 

방법 5: 서포트 함수 array_get() 제작 (재사용성 높음)

✓ 재사용 가능한 서포트 함수

<?php
function array_get($array, $key, $default = null) {
    if (is_array($array) && array_key_exists($key, $array)) {
        return $array[$key];
    }
    return $default;
}

// 사용 예제
$user = ['name' => 'Alice', 'email' => 'alice@example.com'];

echo array_get($user, 'name'); // 'Alice'
echo array_get($user, 'phone', 'N/A'); // 'N/A'
echo array_get($user, 'address', '주소 없음'); // '주소 없음'
?>

설명: 복잡한 배열 구조나 여러 곳에서 데이터에 접근할 때, 이 함수를 만들어두면 코드 가독성이 훨씬 좋다.

 

3단계: 실전 예제 - 폼 데이터 처리

✗ 잘못된 코드 (여러 에러 발생)

<?php
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
    $name = $_POST['name'];
    $email = $_POST['email'];
    $phone = $_POST['phone']; // Warning: Undefined array key "phone"
    $message = $_POST['message']; // Warning: Undefined array key "message"
    
    // 저장 로직...
}
?>

✓ 올바른 코드 (안전한 처리)

<?php
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
    $name = $_POST['name'] ?? '';
    $email = $_POST['email'] ?? '';
    $phone = $_POST['phone'] ?? ''; // 선택 필드
    $message = $_POST['message'] ?? ''; // 선택 필드
    
    // 유효성 검사
    if (empty($name) || empty($email)) {
        die('필수 필드를 입력하세요.');
    }
    
    // 저장 로직...
    echo '정보 저장 완료';
}
?>

설명: 사용자 입력 데이터는 예측 불가능하므로 항상 ?? 연산자나 isset()으로 기본값을 지정하고, 필수 필드는 empty()로 검사한다.

 

4단계: 주의사항과 흔한 실수
상황 ✗ 잘못된 방법 ✓ 올바른 방법
NULL 값 구분 필요 isset($array['key'])
(NULL 값을 감지 못함)
array_key_exists('key', $array)
(키 존재 여부만 확인)
빠른 기본값 설정 if (isset(...)) { ... } else { ... } $var = $array['key'] ?? 'default';
에러 무시 (나쁜 관행) @$array['key']
(에러만 숨김, 디버깅 어려움)
array_get($array, 'key')
(구조화된 처리)
중첩 배열 접근 $data['user']['phone']
(중간에 없으면 에러)
$data['user']['phone'] ?? null
(각 단계마다 ?? 처리)

 

5단계: PHP 8 이상에서 에러 레벨 설정 (선택사항)

php.ini에서 에러 리포팅 레벨을 조정할 수 있지만, 근본 해결은 아니다.

<?php
// 임시로 경고 억제 (권장하지 않음)
error_reporting(E_ALL & ~E_WARNING);

// 또는
ini_set('display_errors', 0);
?>

경고: 에러 메시지를 숨기는 것은 버그 추적을 어렵게 만든다. 반드시 코드 자체를 수정하는 것이 정답이다.

 

마무리

Warning: Undefined array key 에러는 배열 접근의 안전성 문제를 지적하는 PHP의 친절한 경고다. 이 에러를 무시하거나 억제하는 대신, 위의 5가지 방법(isset, array_key_exists, ??, ??=, array_get) 중 상황에 맞는 것을 선택해 처리하면 된다.

특히 사용자 입력, 외부 API 응답, 데이터베이스 결과처럼 구조를 신뢰할 수 없는 데이터를 다룰 때는 항상 배열 키 존재 여부를 먼저 확인하는 습관을 들이자. 이런 작은 방어 코딩이 모여서 버그 없는 안정적인 서버를 만드는 것이다. 이 글의 '서포트 함수 array_get()' 부분을 참고해 프로젝트에 추가하면, 향후 배열 접근 에러로 고민할 일이 훨씬 줄어들 것이다.