Menu

자바스크립트 for...of vs for...in 차이와 사용법

자바스크립트의 for...of와 for...in, 도대체 뭐가 다를까요? 값과 키의 차이부터 배열·객체 순회, 실전에서 언제 뭘 써야 하는지 정리했습니다.

이름은 비슷한데, 하는 일은 완전히 다른 두 반복문

자바스크립트에는 생김새가 거의 똑같지만 전혀 다르게 동작하는 반복문이 두 가지 있습니다. for...of는 이터러블의 값(value) 을 하나씩 훑고, for...in은 객체의 키(key) 를 훑습니다. 글자 하나 차이지만 동작은 완전히 다르죠.

for offor in 차이를 한 번에 보여주는 예제를 먼저 살펴봅시다:

index.js
Output
Click Run to see the output here.

첫 번째 반복문은 값인 사과, 바나나, 체리를 출력하고, 두 번째는 키를 문자열로 바꾼 0, 1, 2를 출력합니다. 둘을 헷갈려서 잘못 고르면 "내 배열에 왜 숫자만 들어 있지?" 하면서 10분을 날리기 딱 좋습니다.

for...of: 이터러블이면 뭐든 값을 꺼낸다

for...of는 자바스크립트에서 가장 자주 쓰게 되는 반복문입니다. 자바스크립트가 이터러블(iterable) 로 인정하는 건 뭐든 순회할 수 있는데, 배열, 문자열, Map, Set, NodeList, 제너레이터 등이 모두 해당됩니다.

index.js
Output
Click Run to see the output here.

인덱스로 씨름할 필요도 없고, scores[i] 같은 표현도 필요 없습니다. 값을 달라고 하면 값이 그대로 나옵니다. 문자열도 이터러블이라서 for...of로 한 글자씩 순회할 수 있습니다:

index.js
Output
Click Run to see the output here.

대부분의 유니코드 코드 포인트에 대해서도 제대로 동작하기 때문에, 문자열을 숫자 인덱스로 접근하는 방식보다 작지만 분명한 장점이 있습니다.

for...of에서 인덱스 가져오기

for...of가 바로 내어주지 않는 한 가지가 바로 인덱스입니다. 인덱스가 필요할 땐 entries()와 함께 쓰면 됩니다:

index.js
Output
Click Run to see the output here.

names.entries()[index, value] 형태의 쌍을 돌려주고, 앞쪽의 구조 분해로 이걸 두 개의 변수로 나눠 받는 겁니다. 단지 i가 필요하다는 이유만으로 고전적인 for (let i = 0; ...) 문법으로 돌아가는 것보다 이 방식이 훨씬 깔끔해요.

for...in: 객체의 키 순회하기

for...in은 일반 객체(plain object)를 위한 문법입니다. 객체의 열거 가능한(enumerable) 문자열 키들을 하나씩 훑어요:

index.js
Output
Click Run to see the output here.

값이 아니라 키가 넘어온다는 점에 주의하세요. 값을 꺼내려면 user[key]처럼 다시 객체에 접근해야 합니다. 그리고 키는 항상 문자열입니다 — 숫자처럼 보여도 결국 문자열이에요.

for...in은 프로토타입 체인까지 거슬러 올라가기 때문에, 상속받은 속성까지 같이 나올 수 있습니다. 직접 만든 리터럴 객체에서는 거의 문제가 되지 않지만, 클래스 인스턴스나 라이브러리에서 넘어온 객체를 순회할 때는 방어적으로 작성하는 게 좋습니다:

index.js
Output
Click Run to see the output here.

Object.hasOwn(user, key)를 쓰면 상속된 속성은 걸러낼 수 있습니다. 사실 요즘 코드에서는 for...in을 거의 쓰지 않고, 대신 Object.keys, Object.values, Object.entries를 활용하는 게 일반적이에요. 자연스럽게 다음 주제로 이어집니다.

자바스크립트에서 객체를 순회하는 가장 요즘 방식

for...in 대신 for...ofObject.* 헬퍼를 조합하는 방법을 살펴볼게요. 상황에 맞게 아래 셋 중 하나를 골라 쓰면 됩니다:

index.js
Output
Click Run to see the output here.

Object.entries가 특히 깔끔합니다. [key, value] 쌍을 구조 분해로 꺼내 쓰면 코드가 거의 영어 문장처럼 읽히죠. 게다가 이 메서드들은 객체의 고유한 열거 가능 속성만 반환하기 때문에, 상속받은 불필요한 속성이 딸려올 걱정도 없습니다.

