|
| 1 | +## 비동기 프로그래밍 |
| 2 | + |
| 3 | +- 자바스크립트에서 동기 코드는 블로킹 방식으로 실행 |
| 4 | +- 코드가 순서대로 한 번에 한 문장씩 실행됨을 의미 |
| 5 | +- 비동기 코드는 논블로킹 방식으로 실행 |
| 6 | +- 코드의 나머지 부분을 차단하지 않고 오래 실행되는 작업을 수행할 때 유용 |
| 7 | + - 네트워크 요청, 파일 시스템 액세스, 데이터베이스 쿼리 등 |
| 8 | + |
| 9 | + |
| 10 | +## 콜백 함수 |
| 11 | + |
| 12 | +- 비동기 코드를 작성하기 위한 원시적인 방법 |
| 13 | +- 다른 함수의 인수로 전달되어 비동기 작업 이후 실행 |
| 14 | +- 주요 단점으로는 '콜백 지옥'이 발생할 수 있음 |
| 15 | + |
| 16 | + |
| 17 | +## 프로미스 패턴 |
| 18 | + |
| 19 | +> 자바스크립트에서 비동기 작업을 처리하는 더 나은 방법 |
| 20 | +
|
| 21 | +- 프로미스는 비동기 작업의 결과를 나타내는 객체 |
| 22 | + - 대기(pending), 이행(fulfilled), 거부(rejected) 상태를 가짐 |
| 23 | + |
| 24 | + |
| 25 | +### 프로미스 생성 |
| 26 | + |
| 27 | +- Promise 생성자를 사용하여 프로미스 객체를 생성 |
| 28 | + - 함수를 인수로 받으며 함수는 resolve와 reject를 인수로 받음 |
| 29 | + - `new Promise((resolve, reject) => { ... })` |
| 30 | + - resolve: 프로미스가 성공적으로 완료되었을 때 호출 |
| 31 | + - reject: 프로미스가 실패했을 때 호출 |
| 32 | +- 호출자는 반환된 Promise 객체의 .then 및 .catch 메서드를 호출하여 요청 결과 처리 |
| 33 | + |
| 34 | + |
| 35 | +### 프로미스의 장점 |
| 36 | + |
| 37 | +- 콜백보다 체계적이고 가독성 높은 비동기 처리 가능 |
| 38 | +- 콜백 지옥을 방지할 수 있음 |
| 39 | + |
| 40 | + |
| 41 | +### 프로미스 병렬 처리 |
| 42 | + |
| 43 | +> Promise.all 메서드를 사용하여 여러 프로미스를 병렬로 처리 |
| 44 | +
|
| 45 | +```javascript |
| 46 | +Promise.all([promise1, promise2, promise3]) |
| 47 | + .then((values) => { |
| 48 | + console.log(values); |
| 49 | + }); |
| 50 | +``` |
| 51 | + |
| 52 | + |
| 53 | +### 프로미스 순차 실행 |
| 54 | + |
| 55 | +> Promise.resolve 메서드를 사용하여 프로미스를 순차적으로 실행 |
| 56 | +
|
| 57 | +```javascript |
| 58 | +Promise.resolve() |
| 59 | + .then(() => promise1()) |
| 60 | + .then(() => promise2()) |
| 61 | + .then(() => promise3()) |
| 62 | + .then(() => console.log('All done!')); |
| 63 | +``` |
| 64 | + |
| 65 | + |
| 66 | +### 프로미스 메모이제이션 |
| 67 | + |
| 68 | +> 프로미스를 캐시하여 중복 호출을 방지 |
| 69 | +
|
| 70 | +```javascript |
| 71 | +const cache = new Map(); |
| 72 | + |
| 73 | +function memoizedFunc(url) { |
| 74 | + if (cache.has(url)) { |
| 75 | + return cache.get(url); |
| 76 | + } |
| 77 | + |
| 78 | + return new Promise((resolve, reject) => { |
| 79 | + fetch(url) |
| 80 | + .then((response) => response.json()) |
| 81 | + .then((data) => { |
| 82 | + cache.set(url, data); |
| 83 | + resolve(data); |
| 84 | + }) |
| 85 | + .catch(reject); |
| 86 | + }); |
| 87 | +} |
| 88 | +``` |
| 89 | + |
| 90 | + |
| 91 | +### 프로미스 데코레이터 |
| 92 | + |
| 93 | +> 고차 함수를 사용하여 프로미스를 래핑 |
| 94 | +
|
| 95 | +```javascript |
| 96 | +function logger(fn) { |
| 97 | + return function(...args) { |
| 98 | + console.log('Function called with', args); |
| 99 | + return fn(...args).then((result) => { |
| 100 | + console.log('Function returned', result); |
| 101 | + return result; |
| 102 | + }); |
| 103 | + }; |
| 104 | +} |
| 105 | + |
| 106 | +const makeRequestWithLogger = logger(makeRequest); |
| 107 | + |
| 108 | +makeRequestWithLogger('http://example.com') |
| 109 | + .then((data) => console.log(data)); |
| 110 | + .catch((error) => console.error(error)); |
| 111 | +``` |
| 112 | + |
| 113 | + |
| 114 | +## async/await 패턴 |
| 115 | + |
| 116 | +> 비동기 코드를 마치 동기 코드처럼 작성할 수 있게 해주는 최신 문법 |
| 117 | +
|
| 118 | +- async/await는 프로미스를 기반으로 동작 |
| 119 | +- async 함수는 항상 Promise를 반환 |
| 120 | + |
| 121 | + |
| 122 | +### 비동기 반복 |
| 123 | + |
| 124 | +> for-await-of 반복문을 사용하여 비동기 반복 가능 객체를 순회 |
| 125 | +
|
| 126 | +```javascript |
| 127 | +async function* createAsyncIterable() { |
| 128 | + yield 1; |
| 129 | + yield 2; |
| 130 | + yield 3; |
| 131 | +} |
| 132 | + |
| 133 | +async function main() { |
| 134 | + for await (const value of createAsyncIterable()) { |
| 135 | + console.log(value); |
| 136 | + } |
| 137 | +} |
| 138 | +``` |
| 139 | + |
| 140 | + |
| 141 | +### 비동기 병렬 |
| 142 | + |
| 143 | +> Promise.all 메서드를 사용하여 여러 프로미스를 병렬로 처리 |
| 144 | +
|
| 145 | +```javascript |
| 146 | +async function main() { |
| 147 | + const [result1, result2, result3] = await Promise.all([ |
| 148 | + promise1(), |
| 149 | + promise2(), |
| 150 | + promise3(), |
| 151 | + ]); |
| 152 | + |
| 153 | + console.log(result1, result2, result3); |
| 154 | +} |
| 155 | +``` |
| 156 | + |
| 157 | + |
| 158 | +### 비동기 순차 실행 |
| 159 | + |
| 160 | +> Promise.resolve 메서드를 사용하여 프로미스를 순차적으로 실행 |
| 161 | +
|
| 162 | +```javascript |
| 163 | +async function main() { |
| 164 | + let result = await Promise.resolve(); |
| 165 | + |
| 166 | + result = await promise1(); |
| 167 | + result = await promise2(); |
| 168 | + result = await promise3(); |
| 169 | + |
| 170 | + console.log(result); |
| 171 | +} |
| 172 | +``` |
| 173 | + |
| 174 | + |
| 175 | +### async/await 데코레이터 |
| 176 | + |
| 177 | +> 고차 함수를 사용하여 async 함수를 래핑 |
| 178 | +
|
| 179 | +사용법이 python이나 java의 데코레이터와 비슷해서 신기해서 가져왔어요. |
| 180 | + |
| 181 | +```javascript |
| 182 | +function asyncLogger(fn) { |
| 183 | + return async function(...args) { |
| 184 | + console.log('Function called with', args); |
| 185 | + const result = await fn(...args); |
| 186 | + console.log('Function returned', result); |
| 187 | + return result; |
| 188 | + }; |
| 189 | +} |
| 190 | + |
| 191 | +@asyncLogger |
| 192 | +async function main() { |
| 193 | + const data = await makeRequest('http://example.com'); |
| 194 | + console.log(data); |
| 195 | +} |
| 196 | +``` |
| 197 | + |
| 198 | + |
| 199 | +## 총평 |
| 200 | + |
| 201 | +이번 장은 비동기 프로그래밍에 대해 알아봤어요. 콜백함수부터 프로미스, async-await 등 자바스크립트의 비동기 처리 방식은 3가지의 비교가 정형화되어 있어서 어느 정도 알고 있던 내용인 것 같네요. 어느 정도 비동기에 대해서 알게된 이후엔 Promise.all, Promise.allSettled, Promise.race 등 다양한 메서드들을 접할 수 있었고, 이번 책의 내용에서 소개되었을 때 보다 쉽게 짚고 넘어갈 수 있었어요. |
| 202 | + |
| 203 | +반면 내용에서 decorator를 사용하여 래핑하는 방법이나 메모이제이션 방법 등은 신기했어요. 생각해보지 않거나 잘 활용하지 않아본 활용 사례들도 몇몇 있었고요. 그래서 눈길이 가는 예시들만 정리해보게 되었습니다. 이번 장을 통해 비동기 프로그래밍에 대해 전체적으로 다시 한 번 정리할 수 있었던 것 같아서 좋았어요. |
0 commit comments