DB에서 데이터를 조회한 뒤 PHP 단에서 특정 키(Key) 기준으로 연관 배열 목록을 재정렬해야 할 때, 매번 usort()나 array_multisort()의 복잡한 익명 함수 문법 때문에 애를 먹은 적이 있을 것이다.
다만 대부분의 개발자들은 array_multisort()에 인자를 전달하는 방식이나 usort()의 우주선 연산자(<=>) 작동 원리를 정확히 모른 채 인터넷에서 검색한 예제 코드를 복사해서 붙여넣곤 한다.
이번에는 다차원 배열 정렬이 왜 번거로운지, 이를 직관적으로 해결하는 array_sort_by_key() 서포트 함수가 왜 필요한지, 그리고 실무에서 어떻게 작성하고 활용하는지 완벽하게 정리해서 소개하겠다.
PHP 기본 내장 함수인 sort()나 asort()는 1차원 배열의 값이나 키를 정렬하는 데 최적화되어 있다.
하지만 실무에서 다루는 데이터는 대부분 데이터베이스 쿼리 결과나 JSON API 응답값처럼 배열 안에 연관 배열이 들어있는 다차원 구조(Array of Arrays 또는 Array of Objects)다.
예를 들어 회원 목록 데이터에서 'age' 내림차순이나 'created_at' 오름차순으로 정렬하려면 기본 함수만으로는 처리가 불가능하다.
| 함수명 | 정렬 대상 | 다차원 배열 특정 키 정렬 가능 여부 | 단점 및 실무 적용성 |
|---|---|---|---|
| sort() / rsort() | 1차원 배열 (값 기준) | 불가능 | 인덱스가 재배열되며 다차원 키 지정 불가 |
| usort() | 다차원 배열 (콜백 기준) | 가능 (콜백 작성 필요) | 매번 콜백 함수 작성 필요, 코드 가독성 저하 |
| array_multisort() | 여러 배열 또는 다차원 배열 | 가능 (컬럼 추출 필요) | array_column()으로 1차원 배열을 먼저 뽑아내야 해서 번거로움 |
매번 array_column()을 호출하여 컬럼 배열을 만들고 array_multisort()를 실행하는 것은 코드 중복을 야기하고 직관성을 떨어뜨린다.
따라서 우리가 원하는 것은 '대상 배열', '정렬 기준 키', '정렬 방향(ASC/DESC)' 단 3개의 인자만 전달하면 원본 인덱스를 보존하거나 재정렬하여 깔끔한 결과를 반환해주는 서포트 함수다.
if (!function_exists('array_sort_by_key')) {
/**
* 다차원 연관 배열을 특정 키 기준으로 정렬합니다.
*
* @param array $array 정렬할 다차원 배열
* @param string $key 정렬 기준이 되는 키
* @param int $sortOrder SORT_ASC 또는 SORT_DESC
* @param int $sortFlags SORT_REGULAR, SORT_NUMERIC, SORT_STRING 등
* @return array 정렬된 새 배열
*/
function array_sort_by_key(array $array, string $key, int $sortOrder = SORT_ASC, int $sortFlags = SORT_REGULAR): array
{
if (empty($array)) {
return [];
}
// 대상 키의 값만 1차원 배열로 추출
$columnValues = array_column($array, $key);
// 해당 키가 없는 요소가 있을 경우를 대비한 예외 처리
if (count($columnValues) !== count($array)) {
// usort 기반 안전한 대체 정렬
usort($array, function ($a, $b) use ($key, $sortOrder) {
$valA = $a[$key] ?? null;
$valB = $b[$key] ?? null;
if ($valA === $valB) {
return 0;
}
if ($sortOrder === SORT_ASC) {
return ($valA > $valB) ? 1 : -1;
} else {
return ($valA < $valB) ? 1 : -1;
}
});
return $array;
}
// array_multisort를 사용하여 효율적으로 정렬
array_multisort($columnValues, $sortOrder, $sortFlags, $array);
return $array;
}
}
사용자 목록 데이터에서 점수('score')를 기준으로 내림차순(SORT_DESC) 정렬하는 실무 상황을 비교해보자.
✗ 비효율적이거나 복잡한 기존 코드 방식:
$users = [
['name' => '김철수', 'score' => 85],
['name' => '이영희', 'score' => 92],
['name' => '박민수', 'score' => 78],
];
// 방법 1: usort 사용 (매번 클로저 작성 필요)
usort($users, function ($a, $b) {
return $b['score'] <=> $a['score']; // 내림차순
});
// 방법 2: array_multisort 사용 (임시 컬럼 배열 필요)
$scores = array_column($users, 'score');
array_multisort($scores, SORT_DESC, $users);
// 코드가 산만해지고 임시 변수가 생성됨✓ 서포트 함수를 활용한 올바른 개선 코드:
$users = [
['name' => '김철수', 'score' => 85],
['name' => '이영희', 'score' => 92],
['name' => '박민수', 'score' => 78],
];
// 서포트 함수 호출 한 줄로 직관적 처리
$sortedUsers = array_sort_by_key($users, 'score', SORT_DESC);
print_r($sortedUsers);출력 결과:
Array
(
[0] => Array
(
[name] => 이영희
[score] => 92
)
[1] => Array
(
[name] => 김철수
[score] => 85
)
[2] => Array
(
[name] => 박민수
[score] => 78
)
)
다차원 배열 정렬 서포트 함수를 사용할 때 개발자들이 자주 겪는 실수 3가지를 점검해보자.
1. 정렬 키가 누락된 요소가 포함된 경우
✗ 데이터 중 일부 배열에 정렬 기준 키가 존재하지 않으면 array_column()의 개수와 원본 배열의 개수가 달라져 array_multisort() 실행 시 Warning 에러가 발생한다.
✓ 위 서포트 함수 예제처럼 `count($columnValues) !== count($array)` 구문으로 검증하여, 키가 누락된 경우 `null` 병합 연산자(`??`)를 활용한 안전한 대체 정렬 로직(usort)으로 우회하도록 구현해야 한다.
2. 숫자 형태의 문자열 정렬 문제 ('10'이 '2'보다 앞에 오는 경우)
✗ 문자열 타입으로 작성된 숫자('100', '20', '5')를 기본 정렬 플래그(SORT_REGULAR)로 정렬하면 사전순으로 정렬되어 '100'이 '20'보다 앞에 오게 된다.
✓ 숫자로 비교해야 할 때는 함수 4번째 인자로 `SORT_NUMERIC` 플래그를 정확히 전달해야 한다.
// 숫자형 문자열 정렬 시 SORT_NUMERIC 활용
$products = [
['id' => 1, 'price' => '1000'],
['id' => 2, 'price' => '200'],
];
$sorted = array_sort_by_key($products, 'price', SORT_ASC, SORT_NUMERIC);
다차원 배열 정렬은 웹 개발에서 회원 목록, 상품 데이터, 게시글 리스트 등을 다룰 때 매일같이 접하는 작업이다.
매번 익명 콜백을 작성하거나 임시 배열을 만들어 array_multisort()를 호출하는 복잡한 방식 대신, 프로젝트 공통 유틸리티 파일에 array_sort_by_key() 같은 서포트 함수를 정의해두면 코드 생산성과 가독성이 비약적으로 향상된다.
PHP 다차원 배열 정렬 서포트 함수 구현은 코드의 가독성을 높이고 유지보수성을 극대화하는 핵심 요소다.
함수 하나를 잘 만들어 두는 작지만 실용적인 습관이 모여 가독성 높고 버그 없는 견고한 애플리케이션을 만든다는 점을 잊지 말자.
이 글의 2단계 코드 구현부를 참고해 프로젝트의 헬퍼/서포트 파일에 추가해두면, 복잡한 다차원 배열 정렬을 단 한 줄의 깔끔한 코드로 처리하는 최선의 결과를 얻을 수 있을 것이다.