병렬 연산을 사용해 텍스트에서 문자의 빈도를 세어요.
병렬성이란 순차적으로도 할 수 있는 일을 병렬로 처리하는 것을 말해요. 흔한 예시가 바로 문자의 빈도를 세는 거예요. 병렬성을 활용해 여러 텍스트로 이루어진 목록에서 각 문자의 전체 빈도를 계산해요.
JavaScript는 본질적으로 단일 스레드라서, 다른 언어들이 병렬 코드 실행을 처리하기 위해 갖추고 있는 언어 기능이 많이 없어요.
사실 "진짜" 병렬 코드 실행을 하는 유일한 방법은 Worker threads(또는 Web Workers)를 쓰는 거예요.
async functions나 Promises처럼 병렬로 실행되는 것처럼 보이는 코드는 거의 항상 실제로는 동시에 실행돼요.
현대 JavaScript가 이런 사용에 최적화되어 있어서 이게 더 나은 경우가 많고, Promise.all()이나 다른 동시 실행 기법을 써서 병렬 실행을 "흉내 내는"(또는 "속이는") 코드도 자주 보게 될 거예요.
To pass the tests for this exercise, your solution needs to execute _concurrently_ (or in parallel),
meaning that synchronous solutions (e.g. a simple `for` loop) will not pass.
두 개념의 차이를 잘 보여 주는 간단한 정의를 소개할게요.
완전성을 위해 동기 실행의 정의도 알아볼게요.
JavaScript는 기본적으로 단일 스레드지만, 코드를 병렬로 실행하는 방법이 있어요.
JavaScript를 브라우저에서 실행한다면(예를 들어 웹 앱에서), 병렬성을 얻는 방법은 Web Worker API를 사용하는 거예요. MDN의 설명에 따르면:
Web Worker를 사용하면 애플리케이션의 메인 실행 스레드와 분리된 백그라운드 스레드에서 스크립트 작업을 실행할 수 있어요.
반대로 JavaScript가 Exercism의 대상 런타임인 Node.js에서 실행된다면, 이와 같은 개념을 Worker threads라고 해요.
Be aware that the implementation of the worker API differs largely between browsers and other JavaScript environments.
Make sure to read the documentation for your specific runtime!
다음은 Web Worker API의 간단한 예제예요. (Medium에서 가져왔어요)
// main.js
const myWorker = new Worker('worker.js');
myWorker.postMessage(5);
myWorker.onmessage = function (event) {
console.log('Received result from worker:', event.data);
};
// worker.js
onmessage = function (event) {
console.log('Received number from main thread:', event.data);
// Perform computation
const result = event.data * 2;
// Send result back to the main thread
postMessage(result);
};
그리고 다음은 Worker threads API의 예제예요. (문서에서 가져왔어요)
const {
Worker,
isMainThread,
parentPort,
workerData,
} = require('node:worker_threads');
if (isMainThread) {
module.exports = function parseJSAsync(script) {
return new Promise((resolve, reject) => {
const worker = new Worker(__filename, {
workerData: script,
});
worker.on('message', resolve);
worker.on('error', reject);
worker.on('exit', (code) => {
if (code !== 0)
reject(new Error(`Worker stopped with exit code ${code}`));
});
});
};
} else {
const { parse } = require('some-js-parsing-library');
const script = workerData;
parentPort.postMessage(parse(script));
}
Currently it is not possible to implement parallelism using the online editor.
Please implement `Worker threads` using Node.js locally and submit your solution via CLI!
더 나아가고 싶다면, 자신의 구현을 Worker threads를 활용하도록 응용할 수 있을지 고민해 봐요.
Exercism에 가입하고 JavaScript 트랙을 개념 37개연습 문제 159개, 그리고 실제 사람의 멘토링과 함께 배우고 익혀 보세요. 모두 무료예요.
동시성과 병렬성의 차이를 살펴보고, JavaScript, Go, Elixir, Rust 같은 언어들이 택한 여러 접근법을 함께 봐요.