배열에는 for...in을 쓰지 마세요

문법적으로는 쓸 수 있지만, 실수하기 딱 좋습니다:

index.js
Output
Click Run to see the output here.

0, 1, 2는 물론이고 tag까지 전부 나와버립니다. 누군가 배열에 붙여놓은 프로퍼티나, 폴리필로 Array.prototype에 추가된 것들까지 몽땅 끌려 나오죠. 게다가 키는 문자열이라 key + 1을 하면 더하기가 아니라 문자열 이어붙이기가 됩니다. 거기에 순회 순서도 모든 엣지 케이스에서 배열 순서와 일치한다는 보장이 없어요.

상황별 정리:

  • 배열 값만 필요할 때? for...of arr.
  • 배열의 인덱스와 값을 같이? for...of arr.entries().
  • 인덱스만 세면서 돌리고 싶을 때? 전통의 for (let i = 0; i < arr.length; i++).
  • 객체의 키나 엔트리를 순회하고 싶을 때? Object.keys(obj) 또는 Object.entries(obj)for...of를 붙이세요.

정리하자면, for...in은 쓸 일이 거의 없는 틈새 도구입니다. for...ofObject의 헬퍼 메서드만 있으면 웬만한 상황은 다 커버됩니다.

break와 continue는 둘 다 잘 동작합니다

두 반복문 모두 흔히 쓰는 조기 탈출 문법을 그대로 지원합니다:

index.js
Output
Click Run to see the output here.

continue는 현재 반복을 건너뛰고 다음으로 넘어가며, break는 반복문 자체를 빠져나옵니다. 사실 이 점이 .forEach()보다 for...of를 선호하는 가장 큰 이유이기도 합니다. forEach의 콜백 안에서는 break로 빠져나올 수 없지만, for...of에서는 얼마든지 가능하거든요.

for of와 for in 차이 한눈에 정리

index.js
Output
Click Run to see the output here.

반복문은 네 가지지만 쓰임새는 명확합니다. 반복 가능한(iterable) 값에서 을 꺼내 쓰고 싶다면 for...of를 씁니다. 객체의 프로퍼티를 다루고 싶다면 Object.keys / Object.values / Object.entriesfor...of를 조합하면 됩니다. for...in은 상속된 것까지 포함해서 객체의 열거 가능한 문자열 키를 전부 훑어야 하는, 그런 드문 경우에만 남겨두세요.

다음 주제: truthy와 falsy

자바스크립트의 모든 반복문과 if는 결국 같은 질문을 던집니다. 이 값은 참으로 간주될까? 그런데 이 답이 항상 직관적이지만은 않습니다. 빈 문자열, 0, null, undefined는 여러분 예상과 다르게 동작할 수 있거든요. 다음 장에서는 truthy·falsy 값에 대해 알아봅니다.

자주 묻는 질문

for...of와 for...in, 정확히 뭐가 다른가요?

for...of는 배열, 문자열, Map, Set 같은 이터러블의 값(value) 을 순회합니다. 반면 for...in은 객체의 키(프로퍼티 이름) 을 순회하죠. 예를 들어 ['a', 'b'] 배열에서 for...of'a', 'b'를 꺼내주지만, for...in'0', '1'을 문자열로 돌려줍니다.

객체에도 for...of를 쓸 수 있나요?

바로는 안 됩니다. 일반 객체(plain object)는 이터러블이 아니거든요. 대신 Object.keys(obj), Object.values(obj), Object.entries(obj)로 배열을 뽑은 다음 for...of로 돌리면 됩니다. 실무에서는 for (const [key, value] of Object.entries(obj)) 패턴이 가장 많이 쓰입니다.

배열에 for...in을 쓰면 왜 안 되나요?

동작은 합니다. 하지만 for...in은 상속된 프로퍼티까지 포함해서 열거 가능한 모든 속성을 훑기 때문에, 누군가 Array.prototype에 뭔가 추가해놨다면 그것까지 딸려 나옵니다. 게다가 키가 문자열로 반환되고, 숫자형 키의 순회 순서도 항상 보장되지는 않아요. 값이 필요하면 for...of, 인덱스가 꼭 필요하면 전통적인 for 문을 쓰는 걸 추천합니다.

Coddy로 코딩 배우기

시작하기