HOWTO · JavaScript

JavaScript에서 객체 비교

수동으로 또는 JavaScript의 JSON.stringify() 함수를 사용하여 객체를 비교할 수 있습니다.

이 페이지의 내용

JavaScript의 엄격 동등 연산자(===)는 객체를 참조로 비교합니다. 따라서 속성이 같더라도 따로 만든 두 객체는 서로 같지 않습니다. 내용을 비교하려면 데이터 형태와 중요한 필드에 맞는 방법을 선택하세요. JSON.stringify()는 직렬화된 문자열을 비교하고, 수동 비교는 선택한 속성에 집중할 수 있으며, Object.keys() 반복문은 최상위 고유 열거 가능 문자열 키 속성을 비교할 수 있습니다. 심벌 키 속성은 이 비교에 포함되지 않습니다.

JavaScript에서 객체 동일성이 의미하는 것

문자열이나 숫자 같은 원시 값은 ===로 값을 비교합니다. 객체의 경우에는 두 변수가 같은 객체를 가리키는지 확인합니다. 한 객체를 다른 변수에 할당하면 참조가 유지되지만, 속성이 같은 객체를 새로 만들면 참조는 같지 않습니다. 비교의 목적이 객체의 정체성이 아니라 데이터를 설명하는 것이라면 이 차이를 알아야 합니다.

JSON.stringify()로 객체 비교하기

단순한 JSON 호환 데이터라면 JSON.stringify()로 각 객체를 문자열로 변환한 다음 ===로 비교할 수 있습니다. 속성이 같은 순서로 있으면 직렬화된 문자열도 같습니다. 데이터 구조와 속성 순서를 제어할 수 있을 때 간편하게 확인하기 좋은 방법입니다.

다음 자체 완결형 예제를 실행해 보세요.

이 섹션의 코드와 표시되는 레이블 또는 출력은 영어로 유지됩니다.

const first = { name: 'Apple', price: 2 };
const same = { name: 'Apple', price: 2 };
const reordered = { price: 2, name: 'Apple' };
console.log(JSON.stringify(first) === JSON.stringify(same));
console.log(JSON.stringify(first) === JSON.stringify(reordered));

이 비교는 속성 순서에 영향을 받으므로 일반적인 깊은 동등성 검사로 사용할 수 없습니다. 직렬화에는 JSON에만 해당하는 동작도 있습니다. 예를 들어 값이 undefined인 객체 속성은 결과에서 제외되며, 순환 참조는 직렬화할 수 없습니다.

선택한 속성을 수동으로 비교하기

일치 여부를 특정 필드만으로 판단한다면 해당 필드를 직접 비교하세요. 이렇게 하면 관련 없는 데이터가 판단에 끼어들지 않고, 함수에 비교 기준도 명확히 드러납니다. 아래 예제는 name과 price를 비교하므로 다른 속성이 바뀌어도 결과에는 영향을 주지 않습니다. 다른 필드도 동등성 판단에 포함해야 한다면 조건을 추가하세요.

이 섹션의 코드와 표시되는 레이블 또는 출력은 영어로 유지됩니다.

function sameFruit(a, b) {
  return a.name === b.name && a.price === b.price;
}

const first = { name: 'Apple', price: 2, color: 'red' };
const second = { name: 'Apple', price: 2, color: 'green' };
console.log(sameFruit(first, second));

이는 선택한 값만 얕게 비교합니다. 선택한 값 자체가 객체라면 ===는 여전히 중첩된 값이 같은 참조를 공유하는지 확인할 뿐, 그 내용을 재귀적으로 비교하지 않습니다.

모든 고유 열거 가능 속성 비교하기

최상위 필드 구성이 달라질 수 있는 객체라면 고유 열거 가능 문자열 키 속성과 값을 비교하세요. Object.keys()는 열거 가능한 경우에도 심벌 키 속성을 제외하므로, 이 방법으로는 그런 속성을 비교할 수 없습니다. 키 개수가 같은지 확인하고, 첫 번째 객체의 각 키가 두 번째 객체의 고유 속성인지 검사한 다음 해당 값을 비교합니다. 키 포함 여부 확인은 중요합니다. 키 개수만 같으면 값이 모두 undefined인 서로 다른 키 집합을 실수로 일치한다고 판단할 수 있습니다.

이 섹션의 코드와 표시되는 레이블 또는 출력은 영어로 유지됩니다.

function sameOwnValues(a, b) {
  const keysA = Object.keys(a);
  const keysB = Object.keys(b);
  if (keysA.length !== keysB.length) return false;

  for (const key of keysA) {
    if (!Object.hasOwn(b, key) || a[key] !== b[key]) return false;
  }
  return true;
}

const first = { name: 'Apple', price: 2 };
const second = { price: 2, name: 'Apple' };
const differentKeys = { name: 'Apple', color: undefined };
console.log(sameOwnValues(first, second));
console.log(sameOwnValues({ name: undefined }, differentKeys));

Object.keys()는 고유 열거 가능 문자열 키 속성을 반환하며, 상속된 속성과 열거 불가능한 속성은 물론 모든 심벌 키 속성도 무시합니다. 따라서 문자열 키와 값이 같고 열거 가능한 심벌 키 속성만 다른 두 객체는 이 비교에서 같다고 판단될 수 있습니다. 이 방법은 값을 한 단계 깊이까지만 비교하므로 중첩 객체는 참조로 비교하며, NaN 같은 값은 엄격 동등 비교에서 자기 자신과도 일치하지 않습니다. 최신 JavaScript에서는 Object.hasOwn()을 사용할 수 있습니다. 구형 환경에서는 키 포함 여부를 검사할 때 Object.prototype.hasOwnProperty.call(b, key)를 사용하세요.

비교 방법 선택하기

속성 순서가 일정하게 유지되는 제어된 JSON 호환 데이터에서 간결한 비교가 필요하다면 JSON.stringify()를 사용하세요. 알려진 일부 속성만으로 일치 여부를 판단한다면 해당 속성만 비교하면 됩니다. 삽입 순서와 관계없이 모든 고유 열거 가능 최상위 문자열 키 속성이 일치해야 한다면 키와 값을 순회하는 방법을 사용하세요. 열거 가능한 심벌 키 속성은 이 비교 대상에 포함되지 않습니다. 중첩 구조, 특수 값 또는 애플리케이션별 타입을 값 기준으로 비교해야 한다면 규칙을 명시적으로 정의하거나 전용 깊은 비교 구현을 사용하세요. 위의 얕은 비교 방법을 보편적인 객체 동등성 검사로 취급해서는 안 됩니다.