안녕하세요!
오늘은 Observer 설계패턴, thread, event emitter, Publisher와 Subscriber 패턴 등 배운게 많아 차근차근 정리해보겠습니다.
Pub - Sub 구조
해당 구조는 많은 곳에서 쓰이는데, 이전에 제가 소개한 MQTT라는 통신도 이와 같은 구조였습니다. MQTT를 통해 해당 구조를 이해하고 싶으시면 아래 글을 참고해주세요!
[프로그래밍 언어/통신] - [MQTT] MQTT란 무엇일까? - 1편 (MQTT/Publish/Subscribe/Topic)
전 이 구조를 이해하기 가장 좋은 방법으로 Youtube와 매칭지어서 이해했습니다.
(현실 youtube와는 다르게 구독을 하고 나서 알림을 받아야만 해당 영상을 볼 수 있다고 가정하고 생각해주세요!)
유튜브에서 유튜버들이 항상 외치는 구독 부탁드린다는 말에서 구독이 영어로 Subscribe이거든요. 그리고 유튜버을 Publisher로 보시면 됩니다.
Youtube 세상에서는 각 유튜버별로 유튜브 서버에 채널이 하나씩 있습니다.
유튜브에는 구독한 유튜버가 영상을 올릴 때 마다 알림이 오도록 하는 기능이 있습니다.
각 구독자별로 아래와 같이 유튜버들을 좋아해서 구독한 상황이라고 가정해보겠습니다.
이 상태에서 유튜버 A와 유튜버 B가 본인의 채널에 영상을 업로드한다면 알림은 어떻게 가게 될까요?
구독한 그대로 영상이 올라오자마자 구독자들에게 해당 유튜버 채널에 알림이 오게 됩니다.
이 모습 그대로를 구독자를 Subscriber, 유튜버를 Publisher로 하여 생각하게 되면 Pub - Sub 구조 완성입니다!
특징
위 상황을 보시면 구독자는 유튜버에게 지금 직접 특정 영상을 내놓으라고 하지 않습니다.
그리고 유튜버도 특정 구독자에게 주기 위한 영상을 찍지 않습니다.
현재 Pub-Sub구조에서 구독자는 Youtube 내에서 내가 좋아하는 유튜버의 채널을 구독하고 영상이 올라오길 기다릴뿐입니다.
그리고 유튜버는 누가 나를 구독했는지 신경쓸 필요 없이 그저 Youtube의 내 채널에 내가 찍을 영상을 올릴 뿐입니다.
결론적으로 Publisher는 데이터를 줄 뿐, Subscriber는 구독 할 뿐이고, 중간에서 이에 맞게 데이터를 전달해주는 일을 하는 역할인 Youtube와 같은 Broker라는 것이 있습니다.
그리고 이렇게 알림을 보내는 디자인 패턴을 Observer 설계패턴이라고 합니다.
Multi Thread
Thread는 프로세스 내에서 실행되는 독립적인 실행 단위. 여러 Thread를 사용하면 병렬로 작업을 수행할 수 있어 프로그램의 효율성을 높일 수 있음.
Thread를 여러 개 쓰는 Multi Thread는 내가 만든 프로그램이 좀 많이 빡센 작업을 해야 할 것 같을 때 쓰입니다.
6초 걸리는 작업이 있다고 해봅시다. 하나의 Thread에서 전부 실행하게 되면 작업이 완료되는데 6초가 걸립니다.
그럼 이 작업을 빠르게 끝내기 위해 Thread를 하나 더 써본다고 해봅시다.
Thread가 하나 더 늘면서 작업 중 오래 걸리는 부분을 따로 떼어 새로운 Thread에서 작업하도록 했습니다.
그래서 각 작업이 완료되는데 각각 3초씩 걸린다 했을 때, Thread 두개가 병렬로 작업을 처리하여 3초만에 작업을 완료할 수 있습니다.
worker_thread
worker_thread는 node.js에서 멀티 스레드를 사용하기 위한 모듈입니다.
예시를 통해 알아보겠습니다.
// main.js
const { Worker, parentPort } = require('worker_threads');
const worker = new Worker('./worker.js');
worker.on('message', (message) => {
console.log('Result from worker:', message);
});
worker.postMessage({ num1: 1, num2: 2 });
console.log('Message posted to worker');
// worker.js
const { parentPort } = require('worker_threads');
parentPort.on('message', (message) => {
const result = message.num1 + message.num2;
parentPort.postMessage(result);
});
// 출력 결과
Message posted to worker
Result from worker: 3
여기서 특이점으로는 코드에서는 더 아래에 나온 Message posted to worker란 문구가 출력에선 더 위에 나왔단 점입니다.
어떻게 진행이 되는 것인지 알아봅시다.
1. 선언
const worker = new Worker('./worker.js');
선언은 위와 같이 멀티 스레드로 작업할 코드를 작성한 파일의 경로를 입력해줍니다.
2. 메시지 전달
worker.postMessage({ num1: 1, num2: 2 });
worker.on이 위에 있는데 왜 이것부터 하냐구요? 일단 전달할 메시지를 먼저 전달하고 on을 실행하게 되기 때문입니다.
num1: 1, num2: 2가 들어있는 객체를 이제 ./worker.js로 전달합니다. 그럼 worker.js에서 진행을 해봅시다.
3. 멀티 스레드의 작업 실행
parentPort.on('message', (message) => {
const result = message.num1 + message.num2;
parentPort.postMessage(result);
});
부모로부터 즉 main.js로부터 온 message를 통해 위와 같은 행동을 실행합니다. message에는 2번 과정으로 인해 { num1: 1, num2: 2 }가 담겨있기 때문에 result는 3이 되고, 3은 다시 부모에게 message로 전달되게 됩니다.
4. 메인 스레드의 작업 실행
worker.on('message', (message) => {
console.log('Result from worker:', message);
});
이제 worker.on()을 실행할 차례입니다.
worker.on()은 비동기적으로 진행됩니다. worker로 부터 전송되는 메시지를 받게 되면 실행될 준비를 하는 녀석이기 때문에 메시지가 오기까지 기다리게 되면서 이제야 실행이 됩니다.
3번 과정에서 message에는 result의 값, 즉 3이 들어가게 되고, 그래서 Result from worker: 3이 됩니다.
Event Emitter
내용 추가 필요
'부스트캠프 9기 > 챌린지' 카테고리의 다른 글
[부스트캠프 9기 챌린지] 학습 정리 - 13일차 (0) | 2024.07.31 |
---|---|
[부스트캠프 9기 챌린지] 학습 정리 - 11일차 (0) | 2024.07.29 |
[부스트캠프 9기 챌린지] 학습 정리 - 08일차 (0) | 2024.07.24 |
[부스트캠프 9기 챌린지] 학습 정리 - 07일차 (0) | 2024.07.23 |
[부스트캠프 9기 챌린지] 학습 정리 - 06일차 (0) | 2024.07.22 |