HOWTO · JavaScript
JavaScript에서 두 배열 비교
이 튜토리얼에서는 JavaScript에서 두 배열을 비교하는 몇 가지 방법을 소개합니다.
이 페이지의 내용
JavaScript의 === 연산자는 배열의 내용을 비교하지 않고 참조를 비교하므로, 내용이 같더라도 별도로 만든 두 배열은 이 비교에서 같지 않습니다. 배열의 내용을 비교하려면 순서와 요소 값에 적용할 규칙을 먼저 정해야 합니다. 같은 순서의 원시 값을 비교할 때는 길이를 확인한 다음 각 위치의 요소를 비교하세요. JSON.stringify()는 직렬화 규칙이 데이터에 맞을 때만 사용하고, 순서가 중요하지 않다면 복사본을 정렬해 비교하세요. 이러한 기본 방법은 중첩 배열과 객체를 구조가 아닌 참조로 비교합니다.
두 배열이 같다는 것은 무엇을 의미할까요?
먼저 작업에서 ‘같다’는 말이 무엇을 뜻하는지 정하세요. 순서가 중요한 비교에서는 길이가 같고 모든 인덱스의 값이 일치해야 합니다. 순서와 무관한 비교에서는 배열을 모음으로 취급하지만, 중복 값도 고려해야 합니다. 예를 들어 [1, 1, 2]와 [1, 2, 2]는 서로 다른 값의 종류가 같다는 이유만으로 동등하지 않습니다.
요소를 얕게 비교할지, 구조까지 비교할지도 정해야 합니다. 엄격한 동등성은 숫자나 문자열 같은 원시 값이 일치하는지 확인할 때 적합합니다. 객체와 중첩 배열의 경우 엄격한 동등성은 두 위치가 같은 객체를 참조하는지 확인하며, 객체의 속성이나 내부 내용을 비교하지 않습니다.
루프 또는 Array.prototype.every()로 배열을 순서대로 비교하기
독립 함수로 구현하면 기본 제공 Array.prototype을 수정하지 않아도 됩니다. 다음 버전은 먼저 길이를 확인한 다음 대응하는 값들을 엄격한 동등성으로 비교합니다. 순서가 중요하고 비교가 얕은 방식입니다.
이 예제를 실행해 보세요:
이 섹션의 코드와 표시되는 레이블 또는 출력은 영어로 유지됩니다.
function arraysEqual(left, right) {
if (left.length !== right.length) return false;
return left.every((value, index) => value === right[index]);
}
const first = ["red", "green", "blue"];
const second = ["red", "green", "blue"];
console.log(arraysEqual(first, second));
true
값이 달라지거나 길이가 다른 경우에도 함수는 일치하지 않는 것으로 판단합니다. 다음 추가 호출은 실행되지 않은 예시입니다:
function arraysEqual(left, right) {
if (left.length !== right.length) return false;
return left.every((value, index) => value === right[index]);
}
console.log(arraysEqual(["red", "green"], ["red", "blue"]));
console.log(arraysEqual(["red", "green"], ["red", "green", "blue"]));
첫 번째 호출은 두 번째 요소가 다르므로 false를 반환하고, 두 번째 호출은 배열 길이가 다르므로 false를 반환합니다.
각 인덱스의 비교 방식을 직접 조정하려면 for 루프로 같은 규칙을 구현할 수 있습니다. 길이가 다르면 일치하지 않는 것으로 처리하고, 처음 불일치하는 위치에서 false를 반환하며, 모든 위치가 일치하면 true를 반환합니다. Array.prototype.every()를 사용하면 코드가 더 간결해지고 콜백이 false를 반환하는 즉시 순회를 멈춥니다. 이 메서드는 희소 배열에서 할당되지 않은 슬롯을 건너뜁니다. 따라서 희소 배열을 대상으로 할 때는 각 인덱스를 읽는 루프와 결과가 다를 수 있습니다. 이 차이가 중요하다면 빈 슬롯이 없는 배열을 사용하거나 빈 슬롯을 처리할 규칙을 정하세요.
JSON.stringify()로 배열 비교하기
JSON과 호환되는 값을 담은 배열이라면 직렬화한 결과를 비교하는 방법이 간결합니다: JSON.stringify(left) === JSON.stringify(right). 이 방식은 순서를 고려하므로 [1, 2]와 [2, 1]의 비교 결과는 다릅니다. 직렬화에는 구체적인 규칙도 있습니다. 배열의 undefined 같은 일부 값은 null로 직렬화되고, undefined 값이 있는 객체 속성은 생략됩니다. 직렬화 가능한 속성이 같은 별개의 객체는 같은 문자열로 직렬화될 수 있지만, 이것이 일반적인 깊은 동등성 비교를 정의하는 것은 아닙니다. 속성 순서와 사용자 지정 직렬화 동작도 결과에 영향을 줄 수 있습니다. 이러한 규칙이 데이터 계약에 맞는 경우에만 이 방법을 선택하세요. 보편적인 동등성 검사로 사용하거나 큰 배열에서 더 빠르다고 가정해서는 안 됩니다.
순서와 무관하게 배열 비교하기
순서가 중요하지 않고 요소가 원시 값이라면 얕은 복사본을 정렬하고 정렬된 각 위치를 비교하세요. 입력 배열에 바로 sort()를 호출하면 원본이 변경되므로, 먼저 slice()로 복사해야 합니다. 기본 정렬은 문자열 표현을 기준으로 비교합니다. 숫자처럼 다른 정렬 기준이 필요한 값에는 비교 함수를 제공하세요. 정렬에는 추가 작업이 필요하며, 서로 다른 유형을 섞어 비교하려면 명시적인 정렬 규칙이 필요합니다. 길이와 요소를 확인하면 중복 값의 개수도 유지됩니다.
원시 문자열 배열은 복사본을 정렬한 뒤 각 값을 엄격한 동등성으로 비교할 수 있습니다. 아래의 완전한 예시는 실행되지 않았으며, 비교 결과와 두 원본 배열을 출력합니다:
이 섹션의 코드와 표시되는 레이블 또는 출력은 영어로 유지됩니다.
function arraysHaveSameValues(left, right) {
if (left.length !== right.length) return false;
const sortedLeft = left.slice().sort();
const sortedRight = right.slice().sort();
return sortedLeft.every((value, index) => value === sortedRight[index]);
}
const left = ["pear", "apple", "pear"];
const right = ["pear", "pear", "apple"];
console.log(arraysHaveSameValues(left, right));
console.log(left);
console.log(right);
이 배열에서는 비교 규칙이 true를 반환하며, 복사본을 정렬하므로 두 입력 배열의 원래 순서는 그대로 유지됩니다. 복사본 두 개를 정렬하고 모든 위치를 비교하면 중복 값의 개수도 보존됩니다. 어떤 값의 개수가 서로 다른 배열은 일치하지 않습니다. 여기서 기본 정렬과 엄격한 동등성은 문자열을 기준으로 합니다. 값의 유형이 섞여 있다면 해당 유형에 맞는 비교 함수와 동등성 규칙이 필요합니다. 객체를 비교하려면 의도한 동등성을 나타내는 키를 정하거나 해당 객체에 맞는 매칭 전략을 사용하세요. 기본 정렬만으로는 객체의 동등성을 판단할 수 없습니다.
중첩 배열과 객체 처리하기
순서대로 비교하는 예시와 정렬 예시는 각 요소에 엄격한 동등성을 적용합니다. 따라서 [{ id: 1 }]처럼 별도로 만든 값 두 개는 눈에 보이는 속성이 같아도 해당 위치에서 같지 않은 것으로 비교됩니다. 중첩 배열도 마찬가지입니다. 구조적 동등성이 필요하다면 지원하는 각 유형의 동작을 정의하는 재귀 비교를 구현하거나 애플리케이션에 적합한 전용 깊은 비교 라이브러리를 사용하세요. 사용하기 전에 날짜, 맵, 세트, 프로토타입, 순환 참조, 특수 숫자 값을 어떻게 처리할지 정해야 합니다. 깊은 비교 도구마다 구현하는 규칙이 다를 수 있습니다.
JSON과 호환된다고 확인된 데이터라면 위에서 설명한 제한을 고려해 직렬화를 간결한 구조 비교에 활용할 수 있습니다. 그 외의 경우에는 동등성 규칙을 명시하고 애플리케이션에 중요한 사례를 테스트하세요. 실용적으로는 필요한 순서 및 값 의미에 맞는 가장 단순한 방법을 선택하면 됩니다. 순서가 중요한 원시 값에는 every() 또는 루프를, 제약이 명확한 JSON 데이터에는 직렬화를, 그 밖의 요구에는 의도적인 매칭 또는 깊은 동등성 전략을 사용하세요.