본문으로 건너뛰기
yceffort
PostsSeriesTagsAbout🧪 Research
EN

Tweaks

theme
accent palette
film grain
minimal mode
BACK TO INDEX
◆ ESSAY
--min
--year
KOoriginal

mailMail icongithubtwitter
yceffort
•
© 2026
•
https://yceffort.kr
BACK TO INDEX
◆ ESSAY

자바스크립트의 배열, 그리고 이터러블과 이터레이터 (ES6)

avatar
yceffort
2021-02-21 · 6분
6min
2021year
KOoriginal
javascript

자바스크립트는 6가지 원시 타입이 있으며, 그 외에는 모두 객체 타입이다. 따라서 배열도 객체 중 하나라고 볼 수 있다. 그렇다면 아래의 객체도 배열이라고 볼 수 있을까?

const a = {
  0: 0,
  1: 1,
  2: 2,
  length: 3,
}

a[0] // 0
a[1] // 1
a[2] // 2
a.length //3

그렇다면 정확히 배열이라는 것은 무엇일까?

배열

기본 정보

배열은 아래 4가지 방법으로 생성할 수 있다.

  • 배열 리터럴 ([])
  • Array 생성자 함수
  • Array.of
  • Array.from
const a = {
  0: 0,
  1: 1,
  2: 2,
  length: 3,
}

const b = [1, 2, 3]

typeof a // object
typeof b // object

Object.getPrototypeOf(a) === Object.prototype
Object.getPrototypeOf(b) === Array.prototype // true

객체와 배열은 기본적으로 다음과 같은 서로다른 특징이 있다.

ObjectArray
structurekey & valueindex & element
referenceproperty keyindex
orderXO
length propertyXO

가장 큰 차이로는, 순서와 length property 유무다.

희소배열

자바스크립트의 배열은, 일반적인 밀집 배열이 아니다.

여기서 밀집 배열이란, 데이터 타입이 통일되어 있으며 서로 메모리 상에서 연속적으로 인접해 있는 배열을 의미한다. 밀집배열은 따라서 데이터에 접근하는게 효율적이고, 빠르다.

그러나 자바스크립트는 희소배열 형태로 되어 있다. 희소배열은, 밀집 배열과 반대로 배열의 요소를 위한 데이터 공간과 크기가 다르고, 연속적으로 밀집되어 있지도 않은 배열을 의미한다. 이경우 당연히 접근하는데 속도는 조금 느리지만, 요소를 삽입하거나 삭제하는 경우에는 더 빠르다.

이터레이션 프로토콜

이터테이련 프로토콜이란, 앞서 언급한 배열 처럼, 순회 가능한 자료 구조를 만들기 위하여 ECMAScript 에서 정의한 규악이다.

ES6 이전에는 배열, 문자열, DOM 콜렉션 등이 각자 방법으로 데이터를 순회할 수 있도록 구성되어 있었지만, ES6에 들어서면서 이러한 순회 가능한 데이터 들이 이터레이션 프로토콜을 준수하여 동일하게 동작하게 끔 설계했다. 이러한 이터레이션 프로토콜에는 두가지가 있다.

이터러블 프로토콜

어떠한 값들이 루프되는 것과 같은 이터레이션 동작을 정의하거나, 사용자 정의하는 것을 의미한다. 다시 말해, Symbol.iterator를 호출하면 이터레이터를 반환하는 것을 이터러블 프로토콜 이라고 한다.

즉, 해당 객체에 프로토타입을 통해서든, 직접 구현을 했든, Symbol.iterator를 호출할 수있고 그것이 이터레이터를 반환한다면, 이터러블이다.

const a = {
  0: 0,
  1: 1,
  2: 2,
  length: 3,
}

const b = [1, 2, 3]

a[Symbol.iterator] // undefined
b[Symbol.iterator] === Array.prototype[Symbol.iterator] // true

이터레이터 프로토콜

값들의 순서를 만드는 표준 방법을 의미한다. 객체가 next()를 가지고 있고, 그 객체가 value와 done (true, false)를 리턴한다면 이터레이터 프로토콜을 준수한 이터레이터다.

나만의 이터러블 만들어보기

피보나치 배열을 리턴하는 이터러블을 만들어보자.

