배열에서 특정 키들만 빼내야 할 때가 있다. 보통 개발자들은 반복문을 돌려서 foreach로 하나씩 담거나, 더 복잡한 경우 정규표현식을 섞어가며 처리한다. 다만 PHP에서 제공하는 array_keys() 함수의 정확한 동작과 검색 필터링 옵션을 모르는 경우가 많다. 이번에는 array_keys()의 기본 사용법부터 검색 값 필터링, 엄격한 타입 비교까지 완벽하게 정리해서 소개하겠다.

 

1단계. array_keys() 기초 이해하기

array_keys()는 배열의 모든 키를 새로운 배열로 반환하는 함수다. 단순하게 들리지만, 선택적 매개변수로 특정 값을 가진 키만 필터링할 수 있다.

함수 선언은 다음과 같다.

array_keys(array $array, mixed $filter = null, bool $strict = false): array

매개변수를 설명하면 첫 번째는 대상 배열, 두 번째는 선택적 검색 값, 세 번째는 타입 엄격 비교 여부다.

 

기본 사용법. 모든 키 추출
$user = array(
    'id' => 1,
    'name' => 'John',
    'email' => 'john@example.com',
    'status' => 'active'
);

$keys = array_keys($user);
print_r($keys);
// 출력: Array ( [0] => id [1] => name [2] => email [3] => status )

모든 키가 새 배열로 반환되고, 원본 배열의 타입(연관 배열)과 관계없이 항상 0부터 시작하는 인덱스 배열로 반환된다.

 

2단계. 검색 값으로 필터링된 키 추출

두 번째 매개변수에 값을 지정하면, 그 값을 가진 키들만 반환된다.

$roles = array(
    'admin' => 'active',
    'editor' => 'active',
    'viewer' => 'inactive',
    'guest' => 'inactive'
);

$active_roles = array_keys($roles, 'active');
print_r($active_roles);
// 출력: Array ( [0] => admin [1] => editor )

이렇게 하면 'active' 값을 가진 키들(admin, editor)만 추출된다. 반복문으로 하나하나 확인하는 것보다 훨씬 간결하다.

 

숫자 값 필터링 시 주의. 타입 자동 변환

숫자를 다룰 때는 타입 자동 변환으로 예상 밖의 결과가 나올 수 있다.

✗ 잘못된 방식 (타입 변환으로 오류)

$scores = array(
    'player1' => 100,
    'player2' => '100',
    'player3' => 50,
    'player4' => true
);

$result = array_keys($scores, 100);
print_r($result);
// 출력: Array ( [0] => player1 [1] => player2 [2] => player4 )
// player2(문자 '100')와 player4(true)까지 매칭됨. 왜? PHP에서 100 == '100' == true이기 때문

이 문제를 해결하려면 세 번째 매개변수 $strict를 true로 설정해야 한다.

✓ 올바른 방식 (엄격한 타입 비교)

$scores = array(
    'player1' => 100,
    'player2' => '100',
    'player3' => 50,
    'player4' => true
);

$result = array_keys($scores, 100, true);
print_r($result);
// 출력: Array ( [0] => player1 )
// player1만 정확히 int 100과 일치

세 번째 인자를 true로 주면 === 연산자로 비교하므로, 타입과 값이 완벽히 일치해야만 필터링된다.

 

3단계. 실전 예제. 설정 검증 및 상태 그룹핑
사용 예시 1. 활성화된 설정 키만 추출
$config = array(
    'database_enabled' => true,
    'cache_enabled' => false,
    'logging_enabled' => true,
    'email_enabled' => false,
    'api_enabled' => true
);

// 활성화된 기능들의 키만 필요할 때
$enabled_features = array_keys($config, true);
echo implode(', ', $enabled_features);
// 출력: database_enabled, logging_enabled, api_enabled

// 이를 이용해 활성화된 모듈만 로드
foreach ($enabled_features as $feature) {
    load_module($feature);
}

설정 배열에서 true 값을 가진 기능들만 추출해서 초기화 로직에 사용한다. 반복문 없이도 필요한 키만 간단히 뽑아낼 수 있다.

사용 예시 2. 주문 상태별로 키 분류
$orders = array(
    'order_001' => 'completed',
    'order_002' => 'pending',
    'order_003' => 'completed',
    'order_004' => 'cancelled',
    'order_005' => 'pending',
    'order_006' => 'completed'
);

