[JS] ์๋ฐ์คํฌ๋ฆฝํธ ์ ๋๋ ์ดํฐ Generator ์ด ์ ๋ฆฌ
์ ๋๋ ์ดํฐ๋ ES6์ ๋์ ๋ ํน์ํ ํจ์๋ค. ํจ์ ํธ์ถ์๊ฐ ํจ์ ์คํ์ ์ ์ดํ ์ ์๊ณ , ํจ์ ํธ์ถ์์ ํจ์ ์ํ๋ฅผ ์ฃผ๊ณ ๋ฐ์ ์๋ ์๋ค. ์ด๋ฐ ํน์ง ๋๋ฌธ์ ์ ๋๋ ์ดํฐ ํจ์์์ ์ฝ๋ ๋ธ๋ก์ ์คํ์ ์ ์ ๋ฉ์ท๋ค๊ฐ ํ์ํ ์์ ์ ์ฌ๊ฐํ ์ ์๋ค. ์ผ๋ฐ ํจ์๋ 0~1๊ฐ ๊ฐ๋ง ๋ฐํํ ์ ์์ง๋ง, ์ ๋๋ ์ดํฐ ํจ์๋ ์ฌ๋ฌ๊ฐ์ ๊ฐ์ ํ์์ ๋ฐ๋ผ ํ๋์ฉ ๋ฐํํ ์ ์๋ค.
์ ๋๋ ์ดํฐ ํจ์์ ํน์ง
- ํจ์ ํธ์ถ์์๊ฒ ํจ์ ์คํ์ ์ ์ด๊ถ์ ์๋(yield)ํ ์ ์๋ค
- ์ผ๋ฐ ํจ์ : ํจ์ ํธ์ถ์(caller)๋ ํจ์๋ฅผ ํธ์ถํ ์ดํ ํจ์ ์คํ์ ์ ์ดํ ์ ์๋ค.
- ์ ๋๋ ์ดํฐ ํจ์ : ํจ์ ํธ์ถ์๊ฐ ํจ์ ์คํ์ ์ ์ดํ ์ ์๋ค(ํจ์ ์คํ ์ผ์ ์ ์ง / ์ฌ๊ฐ)
- ํจ์ ํธ์ถ์์ ํจ์ ์ํ๋ฅผ ์ฃผ๊ณ ๋ฐ์ ์ ์๋ค
- ์ผ๋ฐ ํจ์ : ๋งค๊ฐ๋ณ์๋ฅผ ํตํด ๊ฐ์ ์ ๋ฌ๋ฐ๊ณ ํจ์ ์ฝ๋๋ฅผ ์ผ๊ด ์คํํ ๊ฒฐ๊ณผ๊ฐ์ ์ธ๋ถ๋ก ๋ฐํํ๋ค.
- ์ ๋๋ ์ดํฐ ํจ์ : ํจ์ ํธ์ถ์์๊ฒ ์ํ๋ฅผ ์ ๋ฌํ๊ฑฐ๋, ํจ์ ํธ์ถ์๋ก๋ถํฐ ์ํ๋ฅผ ์ ๋ฌ๋ฐ์ ์ ์๋ค.
- ์ ๋๋ ์ดํฐ ํจ์๋ฅผ ํธ์ถํ๋ฉด ์ ๋๋ ์ดํฐ ๊ฐ์ฒด๋ฅผ ๋ฐํํ๋ค
- ์ผ๋ฐ ํจ์ : ํจ์๋ฅผ ํธ์ถํ๋ฉด ํจ์ ์ฝ๋๋ฅผ ์ผ๊ด ์คํํ๊ณ ๊ฐ์ ๋ฐํํ๋ค.
- ์ ๋๋ ์ดํฐ ํจ์ : ์ดํฐ๋ฌ๋ธ์ธ ๋์์ ์ดํฐ๋ ์ดํฐ์ธ ์ ๋๋ ์ดํฐ ๊ฐ์ฒด๋ฅผ ๋ฐํํ๋ค
์ ๋๋ ์ดํฐ ํจ์ ์ ์ ๋ฐฉ๋ฒ
๐ก ์ ๋๋ ์ดํฐ ํจ์๋ ์ดํฐ๋ฌ๋ธ์ด๋ค. ๋ฐ๋ผ์ ํจ์ ์์ฒด์ ์ ๊ฐ ๋ฌธ๋ฒ์ ์ฌ์ฉํ ์๋ ์๋ค.
์ ๋๋ ์ดํฐ ํจ์๋ function*
ํค์๋๋ก ์ ์ธํ๊ณ ํจ์ ๋ณธ๋ฌธ์ 1๊ฐ ์ด์์ yield
ํํ์์ ํฌํจํ๋ค. ๋๋จธ์ง ์ผ๋ฐ ํจ์๋ฅผ ์ ์ํ๋ ๊ฒ๊ณผ ๋์ผํ๋ค. *
๊ธฐํธ๋ ์ ์คํฐ๋ฆฌ์คํฌ(Asterisk)๋ผ๊ณ ๋ถ๋ฅด๋ฉฐ function
ํค์๋์ ํจ์ ์ด๋ฆ ์ฌ์ด๋ผ๋ฉด ์ด๋์ ๋ถ์ฌ๋ ์๊ด์๋ค. ๋๋ถ๋ถ์ function
ํค์๋ ๋ฐ๋ก ๋ค์ ๋ถ์ธ๋ค. ex) function*
// ์ ์ธ์
function* genDecFunc() {
yield 1;
}
// ํํ์
const genExpFunc = function* () {
/* ... */
};
// ๊ฐ์ฒด ๋ฉ์๋
const obj = {
*genObjMethod() {
/* ... */
},
};
// ํด๋์ค ๋ฉ์๋
class MyClass {
*genClsMethod() {
/* ... */
}
}
โ๏ธ ์ ๋๋ ์ดํฐ ํจ์๋ ํ์ดํ ํจ์๋ก ์ ์ํ ์ ์๊ณ , new
์ฐ์ฐ์๋ฅผ ์ฌ์ฉํ๋ ์์ฑ์ ํจ์๋ก ํธ์ถํ ์ ์๋ค.
const genArrowFunc = * () => { /* ... */ } // Error! Unexpected token '*'
function* genFunc() { /* ... */ }
new genFunc(); // Error! genFunc is not a constructor
์ ๋๋ ์ดํฐ ํจ์ ์์ฒด๋ ์ดํฐ๋ฌ๋ธ์ด๋ฏ๋ก ์๋์ฒ๋ผ ์ ๊ฐ๋ฌธ๋ฒ์ ์ฌ์ฉํ ์๋ ์๋ค.
function* generateSequence() {
yield 1;
yield 2;
yield 3;
}
const res = [0, ...generateSequence()]; // [0, 1, 2, 3]
console.log(Symbol.iterator in generateSequence.prototype); // true
// ์ ๋๋ ์ดํฐ ํจ์๋ Symbol.iterator ๋ฉ์๋๋ฅผ ์์๋ฐ์ผ๋ฏ๋ก ์ดํฐ๋ฌ๋ธ์ด๋ค
์ ๋๋ ์ดํฐ ๊ฐ์ฒด
๐ก ์ ๋๋ ์ดํฐ ๊ฐ์ฒด๋ ์ดํฐ๋ฌ๋ธ(iterable)์ด๋ฉด์ ์ดํฐ๋ ์ดํฐ(iterator)๋ค.
์ผ๋ฐ ํจ์๋ฅผ ํธ์ถํ๋ฉด ํจ์์ ์ฝ๋ ๋ธ๋ก์ ์คํํ๋ค. ๋ฐ๋ฉด ์ ๋๋ ์ดํฐ ํจ์๋ฅผ ํธ์ถํ๋ฉด ์ ๋๋ ์ดํฐ ๊ฐ์ฒด๋ฅผ ์์ฑํ ํ ๋ฐํํ๋ค. ์ ๋๋ ์ดํฐ ๊ฐ์ฒด๋ Symbol.iterator
๋ฉ์๋๋ฅผ ์์ ๋ฐ๋ ์ดํฐ๋ฌ๋ธ์ด๋ฉด์ value
, done
ํ๋กํผํฐ๋ฅผ ๊ฐ๋ ์ดํฐ๋ ์ดํฐ ๋ฆฌ์ ํธ ๊ฐ์ฒด๋ฅผ ๋ฐํํ๋ next
๋ฉ์๋๋ฅผ ์์ ํ๋ ์ดํฐ๋ ์ดํฐ๋ค.
// ์ ๋๋ ์ดํฐ ํจ์ ์ ์
function* genFunc() {
yield 1;
yield 2;
yield 3;
}
// ์ ๋๋ ์ดํฐ ํจ์๋ฅผ ํธ์ถํด์ ์ ๋๋ ์ดํฐ ๊ฐ์ฒด ๋ฐํ
// ์ ๋๋ ์ดํฐ ๊ฐ์ฒด๋ ์ดํฐ๋ฌ๋ธ์ด๋ฉด์ ์ดํฐ๋ ์ดํฐ๋ค
const generator = genFunc();
console.log(Symbol.iterator in generator); // true (์ดํฐ๋ฌ๋ธ)
console.log('next' in generator); // true (์ดํฐ๋ ์ดํฐ)
์ ๋๋ ์ดํฐ ๊ฐ์ฒด๋ next
๋ฉ์๋๋ฅผ ๊ฐ๋ ์ดํฐ๋ ์ดํฐ์ง๋ง, ์ดํฐ๋ ์ดํฐ์๋ ์๋ return
, throw
๋ฉ์๋๋ฅผ ๊ฐ๋๋ค. ์ ๋๋ ์ดํฐ ๊ฐ์ฒด์ next
, return
, throw
๋ฉ์๋๋ฅผ ํธ์ถํ๋ฉด ์๋์ฒ๋ผ ๋์ํ๋ค.
function* genFunc() {
try {
yield 1;
yield 2;
yield 3;
} catch (e) {
console.error(e);
}
}
const generator = genFunc();
generator.next(); // {value: 1, done: false}
generator.return('End'); // {value: 'End', done: true}
generator.throw('Error'); // {value: undefined, done: true}
next
๋ฉ์๋ ํธ์ถ
์ ๋๋ ์ดํฐ ํจ์์yield
ํํ์๊น์ง ์ฝ๋ ๋ธ๋ก ์คํํ๊ณ ,yield
๋ ๊ฐ์value
ํ๋กํผํฐ ๊ฐ์ผ๋ก,false
๋ฅผdone
ํ๋กํผํฐ ๊ฐ์ผ๋ก ๊ฐ๋ ์ดํฐ๋ ์ดํฐ ๋ฆฌ์ ํธ ๊ฐ์ฒด ๋ฐํ.return
๋ฉ์๋ ํธ์ถ
์ธ์๋ก ์ ๋ฌ๋ฐ์ ๊ฐ์value
ํ๋กํผํฐ ๊ฐ์ผ๋ก,true
๋ฅผdone
ํ๋กํผํฐ ๊ฐ์ผ๋ก ๊ฐ๋ ์ดํฐ๋ ์ดํฐ ๋ฆฌ์ ํธ ๊ฐ์ฒด ๋ฐํ.throw
๋ฉ์๋ ํธ์ถ
์ธ์๋ก ์ ๋ฌ๋ฐ์ ์๋ฌ๋ฅผ ๋ฐ์์ํค๊ณundefined
๋ฅผvalue
ํ๋กํผํฐ ๊ฐ์ผ๋ก,true
๋ฅผdone
ํ๋กํผํฐ ๊ฐ์ผ๋ก ๊ฐ๋ ์ดํฐ๋ ์ดํฐ ๋ฆฌ์ ํธ ๊ฐ์ฒด ๋ฐํ
์ ๋๋ ์ดํฐ ์ผ์ ์ค์ง์ ์ฌ๊ฐ
์ ๋๋ ์ดํฐ๋ yield
ํค์๋์ next
๋ฉ์๋๋ฅผ ์ด์ฉํด ์คํ์ ์ ์ ์ค์งํ๋ค๊ฐ ํ์ํ ์์ ์ ๋ค์ ์ฌ๊ฐํ ์ ์๋ค. ์ผ๋ฐ ํจ์๋ ํธ์ถ ์ดํ ํจ์๊ฐ ์ ์ด๊ถ์ ๋
์ ํ์ง๋ง, ์ ๋๋ ์ดํฐ๋ ํจ์ ํธ์ถ์์๊ฒ ์ ์ด๊ถ์ ์๋ํด์ ํ์ํ ์์ ์ ํจ์ ์คํ์ ์ฌ๊ฐํ ์ ์๋ค.
์ ๋๋ ์ดํฐ ํจ์๋ฅผ ํธ์ถํ๋ฉด ์ ๋๋ ์ดํฐ ๊ฐ์ฒด๋ฅผ ๋ฐํํ๊ณ , ์ ๋๋ ์ดํฐ ๊ฐ์ฒด์ ์๋ next
๋ฉ์๋๋ฅผ ํธ์ถํ๋ฉด ์ ๋๋ ์ดํฐ ํจ์์ ์ฝ๋ ๋ธ๋ก์ yield
ํํ์๊น์ง๋ง ์คํํ๋ค. yield
ํค์๋๋ ์ ๋๋ ์ดํฐ ํจ์์ ์คํ์ ์ผ์ ์ค์ง์ํค๊ฑฐ๋ yield
ํค์๋ ๋ค์ ์ค๋ ํํ์ ํ๊ฐ ๊ฒฐ๊ณผ๋ฅผ ์ ๋๋ ์ดํฐ ํจ์ ํธ์ถ์์๊ฒ ๋ฐํํ๋ค.
// ์ ๋๋ ์ดํฐ ํจ์ ์ ์
function* genFunc() {
yield 1;
yield 2;
yield 3;
}
const generator = genFunc();
// next ๋ฉ์๋๋ฅผ ๊ฐ๋ ์ ๋๋ ์ดํฐ ๊ฐ์ฒด ๋ฐํ(์ดํฐ๋ฌ๋ธ+์ดํฐ๋ ์ดํฐ)
generator.next(); // {value: 1, done: false}
// next ๋ฉ์๋๋ฅผ ํธ์ถํด์ ์ฒซ๋ฒ์งธ yield ํํ์๊น์ง ์คํํ๊ณ ์ผ์ ์ค์ง
// next ๋ฉ์๋๊ฐ ๋ฐํํ๋ ๊ฐ์ฒด๋ ์ดํฐ๋ ์ดํฐ ๋ฆฌ์ ํธ ๊ฐ์ฒด
// value ํ๋กํผํฐ์ ์ฒซ๋ฒ์งธ yield ํํ์์์ yield๋ ๊ฐ 1 ํ ๋น
// ํจ์๋ฅผ ๋๊น์ง ์คํํ์ง ์์์ผ๋ฏ๋ก done ํ๋กํผํฐ์ false ํ ๋น
generator.next(); // {value: 2, done: false}
// ๋๋ฒ์งธ yield ํํ์๊น์ง ์คํํ๊ณ ์ผ์ ์ค์ง
generator.next(); // {value: 3, done: false}
// ์ธ๋ฒ์งธ yield ํํ์๊น์ง ์คํํ๊ณ ์ผ์ ์ค์ง
generator.next(); // {value: undefined, done: true}
// ๋จ์ yield ํํ์์ด ์์ผ๋ฏ๋ก ์ ๋๋ ์ดํฐ ํจ์์ ๋ง์ง๋ง๊น์ง ์คํ
// yield ํํ์์ด ์์ผ๋ฏ๋ก value ํ๋กํผํฐ์ undefined ํ ๋น
// ์ ๋๋ ์ดํฐ ํจ์๋ฅผ ๋๊น์ง ์คํํ์ผ๋ฏ๋ก done ํ๋กํผํฐ์ true ํ ๋น
์ ๋๋ ์ดํฐ ๊ฐ์ฒด์ next
๋ฉ์๋๋ฅผ ํธ์ถํ๋ฉด yield
ํํ์๊น์ง ์คํํ๊ณ ์ผ์ ์ค์ง๋๋ฉฐ, ์ด๋ ํจ์ ์ ์ด๊ถ์ด ํธ์ถ์๋ก ์๋๋๋ค. ์ดํ next
๋ฉ์๋๋ฅผ ๋ค์ ํธ์ถํ๋ฉด ๋ง์ง๋ง ์ฝ๋ ์คํ ์ง์ ๋ถํฐ ๋ค์ yield
ํํ์๊น์ง ์คํํ๊ณ ์ผ์์ค์ง๋๋ค. next
๋ฉ์๋๊ฐ ๋ฐํํ๋ ์ดํฐ๋ ์ดํฐ ๋ฆฌ์ ํธ ๊ฐ์ฒด๋ ์๋ ์์ฑ์ ๊ฐ์ง๋ค.
value
:yield
ํํ์์์yield
๋ ๊ฐ(yield
ํค์๋ ๋ค์ ์๋ ๊ฐ)done
: ์ ๋๋ ์ดํฐ ํจ์๋ฅผ ๋๊น์ง ์คํํ๋์ง ์ฌ๋ถ๋ฅผ ๋ํ๋ด๋ Boolean ๊ฐ
์ ๊ณผ์ ์ ์ ๋ฆฌํด๋ณด๋ฉด ์๋์ ๊ฐ๋ค.
generator.next() → yield →
generator.next() → yield →
... →
generator.next() → return
next ๋ฉ์๋์ ๊ฐ ์ ๋ฌํ๊ธฐ
๐ก ์ ๋๋ ์ดํฐ ํจ์์์ ๋ฐํ๊ฐ์ ํฐ ์๋ฏธ๊ฐ ์๋ค. ์ผ๋ฐ์ ์ผ๋ก ์ ๋๋ ์ดํฐ์์ return
๋ฌธ์ ์ฌ์ฉํ์ฌ ๊ฐ์ ๋ฐํํ ํ์๊ฐ ์์ผ๋ฉฐ, ์ข
๋ฃ์ ์๋ฏธ๋ก๋ง ์ฌ์ฉํ๋ค.
์ดํฐ๋ ์ดํฐ์ next
๋ฉ์๋์ ๋ฌ๋ฆฌ ์ ๋๋ ์ดํฐ ๊ฐ์ฒด์ next
๋ฉ์๋๋ ์ธ์๋ฅผ ๋ฐ์ ์ ์๋ค. next
๋ฉ์๋๊ฐ ์ ๋ฌ๋ฐ์ ์ธ์๋ ์ ๋๋ ์ดํฐ ํจ์์ yield
ํํ์์ ํ ๋น๋ฐ๋ ๋ณ์์ ํ ๋น๋๋ค. yield
ํํ์์ ํ ๋น๋ฐ๋ ๋ณ์์(์๋ ์์์์ x
, y
๋ณ์) yield
ํํ์์ ํ๊ฐ ๊ฒฐ๊ณผ๊ฐ ํ ๋น๋์ง ์๋์ ์ ์ฃผ์ํ๋ค. ์ฒซ next()
๋ฉ์๋ ํธ์ถ์ ์ธ์๋ฅผ ๋ฐ์ง ์์ผ๋ฏ๋ก ์ฃผ์ํ๋ค.
function* getFunc() {
const x = yield 1; // ๋ณ์ x๋ ๋๋ฒ์งธ next ๋ฉ์๋๋ฅผ ํธ์ถํ ๋ ๊ฒฐ์ ๋๋ค
const y = yield x + 10; // ๋ณ์ y๋ ์ธ๋ฒ์งธ next ๋ฉ์๋๋ฅผ ํธ์ถํ ๋ ๊ฒฐ์ ๋๋ค
return x + y;
}
const generator = getFunc();
// next ๋ฉ์๋๋ฅผ ๊ฐ๋ ์ ๋๋ ์ดํฐ ๊ฐ์ฒด ๋ฐํ(์ดํฐ๋ฌ๋ธ+์ดํฐ๋ ์ดํฐ)
let res = generator.next(); // {value: 1, done: false}
// ์ฒ์ ํธ์ถํ๋ next ๋ฉ์๋์๋ ์ธ์๋ฅผ ์ ๋ฌํ์ง ์๋๋ค(์ ๋ฌํด๋ ๋ฌด์๋๋ค)
// ์ฒซ๋ฒ์งธ yield ํํ์๊น์ง ์คํํ๊ณ ์ผ์ ์ค์ง๋๋ฉฐ, yield๋ ๊ฐ 1์ ์ดํฐ๋ ์ดํฐ ๋ฆฌ์ ํธ ๊ฐ์ฒด์ value ํ๋กํผํฐ์ ํ ๋น๋๋ค
// ์ด ์์ ์์ x ๋ณ์์๋ ์๋ฌด๊ฒ๋ ํ ๋น๋์ง ์์๋ค. x ๋ณ์ ๊ฐ์ ๋ค์ next ๋ฉ์๋๋ฅผ ํธ์ถํ ๋ ๊ฒฐ์ ๋๋ค
res = generator.next(10); // {value: 20, done: false}
// next ๋ฉ์๋ ์ธ์๋ก ์ ๋ฌํ 10์ getFunc ํจ์์ x ๋ณ์์ ํ ๋น๋๋ค
// next ๋ฉ์๋๊ฐ ๋ฐํํ๋ ์ดํฐ๋ ์ดํฐ ๋ฆฌ์ ํธ ๊ฐ์ฒด์ value ํ๋กํผํฐ์๋ ๋ ๋ฒ์งธ yield๋ ๊ฐ 20์ด ํ ๋น๋๋ค
res = generator.next(20); // {value: 30, done: true}
// next ๋ฉ์๋ ์ธ์๋ก ์ ๋ฌํ 20์ getFunc ํจ์์ y ๋ณ์์ ํ ๋น๋๋ค
// next ๋ฉ์๋๊ฐ ๋ฐํํ๋ ์ดํฐ๋ ์ดํฐ ๋ฆฌ์ ํธ ๊ฐ์ฒด์ value ํ๋กํผํฐ์๋ ์ ๋๋ ์ดํฐ ํจ์์ ๋ฐํ๊ฐ 30์ด ํ ๋น๋๋ค
// ์ ๋๋ ์ดํฐ ํจ์๋ฅผ ๋๊น์ง ์คํํ์ผ๋ฏ๋ก done ํ๋กํผํฐ์ true๊ฐ ํ ๋น๋๋ค
์ด์ฒ๋ผ ์ ๋๋ ์ดํฐ์์ next
๋ฉ์๋๋ฅผ ์ด์ฉํด yield
ํํ์๊น์ง ํจ์๋ฅผ ์คํ์์ผ ์ ๋๋ ์ดํฐ ๊ฐ์ฒด๊ฐ ๊ด๋ฆฌํ๋ ์ํ(yield
๋ ๊ฐ)๋ฅผ ๊ฐ์ ธ์ค๊ฑฐ๋, next
๋ฉ์๋์ ์ธ์๋ฅผ ์ ๋ฌํด์ ์ ๋๋ ์ดํฐ ๊ฐ์ฒด์ ์ํ(yield
ํํ์์ ํ ๋น๋ฐ๋ ๋ณ์) ๊ฐ์ ์ฃผ์
ํ ์๋ ์๋ค.
์ ๋๋ ์ดํฐ์ ํ์ฉ
์ดํฐ๋ฌ๋ธ ๊ตฌํ
์๋ range
๋ณ์๋ ์ซ์ ๊ฐ๊ฒฉ์ from
(1)๊ณผ to
(5) ์์ฑ์ผ๋ก ๋ํ๋ด๊ณ ์๋ ์ผ๋ฐ์ ์ธ ๊ฐ์ฒด๋ค. ์ผ๋ฐ ๊ฐ์ฒด๋ ์ดํฐ๋ฌ๋ธ์ด ์๋๋ฏ๋ก ๋ฐ๋ณต๋ฌธ์ ๋๋ฆด ์ ์๊ธฐ ๋๋ฌธ์ Symbol.iterator
๋ฉ์๋๋ฅผ ์ถ๊ฐํด์ ๋ฐ๋ณต ๊ฐ๋ฅํ ๊ฐ์ฒด๋ก ๋ง๋ค์๋ค. — ์ดํฐ๋ฌ๋ธ๊ณผ ๊ด๋ จํ ๋ ์์ธํ ๋ด์ฉ์ ๋งํฌ ์ฐธ๊ณ
// ์ฝ๋ ์ฐธ๊ณ JavaScript Info
const range = {
from: 1,
to: 5,
// for..of ์ต์ด ํธ์ถ ์, Symbol.iterator๊ฐ ํธ์ถ๋๋ค.
[Symbol.iterator]() {
// Symbol.iterator๋ ์ดํฐ๋ ์ดํฐ ๊ฐ์ฒด๋ฅผ ๋ฐํํ๋ค.
// for..of๋ ๋ฐํ๋ ์ดํฐ๋ ์ดํฐ ๊ฐ์ฒด๋ง์ ๋์์ผ๋ก ๋์ํ๊ณ , ์ด๋ ๋ค์ ๊ฐ๋ ์ ํด์ง๋ค.
return {
current: this.from,
last: this.to,
// for..of ๋ฐ๋ณต๋ฌธ์ ์ํด ๊ฐ ์ดํฐ๋ ์ด์
๋ง๋ค next()๊ฐ ํธ์ถ๋๋ค.
next() {
// next()๋ ๊ฐ์ฒด ํํ์ ๊ฐ, {done:.., value :...}์ ๋ฐํํด์ผ ๋๋ค.
if (this.current <= this.last) {
return { done: false, value: this.current++ };
}
return { done: true };
},
};
},
};
console.log([...range]); // [1, 2, 3, 4, 5]
Symbol.iterator
๋์ ์ ๋๋ ์ดํฐ ํจ์๋ฅผ ์ฌ์ฉํ๋ฉด, ์ ๋๋ ์ดํฐ ํจ์๋ก ๋ฐ๋ณตํ ์ ์๋ค. ๊ฐ์ range
๊ฐ์ฒด์ง๋ง ์ ๋๋ ์ดํฐ๋ฅผ ์ฌ์ฉํด์ ๋ ๊น๋ํ๊ฒ ์์ฑํ ์ ์๋ค.
const range = {
from: 1,
to: 5,
*[Symbol.iterator]() {
for (let value = this.from; value <= this.to; value++) {
yield value;
}
},
};
console.log([...range]); // [1, 2, 3, 4, 5]
ํผ๋ณด๋์น ์๋ฅผ ๋ฐํํ๋ ์ดํฐ๋ฌ๋ธ ๊ตฌํ
์ ๋๋ ์ดํฐ ํจ์๋ฅผ ์ฌ์ฉํ๋ฉด ์ดํฐ๋ ์ด์ ํ๋กํ ์ฝ์ ์ค์ํด ์ดํฐ๋ฌ๋ธ์ ์์ฑํ๋ ๋ฐฉ์๋ณด๋ค ๋ ๊ฐ๋จํ๊ฒ ์ดํฐ๋ฌ๋ธ์ ๊ตฌํํ ์ ์๋ค. ์๋๋ ์ดํฐ๋ ์ด์ ํ๋กํ ์ฝ์ ์ค์ํ์ฌ ํผ๋ณด๋์น ์์ด์ ์์ฑํ๋ ํจ์๋ค. ์๋ ์ฝ๋ ์ดํด๊ฐ ์ ์๋๋ค๋ฉด ์ดํฐ๋ฌ๋ธ ํฌ์คํ ์ ์ฐธ๊ณ ํ๋ฉด ์ข๋ค.
// ์ดํฐ๋ ์ด์
ํ๋กํ ์ฝ์ ์ค์ํด์ ๋ฌดํ ์ดํฐ๋ฌ๋ธ์ ์์ฑํ๋ ํจ์
// infiniteFibonacci์ ์ดํฐ๋ฌ๋ธ ๊ฐ์ฒด๊ฐ ๋ด๊ธด๋ค {next: ƒ, Symbol(Symbol.iterator): ƒ}
const infiniteFibonacci = (function () {
let [pre, cur] = [0, 1];
return {
// ์ดํฐ๋ฌ๋ธ ๊ฐ์ฒด ๋ฐํ
[Symbol.iterator]() {
return this;
},
next() {
[pre, cur] = [cur, pre + cur];
return { value: cur }; // ๋ฌดํ ์ดํฐ๋ฌ๋ธ์ด๋ฏ๋ก done ํ๋กํผํฐ๋ฅผ ์๋ตํ๋ค
},
};
})();
// for of ๋ฌธ์ ์์ํ๋ฉด Symbol.iterator ๋ฉ์๋๊ฐ ํธ์ถ๋๊ณ ์ดํฐ๋ ์ดํฐ ๊ฐ์ฒด๋ฅผ ๋ฐํํ๋ค
// ์ํ๋ฅผ ์์ํ๋ฉด ์ดํฐ๋ ์ดํฐ ๊ฐ์ฒด์ ์๋ next ๋ฉ์๋๋ฅผ ํธ์ถํด์ ์ดํฐ๋ ์ดํฐ ๋ฆฌ์ ํธ ๊ฐ์ฒด๊ฐ ๋ฐํ๋๋ค
// ์ดํฐ๋ ์ดํฐ ๋ฆฌ์ ํธ ๊ฐ์ฒด์ value ํ๋กํผํฐ ๊ฐ์ for of ๋ฌธ์ ๋ณ์์ ํ ๋น๋๋ค.
// ์ํ๋ ์ดํฐ๋ ์ดํฐ ๋ฆฌ์ ํธ ๊ฐ์ฒด์ done ํ๋กํผํฐ๊ฐ true ์ผ๋๊น์ง ๊ณ์๋๋ค.
// ํ์ง๋ง ์์์ ๊ตฌํํ ์ดํฐ๋ฌ๋ธ ๊ฐ์ฒด๋ done ์์ฑ์ด ์์ผ๋ฏ๋ก ๋ฌดํ ๋ฐ๋ณตํ๋ค
for (const fiboNum of infiniteFibonacci) {
if (fiboNum > 30) break;
console.log(fiboNum); // 1, 2, 3, 5, 8, 13, 21
}
์ ๋๋ ์ดํฐ๋ฅผ ์ฌ์ฉํ๋ฉด ์๋ณด๋ค ๋ ๊น๋ํ๊ฒ ์ดํฐ๋ฌ๋ธ์ ๊ตฌํํ ์ ์๋ค. ์ ๋๋ ์ดํฐ ํจ์๊ฐ ๋ฐํํ๋ ์ ๋๋ ์ดํฐ ๊ฐ์ฒด ์์ฒด๊ฐ ์ดํฐ๋ฌ๋ธ์ด์ ์ดํฐ๋ ์ดํฐ์ด๋ฏ๋ก, Symbol.iterator
, next
๋ฉ์๋๊ฐ ํฌํจ๋ ์ดํฐ๋ฌ๋ธ ๊ฐ์ฒด๋ฅผ ๋ฐ๋ก ๊ตฌํํ์ง ์์๋ ๋๋ค.
const infiniteFibonacci = (function* () {
let [pre, cur] = [0, 1];
while (true) {
[pre, cur] = [cur, pre + cur];
yield cur;
}
})();
for (const fiboNum of infiniteFibonacci) {
if (fiboNum > 30) break;
console.log(fiboNum); // 1, 2, 3, 5, 8, 13, 21
}
๋น๋๊ธฐ ์ฒ๋ฆฌ โญ๏ธ
๐ก ์ ๋๋ ์ดํฐ ํจ์๋ฅผ ์ด์ฉํด์ ๋น๋๊ธฐ ์ฒ๋ฆฌ๋ฅผ ๋๊ธฐ ์ฒ๋ฆฌ์ฒ๋ผ ๋์ํ๋๋ก ๊ตฌํํ๋ฉด ์ฝ๋๊ฐ ๋๋ฌด ์ฅํฉํด์ง๊ณ ๊ฐ๋ ์ฑ๋ ๋จ์ด์ง๋ค. ES8(ES 2017)์ ๋์ ๋ async/await ํค์๋๋ฅผ ์ฌ์ฉํ๋๊ฒ ๊ฐ์ฅ ๊น๋ํ๋ค.
์ ๋๋ ์ดํฐ ํจ์๋ next
๋ฉ์๋์ yield
ํํ์์ ์ด์ฉํด ํจ์ ํธ์ถ์(caller)์ ํจ์์ ์ํ๋ฅผ ์ฃผ๊ณ ๋ฐ์ ์ ์๋ค. ์ด๋ฐ ํน์ฑ์ ํ์ฉํด ํ๋ก๋ฏธ์ค๋ฅผ ์ฌ์ฉํ ๋น๋๊ธฐ ์ฒ๋ฆฌ๋ฅผ then
, catch
, finally
๊ฐ์ ํ๋ก๋ฏธ์ค ํ์ ์ฒ๋ฆฌ ๋ฉ์๋ ์์ด ๋๊ธฐ ์ฒ๋ฆฌ์ฒ๋ผ ๊ตฌํํ ์ ์๋ค.
// ๊ดํธ ๋ฒํธ๋ ์๋ ์์๋ฅผ ์๋ฏธํ๋ค
const async = (generatorFunc) => {
const generator = generatorFunc(); // โต
const onResolved = (arg) => {
const result = generator.next(arg); // โธ
return result.done
? result.value // โผ
: result.value.then((res) => onResolved(res)); // โบ
};
return onResolved; // โถ
};
async(function* fetchTodo() {
// โด
const url = 'https://jsonplaceholder.typicode.com/todos/1';
const response = yield fetch(url); // โน
const todo = yield response.json(); // โป
console.log(todo); // {userId: 1, id: 1, title: 'delectus aut autem', completed: false}
})(); // โท
์ ์ฝ๋๋ ์๋ ์์๋๋ก ๋์ํ๋ค.
- ์ ๋๋ ์ดํฐ ํจ์๋ฅผ ์ธ์๋ก ๋ฐ์
async
ํจ์ ํธ์ถ(1).async
ํจ์ ๋ด์์ ์ธ์๋ก ๋ฐ์ ์ ๋๋ ์ดํฐ ํจ์๋ฅผ ์คํํด์ ์ ๋๋ ์ดํฐ ๊ฐ์ฒด๋ฅผ ์์ฑ(2)ํ๊ณonResolved
ํจ์๋ฅผ ๋ฐํ(3)ํ๋ค.async
ํจ์๊ฐ ๋ฐํํonResolved
ํจ์๋ ์ฆ์ ํธ์ถ(4)๋ผ์ ๋ฐฉ๊ธ ์์ฑํ๋ ์ ๋๋ ์ดํฐ ๊ฐ์ฒด์next
๋ฉ์๋๋ฅผ ํธ์ถ(5)ํ๋ค. next
๋ฉ์๋๋ฅผ ํธ์ถ(5)ํ๋ฉด ์ ๋๋ ์ดํฐ ํจ์์ ์ฒซ๋ฒ์งธyield
๋ฌธ(6)๊น์ง ์คํ๋๋ค.next
๋ฉ์๋๊ฐ ๋ฐํํ ์ดํฐ๋ ์ดํฐ ๋ฆฌ์ ํธ ๊ฐ์ฒด์done
ํ๋กํผํฐ ๊ฐ์ดfalse
์ด๋ฏ๋ก, ์ฒซ๋ฒ์งธ yield๋ fetch ํจ์๊ฐ ๋ฐํํ ํ๋ก๋ฏธ์ค๊ฐ(value
์์ฑ๊ฐ), resolveํ Response ๊ฐ์ฒด(๋น๋๊ธฐ ์ฒ๋ฆฌ ๊ฒฐ๊ณผ)๋ฅผonResolved
ํจ์์ ์ธ์๋ก ๋๊ฒจ์ ์ฌ๊ทํธ์ถ(7)ํ๋ค.onResolved
ํจ์๊ฐ ์ธ์๋ก ๋ฐ์ Response ๊ฐ์ฒด๋ฅผnext
๋ฉ์๋ ์ธ์๋ก ์ ๋ฌํด์ ํธ์ถ(5)ํ๋ค. ์ ๋ฌํ ์ธ์๋ ์ ๋๋ ์ดํฐ ํจ์์response
๋ณ์(6)์ ํ ๋น๋๊ณ ๋๋ฒ์งธyield
๋ฌธ(8)๊น์ง ์คํ๋๋ค.next
๋ฉ์๋๊ฐ ๋ฐํํ ์ดํฐ๋ ์ดํฐ ๋ฆฌ์ ํธ ๊ฐ์ฒด์done
ํ๋กํผํฐ ๊ฐ์ดfalse
์ด๋ฏ๋ก, ๋๋ฒ์งธyield
๋response.json
๋ฉ์๋๊ฐ ๋ฐํํ ํ๋ก๋ฏธ์ค๊ฐ(value
์์ฑ๊ฐ), resolveํtodo
๊ฐ์ฒด๋ฅผonResolved
ํจ์์ ์ธ์๋ก ๋๊ฒจ์ ์ฌ๊ทํธ์ถ(7)ํ๋ค.onResolved
ํจ์๊ฐ ์ธ์๋ก ๋ฐ์todo
๊ฐ์ฒด๋ฅผnext
๋ฉ์๋ ์ธ์๋ก ์ ๋ฌํด์ ํธ์ถ(5)ํ๋ค. ์ ๋ฌํ ์ธ์๋ ์ ๋๋ ์ดํฐ ํจ์์todo
๋ณ์(8)์ ํ ๋น๋๊ณ , ์ ๋๋ ์ดํฐ ํจ์๊ฐ ๋๊น์ง ์คํ๋ผ์ ์ฝ์์ ์ฐ๋๋ค.next
๋ฉ์๋๊ฐ ๋ฐํํ ์ดํฐ๋ ์ดํฐ ๋ฆฌ์ ํธ ๊ฐ์ฒด์done
ํ๋กํผํฐ ๊ฐ์ดtrue
์ด๋ฏ๋ก(์ ๋๋ ์ดํฐ ํจ์๊ฐ ๋๊น์ง ์คํ๋จ) ์ ๋๋ ์ดํฐ ํจ์์ ๋ฐํ๊ฐ์ธundefined
(value
์์ฑ๊ฐ)๋ฅผ ๋ฐํ(9)ํ๊ณ ์ข ๋ฃํ๋ค.
์ ๋๋ ์ดํฐ ์ปดํฌ์ง์
์ ๋๋ ์ดํฐ์ ํน์ ๋ฌธ๋ฒ์ธ ์ปดํฌ์ง์
yield*
์ ์ฌ์ฉํ๋ฉด ์ ๋๋ ์ดํฐ๋ฅผ ๋ค๋ฅธ ์ ๋๋ ์ดํฐ์ ์ฝ์
(์๋ฒ ๋)ํ ์ ์๋ค. ์๋๋ start
end
๊ฐ์ ๋ฐ์ ์ฐ์๋ ์ซ์๋ฅผ ์์ฑํ๋ ์ ๋๋ ์ดํฐ ํจ์๋ค.
function* generateSequence(start, end) {
for (let i = start; i <= end; i++) yield i;
}
const generator = generateSequence(0, 10);
generator.next(); // {value: 0, done: false}
generator.next(); // {value: 1, done: false}
// ...
์ ํจ์๋ฅผ ์ด์ฉํด ์ซ์ 0~9(์ ๋์ฝ๋ 48~57), ์ํ๋ฒณ ๋๋ฌธ์ A~Z(์ ๋์ฝ๋ 65~90), ์ํ๋ฒณ ์๋ฌธ์ a~z(์ ๋์ฝ๋ 97~122)๊น์ง ์ฐ์์ ์ผ๋ก ์์ฑํ๋ ํจ์๋ฅผ ๋ง๋ ๋ค๊ณ ๊ฐ์ ํด๋ณธ๋ค. ์ผ๋ฐ ํจ์๋ฅผ ์ด์ฉํ๋ค๋ฉด ํจ์๋ฅผ ์ฌ๋ฌ๊ฐ ๋ง๋ค๊ณ , ๊ฐ๊ฐ์ ํจ์ ํธ์ถ ๊ฒฐ๊ณผ๋ฅผ ์ ์ฅํ ํ ๋ค์ ์กฐํฉํด์ผ ์ํ๋ ๊ธฐ๋ฅ์ ๊ตฌํํ ์ ์๋ค.
yield*
์ง์์๋ ์คํ์ ๋ค๋ฅธ ์ ๋๋ ์ดํฐ์๊ฒ ์์ํ๋ค. ์๋ ์ฝ๋์์ generateSequence
์ ๋๋ ์ดํฐ ํจ์์๊ฒ ์คํ์ ์์ํด์, ์์๋ฐ์ ์ ๋๋ ์ดํฐ๊ฐ ๋ฐ๋ณต์ ์ํํ ์ฐ์ถ ๊ฐ๋ค์ ๋ฐ์ผ๋ก ์ ๋ฌํ๊ณ ์๋ค.
// ์ปดํฌ์ง์
์ ์ ์ฉํ ์ ๋๋ ์ดํฐ ์์
function* generateSequence(start, end) {
for (let i = start; i <= end; i++) yield i;
}
function* generatePasswordCodes() {
yield* generateSequence(48, 57); // 0..9
yield* generateSequence(65, 90); // A..Z
yield* generateSequence(97, 122); // a..z
}
let str = '';
for (const code of generatePasswordCodes()) {
str += String.fromCharCode(code);
// fromCharCode ๋ฉ์๋๋ ์ ๋์ฝ๋(์์คํค์ฝ๋) ๊ฐ์ ๋ฐ์ ํด๋นํ๋ ๋ฌธ์์ด ๋ฐํํ๋ค
// ์ฒซ๋ฒ์งธ ์ปดํฌ์ง์
: 0 -> 01 -> 012 -> ...
// ๋๋ฒ์งธ ์ปดํฌ์ง์
: ...789A -> ...789AB -> ...789ABC -> ...
// ์ธ๋ฒ์งธ ์ปดํฌ์ง์
: ...XYZa -> ...XYZab -> ...XYZabc -> ...
}
console.log(str); // 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz
function* generateAlphaNum() {
for (let i = 48; i <= 57; i++) yield i; // yield* generateSequence(48, 57);
for (let i = 65; i <= 90; i++) yield i; // yield* generateSequence(65, 90);
for (let i = 97; i <= 122; i++) yield i; // yield* generateSequence(97, 122);
}
let str = '';
for (const code of generateAlphaNum()) {
str += String.fromCharCode(code);
}
console.log(str); // 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz
์ด์ฒ๋ผ ์ ๋๋ ์ดํฐ ์ปดํฌ์ง์ ์ ์ฌ์ฉํ๋ฉด ํ ์ ๋๋ ์ดํฐ์ ํ๋ฆ์ ์์ฐ์ค๋ฝ๊ฒ ๋ค๋ฅธ ์ ๋๋ ์ดํฐ์๊ฒ ๋๊ธธ ์ ์๋ค. ์ค๊ฐ ๊ฒฐ๊ณผ๋ฅผ ์ ์ฅํ๋ ์ถ๊ฐ์ ์ธ ๋ฉ๋ชจ๋ฆฌ๋ ํ์ํ์ง ์๋ ์ฅ์ ๋ ์๋ค.
๋น๋๊ธฐ ์ ๋๋ ์ดํฐ
๊ธฐ๋ณธ ์ฌ์ฉ๋ฒ
์ผ๋ฐ ์ ๋๋ ์ดํฐ ํจ์์ ๋ชจ๋ ๊ฐ์ ๋๊ธฐ์ ์ผ๋ก ์์ฐ๋๋ค. ์ฆ, ์ผ๋ฐ ์ ๋๋ ์ดํฐ๋ ๋๊ธฐ์ ๋ฌธ๋ฒ์ด๋ค. ์ ๋๋ ์ดํฐ ํจ์์ ๋น๋๊ธฐ ์์
์ ํ๊ณ ์ถ๋ค๋ฉด ํจ์๋ช
์์ async
ํค์๋๋ฅผ ๋ถ์ด๋ฉด ๋๋ค. ๊ทธ๋ผ generator.next
๋ฉ์๋๋ ์ดํฐ๋ ์ดํฐ ๋ฆฌ์ ํธ ๊ฐ์ฒด๋ฅผ ํ๋ก๋ฏธ์ค๋ก ๊ฐ์ธ์ ๋ฐํํ๋ค. next
๋ฉ์๋๊ฐ ๋ฐํํ๋ ์ดํฐ๋ ์ดํฐ ๋ฆฌ์ ํธ ๊ฐ์ฒด๊ฐ ํ๋ก๋ฏธ์ค์ด๋ฏ๋ก ๋ฐ๋ณต ์์
์ ํ ๋๋ await
ํค์๋๋ฅผ ๋ถ์ฌ์ผ ํ๋ค. ex) for await ...of
๋๊ธฐ ์ ๋๋ ์ดํฐ | ๋น๋๊ธฐ ์ ๋๋ ์ดํฐ(async generator) | |
์ ์ธ ๋ฐฉ๋ฒ | function* |
async function* |
next() ๋ฉ์๋ ๋ฐํ๊ฐ |
{ value: any, done: Boolean } |
Promise { value: any, done: Boolean } |
async function* generateSequence(start, end) {
for (let i = start; i <= end; i++) {
await new Promise((resolve) => setTimeout(resolve, 1000));
yield i;
}
}
(async () => {
const generator = generateSequence(1, 5);
for await (const value of generator) console.log(value);
// 1์ด ๊ฐ๊ฒฉ์ผ๋ก 1~5๊น์ง ์ถ๋ ฅ
})();
๐ก async ์ ๋๋ ์ดํฐ์์ generator.next()
๋ฉ์๋๋ฅผ ์ง์ ํธ์ถํ ๋๋ ์์ await
ํค์๋๋ฅผ ๋ถ์ฌ์ผ ํ๋ค(next()
๋ฉ์๋๊ฐ ํ๋ก๋ฏธ์ค๋ฅผ ๋ฐํํ๋ฏ๋ก). await
ํค์๋๋ async
ํจ์์์๋ง ์๋ํ๋ ์ ๋ ์์ง ๋ง๊ฒ.
(async () => {
const generator = generateSequence(1, 5);
const result = await generator.next();
console.log(result) // {value: 1, done: false}
})();
๋น๋๊ธฐ ์ดํฐ๋ฌ๋ธ
์ ์ ๋๋ ์ดํฐ ํ์ฉ ํํธ์์ ์ ๋๋ ์ดํฐ๋ฅผ ์ด์ฉํด ๋๊ธฐ์ ์ผ๋ก ์๋ํ๋ ์ดํฐ๋ฌ๋ธ์ ๊ตฌํํ์๋ค.
const range = {
from: 1,
to: 5,
*[Symbol.iterator]() {
for (let value = this.from; value <= this.to; value++) {
yield value;
}
},
};
console.log([...range]); // [1, 2, 3, 4, 5]
Symbol.iterator
๋ ๋๊ธฐ ์ดํฐ๋ ์ดํฐ๋ค. ์์์ ๊ตฌํํ ๋๊ธฐ ์ดํฐ๋ฌ๋ธ์ ๋น๋๊ธฐ๋ก ์๋ํ๊ฒ ํ๋ ค๋ฉด ๋น๋๊ธฐ ์ดํฐ๋ ์ดํฐ์ธ Symbol.asyncIterator
๋ก ๋ฐ๊ฟ์ฃผ๋ฉด ๋๋ค.
const range = {
from: 1,
to: 5,
async *[Symbol.asyncIterator]() {
for (let value = this.from; value <= this.to; value++) {
await new Promise((resolve) => setTimeout(resolve, 1000));
yield value;
}
},
};
(async () => {
for await (const value of range) console.log(value);
})(); // 1์ด ๊ฐ๊ฒฉ์ผ๋ก 1~5๊น์ง ์ถ๋ ฅ
๐ก ์ ๊ฐ ๋ฌธ๋ฒ์ ์ผ๋ฐ ์ดํฐ๋ ์ดํฐ(Symbol.iterator
)๊ฐ ํ์ํ๋ฏ๋ก ๋น๋๊ธฐ ์ดํฐ๋ ์ดํฐ์์ ์๋ํ์ง ์๋๋ค.
console.log(...range); // Found non-callable @@iterator
ํ์ฉ ์์ — ํ์ด์ง๋ค์ด์
๊ฒ์ํ ๊ฐ์ ์ฌ์ดํธ๋ ๊ธ์ด ๋ง๊ธฐ ๋๋ฌธ์ ๋ณดํต ํ์ด์ง๋ค์ด์ ์ ์ด์ฉํ๋ค. ์ด๋ ์๋ฒ์์ ์ผ์ ์ซ์ ๋จ์(ํ ํ์ด์ง)๋ก ๋์ด์ ์ ๋ณด๋ฅผ ์ ์กํ๋๊ฒ ์ผ๋ฐ์ ์ด๋ค. GitHub์ ์ปค๋ฐ ์ด๋ ฅ์ ํ์ธํ ๋๋ ์ด ํ์ด์ง๋ค์ด์ ์ด ํ์ฉ๋๋ค.
- ํด๋ผ์ด์ธํธ๊ฐ
https://api.github.com/repos/<repo>/commits
URL๋ก ์์ฒญ ์ ์ก - ์๋ฒ(GitHub)์์ 30๊ฐ์ ์ปค๋ฐ ์ ๋ณด๊ฐ ๋ด๊ธด JSON๊ณผ, ๋ค์ ํ์ด์ง์ ๋ํ Link๋ฅผ Header์ ๋ด์ ์๋ต
- ๋ ๋ง์ ์ปค๋ฐ ์ ๋ณด(๋ค์ ํ์ด์ง)๊ฐ ํ์ํ๋ฉด ํค๋์ ๋ด๊ธด ๋งํฌ๋ฅผ ์ด์ฉํด ๋ค์ ์์ฒญ ์ ์ก
- ๋ฐ๋ณต...
๊ตฌํ ๋ฐฉ๋ฒ
async ์ ๋๋ ์ดํฐ๋ฅผ ์ด์ฉํ๋ฉด ํ์ด์ง๋ค์ด์
๊ณผ ๊ด๋ จํ ์์
์ ์์ฝ๊ฒ ๊ตฌํํ ์ ์๋ค. ์๋ ์์์์ ์ฒซ๋ฒ์งธ ์ปค๋ฐ ๋ฆฌ์คํธ๋ฅผ ๋ฐ์์จ ํ(30๊ฐ ์ปค๋ฐ) ๋ฐ๋ณต๋ฌธ์ ํตํด ๋ชจ๋ ์ปค๋ฐ์ ํ๋์ฉ ๋ฐํ(yield
)ํ๋ฉด, ๋ค์ while
๋ฌธ์ ์ฒ์์ผ๋ก ๋์๊ฐ ๊ทธ ๋ค์ ์ปค๋ฐ ๋ฆฌ์คํธ(๋๋ฒ์งธ)๋ฅผ ๋ฐ์์์ ๋ฐํํ๋ ์์
์ ๋ฐ๋ณตํ๋ค.
// ์ฝ๋ ์ฐธ๊ณ JavaScript Info
async function* fetchCommits(repo) {
let url = `https://api.github.com/repos/${repo}/commits`;
while (url) {
const response = await fetch(url, {
// (1) GitHub๋ ๋ชจ๋ ์์ฒญ์ user-agent ํค๋๋ฅผ ๊ฐ์ ํจ
headers: { 'User-Agent': 'Our script' },
});
// (2) ์ปค๋ฐ ์ ๋ณด๊ฐ ๋ด๊ธด ๋ฐฐ์ด [{...}, {...}]
// { author, comments_url, commit, committer, html_url, node_id, parents, sha, url }
const body = await response.json();
// (3) ํค๋์์ ๋ค์ ํ์ด์ง๋ฅผ ๋ํ๋ด๋ URL ์ถ์ถ
let nextPage = response.headers.get('Link').match(/<(.*?)>; rel="next"/);
nextPage = nextPage?.[1];
url = nextPage;
// (4) ํ์ฌ ํ์ด์ง๊ฐ ๋๋ ๋๊น์ง ์ปค๋ฐ์ ํ๋์ฉ ๋ฐํ(yield).
for (const commit of body) yield commit;
}
}
(async () => {
let count = 0;
for await (const { commit } of fetchCommits('romantech/search-times')) {
const {
author: { name, date },
message,
} = commit;
// [Johan/2021-11-14] Merge pull request...
console.log(`[${name}/${date.match(/(.*?)T/)[1]}] ${message}`);
if (++count === 100) break; // 100๋ฒ์งธ ์ปค๋ฐ์์ ๋ฉ์ถฅ
}
})();
์ ๊ท์์ผ๋ก URL๋ง ์ถ์ถํ๊ธฐ โญ๏ธ
response.headers
์๋ต ํค๋๋ Map๊ณผ ์ ์ฌํ ํํ๋ก ์ ์ฅ๋๊ณ , ์ฌ์ฉํ๋ ๋ฉ์๋๋ ๋น์ทํ๋ค. get
๋ฉ์๋๋ฅผ ์ด์ฉํด์ Link Header๋ฅผ ์กฐํํ๋ฉด ์๋์ฒ๋ผ ๋์ด ์๋ค. rel=”next”
์ผ์ชฝ์ ์๋ ์ฃผ์๊ฐ ๋ค์ ์ปค๋ฐ ๋ฆฌ์คํธ๋ฅผ ์์ฒญํ ์ ์๋ ์ฃผ์๋ค.
# response.headers.get('Link') ์กฐํ ๊ฒฐ๊ณผ ์์
<https://api.github.com/repositories/93253246/commits?page=3>; rel="next",
<https://api.github.com/repositories/93253246/commits?page=196>; rel="last",
<https://api.github.com/repositories/93253246/commits?page=1>; rel="first",
<https://api.github.com/repositories/93253246/commits?page=1>; rel="prev"|
<
, >
ํ์ด๊ดํธ ์์ ์๋ URL๋ง ํ์ํ๋ฏ๋ก ์๋์ฒ๋ผ ์ ๊ท์์ ์ฌ์ฉํด์ ์ถ์ถํ ์ ์๋ค.
.
๋ฉํ๋ฌธ์ : ์์ ๋ฌธ์*
์๋์ : 0๋ฒ ์ด์ ์ผ์น?
์๋์ : 0๋ฒ ๋๋ 1๋ฒ ์ผ์น (๊ธฐ๋ณธ Greedy)?
์๋์๋ ๊ธฐ๋ณธ์ ์ผ๋ก ์ต๋ํ ๋ง์ ๊ฐ์ ๋งค์นญ์ํค์ง๋ง(Greedy๋ก ์๋),*
์๋์ ๋ค์ ์ฌ์ฉํ๋ฉด(*?
) ๊ฐ์ฅ ์ ์ ๋ฌธ์์ด์ ๋งค์นญ์ํจ๋ค(Lazy๋ก ์๋).<(...)>
์๊ดํธ๋ฅผ ์ด์ฉํด ๊ทธ๋ฃนํํ๋ฉด<>
ํ์ด๊ดํธ ์์ชฝ์()
์๊ดํธ๋ก ๋ฌถ์ ๊ทธ๋ฃน์ด ๋งค์นญ๋๊ณ , ๋งค์นญ๋ ๊ทธ๋ฃน์match
๋ฉ์๋๊ฐ ๋ฐํํ๋ ๋ฐฐ์ด์ 1๋ฒ์งธ ์ธ๋ฑ์ค๋ก ์ ๊ทผํ ์ ์๋ค.
'eeeAiiZuuuuAoooZeeee'.match(/A.*Z/g); // ['AiiZuuuuAoooZ']
// A์ Z์ฌ์ด ์์ ๋ฌธ์(.)๊ฐ 0๋ฒ ์ด์ ์ผ์นํ๋ ๊ฒ ์ค ์ต๋ํ ๋ง์ ๊ฐ์ผ๋ก ๋ฐํ(Greedy)
'eeeAiiZuuuuAoooZeeee'.match(/A.*?Z/g); // ['AiiZ', 'AoooZ']
// A์ Z์ฌ์ด ์์ ๋ฌธ์(.)๊ฐ 0๋ฒ ์ด์ ์ผ์นํ๋ ๊ฒ ์ค ์ต๋ํ ์ ์ ๊ฐ์ผ๋ก ๋ฐํ(Lazy)
'eee<AiiZ>uuuu<AoooZ>eeee'.match(/<(.*?)>/); // ['<AiiZ>', 'AiiZ']
// ๋ฐํํ ๋ฐฐ์ด์ 0๋ฒ ์ธ๋ฑ์ค๋ full match๋ ์์ญ, 1๋ฒ ์ธ๋ฑ์ค๋ ์บก์ฒ๋ง ๊ทธ๋ฃน ์์ญ
// g ํ๋๊ทธ๋ฅผ ๋ถ์ด๋ฉด "๊ทธ๋ฃน"์ ํฌํจํ์ง ์์ ๋ฐฐ์ด์ ๋ฐํํ๋ฏ๋ก g ํ๋๊ทธ๋ ๋ถ์ด์ง ์๋๋ค
// ์ผ์นํ๋ ๋ชจ๋ ๊ฐ์ ์ฐพ์์ผํ ๋(g ํ๋๊ทธ๋ฅผ ๋ถ์ฌ์ผํ๋ ์ํฉ) matchAll ๋ฉ์๋๋ฅผ ์ฌ์ฉํ๋ค
// *? ์๋์๋ ๊ฐ์ฅ ์ ์ ๊ฐ์ ์ฐพ์ผ๋ฏ๋ก ์ฒซ๋ฒ์งธ <> ํ์ด๊ดํธ ์์ชฝ ์์ญ์ด ๋งค์นญ๋๋ฉด ์ฐพ๊ธฐ๋ฅผ ์ข
๋ฃํจ
// ๋ง์ฝ * ์๋์๋ง ๋ถ์๋ค๋ฉด ์ฒซ๋ฒ์งธ ํ์ด๊ดํธ ์์ชฝ ์์ญ์ด ๋งค์นญ๋ผ๋ ๋ฉ์ถ์ง ์๊ณ ์ฐพ๊ธฐ๋ฅผ ๊ณ์ํด์,
// ๋ง์ง๋ง > ๋ถ๋ถ์ธ ...AoooZ> ๊น์ง ์ฐพ๊ธฐ๋ฅผ ๊ณ์ํจ. ๋ฐ๋ผ์ AIIZ>uuu<AoooZ ๊ฐ ๋งค์นญ๋จ
.*?
ํน์.+?
์๋์์replace
๋ฉ์๋๋ฅผ ์ฌ์ฉํด์ ํ๊ทธ์ ์ฝํ ์ธ ๋ถ๋ถ๋ง ์ถ์ถํ ์๋ ์๋ค
const element = '<pre>Hello World</pre>';
const contents = element.replace(/<.+?>/g, ''); // + ์๋์๋ 1๋ฒ ์ด์ ์ผ์น
console.log(contents); // Hello World
console.log(element.match(/<.+?>/g)); // ['<pre>', '</pre>']
๋ ํผ๋ฐ์ค
- <๋ชจ๋ ์๋ฐ์คํฌ๋ฆฝํธ Deep Dive> 878p~883p
- JavaScript Info
๊ธ ์์ ์ฌํญ์ ๋ ธ์ ํ์ด์ง์ ๊ฐ์ฅ ๋น ๋ฅด๊ฒ ๋ฐ์๋ฉ๋๋ค. ๋งํฌ๋ฅผ ์ฐธ๊ณ ํด ์ฃผ์ธ์
'๐ช Programming' ์นดํ ๊ณ ๋ฆฌ์ ๋ค๋ฅธ ๊ธ
๋๊ธ
์ด ๊ธ ๊ณต์ ํ๊ธฐ
-
๊ตฌ๋
ํ๊ธฐ
๊ตฌ๋ ํ๊ธฐ
-
์นด์นด์คํก
์นด์นด์คํก
-
๋ผ์ธ
๋ผ์ธ
-
ํธ์ํฐ
ํธ์ํฐ
-
Facebook
Facebook
-
์นด์นด์ค์คํ ๋ฆฌ
์นด์นด์ค์คํ ๋ฆฌ
-
๋ฐด๋
๋ฐด๋
-
๋ค์ด๋ฒ ๋ธ๋ก๊ทธ
๋ค์ด๋ฒ ๋ธ๋ก๊ทธ
-
Pocket
Pocket
-
Evernote
Evernote
๋ค๋ฅธ ๊ธ
-
[React] ๋ ๊ฐ์ง ๋ฐฉ๋ฒ์ผ๋ก ๊ตฌํํด๋ณด๋ ๋ฌดํ ์คํฌ๋กค Infinite Scroll
[React] ๋ ๊ฐ์ง ๋ฐฉ๋ฒ์ผ๋ก ๊ตฌํํด๋ณด๋ ๋ฌดํ ์คํฌ๋กค Infinite Scroll
2024.05.04 -
[JS] ์๋ฐ์คํฌ๋ฆฝํธ ํํ์ ํ๊ฐ ์์์ ๊ฒฐํฉ์ฑ
[JS] ์๋ฐ์คํฌ๋ฆฝํธ ํํ์ ํ๊ฐ ์์์ ๊ฒฐํฉ์ฑ
2024.05.03 -
[JS] ์๋ฐ์คํฌ๋ฆฝํธ ์ดํฐ๋ฌ๋ธ Iterable ์ด ์ ๋ฆฌ
[JS] ์๋ฐ์คํฌ๋ฆฝํธ ์ดํฐ๋ฌ๋ธ Iterable ์ด ์ ๋ฆฌ
2024.05.03 -
[React] ๋ฆฌ์กํธ ํ์๊ธฐ(TypeWriter) ํจ๊ณผ ๊ตฌํํ๊ธฐ feat.์ ๋๋ ์ดํฐ
[React] ๋ฆฌ์กํธ ํ์๊ธฐ(TypeWriter) ํจ๊ณผ ๊ตฌํํ๊ธฐ feat.์ ๋๋ ์ดํฐ
2024.05.03