const fibonacci = function (max) {
  let prev = 0
  let curr = 1

  return {
    [Symbol.iterator]() {
      return {
        next() {
          last = prev + curr
          prev = curr
          curr = last

          return {
            value: curr,
            done: curr >= max,
          }
        },
      }
    },
  }
}

const fibonacci100 = fibonacci(100)

for (const i of fibonacci100) {
  console.log(i) // 1, 2, 3, 5, 8, 13, 21, 34, 55, 89
}

const result = [...fibonacci100] // [1, 2, 3, 5, 8, 13, 21, 34, 55, 89]

const iterator = fibonacci(100)[Symbol.iterator]()

console.log(iterator.next()) // { value: 1, done: false }
console.log(iterator.next()) // { value: 2, done: false }
console.log(iterator.next()) // { value: 3, done: false }
console.log(iterator.next()) // { value: 5, done: false }

위와 같은 동작은 배열과 유사하다.

const a = [1, 2, 3, 5]
const iterator = a[Symbol.iterator]()

console.log(iterator.next()) // { value: 1, done: false }
console.log(iterator.next()) // { value: 2, done: false }
console.log(iterator.next()) // { value: 3, done: false }
console.log(iterator.next()) // { value: 5, done: false }
console.log(iterator.next()) // { value: undefined, done: true}

이터러블 이면서, 이터레이터인 객체를 리턴

const fibonacciFunc = function (max) {
  let prev = 0
  let curr = 1

  return {
    [Symbol.iterator]() {
      // 메소드 함수의 this는 메서드를 호출한 객체에 바인딩 된다.
      // 즉
      /*
            {
              next: [Function: next],
              [Symbol(Symbol.iterator)]: [Function: [Symbol.iterator]]
            }
            */
      return this
    },
    next() {
      last = prev + curr
      prev = curr
      curr = last

      return {
        value: curr,
        done: curr >= max,
      }
    },
  }
}

const fibonacci100 = fibonacciFunc(100)

for (const i of fibonacci100) {
  console.log(i) // 1, 2, 3, 5, 8, 13, 21, 34, 55, 89
}

const result = [...fibonacci100] // [1, 2, 3, 5, 8, 13, 21, 34, 55, 89]

const iterator = fibonacciFunc(100)

console.log(iterator.next()) // { value: 1, done: false }
console.log(iterator.next()) // { value: 2, done: false }
console.log(iterator.next()) // { value: 3, done: false }
console.log(iterator.next()) // { value: 5, done: false }

관련 글

  • #turbopack#nextjs#bundler

    Next.js turbopack에서 싱글톤이 두 개가 됐다: scope hoisting 버그와 순환 import

    Next.js 16 turbopack 프로덕션 빌드에서 모듈 스코프 싱글톤이 런타임에 두 개가 됐다. 같은 동기 구간에서 조건 판정이 뒤집히고, 응답이 도착해도 타임아웃이 나는 증상을 번들 산출물로 추적한 기록. scope hoisting의 부분 병합, 순환 import, 이미 고쳐져 있던 upstream 버그, 그리고 뒤늦게 돌린 단일 변수 실험까지.

    2026-08-19·28분
  • #javascript#animation#web-animations-api

    number-flow를 구형 브라우저로 이식하기: 다섯 가지 결정과 두 가지 번복

    number-flow가 애니메이션을 켜는 최소 버전은 Chrome 125, Safari 17.2다. 이 하한을 Chrome 66과 WebKit 16.4까지 내리는 포크를 만들면서 내린 결정들과, 뒤집게 된 판단 두 가지, 그리고 자동 강등을 포기한 Safari 버그 조사의 기록.

    2026-08-11·44분
  • #nodejs#security#javascript

    Node.js vm 모듈의 함정: 샌드박스가 아닌 이유

    집필 중인 Node.js Deep Dive의 5.2장(vm 모듈의 함정) 일부를 미리 공개합니다.

    2026-02-27·25분
  • #nodejs#javascript

    Node.js Deep Dive (가제) 베타 리더를 모십니다.

    많관부22

    2026-02-19·5분

새 글을 놓치고 싶지 않으시다면 RSS로 구독해 주세요.

RSS 구독 →

yceffort — 프론트엔드 엔지니어입니다. 발표·기술 자문·기고 문의는 이곳에서 받고 있습니다.

← Back to the blogIssue on GitHub →