[JS] 제너레이터, 개발자도 잘 모른다던데...?

준리·2022년 9월 14일
0

비동기 프로그래밍

목록 보기
1/10
post-thumbnail

두 개의 수를 입력 받아 더하기를 수행하는 제너레이터 를 작성하시오.

(실행 결과: 1과 2를 넣었을 때)
첫 번째 수? → 1
두 번째 수? → 2
3

자바스크립트 개발자 여러분, Yield를 아십니까? 아마 많이 생소할 것이다. 제너레이터라니... yield를 몰라서 면접에서 혼쭐난 개발자분도 계셨다. 사실 잘 쓰지 않는 제너레이터를 왜 알아야할까...(쓰지 않는게 아니라 생소할 뿐이었다. 비교적 최신문법) 나 또한 deep dive javascript 를 공부하며, 그냥 훌러덩 넘어간 부분이었는데, 현재 사용하는 비동기와 그에 따른 기술의 전반적인 이해를 위해선 이터레이터와 더불어 반드시 필요한 내용이었다. 대-충 그냥저냥 비동기를 사용했다면 반드시 generator와 yield에 대해서 알아두자.

3rd) Generator yield & next() - ES2016 ~ ES2017

generator : 함수 실행을 제어하는 함수

function * function 에 *이 찍힌 것을 본 적이 있는가? 이를 보게 된다면 이 것은 generator이다. 아마 본 적이 없을 것이다. 이는 함수의 실행을 제어하겠다는 의미인데, 함수를 부른 caller에게 특정 상황에서 실행의 제어권을 넘긴다는 소리다.

caller는 함수를 부른 친구이다. 실행시 yield를 만나면 제너레이터는 호출자(caller)에게 제어권을 넘겨야한다.

function* ~ 👮🏽‍♂️yield

function* 제너레이터() {
  yield hi
   ...
}
제너레이터(); <<< 얘가 caller(콜러콜러)

generator를 호출하면 iterator를 얻는다. 즉, next() 메서드를 호출 가능하다는 뜻이다.
(next() -> yield -> next() -> yield -> ... -> return)

제너레이터 함수는 화살표 함수와 생성자 함수로 표현할 수 없으며 반드시 function* 키워드를 사용한다.

👨🏽‍💻Add 제너레이터 작성

function* 제너레이터() {
    const a = yield "첫번째 수는?";
    const b = yield "두번째 수는?";
    console.log("a, b :>> ", a, b);
    return a + b;
}
const it = 제너레이터();
console.log(it.next());
console.log(it.next(1));
console.log(it.next(2));

함수가 중간에 멈춘다는 것을 볼 수 있다. 신기하다. 지혼자 실행하고 결과만 반환하던 놈인데, 내가 yield라는 애의 도움을 통해서 함수를 통제 할 수 있었다. next()를 사용할 수 있는 것으로 봐서 이는 iterator를 반환한다고 볼 수 있다.

iterator를 generator로 바꿔보기

기존 작성한 Stack과 Queue의 iterator를 generator 함수로 작성하고, p.109의 지하철 노선도 iterator를 generator함수로 작성하시오.
(기능은 동일함)

#1 stack과 queue // iterator -> generator

iterator 만들기 // next() 함수를 직접 작성해서 리턴해줬었다.

    [Symbol.iterator]() {
        let idx = -1;
        return {
            next: () => {
                idx += 1;
                return { value: this._arr[idx], done: !this._arr[idx] };
            },
        };
    }

generator 만들기 // next()를 사용할 수 있기 때문에 아래처럼 만들 수 있다.

    *[Symbol.iterator]() {
        for (const k of this._arr) {
            yield k;
        }
    }

#2 단방향 subway // iterator -> generator

iterator 만들기 // next() 함수를 직접 작성해서 리턴해줬었다.

    [Symbol.iterator]() {
        let idx = LINE2.indexOf(this.start) - 1;
        console.log("🚀 ~ file: shsubway.js ~ line 14 ~ Subway ~ idx", idx);
        let done = false;
        return {
            next: () => {
                idx = idx === LINE2.length - 1 ? 0 : idx + 1;
                done = done || LINE2[idx - 1] === this.end;
                return { value: done ? undefined : LINE2[idx], done };
            },
        };
    }

generator 만들기 // next()를 사용할 수 있기 때문에 아래처럼 만들 수 있다.

    *[Symbol.iterator]() {
        let idx = LINE2.indexOf(this.start) - 1;
        let done = false;
        while (!done) {
            idx = idx === LINE2.length - 1 ? 0 : idx + 1;
            done = done || LINE2[idx - 1] === this.end;
            yield LINE2[idx];
        }
    }

결론

중간에 멈추는 건 어디서 본 적이 있지않은가. 모르고 사용했던 acync/await와 비슷한 모습이 보인다. 비동기처리를 위해 기다리는 모습이 yield와 닮아있다. 비동기가 어떻게 멈추는지 generator를 보며 이해할 수 있었다.

출처

SSAC 영등포 교육기관에서 풀스택 실무 프로젝트 과정을 수강하고 있다. JS전반을 깊이 있게 배우고 실무에 사용되는 프로젝트를 다룬다. 앞으로 그 과정 중의 내용을 블로그에 다루고자 한다.

profile
트렌디 풀스택 개발자

0개의 댓글