// 상태별로 주문 번호 분류
$completed = array_keys($orders, 'completed');
$pending = array_keys($orders, 'pending');
$cancelled = array_keys($orders, 'cancelled');

echo "완료: " . count($completed) . "건\n";
echo "대기: " . count($pending) . "건\n";
echo "취소: " . count($cancelled) . "건\n";
// 출력:
// 완료: 3건
// 대기: 2건
// 취소: 1건

대량의 배열 데이터를 상태별로 분류할 때 매우 유용하다. 데이터베이스 쿼리 결과나 API 응답을 빠르게 그룹화할 수 있다.

 

4단계. 주의사항. 흔한 실수와 해결책
실수 1. 검색 값이 없을 때 빈 배열 반환
✗ 잘못된 처리

$status = array(
    'user_1' => 'online',
    'user_2' => 'offline',
    'user_3' => 'online'
);

$sleeping = array_keys($status, 'sleeping');
echo count($sleeping); // 출력: 0

// 이 후 코드에서 $sleeping[0]에 접근하면 Notice 발생
echo $sleeping[0]; // PHP Warning: Undefined array key 0

검색 값이 배열에 없으면 빈 배열이 반환된다. 후속 처리에서 결과 배열을 바로 접근하면 오류가 난다.

✓ 올바른 처리

$status = array(
    'user_1' => 'online',
    'user_2' => 'offline',
    'user_3' => 'online'
);

$sleeping = array_keys($status, 'sleeping');

if (empty($sleeping)) {
    echo "해당 상태의 사용자가 없습니다.";
} else {
    foreach ($sleeping as $user_id) {
        notify_user($user_id);
    }
}

항상 결과 배열이 비어있을 가능성을 고려해서 empty() 체크를 먼저 하자.

실수 2. 숫자 키와 문자 키 혼동
✗ 잘못된 사용

$mixed = array(
    1 => 'apple',
    '1' => 'orange',  // 동일한 키로 덮어씌워짐
    2 => 'banana'
);

$keys = array_keys($mixed);
print_r($keys);
// 출력: Array ( [0] => 1 [1] => 2 )
// 실제로는 문자 '1'은 정수 1로 변환되어 오버라이드됨

PHP는 숫자 문자열을 자동으로 정수로 변환한다. 의도하지 않은 키 중복이 발생할 수 있다.

✓ 올바른 방식

$mixed = array(
    1 => 'apple',
    'first' => 'orange',  // 문자 키로 명확히 구분
    2 => 'banana'
);

$keys = array_keys($mixed);
print_r($keys);
// 출력: Array ( [0] => 1 [1] => first [2] => 2 )

키를 명확하게 문자열로 작성해서 혼동을 피하자.

실수 3. 다차원 배열에서 첫 레벨 키만 추출
$users = array(
    'admin' => array('name' => 'Alice', 'role' => 'admin'),
    'editor' => array('name' => 'Bob', 'role' => 'editor'),
    'viewer' => array('name' => 'Charlie', 'role' => 'viewer')
);

$keys = array_keys($users);
print_r($keys);
// 출력: Array ( [0] => admin [1] => editor [2] => viewer )
// 중첩 배열 내부의 키는 추출 불가

array_keys()는 첫 번째 레벨의 키만 추출한다. 중첩 배열 내부의 키가 필요하면 재귀 함수로 별도 처리해야 한다.

 

5단계. 핵심 정리 및 다음 단계

array_keys()는 배열 키 추출이라는 단순한 역할을 넘어, 검색 값 필터링과 엄격한 타입 비교로 강력한 데이터 분류 도구가 된다. 상태별 주문 분류, 활성화된 설정 추출, 사용자 역할 필터링 같은 실무에서 자주 마주치는 작업들을 한 줄의 함수 호출로 처리할 수 있다는 점이 핵심이다. 세 번째 매개변수 $strict를 true로 설정하면 타입 강제 변환으로 인한 예상 밖의 매칭을 완벽히 차단할 수 있으니, 숫자나 boolean 값을 다룰 때는 반드시 기억해두자. 이 글의 '검색 값 필터링' 부분과 '엄격한 타입 비교' 코드를 참고해 현재 프로젝트의 배열 필터링 로직을 점검해보면, 불필요한 반복문을 제거하고 코드 가독성을 한 단계 끌어올릴 수 있을 것이다.