(JS) Object.keys과 Object.entries 중 어떤 것을 써야할까?

Apr 17, 2025

JavaScript에서 객체 속성을 순회하기 위해 Object.keysObject.entries를 많이 사용합니다.
사용법과 성능 측면에서 이 둘의 차이를 살펴보고 어떻게 활용하면 좋을지 알아봅니다.

사용법

먼저, Object.keys와 Object.entries의 사용법을 간단히 짚어봅니다.
props라는 JSON 객체에서 data-test-로 시작하는 속성을 추출하고 싶다고 가정해봅시다.

const props = {
  href: '/',
  class: 'link',
  'data-test-id': 'test',
  'data-test-name': '테스트',
};js

Object.keys객체의 속성 키를 배열로 반환하는 함수입니다. 객체의 속성값을 접근하기 위해선 obj[key] 같이 다시 객체에 직접 접근을 해야 합니다. data-test-로 시작하는 속성만을 객체로 추출하기 위해선 아래와 같이 Array.reduce를 활용하면 될 것 같습니다.

Object.keys(props).reduce((acc, key) => {
  if (key.startsWith('data-test-')) {
    acc[key] = props[key];
  }
  return acc;
}, {});
// { data-test-id: 'test', data-test-name: '테스트' }js

Object.entries객체의 속성을 [키, 값] 배열로 반환하는 함수입니다. 앞서 작성한 로직을 그대로 옮겨보면 아래와 같습니다.

Object.entries(props).reduce((acc, [key, value]) => {
  if (key.startsWith('data-test-')) {
    acc[key] = value;
  }
  return acc;
}, {});
// { data-test-id: 'test', data-test-name: '테스트' }js

객체를 새로운 Object, Map 등 객체로 변환할 때 코드를 간결하게 작성할 수 있습니다. [키, 값] 배열을 그대로 Object.fromEntries, new Map의 인자로 건네주면 새로운 객체가 생성됩니다.

const filteredEntries = Object.entries(props).filter(([key]) =>
  key.startsWith('data-test-'),
);

Object.fromEntries(filteredEntries);
// { data-test-id: 'test', data-test-name: '테스트' }

new Map(filteredEntries);
// Map(2) {'data-test-id' => 'test', 'data-test-name' => '테스트'}js

이렇게 사용법을 살펴봤을 때, 객체의 키만 필요하다면 Object.keys를, 키와 값이 모두 필요하다면 Object.entries를 선택하는 것이 적합해 보입니다.

성능

성능적인 측면에서도 비교를 해보겠습니다.

알고리즘 성능을 고려할 때 보통 시간 복잡도공간 복잡도를 고려를 합니다. 먼저 결론을 도표로 정리하면 아래와 같습니다.

시간 복잡도공간 복잡도
Object.keysO(n)O(n)
Object.entriesO(n)O(2n) ~= O(n + a)

시간 복잡도를 살펴보면, Object.keys와 Object.entries는 모두 객체의 속성 개수만큼 배열을 순회하기에 O(속성수), 즉 O(n)의 시간 복잡도를 갖게 됩니다.

공간 복잡도를 살펴보면, Object.keys는 key만을 담은 일차원 배열을 생성하지만, Object.entries는 [key, value] 형태의 이차원 배열을 생성합니다. 따라서 Object.entries는 Object.keys보다 2배의 메모리를 사용하게 되고 value가 문자열이 아닌 객체라면 2배 이상의 메모리를 사용하게 됩니다.

공간 복잡도가 높아지면 메모리 할당/해제 비용이 증가하고, CPU의 캐시 적중률이 저하되어 코드 실행 속도가 느려질 수 있습니다.

위에 작성한 예시 코드를 measurethat사이트에서 실행 속도를 측정해보았습니다. 벤치마크는 주어진 시간 동안 예시 코드를 몇회 실행할 수 있는지를 기준으로 하고 있습니다.

250424-130144

V8 엔진(Chrome) 기준 Object.keys는 약 17.5 M ops/sec, Object.entries는 약 16.4 M ops/sec를 기록했습니다. 즉, Object.keys가 Object.entries보다 약 6% 더 빠르게 동작했습니다. 만약 속성 수가 많고 속성 값이 무겁다면 차이가 더 크게 벌어질 것 같습니다.

실무에서 속성 개수가 수십 개 정도인 일반 객체를 다룰 때 성능 차이가 거의 없으므로, 가독성·편의성에 따라 Object.entries를 써도 무방합니다. 다만 속성이 수천 개 이상이거나 자주 반복되는 루프 안에서 자주 호출해야 한다면, Object.keys를 쓰는 것이 권장됩니다.

다른 대안

객체의 속성을 순회하기 위해서 Object.values와 for…in을 활용할 수도 있습니다.

Object.values

객체의 속성값만 순회할 때 유용합니다.

  • 성능 지표는 Object.keys > Object.values > Object.entries 순으로 좋습니다.
  • value로 key를 접근하기 어려운 점이 있습니다.

for…in

mesurethat에서 성능은 더 좋지만, 가독성 문제로 사용이 권장되지 않습니다.

  • 배열을 순회하는 for...of와 헷갈리기 쉽습니다.
  • 선언형 vs 명령형 프로그래밍
  • prototype 값도 순회되기에 DOM Element 같은 확장된 객체 속성을 순회할 때 불리합니다. hasOwnProperty로 값을 필터링 해줘야 합니다.
const props = {
  href: '/',
  class: 'link',
  'data-test-id': 'test',
  'data-test-name': '테스트',
};

const result = {};
for (const key in props) {
  if (key.startsWith('data-test-')) {
    result[key] = props[key];
  }
}
console.log(result);
// { data-test-id: 'test', data-test-name: '테스트' }js

맺으면서

“악마는 디테일에 있다”는 말이 있습니다.
도구의 작은 디테일을 알고 이를 활용하여 더 날카로운 코드를 작성해보면 좋을 것 같습니다.

Object.keysObject.entries
성능더 빠름, 메모리 효율약간 느림, 메모리 더 사용
코드 간결성키만 필요할 때 적합키·값 모두 필요할 때 간결
확장성제한적Object.fromEntries, Map 연계에 유리