트랙
/
JavaScript
JavaScript
/
연습 문제
/
병렬 문자 빈도
병렬 문자 빈도

병렬 문자 빈도

보통

지침

병렬 연산을 사용해 텍스트에서 문자의 빈도를 세어요.

병렬성이란 순차적으로도 할 수 있는 일을 병렬로 처리하는 것을 말해요. 흔한 예시가 바로 문자의 빈도를 세는 거예요. 병렬성을 활용해 여러 텍스트로 이루어진 목록에서 각 문자의 전체 빈도를 계산해요.

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는 기본적으로 단일 스레드지만, 코드를 병렬로 실행하는 방법이 있어요.

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를 활용하도록 응용할 수 있을지 고민해 봐요.


더 읽어볼 자료

GitHub에서 편집 링크가 새 창이나 탭에서 열려요
JavaScript Exercism

병렬 문자 빈도 문제를 시작해 볼 준비가 됐나요?

Exercism에 가입하고 JavaScript 트랙을 개념 37개연습 문제 159개, 그리고 실제 사람의 멘토링과 함께 배우고 익혀 보세요. 모두 무료예요.

병렬 문자 빈도 깊이 살펴보기!

동시성과 병렬성의 차이를 살펴보고, JavaScript, Go, Elixir, Rust 같은 언어들이 택한 여러 접근법을 함께 봐요.