JavaScript 배열 정렬: `sort()` 메서드 완벽 활용 가이드
JavaScript에서 배열을 정렬하는 것은 매우 흔한 작업입니다. sort()
메서드를 사용하면 간단하게 배열을 정렬할 수 있지만, 문자열과 숫자를 정렬하는 방식에 미묘한 차이가 있어 주의가 필요합니다. 이 가이드에서는 sort()
메서드의 기본적인 사용법부터 복잡한 객체 배열 정렬까지 자세히 다루며, 각 예제에 상세한 주석을 달아 설명해 드립니다.
1. 문자열 배열 오름차순 정렬 (기본 `sort()` 동작)
sort()
메서드는 **기본적으로 배열 요소를 문자열로 변환하여 유니코드(UTF-16) 코드 포인트 값에 따라 오름차순으로 정렬**합니다. 따라서 문자열 배열의 경우, 추가적인 설정 없이도 원하는 결과를 얻을 수 있습니다.
// 과일 이름 문자열 배열 선언
const fruits = ["Banana", "Orange", "Apple", "Mango"];
// fruits 배열을 알파벳 순서(오름차순)로 정렬합니다.
// sort() 메서드는 기본적으로 배열 요소를 문자열로 변환하여 유니코드 값에 따라 정렬합니다.
fruits.sort();
// 정렬된 배열을 콘솔에 출력합니다.
// 예상 출력: ["Apple", "Banana", "Mango", "Orange"]
console.log("문자열 배열 오름차순 정렬:", fruits);
2. 숫자 배열 오름차순 정렬 (비교 함수 사용 필수!)
숫자 배열을 sort()
메서드만으로 정렬하면 예상과 다른 결과가 나올 수 있습니다. 예를 들어, [10, 2, 1]
을 정렬하면 [1, 10, 2]
가 될 수 있는데, 이는 '10'이 '2'보다 '1' 다음에 오기 때문입니다. 숫자 정렬을 위해서는 반드시 **비교 함수(compare function)**를 제공해야 합니다.
오름차순 정렬의 비교 함수: a - b
a - b
의 결과가 음수면a
가b
보다 앞에 옵니다.a - b
의 결과가 양수면b
가a
보다 앞에 옵니다.a - b
의 결과가 0이면 순서가 변경되지 않습니다.
// 숫자 배열 선언
const numbersAsc = [40, 100, 1, 5, 25, 10];
// numbersAsc 배열을 숫자 값 기준 오름차순으로 정렬합니다.
// sort() 메서드에 비교 함수(compareFunction)를 인자로 전달합니다.
// 이 함수는 배열의 두 요소(a, b)를 비교하여 정렬 순서를 결정합니다.
numbersAsc.sort(function(a, b) {
// a - b가 음수이면, a가 b보다 작다는 의미이므로 a가 b보다 먼저 위치합니다.
// a - b가 양수이면, b가 a보다 작다는 의미이므로 b가 a보다 먼저 위치합니다.
// 결과적으로 작은 숫자가 앞으로 오게 되어 오름차순 정렬이 됩니다.
return a - b;
});
// 정렬된 배열을 콘솔에 출력합니다.
// 예상 출력: [1, 5, 10, 25, 40, 100]
console.log("숫자 배열 오름차순 정렬:", numbersAsc);
3. 숫자 배열 내림차순 정렬 (비교 함수 사용 필수!)
내림차순 정렬 역시 비교 함수를 사용해야 합니다.
내림차순 정렬의 비교 함수: b - a
b - a
의 결과가 음수면b
가a
보다 앞에 옵니다.b - a
의 결과가 양수면a
가b
보다 앞에 옵니다.b - a
의 결과가 0이면 순서가 변경되지 않습니다.
// 숫자 배열 선언
const numbersDesc = [40, 100, 1, 5, 25, 10];
// numbersDesc 배열을 숫자 값 기준 내림차순으로 정렬합니다.
numbersDesc.sort(function(a, b) {
// b - a가 음수이면, b가 a보다 작다는 의미이므로 b가 a보다 먼저 위치합니다.
// b - a가 양수이면, a가 b보다 작다는 의미이므로 a가 b보다 먼저 위치합니다.
// 결과적으로 큰 숫자가 앞으로 오게 되어 내림차순 정렬이 됩니다.
return b - a;
});
// 정렬된 배열을 콘솔에 출력합니다.
// 예상 출력: [100, 40, 25, 10, 5, 1]
console.log("숫자 배열 내림차순 정렬:", numbersDesc);
4. 객체 배열 정렬: 특정 숫자 속성 기준
객체로 이루어진 배열을 정렬할 때는 객체 내부의 특정 속성(예: age
, price
, score
등)을 기준으로 정렬해야 합니다. 이때도 숫자 정렬과 마찬가지로 비교 함수를 사용하여 해당 속성 값들을 비교합니다.
// 이름과 나이를 가진 객체들의 배열 선언
const people = [
{ name: "John", age: 30 },
{ name: "Doe", age: 25 },
{ name: "Jane", age: 35 },
{ name: "Peter", age: 25 }
];
// ----------------------------------------------------
// 나이(age) 속성을 기준으로 오름차순 정렬
// ----------------------------------------------------
// people 배열을 각 객체의 'age' 속성 값을 기준으로 오름차순 정렬합니다.
people.sort(function(a, b) {
// a.age - b.age를 통해 두 객체의 나이를 비교합니다.
// 결과가 음수이면 a 객체가 b 객체보다 앞에 위치하고, 양수이면 b 객체가 앞에 위치합니다.
return a.age - b.age;
});
console.log("나이 기준 객체 배열 오름차순 정렬:", people);
/* 예상 출력:
[
{ name: 'Doe', age: 25 },
{ name: 'Peter', age: 25 }, // age가 같을 경우, 초기 순서 유지 (stable sort) 또는 브라우저마다 다를 수 있음
{ name: 'John', age: 30 },
{ name: 'Jane', age: 35 }
]
*/
// ----------------------------------------------------
// 나이(age) 속성을 기준으로 내림차순 정렬
// ----------------------------------------------------
// people 배열을 각 객체의 'age' 속성 값을 기준으로 내림차순 정렬합니다.
people.sort(function(a, b) {
// b.age - a.age를 통해 두 객체의 나이를 비교합니다.
// 결과가 음수이면 b 객체가 a 객체보다 앞에 위치하고, 양수이면 a 객체가 앞에 위치합니다.
return b.age - a.age;
});
console.log("나이 기준 객체 배열 내림차순 정렬:", people);
/* 예상 출력:
[
{ name: 'Jane', age: 35 },
{ name: 'John', age: 30 },
{ name: 'Doe', age: 25 },
{ name: 'Peter', age: 25 }
]
*/
5. 객체 배열 정렬: 특정 문자열 속성 기준 (`localeCompare()`)
객체 배열을 문자열 속성(예: name
, city
등)을 기준으로 정렬하려면 localeCompare()
메서드를 사용하는 것이 좋습니다. 이 메서드는 **다양한 언어 및 로케일에 따른 문자열 비교를 올바르게 처리**해 주기 때문에, 단순히 <
나 >
연산자를 사용하는 것보다 훨씬 정확합니다.
// 도시 이름과 인구를 가진 객체들의 배열 선언
const cities = [
{ name: "Seoul", population: 9700000 },
{ name: "Busan", population: 3400000 },
{ name: "Jeju", population: 670000 },
{ name: "Daegu", population: 2400000 }
];
// ----------------------------------------------------
// 도시 이름(name) 속성을 기준으로 오름차순 정렬
// ----------------------------------------------------
// cities 배열을 각 객체의 'name' 속성 값을 기준으로 오름차순 정렬합니다.
cities.sort(function(a, b) {
// a.name.localeCompare(b.name)을 사용하여 두 도시 이름을 비교합니다.
// localeCompare()는 현재 로케일에 맞는 문자열 비교를 수행하여
// - 음수: a가 b보다 앞에 와야 함
// - 양수: b가 a보다 앞에 와야 함
// - 0: 순서 변경 없음
// 을 반환합니다.
return a.name.localeCompare(b.name);
});
console.log("이름 기준 객체 배열 오름차순 정렬:", cities);
/* 예상 출력:
[
{ name: 'Busan', population: 3400000 },
{ name: 'Daegu', population: 2400000 },
{ name: 'Jeju', population: 670000 },
{ name: 'Seoul', population: 9700000 }
]
*/
// ----------------------------------------------------
// 도시 이름(name) 속성을 기준으로 내림차순 정렬
// ----------------------------------------------------
// cities 배열을 각 객체의 'name' 속성 값을 기준으로 내림차순 정렬합니다.
cities.sort(function(a, b) {
// b.name.localeCompare(a.name)을 사용하여 역순으로 비교합니다.
return b.name.localeCompare(a.name);
});
console.log("이름 기준 객체 배열 내림차순 정렬:", cities);
/* 예상 출력:
[
{ name: 'Seoul', population: 9700000 },
{ name: 'Jeju', population: 670000 },
{ name: 'Daegu', population: 2400000 },
{ name: 'Busan', population: 3400000 }
]
*/
`sort()` 메서드와 비교 함수에 대한 핵심 정리
원본 배열 변경 (In-place sort)
sort()
메서드는 **원본 배열 자체를 변경**합니다. 만약 원본 배열을 유지하면서 정렬된 새로운 배열을 얻고 싶다면, sort()
를 호출하기 전에 slice()
메서드를 사용하여 배열의 복사본을 만들어야 합니다.
const originalNumbers = [40, 10, 1];
// slice()를 사용하여 원본 배열의 복사본을 만들고, 그 복사본을 정렬합니다.
const sortedNumbers = originalNumbers.slice().sort((a, b) => a - b);
console.log("원본 배열 (변화 없음):", originalNumbers); // 출력: [40, 10, 1]
console.log("정렬된 새로운 배열:", sortedNumbers); // 출력: [1, 10, 40]
비교 함수의 반환 값 의미
compareFunction(a, b)
의 반환 값이 **음수**이면,a
가b
보다 **먼저** 와야 합니다.compareFunction(a, b)
의 반환 값이 **양수**이면,b
가a
보다 **먼저** 와야 합니다.compareFunction(a, b)
의 반환 값이 **0**이면, 두 요소의 상대적인 순서는 **변경되지 않습니다** (하지만 JavaScript 엔진의 구현에 따라 달라질 수 있으므로, 안정적인 정렬을 위해서는 0이 반환되지 않도록 비교 함수를 설계하는 것이 좋습니다).
이 가이드가 여러분의 블로그 게시물에 도움이 되기를 바랍니다! JavaScript 배열 정렬에 대해 더 궁금한 점이 있으시다면 언제든지 질문해주세요.
댓글 없음:
댓글 쓰기