배열에서 값이나 키를 찾을 때 어떤 함수를 쓸지 몰라서 헷갈린 경험이 있을까? 대부분의 PHP 개발자들은 습관적으로 in_array()를 사용하거나, 상황을 제대로 파악하지 못한 채 검색 결과에서 본 함수를 그냥 가져다 쓴다. 다만 각 함수의 차이를 정확히 모르면 성능 저하는 물론이고, 버그까지 야기할 수 있다. 이번에는 array_search(), in_array(), array_key_exists()의 정확한 차이, 언제 어떤 함수를 써야 하는지, 그리고 각각의 위험성을 완벽하게 정리해서 소개하겠다.
array_search(), in_array(), array_key_exists()는 각각 목적이 다르다. 먼저 각 함수가 뭘 하는 함수인지 이해하는 게 첫 번째다.
array_key_exists()는 배열에 특정 키가 존재하는지만 확인한다. 값이 뭔지는 상관없고, 키 자체의 존재 여부만 본다. 반환값은 true/false다.
in_array()는 배열에 특정 값이 있는지 찾는다. 하지만 키는 신경 쓰지 않는다. 값만 있으면 true를 반환한다.
array_search()는 배열에서 특정 값을 찾아서 그 값의 키를 반환한다. 값이 없으면 false를 반환한다. 쉽게 말해 in_array()의 키 반환 버전이다.
직접 코드를 보면서 차이를 명확히 해보자.
$users = array(
1 => 'Alice',
2 => 'Bob',
3 => 'Charlie'
);
// array_key_exists() - 키 존재 확인
if (array_key_exists(1, $users)) {
echo "키 1이 존재함"; // 출력됨
}
if (array_key_exists(4, $users)) {
echo "키 4가 존재함"; // 출력 안 됨
}
// in_array() - 값 존재 확인
if (in_array('Alice', $users)) {
echo "Alice가 있음"; // 출력됨
}
if (in_array('Dave', $users)) {
echo "Dave가 있음"; // 출력 안 됨
}
// array_search() - 값을 찾아서 키 반환
$key = array_search('Bob', $users);
if ($key !== false) {
echo "Bob은 키 " . $key . "에 있음"; // 출력됨: Bob은 키 2에 있음
}
$key = array_search('Eve', $users);
if ($key === false) {
echo "Eve는 없음"; // 출력됨
}
✓ 올바른 코드: array_search()는 키를 반환하므로 false와 반드시 ===로 비교해야 한다. 숫자 0이 키일 수 있기 때문이다.
이제 실무에서 각 함수를 언제 써야 하는지 구체적으로 살펴보자.
// 사용자 정보 배열 (키가 사용자 ID)
$userData = array(
101 => array('name' => 'Alice', 'email' => 'alice@example.com'),
102 => array('name' => 'Bob', 'email' => 'bob@example.com'),
103 => array('name' => 'Charlie', 'email' => 'charlie@example.com')
);
// ✗ 잘못된 코드
if (in_array('Alice', $userData)) { // 배열 값 전체를 검색하므로 느리고 비효율적
// 이 조건은 작동하지 않음
}
// ✓ 올바른 코드
$userId = 101;
if (array_key_exists($userId, $userData)) {
echo "사용자 " . $userData[$userId]['name'] . "이(가) 있음";
}
$allowedRoles = array('admin', 'editor', 'viewer');
// ✗ 잘못된 코드
if (array_key_exists('admin', $allowedRoles)) {
// 이건 키를 찾는 거라 작동 안 함. 배열 키는 0, 1, 2인데 'admin'을 찾으려니까
}
// ✓ 올바른 코드
$userRole = $_SESSION['role'];
if (in_array($userRole, $allowedRoles)) {
echo "권한이 있음";
}
$products = array(
'PROD001' => 'Laptop',
'PROD002' => 'Monitor',
'PROD003' => 'Keyboard'
);
// 상품명으로 상품 ID를 찾아야 할 때
$searchProduct = 'Monitor';
// ✗ 잘못된 코드
if (in_array($searchProduct, $products)) {
// 상품은 찾았지만, ID는 뭔지 알 수 없음
echo "상품이 있음";
}
// ✓ 올바른 코드
$productId = array_search($searchProduct, $products);
if ($productId !== false) {
echo "상품 ID: " . $productId; // 출력: 상품 ID: PROD002
}
$colors = array('red', 'green', 'blue');
// ✗ 잘못된 코드
if (array_search('red', $colors)) {
echo "빨강이 있음";
} else {
echo "빨강이 없음"; // 이게 출력됨! 키가 0이라 false로 판단됨
}
// ✓ 올바른 코드
if (array_search('red', $colors) !== false) {
echo "빨강이 있음"; // 이제 제대로 출력됨
}
$values = array(0, '1', '2', 3);
// ✗ 잘못된 코드 (느슨한 타입 비교)
if (in_array('0', $values)) {
echo "'0'이 있음"; // 출력됨! 0 == '0'이므로
}
// ✓ 올바른 코드 (엄격한 타입 비교)
if (in_array('0', $values, true)) {
echo "'0'이 있음"; // 출력 안 됨
}
$settings = array(
'theme' => 'dark',
'notification' => null
);
// ✗ 잘못된 코드 (isset 사용)
if (isset($settings['notification'])) {
echo "알림 설정이 있음"; // 출력 안 됨. null은 isset에서 false
}
// ✓ 올바른 코드 (array_key_exists 사용)
if (array_key_exists('notification', $settings)) {
echo "알림 설정 키가 있음"; // 출력됨. null이어도 키는 존재
}
| 상황 | 함수 | 반환값 | 예제 |
|---|---|---|---|
| 배열 키의 존재 여부만 확인 | array_key_exists() | true/false | array_key_exists('id', $user) |
| 배열 값의 존재 여부만 확인 | in_array() | true/false | in_array('admin', $roles) |
| 값을 찾아서 그 키를 알아야 함 | array_search() | 키 또는 false | $key = array_search('Bob', $users) |
| null 값까지 포함해서 키 존재 확인 | array_key_exists() | true/false | array_key_exists('setting', $config) |
| 값이 있는지만 빠르게 확인 (타입 안 중요) | in_array() | true/false | in_array($id, $allowedIds) |
수천 개의 요소가 있는 배열에서는 함수 선택이 성능을 크게 좌우한다. array_key_exists()는 해시 테이블 조회라 O(1) 상수 시간이지만, in_array()와 array_search()는 선형 검색이므로 O(n) 시간이 걸린다. 즉 배열이 클수록 in_array() 사용이 느려진다.
대규모 데이터를 자주 검색해야 하면, 배열을 키 기반으로 재구성하거나 isset()을 써서 키 검색으로 전환하는 게 훨씬 빠르다.
// ✗ 느린 코드 (10,000개 아이디 검색)
$userIds = array(1, 2, 3, ..., 10000);
for ($i = 0; $i < 1000; $i++) {
if (in_array($searchId, $userIds)) { // 매번 전체 배열 검색
// ...
}
}
// ✓빠른 코드 (키 기반 검색)
$userIds = array_flip(array(1, 2, 3, ..., 10000)); // 값과 키를 뒤집음
for ($i = 0; $i < 1000; $i++) {
if (isset($userIds[$searchId])) { // O(1) 해시 조회
// ...
}
}
배열 검색 함수 선택은 단순해 보이지만 버그와 성능 문제의 원인이 될 수 있다. array_key_exists()는 키 존재, in_array()는 값 존재, array_search()는 값으로 키를 찾을 때 쓴다는 점을 명확히 해두자. 특히 array_search()의 0 키 함정과 in_array()의 타입 비교, array_key_exists()의 null 값 처리는 반드시 기억해두고, 대규모 배열은 isset() 기반 키 검색으로 성능을 확보하는 습관을 들이면 훨씬 안정적인 코드를 만들 수 있을 것이다.