Notice
Recent Posts
Recent Comments
관리 메뉴

즐겁게, 코드

제너레이터부터 리덕스 사가까지 - 01. 제너레이터 본문

💬 언어/Javascript

제너레이터부터 리덕스 사가까지 - 01. 제너레이터

Chamming2 2021. 4. 5. 20:44

제너레이터를 활용하면 함수의 실행을 중간에 멈췄다가 재개할 수 있습니다.

// 화살표 함수 형태로는 제너레이터를 생성할 수 없습니다.
function* f1() {
  yield 10;
  yield 20;
  return "완료";
}

const gen = f1();

보시면 function 키워드 뒤에 * 이 붙어있는 것을 확인할 수 있는데요, function* 키워드는 제너레이터를 정의하는 문법입니다.

(따라서 화살표 함수 형태로는 제너레이터 함수를 생성할 수 없습니다.)

함수 내에 존재하는 yield는 함수의 실행을 잠깐 멈출 수 있는 분기이며, 제너레이터 함수를 실행하면 제너레이터 객체를 반환합니다.

yield 키워드

yield 키워드에 대해 조금 자세히 다루자면 yield는 제너레이터 내부의 값을 외부로 반환할 수도 있고, 외부의 값을 제너레이터 내부로 가져올 수도 있는 창구의 역할을 합니다.

 

이 때 처음 호출되는 generator.next() 는 인자를 가질 수 없다는 점에 유의하셔야 합니다. (가진다 해도 무시됩니다!)

function* gen() {
  let answer1 = yield "2 + 2 = ?";
  console.log(answer1);
  let answer2 = yield "3 + 6 = ?";
  console.log(answer2);
}

let generator = gen();

// 제너레이터가 "2 + 2 = ?" 가 리턴됩니다. (첫 번째 next에서는 인자를 추가할 수 없습니다.)
const q1 = generator.next().value; 
console.log(q1); // "2 + 2 = ?"

// 4를 제너레이터 내의 answer1에 전달하고, 제너레이터는 "3 + 6 = ?" 을 리턴합니다.
const q2 = generator.next(4).value; 
console.log(q2); // "3 + 6 = ?"
generator.next(9); // 제너레이터 내의 answer2에 9를 전달합니다.

제너레이터의 메서드

제너레이터 객체에는 next, return, throw 라는 메서드가 있습니다.

이 중 next 메서드를 호출하면 yield 키워드를 만날 때까지 실행되고 데이터 객체를 *반환합니다.

(* 눈썰미가 좋다면 아마 눈치채셨겠지만, yield의 존재를 제외하면 이는 이터레이터 프로토콜과 완전히 동일합니다.)

 

[데이터 객체의 형태]

{ value: 10, done: false }
{ value: 20, done: true }
// done 속성이 한번 참으로 바뀌면 거짓으로 되돌릴 수 없으며
// 이후의 value는 반드시 undefined로 고정됩니다.
{ value: undefined, done: true }

이 데이터 객체는 value 와 done 속성으로 이루어져 있는데요, value 속성에는 yieldreturn 값으로 지정된 값이, done 속성은 yield 키워드가 더이상 앞에 없을 때까지 false 값이 담기게 됩니다.

 

[제너레이터 객체의 next 메서드 사용 예시]

function* f1() {
  yield 10;
  yield 20;
  return "완료";
}

const gen = f1();
console.log(gen.next()); // { value: 10, done: false }
console.log(gen.next()); // { value: 20, done: false }
console.log(gen.next()); // { value: '완료', done: true }
console.log(gen.next()); // { value: undefined, done: true }

다음은 제너레이터 객체의 return 메서드입니다.

하나 주의해야 할 것이, return 메서드는 제너레이터가 리턴하는 값이 아닌 인자로 받은 값 을 리턴하고 done 속성값을 참으로 바꿉니다.

function* f1() {
  yield 10;
  yield 20;
  return "이 값이 리턴될 것 같지만";
}

const gen = f1();
console.log(gen.next()); // { value: 10, done: false }
console.log(gen.return("이 값이 리턴됩니다.")); // {value: "이 값이 리턴됩니다.", done: true }
console.log(gen.next()); // { value: undefined, done: true}

return 메서드를 호출하면 done 속성이 곧바로 참으로 바뀌므로, 이후에 실행하는 next 메서드는 값을 리턴하지 못하게 됩니다.

마지막 메서드는 throw 메서드입니다.

function* f1() {
  try {
    yield 10;
    yield 20;
    return "완료";
  } catch (error) {
    console.log("에러 코드 :", error);
  }
}

const gen = f1();
console.log(gen.next()); // { value: 10, done: false }
console.log(gen.throw("404")); // 에러 코드 : 404
                               // { value: undefined, done: true }

throw 메서드의 인자로 주어진 값이 캐치문의 인자로 전달되며, 캐치문을 실행한 후 done 속성은 참이 됩니다.

이게 제너레이터가 가진 정말 모든 특징입니다만... 이걸 대체 어디에 써먹을 수 있는 걸까요?

 

next 메서드를 소개할 때 잠깐 스치듯이 이터레이터 프로토콜과의 유사성을 언급했는데요, 다음 시간에는 반복자로써의 제너레이터 사용 방법을 소개하도록 하겠습니다.

반응형
Comments
소소한 팁 : 광고를 눌러주시면, 제가 뮤지컬을 마음껏 보러다닐 수 있어요!
와!! 바로 눌러야겠네요! 😆