๋๋ง์ ์ฒดํฌํฌ์ธํธ
๋ฌธ์ 1
- ๋ถ์ ๋ฐ ์ค๊ณ โ 2024-07-29
- EventQueue ํด๋์ค ์ค๊ณ ๋ฐ ๊ตฌํ โ 2024-07-29
- EventManager ํด๋์ค ์ค๊ณ ๋ฐ ๊ตฌํ โ 2024-07-29
- EventLoop ํด๋์ค ์ค๊ณ ๋ฐ ๊ตฌํ โ 2024-07-29
- Post ํด๋์ค ์ค๊ณ ๋ฐ ๊ตฌํ โ 2024-07-29
- PostMan ํด๋์ค ์ค๊ณ ๋ฐ ๊ตฌํ โ 2024-07-29
- PostHub ํด๋์ค ์ค๊ณ ๋ฐ ๊ตฌํ โ 2024-07-29
๋ฌธ์ 2
- ๋ถ์ ๋ฐ ์ค๊ณ โ 2024-07-29
- EventQueue ํด๋์ค ์ค๊ณ ๋ฐ ๊ตฌํ โ 2024-07-29
- EventManager ํด๋์ค ์ค๊ณ ๋ฐ ๊ตฌํ โ 2024-07-29
- EventLoop ํด๋์ค ์ค๊ณ ๋ฐ ๊ตฌํ โ 2024-07-29
- Post ํด๋์ค ์ค๊ณ ๋ฐ ๊ตฌํ โ 2024-07-29
- PostMan ํด๋์ค ์ค๊ณ ๋ฐ ๊ตฌํ โ 2024-07-29
- PostHub ํด๋์ค ์ค๊ณ ๋ฐ ๊ตฌํ โ 2024-07-29
- ์ ๋ ฅ ๋ฐ๊ธฐ โ 2024-07-30
- ๋ฐฐ๋ฌ์ ์ค์ผ์ค๋ง
๋ฌธ์ ํด๊ฒฐ๊ณผ์
๋ถ์ ๋ฐ ์ค๊ณ
๋์ ํ๋ฆ

์ฐ์ ๋ด๊ฐ ์๊ฐํ๋ ๋์์ ํ๋ฆ์ ์ด์ ๊ฐ๋ค.
- POS๋ฅผ ํตํด ํ๋ฐฐ ์ ๋ณด๋ฅผ Event queue(POS ์ ์ ๋๊ธฐ ํ)์ enqueueํ๋ค.
- POS ์ ์ ๋๊ธฐ ํ์ ๋ฐฐ์ก ๋ชฉ๋ก์ ๋ฐฐ์ก ๋งค๋์ ๊ฐ ์ฃผ๊ธฐ์ ์ผ๋ก ํ๋ฅผ ํ์ธํ ๋ค ๋ง์ฝ ํ์ ๋๊ธฐ๋ชฉ๋ก์ด ์๋ค๋ฉด ๋ฌผ๋ฅ์ผํฐ๋ก ๋ณด๋
- ์ด๋ฒคํธ ๋ฃจํ๋ ์ฃผ๊ธฐ์ ์ผ๋ก ๋๋ฉด์ ๊ณ์ํด์ ๋ฌผ๋ฅ์ผํฐ์ ์ ๋ฌ๋ ๋ฌผํ ์ด๋ฒคํธ๊ฐ ์๋์ง ํ์ธํ๊ณ , ๋ฌผ๋ฅ์ผํฐ ํ์ ๋ถ๋ฅ ๋๊ธฐ ์ํ๊ฐ ๋ ๋๊น์ง ๊ธฐ๋ค๋ ธ๋ค๊ฐ ๋๊ธฐ์ํ๊ฐ ๋๋ฉด ๋ฌผ๋ฅ์ผํฐ ํ๋ก ๋ฌผ๋ฅ๋ฅผ ๋ณด๋ธ๋ค.
- ๋ฌผ๋ฅ์ผํฐ์ ๋ฌผ๋ฅ์ ๋ฐฐ์ก์์ ์ํ๋ฅผ boolean๊ฐ์ผ๋ก ๋๊ณ , ๋์์ด ๊ฐ๋ฅํ ์ํ์ธ์ง ํ์ธํ๋ฉด์ ๋์์ด ๊ฐ๋ฅํ ๊ฒฝ์ฐ ์์ฌ์๋ ์ด๋ฒคํธ๋ฅผ ํ๋์ฉ ๋ณด๋
์ฌ๊ธฐ์ ๋ฐฐ๋ฌ ๊ธฐ์ฌ๋ ๋ฌผ๋ฅ์ผํฐ ์ง์์ ๊ฒฝ์ฐ ํ ๋ฒ์ 1๊ฐ์ ๋ฌผํ๋ง ๋ฐฐ๋ฌํ ์ ์๋๋ฐ, 1๋ฒ์ ๊ฒฝ์ฐ์๋ ๋ฐฐ๋ฌ๊ธฐ์ฌ๊ฐ 1๋ช ์ด๋ผ๋ ๊ฐ์ ํ์ ํด์ผ ํ๋ฏ๋ก ๊ธฐ์กด ๋ฐฐ๋ฌ์ด ์๋ฃ๋๊ธฐ๊น์ง ๋๊ธฐํ ํ์ ๋ค์ ๋ฐฐ๋ฌ์ ์ถ๋ฐํด์ผ ํ๋ค.
๊ฐ์ฒด ์ฐ๊ด ์ค๊ณ
classDiagram EventQueue <|-- POS PostManager <|-- EventQueue PostHub <|-- EventLoop EventQueue <|-- PostManager PostHub <|-- PostManager Postman <|-- PostHub EventLoop <|-- PostHub PostManager <|-- PostHub class POS{ EventQueue eventQueue post() } class EventQueue{ Array queue PostManager postmanager enqueue() } class EventLoop { PostHub postHub run() showState() } class PostHub { PostMan postman EventLoop eventLoop PostManager postManager boolean isRunning Array classifyQueue classify() } class Postman{ Array deliverList boolean isRunning Array delivered deliver() } class Post{ number time string size #getSizeAndTime(size) } class PostManager { EventQueue eventQueue PostHub postHub run() }
์ด๋ ๊ฒ ์ผ๋จ ์ค๊ณ๋ฅผ ํ๊ณ ์์ํด๋ณด๋ ค ํ๋ค.
๊ฐ์ฒด ๊ตฌํ
POS ํด๋์ค
const { EventQueue } = require("./eventQueue");
class POS {
constructor() {
this.eventQueue = new EventQueue();
}
post(size, count) {
this.eventQueue.enqueue(size, count);
}
}POS๊ฐ์ฒด๋ ์ฒ์ ์ฃผ๋ฌธ์ ๋ฐ๊ณ eventQueue๋ก ํด๋น ์ฃผ๋ฌธ์ ๋๊ฒจ์ค๋ค.
EventQueue ํด๋์ค
const { Post } = require("./post");
const { PostManager } = require("./postManager");
class EventQueue {
static instance;
constructor() {
if (EventQueue.instance) return EventQueue.instance;
this.queue = [];
this.postManager = new PostManager(this);
EventQueue.instance = this;
}
enqueue(size, count) {
for (let i = 0; i < count; i++) {
this.queue.push(new Post(size));
}
this.postManager.postHub.fullpost += count;
}
}
module.exports = { EventQueue };
์ด๋ ๊ฒ EventQueue ํด๋์ค์ enqueue ๋ฉ์๋๋ฅผ ํตํด์ ํด๋น ๋๊ธฐ ๋ฐฐ์ก ๋ชฉ๋ก์ ๋ค์ด๊ฐ๊ฒ ๋๊ณ , ์ด๋ฌํ ๋๊ธฐ ๋ฐฐ์ก์ ๋ชฉ๋ก์ ๊ฒฝ์ฐ์๋ PostManagerํด๋์ค๊ฐ ์ฃผ๊ธฐ์ ์ผ๋ก ๋ด์ฃผ๋ฉด์ ๊ด๋ฆฌํ๊ฒ ๋๋ค.
PostManager ํด๋์ค
const { Runable } = require("./abstractClass");
const { EventQueue } = require("./eventQueue");
const { PostHub } = require("./postHub");
class PostManager extends Runable {
constructor(eventQueue) {
super();
this.eventQueue = eventQueue;
this.postHub = new PostHub(this);
this.run();
}
run() {
setInterval(() => {
if (this.eventQueue.queue.length) {
this.postHub.classifyQueue = this.postHub.classifyQueue.concat([
...this.eventQueue.queue,
"show",
]);
this.eventQueue.queue = [];
}
}, 3000);
}
}
module.exports = { PostManager };
PostManager ํด๋์ค์์๋ run() ๋ฉ์๋๋ฅผ ํตํด์ setInterval()์ ์คํ์์ผ ์ฃผ๊ธฐ์ ์ผ๋ก ๋ชฉ๋ก์ ๋ณด๊ณ ๋ฌผ๋ฅ์ฐฝ๊ณ ์ธ PostHub๋ก ๋๊ฒจ์ค๋ค.
PostHub ํด๋์ค
const { Runable } = require("./abstractClass");
const { EventLoop } = require("./eventLoop");
const { Post } = require("./post");
const { Postman } = require("./postman");
class PostHub extends Runable {
constructor(postManager) {
super();
this.postMan = new Postman();
this.postManager = postManager;
this.classifyQueue = [];
this.isRunning = false;
this.eventLoop = new EventLoop(this);
this.fullpost = 0;
}
classify(post) {
this.isRunning = true;
console.log(`${post.size} ๋ถ๋ฅ ์์`);
setTimeout(() => {
console.log(`${post.size} ๋ถ๋ฅ ์๋ฃ`);
this.postMan.deliverList.push(post);
this.isRunning = false;
}, post.time);
}
}
module.exports = { PostHub };
์ด๋ ๊ฒ ๋ง๋ค์ด์ง PostHub์์๋ eventLoop ๊ฐ์ฒด๋ฅผ ๋ง๋ค์ด ์คํ์ํค๊ฒ ๋๋๋ฐ, eventLoop๋ฌธ์์ classify๋ฅผ ์คํ์์ผ ๋ถ๋ฅ๋ฅผ ํด๋น ๊ฐ์ฒด ๋ด์์ ์งํํ๋ ๋ฐฉ์์ด๋ค. ๋น๋๊ธฐ ๋ฐฉ์์ ์ฌ์ฉํ๊ธฐ ์ํด setTimeout์ ํตํด์ ๋ฌผ๋ฅ์ ํด๋นํ๋ ์๊ฐ๋งํผ, ํ์ ์๋ฃ๋๋๋ก ํ๊ณ , ์ด๋ฌํ ํ ์์ ์์ ์ํ๋ boolean๊ฐ์ผ๋ก ๊ด๋ฆฌํ์ฌ ํด๋น ์์ ์์ ์ํ๋ฅผ ๋ณด๊ณ ๋ถ๋ฅ๋ฅผ ์คํ์ํจ๋ค.
EventLoop ํด๋์ค
const { Runable } = require("./abstractClass");
class EventLoop extends Runable {
constructor(postHub) {
super();
this.postHub = postHub;
this.run();
}
async run() {
const running = setInterval(() => {
if (!this.postHub.isRunning && this.postHub.classifyQueue.length) {
const post = this.postHub.classifyQueue.shift();
if (post === "show") this.showState();
else this.postHub.classify(post);
}
if (
!this.postHub.postMan.isRunning &&
this.postHub.postMan.deliverList.length
) {
const deliver = this.postHub.postMan.deliverList.shift();
this.postHub.postMan.deliver(deliver);
}
if (this.postHub.fullpost === this.postHub.postMan.delivered.length) {
console.log("๋ชจ๋ ๋ฐฐ์ก์ด ์๋ฃ๋์์ต๋๋ค.");
process.exit();
}
}, 1000);
}
showState() {
console.log(
`๋๊ธฐ์ค:${this.postHub.postManager.eventQueue.queue.join(
","
)}/ ๋ถ๋ฅ์ค: ${this.postHub.classifyQueue.join(
","
)}/ ๋ฐฐ์ก์ค:${this.postHub.postMan.deliverList
.map((item) => item.size)
.join(",")}/ ๋ฐฐ์ก์๋ฃ: ${this.postHub.postMan.delivered
.map((item) => item.size)
.join(",")}`
);
}
}
module.exports = { EventLoop };EventLoopํด๋์ค์์๋ ์ฃผ๊ธฐ์ ์ผ๋ก setInterval์ ํตํด์ ์ฃผ๊ธฐ์ ์ผ๋ก ๋ฌผ๋ฅ ์ผํฐ์ ๋จ์ ์๋ ๋ฌผ๋ฅ์ ์์ ์์ ์ํ๋ฅผ ๋ณด๊ณ ๋ถ๋ฅ๋ฅผ ์คํํ๊ณ , ๋ฐฐ์ก์์ ๊ฒฝ์ฐ์๋ ๋๊ฐ์ ๋ฐฉ์์ผ๋ก ๋ฐฐ์ก์์ ์ํ์ ๋ฐฐ๋ฌ ๋ชฉ๋ก์ ๋ณด๊ณ ๋ฐฐ๋ฌ์ ์ฒ๋ฆฌํด๋๊ฐ ์ ์๋๋ก ์คํํ๋ ์กฐ๊ฑด๋ฌธ์ ๊ฑธ์ด์ฃผ์๋ค. ๋ง์ฝ ํํฉ์ด ์์ ๋ค์ด๊ฐ์์ ๊ฒฝ์ฐ๋ฅผ ๊ณ ๋ คํ์ฌ showState๋ผ๋ ๋ฉ์๋๋ฅผ ํด๋น ๊ฐ์ฒด์ ๋ง๋ค์ด์ฃผ๊ณ , PostManager๊ฐ ๋ณด๋ธ show๋ผ๋ ์ด๋ฒคํธ๋ฅผ ๋ฐ๋ก ๊ตฌ๋ณํ์ฌ ๋ฉ์๋๋ฅผ ์คํํ ์ ์๋๋ก ํด์ฃผ์๋ค.
Postํด๋์ค
class Post {
constructor(size) {
[this.time, this.size] = this.#getSizeAndTime(size);
}
#getSizeAndTime(size) {
let time;
let sizeName;
switch (size) {
case 1:
time = 3000;
sizeName = "์ํ";
break;
case 2:
time = 7000;
sizeName = "์คํ";
break;
case 3:
time = 15000;
sizeName = "๋ํ";
break;
default:
time = 0;
sizeName = "";
break;
}
return [time, sizeName];
}
}
module.exports = { Post };
Post ํด๋์ค์ ๊ฒฝ์ฐ ๊ฐ ๋ฐฐ์ก ๋ฌผ๋ฅ์ ๋ํ ์ฌ์ด์ฆ๋ฅผ ํ๊ธ๋ก ๋ฐ์์ผ ํ๊ธฐ ๋๋ฌธ์ ๊ฐ์ฒด๋ก ๋ง๋ค์ด์ ๊ด๋ฆฌํ ์ ์๋๋ก ํ์๋ค.
EventQueue ํด๋์ค
class EventQueue {
static #instance;
constructor() {
if (EventQueue.#instance) return EventQueue.#instance;
this.queue = [];
this.eventLoop;
}
enqueue(size, count) {
for (let i = 0; i < count; i++) {
this.queue.push(size);
}
}
dequeue() {}
}
module.exports = { EventQueue };
EventQueue๋ evenloop์ ์ข ์๊ด๊ณ์ ์๋ค. ์ด๋ฒคํธ ๋ฃจํ ๋ํ ์ฑ๊ธ ํค์ผ๋ก ๊ตฌํํ๋ฉฐ ์ด๋ฅผ EventQueue ๋ด์์ eventloop์ ๋ฉ์๋๋ฅผ ๊ณ์ํด์ ์คํ์ํค๋ฉฐ ๋ฌดํ๋ฃจํ๋ฅผ ๊ตฌํํ๊ธฐ ๋๋ฌธ์ด๋ค.
๋ฌธ์ 2 ์ค๊ณํ๊ธฐ
๋ฌธ์ 2์์๋ ๋ฌผ๋ฅ์ผํฐ๊ฐ 4๊ฐ๋ผ๊ณ ๊ฐ์ ํ๊ณ ๊ทธ ์์ ๋ฐฐ๋ฌ์๊ณผ ๋ถ๋ฅ์์ ์ ๋์ ์ผ๋ก ์กฐ์ ํ ์ ์๋ค.
๋ํ EventEmitter์ ์ถ๊ฐ๋ก ๋ถ๋ฅ์/๋ฐฐ์ก์/์
๋ ฅ ๋ฑ์ ํ์์์ ๊ฐ ์ด๋ฒคํธ๋ฅผ ๋ด๋ณด๋ด์ด EventEmitter๋ก ์ฒ๋ฆฌํด์ผ ํ๊ณ , Promise์ ์ฌ์ฉ์ผ๋ก ๋น๋๊ธฐ๋ฅผ ์ง์ํ ์ ์์ด์ผ ํ๋ค.
๋ฐ๋ผ์ ์ด๋ฐ ๋ชจ์์ผ๋ก ์ค๊ณํด๋ดค๋๋ฐ, ์ ๋ต. ๋ถ๋์น ์ฑ!
์ด๋ฐ ์์ ๋น๋๊ณ ์ค๊ณ๋ ์ฒ์์ด๋ผ ๋๋ฌด ๊ณจ์ํ๋ค
๊ณจ์ํ์ ๊ณ ๋ผํ๋
PostMan ํด๋์ค
const { Runable } = require("./abstractClass");
const { emitter } = require("./eventEmitter");
class Postman {
constructor(id, hub) {
this.delivering = false;
this.id = id;
this.hub = hub;
}
deliver(post) {
return new Promise((resolve, reject) => {
emitter.emit("deliverStart", this, post);
resolve(
setTimeout(() => {
emitter.emit("deliverFinish", this, post);
}, 10000)
);
});
}
}
module.exports = { Postman };
๊ฐ์ฅ ํฌ๊ฒ ๋ณํ๊ฑด ๋ฐฐ์ก์๊ณผ ๋ถ๋ฅ์์ ๋ก์ง์ด๋ค. ๋ฐฐ์ก์/๋ถ๋ฅ์์ ๊ฒฝ์ฐ ์ฌ๋ฌ๋ช ์ด ์๊ธฐ ๋๋ฌธ์ ๊ฐ ์ธ์์ ๋ํด์ ๋ฐฐ์ด๋ก ๊ด๋ฆฌํด์ผ ํ ํ์์ฑ์ ๋๊ผ๋ค. ๋ํ Promise๋ฅผ ์ฌ์ฉํ์ฌ ๋น๋๊ธฐ ์ฒ๋ฆฌ๋ฅผ ํด์ผ ํ๋๋ฐ, ์ด์ ๊น์ง๋ settimeout์ ์ฝ๋ฐฑ์ resolve๋ฅผ ๋๊ณ ํ์ฐธ ๊ณ ๋ฏผํ๋๋ฐ ์๊ฐํด๋ณด๋ ๋ฐ์ผ๋ก ๋บ ๋ค์์ ํด๋น ์ง์๋ค์ ์ํ๋ฅผ ๊ณต์ ํ ์ ์๋ ์์ฑ์ ๋๊ณ ๋ฐ๋ก ๊ด๋ฆฌํ๋ฉด ๋๋ค. ์ด๋ฌํ ๋ถ๋ถ์ emitter๋ฅผ ํตํด ๊ด๋ฆฌํด์ฃผ์๋ค.
Hubworker ํด๋์ค
const { emitter } = require("./eventEmitter");
class HubWorker {
constructor(hub, id) {
this.id = id;
this.working = false;
this.hub = hub;
}
classify(post1, post2) {
let time = post1.time;
if (post2) {
time = post1.time > post2.time ? post1.time : post2.time;
}
emitter.emit("classifyStart", this, post1, post2);
return new Promise((resolve, reject) => {
resolve(
setTimeout(() => {
emitter.emit("classified", this, post1, post2);
}, time)
);
});
}
}
module.exports = { HubWorker };
๊ฐ ๋ถ๋ฅ์๋ ์ธ์๋ง๋ค ๊ด๋ฆฌ๋ฅผ ํด์ฃผ์ด์ผ ํ๊ธฐ ๋๋ฌธ์ ๋ฐ๋ก ํด๋์ค ๊ฐ์ฒด๋ฅผ ๋ง๋ค์ด ๊ด๋ฆฌํ ์ ์๋๋ก ํด์ฃผ์๋ค. ์ฌ๊ธฐ์ ํน์ดํ ์ ์ ํ ์ง์๋น ๋ ๊ฐ์ ํ๋ฐฐ๋ฅผ ๊ด๋ฆฌํ ์ ์๊ธฐ ๋๋ฌธ์ ํ๊ฐ๋ง ๋จ์์ ๊ฒฝ์ฐ๋ ๋ ๊ฐ์ ํ๋ฐฐ๊ฐ ๋ค์ด์ฌ ๊ฒฝ์ฐ๋ฅผ ์กฐ๊ฑด๋ฌธ์ ํตํด ๋ฐ๋ก ์ฒ๋ฆฌํด์ฃผ์๋ค.
EventLoop ํด๋์ค
const { Runable } = require("./abstractClass");
class EventLoop extends Runable {
constructor(postHub) {
super();
this.postHub = postHub;
this.run();
}
async run() {
const running = setInterval(() => {
this.#letsWorkHub();
this.#letsWorkPostman();
}, 1000);
}
#letsWorkHub() {
while (this.postHub.classifyQueue.length) {
let addedWork;
if (this.postHub.classifyQueue.length >= 2) {
addedWork = this.postHub.classifyQueue.shift();
}
const worker = this.#findHubWorker();
if (worker)
worker.classify(this.postHub.classifyQueue.shift(), addedWork);
else return;
}
}
#letsWorkPostman() {
while (this.postHub.postToDeliver.length) {
const postman = this.#findPostMan();
if (postman) postman.deliver(this.postHub.postToDeliver.shift());
else return;
}
}
#findHubWorker() {
for (const worker of this.postHub.hubWorker) {
if (!worker.working) return worker;
}
return false;
}
#findPostMan() {
for (const worker of this.postHub.postMan) {
if (!worker.delivering) return worker;
}
return false;
}
showState() {}
}
module.exports = { EventLoop };
EventLooP๋ ๊ธฐ์กด๊ณผ๋ ๋น์ทํ ๋ฐฉ์์ผ๋ก ๋์ํ์ง๋ง, ์ฌ๊ธฐ์ ์ถ๊ฐ๋ ์ ์ ์ฌ๋ฌ ๋ช ์ ์ง์๋ค์ด ์์ ๊ฒฝ์ฐ์ ๊ฐ๋ฅํ ์ง์์ ๋ฝ์ ํด๋นํ๋ ์ผ์ ๋งก๊ฒจ์ผ ํ๋ค. ์ด๋ฌํ ๋ถ๋ถ์ ๊ณ ๋ คํด์ Property์ ์ถ๊ฐํด๋์ ์ํ boolean ๊ฐ์ ํ์ฉํ์ฌ ํ์ฌ ์ผํ๊ณ ์์ง ์์ ์ง์์ ์ฐพ์ ํด๋น ์ง์์๊ฒ ์ผ์ ํ ๋นํ๋๋ก ํ๋ค.
Posthub ํด๋์ค
const { emitter } = require("./eventEmitter");
const { EventLoop } = require("./eventLoop");
const { HubWorker } = require("./hubWorker");
const { Post } = require("./post");
const { Postman } = require("./postman");
class PostHub {
constructor(postManager, hubWorker, postMen, id) {
this.postMan = Array.from(
{ length: postMen },
(_, idx) => new Postman(idx, this)
);
this.postToDeliver = [];
this.postManager = postManager;
this.hubWorker = Array.from(
{ length: hubWorker },
(_, idx) => new HubWorker(this, idx)
);
this.classifyQueue = [];
this.eventLoop = new EventLoop(this);
this.id = id;
}
}
module.exports = { PostHub };
๊ธฐ์กด์๋ PostHub ํด๋์ค ์์ ๋ถ๋ฅํ๋ ๋ฉ์๋๋ฅผ ๋์์ง๋ง, ์ด๋ฅผ ๋ฐ๋ก Hubworker ํด๋์ค์ ์ธ์คํด์ค๋ค์ ๋ฉ์๋๋ก ๋ค์ด๊ฐ๋ฉด์ ํด๋น ๋ฌผ๋ฅ์ผํฐ์์ ํ์ํ ๋ฉ์๋๋ฅผ ๋ฐ๋ก ํ์์๋ค๊ณ ์๊ฐํ์ฌ ๋ชจ์กฐ๋ฆฌ ๋นผ๋ฒ๋ ธ๋ค.
EventEmitter ํด๋์ค
const EventEmmiter = require("events");
class PostEventEmmiter extends EventEmmiter {}
const emitter = new PostEventEmmiter();
emitter.on("recept", (postManager, count) => {
postManager.sendToHub();
postManager.fullPosts += count;
});
emitter.on("classifyStart", (worker, post1, post2) => {
console.log(
`๋ฌผ๋ฅ์ผํฐ${worker.hub.id}์ ์์
์${worker.id}-${post1.sender}${post1.size} ๋ถ๋ฅ์์`
);
if (post2)
console.log(
`๋ฌผ๋ฅ์ผํฐ${worker.hub.id}์ ์์
์${worker.id}-${post2.sender}${post2.size} ๋ถ๋ฅ์์`
);
worker.working = true;
});
emitter.on("classified", (worker, post1, post2) => {
console.log(
`๋ฌผ๋ฅ์ผํฐ${worker.hub.id}์ ์์
์${worker.id}-${post1.sender}${post1.size} ๋ถ๋ฅ์ข
๋ฃ`
);
if (post2)
console.log(
`๋ฌผ๋ฅ์ผํฐ${worker.hub.id}์ ์์
์${worker.id}-${post2.sender}${post2.size} ๋ถ๋ฅ์ข
๋ฃ`
);
worker.hub.postToDeliver.push(post1);
if (post2) worker.hub.postToDeliver.push(post2);
worker.working = false;
});
emitter.on("deliverStart", (postMan, post) => {
postMan.delivering = true;
console.log(
`๋ฌผ๋ฅ์ผํฐ${postMan.hub.id}์ ๋ฐฐ๋ฌ๊ธฐ์ฌ${postMan.id}-๊ณ ๊ฐ${post.sender}${post.size}๋ฐฐ๋ฌ์์`
);
});
emitter.on("deliverFinish", (postMan, post) => {
postMan.delivering = false;
console.log(
`๋ฌผ๋ฅ์ผํฐ${postMan.hub.id}์ ๋ฐฐ๋ฌ๊ธฐ์ฌ${postMan.id}-๊ณ ๊ฐ${post.sender}${post.size}๋ฐฐ๋ฌ์๋ฃ`
);
postMan.hub.postManager.delivered++;
console.log(
postMan.hub.postManager.delivered,
postMan.hub.postManager.fullPosts
);
if (postMan.hub.postManager.delivered === postMan.hub.postManager.fullPosts) {
console.log("๋ชจ๋ ๋ฌผํ์ด ๋ฐฐ๋ฌ๋์์ต๋๋ค.");
process.exit();
}
});
module.exports = { emitter };
EventEmitter์ ๊ฒฝ์ฐ์๋ ๊ทธ๋ฅ ์์์ ํตํด ๊ธฐ์กด ์ด๋ฒคํธ์๋ฏธํฐ๋ฅผ ์์๋ฐ๊ณ , ๋ด ์ธ์คํด์ค๋ฅผ ๋ง๋ ๋ค์ ํด๋นํ๋ ์ด๋ฒคํธ๋ฅผ ๋ชจ์กฐ๋ฆฌ ํ ๊ณณ์์ ๋ฑ๋ก์์ผ์ฃผ๊ณ ์ฌ์ฉํ๋ค. ์๊ตฌ์ฌํญ์ ๋์์๋๋๋ก ๊ฐ ์์ ์ด ์์ํ๊ฑฐ๋ ๋๋ ๋๋ง๋ค์ ์ด๋ฒคํธ๋ฅผ ๊ฐ๊ฐ ๋ฑ๋กํด์ฃผ์ด ํด๋นํ๋ ์ง์์ํ๋ ์ํ๋ฅผ ๋ณ๊ฒฝํ๊ฑฐ๋ ์ฝ์๋ก ์ฐ๋ ๋ก์ง๋ค๋ก ์ด๋ฃจ์ด์ ธ ์๋ค,. ๋๋ ์ฌ๊ธฐ์ ์ข ๋ฃ ์กฐ๊ฑด์ ๊ฑธ์๋๋ฐ, EventEmitter๊ฐ ๋ฐฐ๋ฌ์ด ์๋ฃ๋์ ๋์์ ์ด๋ฒคํธ๋ฅผ ๋ฐ์์์ผ์ผ ํ๋์ ์ ๊ทธ๋ด๊น ์๊ฐ์ ํด๋ดค๋๋ฐ ์ด์ ๊น์ง ๋ฐฐ๋ฌํ ํ์์ ์ฒ์์ ๋ฐ์๋ ๋ชจ๋ ํ๋ฐฐ๋ค์ ์๋ฅผ ๋ฐ๋ก postManager์์ ๊ด๋ฆฌํ์ฌ ์ค๋ค๋ฉด ์ข ๋ฃ ์กฐ๊ฑด์ ๋ฐ๋ก ๋ง๋ค ์ ์๊ธฐ ๋๋ฌธ์ด๋ผ๊ณ ์๊ฐํ๋ค. ์ด์ ์ฌ๊ธฐ์ ๋ฐฐ๋ฌ์ด ์๋ฃ๋ ๋๋ง๋ค ํํฉ์ ๊ฐฑ์ ํ์ฌ ๋ฐฐ๋ฌํ ๋ฌผํ ๊ฐ์์ ์ด ๊ฐ์๊ฐ ๊ฐ์ผ๋ฉด ํ๋ก๊ทธ๋จ์ ์ข ๋ฃํ๋๋ก ํ๋ค.
PostManager ํด๋์ค
const { emitter } = require("./eventEmitter");
const { PostHub } = require("./postHub");
class PostManager {
constructor(eventQueue, hubWorker, postMen) {
this.eventQueue = eventQueue;
this.postHub = Array.from(
{ length: 4 },
(_, idx) => new PostHub(this, hubWorker, postMen, idx)
);
this.fullPosts = 0;
this.delivered = 0;
}
sendToHub() {
if (this.eventQueue.queue.length) {
this.postHub.sort(
(hub1, hub2) => hub1.classifyQueue.length - hub2.classifyQueue.length
);
this.postHub[0].classifyQueue = this.postHub[0].classifyQueue.concat(
this.eventQueue.queue
);
this.eventQueue.queue = [];
}
}
}
module.exports = { PostManager };
๊ธฐ์กด PostManager์ ์ฌ๊ธฐ์ setInterval์ ํตํด ์ฃผ๊ธฐ์ ์ผ๋ก ํ์ ์๋ pos์ ์์ฒญ๋ค์ ๊ฐ์ ธ์๋ค๋ฉด, ์ฌ๊ธฐ์๋ sendToHub๋ผ๋ ๋ฉ์๋๋ก ๋ฐ๊ฟ eventemitter๋ฅผ ํตํด์ ์คํ์ํฌ ์ ์๋๋ก ํ์๋ค.
๊ฒฐ๊ณผ

ํ์ต๋ฉ๋ชจ
https://luxurious-share-af6.notion.site/Day11-f2a66dd0e7ef45c8bea1e157e37a0998?pvs=4 ์์ธํ ๊ฒ์ ํ์ต ๋ฉ๋ชจ๋ฅผ,,,
๊ฐ์
๊ตฌ์กฐ์ ์ธก๋ฉด
- Runable ์์ ๋นผ๊ธฐ โ 2024-07-30
- Emitter๋ฅผ ํด๋์ค๋ง๋ค ์์ โ 2024-07-30
- ๋ฉ์๋๊ฐ ์๋ ์ด๋ฒคํธ๋ฅผ ์ ๋ฌํ๋ ๋ฐฉ์์ผ๋ก ๋ฆฌํฉํ ๋ง โ 2024-07-30
- ๋ฐฐ์ก์๋ง๋ค ์ ๋ดํ๋ ํ๋ชฉ ์ค์ โ 2024-07-30
- dashboard ํด๋์ค ๋ง๋ค์ด์ ํํฉ ๊ด๋ฆฌ โ 2024-07-30
- main splitํด์ ๋ฐ๋ ์ ๋ ฅ ๋ถ๋ถ ์ ๊ทํํ์์ผ๋ก ๋ฐ๊พธ๊ธฐ
- ์ฌ๋ฌ๊ฐ ์ ๋ ฅ ๋ฐ์ ์ ์๋๋ก ์ค์
- ์ ๋ ฅํ ํ์ ๋ฌผ๋ฅ์ผํฐ๋ ๋ฐฐ์ก ์ฒ๋ฆฌ ์ค์๋ ๋ค์ ์ ๋ ฅ์ ๋ฐ์ ์ ์๊ฒ๋ ์ค์
๊ธฐ๋ฅ์ ์ธก๋ฉด
- ์์ ์๊ฐ ์ฌ๋ฌ๊ฐ
- POS ์ฌ๋ฌ๊ฐ ๋๊ธฐ
- ๋ฐฐ์ก๊ธฐ์ฌ๊ฐ ์ฌ๋ฌ๊ฐ์ ๋ฌผํ ๋ฐฐ์กํ๊ธฐ
๋น๊ธฐ๋ฅ์ ์ธก๋ฉด
- ๋จ์ํ ์คํธ ์คํํ๊ธฐ
- ํ ์คํธ ๋ณด๊ฐํ๊ธฐ
๊ธฐํ
- package-lock.json gitignore ์ฒ๋ฆฌ โ 2024-07-30
๊ตฌ์กฐ์ ์ธก๋ฉด ๊ฐ์
1. Runable ์์ ์ ๊ฑฐ
์ถ์ ํด๋์ค์ฒ๋ผ ์ฌ์ฉํ๊ธฐ ์ํด ์์๋ฐ์๋ Runable์ ์ญ์ ํ๋ค. ์๋์ ๊ฒฝ์ฐ๋ผ๋ฉด run ๋ฉ์๋๋ฅผ ๊ฐ์ง ํด๋์ค๋ค์๊ฒ ์์์์ผ ์ค๋ฒ๋ผ์ด๋ฉํ๋ ๋ฐฉ์์ ๊ฐ์ฒด์งํฅ ์ค๊ณ๋ฅผ ๋ง์ด ๋ณด์์ ๋ฐ๋ผํ๋ คํ๋๋ฐ ์์๊ณผ๋ ๋ค๋ฅด๊ฒ ์ฝ๋๋ฅผ ๋ด๋ ๋ฑํ ํ์๊ฐ ์์ด ๋ณด์ด๋ ์ถ์ํด๋์ค๊ฐ์ ์ญ์ ํ๊ฒ ๋์๋ค.
2. Emitter๋ฅผ ํด๋์ค๋ง๋ค ์์
const EventEmmiter = require("events");
class PostEventEmmiter extends EventEmmiter {}
const emitter = new PostEventEmmiter();
emitter.on("recept", (postManager, count) => {
postManager.sendToHub();
postManager.fullPosts += count;
});
emitter.on("classifyStart", (worker, post1, post2) => {
console.log(
`๋ฌผ๋ฅ์ผํฐ${worker.hub.id}์ ์์
์${worker.id}-${post1.sender}${post1.size} ๋ถ๋ฅ์์`
);
if (post2)
console.log(
`๋ฌผ๋ฅ์ผํฐ${worker.hub.id}์ ์์
์${worker.id}-${post2.sender}${post2.size} ๋ถ๋ฅ์์`
);
worker.working = true;
});
emitter.on("classified", (worker, post1, post2) => {
console.log(
`๋ฌผ๋ฅ์ผํฐ${worker.hub.id}์ ์์
์${worker.id}-${post1.sender}${post1.size} ๋ถ๋ฅ์ข
๋ฃ`
);
if (post2)
console.log(
`๋ฌผ๋ฅ์ผํฐ${worker.hub.id}์ ์์
์${worker.id}-${post2.sender}${post2.size} ๋ถ๋ฅ์ข
๋ฃ`
);
worker.hub.postToDeliver.push(post1);
if (post2) worker.hub.postToDeliver.push(post2);
worker.working = false;
});
emitter.on("deliverStart", (postMan, post) => {
postMan.delivering = true;
console.log(
`๋ฌผ๋ฅ์ผํฐ${postMan.hub.id}์ ๋ฐฐ๋ฌ๊ธฐ์ฌ${postMan.id}-๊ณ ๊ฐ${post.sender}${post.size}๋ฐฐ๋ฌ์์`
);
});
emitter.on("deliverFinish", (postMan, post) => {
postMan.delivering = false;
console.log(
`๋ฌผ๋ฅ์ผํฐ${postMan.hub.id}์ ๋ฐฐ๋ฌ๊ธฐ์ฌ${postMan.id}-๊ณ ๊ฐ${post.sender}${post.size}๋ฐฐ๋ฌ์๋ฃ`
);
postMan.hub.postManager.delivered++;
console.log(
postMan.hub.postManager.delivered,
postMan.hub.postManager.fullPosts
);
if (postMan.hub.postManager.delivered === postMan.hub.postManager.fullPosts) {
console.log("๋ชจ๋ ๋ฌผํ์ด ๋ฐฐ๋ฌ๋์์ต๋๋ค.");
process.exit();
}
});
module.exports = { emitter };๊ธฐ์กด EventEmitter์ ๊ฒฝ์ฐ ํ๋์ emitter ์ธ์คํด์ค๋ฅผ ๋ฃ์ด๋๊ณ , ๊ฐ ์ด๋ฒคํธ์ ๋ํ ์ฝ๋ฐฑํจ์๋ฅผ ๋ชจ๋ ์์ ๋๋ ค๋ฃ๋ ๋ฌด์ํ ๋ฐฉ์์ผ๋ก ์ฝ๋๋ฅผ ์์ฑํ์๋ค. ์์ฑํ๊ณ ๋ณด๋ ์ด๋ฒคํธ๋ช ๋ง๊ณ ๋ ์ ๋๋ก ํ๋จ์ด ์ ๋๋ ์ด๋ฒคํธ๋ค์ด ๋๋ฌดํ์ฌ ์ด๋ฅผ ๋ฆฌํฉํ ๋งํ๋ ๊ฒ์ด ์ฐ์ ์ด๋ผ๊ณ ์๊ฐํ๋ค.
const { DashBoard } = require("./dashboard");
const { EventLoop } = require("./eventLoop");
const { HubWorker } = require("./hubWorker");
const { Postman } = require("./postman");
const EventEmitter = require("events");
class PostHub extends EventEmitter {
constructor(postManager, hubWorker, postMen, id) {
super();
this.postMan = Array.from(
{ length: postMen },
(_, idx) => new Postman(idx, this)
);
this.postToDeliver = [];
this.postManager = postManager;
this.dashBoard = new DashBoard();
this.hubWorker = Array.from(
{ length: hubWorker },
(_, idx) => new HubWorker(this, idx)
);
this.classifyQueue = [];
this.eventLoop = new EventLoop(this);
this.id = id;
this.on("letsWork", this.letsWork);
}
letsWork() {
while (this.classifyQueue.length) {
const [work1, work2] = this.#findPostToClassify();
this.#findWorker().emit("letsClassify", work1, work2);
}
while (this.postToDeliver.length) {
const postman = this.#findPostMan(this.postToDeliver[0].sizeNum);
if (!postman) break;
postman.emit("letsDeliver", this.postToDeliver.shift());
}
}
#findWorker() {
return this.hubWorker.find((worker) => !worker.working);
}
#findPostMan(postSize) {
const foundPostMan = this.postMan.find(
(postman) => postman.id % 4 === postSize % 4
);
if (!foundPostMan)
return this.postMan.find((postman) => !postman.delivering);
return foundPostMan;
}
#findPostToClassify() {
if (this.classifyQueue.length) {
let work = this.classifyQueue.shift();
let addedWork;
if (this.classifyQueue.length >= 2) {
addedWork = this.classifyQueue.shift();
}
return [work, addedWork];
}
}
}
module.exports = { PostHub };
๊ฐ์ฅ ๋ํ์ ์ธ ๋ฌผ๋ฅ์ผํฐ ํด๋์ค๋ฅผ ๋ณด์. EventEmitter๋ฅผ ์์ํด์ ์์์ ์ ์ธํด์ฃผ๋ ๋ฐฉ์์ผ๋ก ๋ฆฌํฉํ ๋ง์ ์งํํ๊ณ , ์ด๋ฌํ ์ด๋ฒคํธ์ ์ฝ๋ฐฑํจ์๋ ๋ฉ์๋๋ก ์ ์ํ์ฌ ๋ณด๋ค ์ด๋ค ๊ฐ์ฒด ์์์ ์ด๋ค ์ด๋ฒคํธ๋ฅผ ๋ค๋ฃจ๋์ง์ ๋ํด์ ๋ช ํํด์ง ๋๋์ ๋ฐ์ ์ ์์๋ค.
3. ๋ฉ์๋๊ฐ ์๋ ์ด๋ฒคํธ ์ ๋ฌ ๋ฐฉ์์ผ๋ก ๋ฆฌํฉํ ๋ง
class EventLoop {
constructor(postHub) {
this.postHub = postHub;
this.run();
}
async run() {
const running = setInterval(() => {
this.postHub.emit("letsWork");
}, 1000);
}
}
module.exports = { EventLoop };๋ฌผ๋ฅ์ผํฐ ํด๋์ค์์ ์ ์ธํ ์ด๋ฒคํธ๋ฅผ ํ์์๊ธฐ ์ํด ์ด๋ฒคํธ๋ฃจํ์ ๊ตฌ์กฐ๋ฅผ ๋ํญ ๋ณ๊ฒฝํ๋ค. ์ด์ ๋ setInterval์ ํตํด ์ฃผ๊ธฐ์ ์ผ๋ก ๋ฐฐ์ก๊ณผ ๋ถ๋ฅ ์ ๋ฌด๋ฅผ ํ๋๋ก ํ๋ ์ด๋ฒคํธ๋ฅผ ๋ฐ์กํ๊ณ , ํด๋น ์ด๋ฒคํธ๋ ์์ ๊ฐ์ฒด์ธ ๋ฌผ๋ฅ์ผํฐ ๊ฐ์ฒด์์ ๋ฉ์๋๋ฅผ ์คํํจ์ผ๋ก์จ ๋ณด๋ค ๋ฐ์ดํฐ์ ์ ์ด ํ๋ฆ์ ์ฉ์ดํ๊ฒ ํ์ ํ ์ ์์๋ค.
4. ๋ฐฐ์ก์๋ง๋ค ์ ๋ดํ๋ ํ๋ชฉ ์ง์
letsWork() {
while (this.classifyQueue.length) {
const [work1, work2] = this.#findPostToClassify();
this.#findWorker().emit("letsClassify", work1, work2);
}
while (this.postToDeliver.length) {
const postman = this.#findPostMan(this.postToDeliver[0].sizeNum);
if (!postman) break;
postman.emit("letsDeliver", this.postToDeliver.shift());
}
}
#findWorker() {
return this.hubWorker.find((worker) => !worker.working);
}
#findPostMan(postSize) {
const foundPostMan = this.postMan.find(
(postman) => postman.id % 4 === postSize % 4
);
if (!foundPostMan)
return this.postMan.find((postman) => !postman.delivering);
return foundPostMan;
}๋๋ฌด ๊ตฌํํ๊ณ ์ถ์๋ ๋ฐฐ์ก์๋ง๋ค ์ ๋ดํ๋ ํ๋ชฉ ๋ํ ๋ฆฌํฉํ ๋ง์ ํตํด ํจ๊ป ๊ตฌํํด์ฃผ์๋ค. ์ฒ์์๋ ๋ฐฐ์ก์๋ง๋ค ์ ๋ดํ๋ ํ๋ชฉ์ ์ด๋ป๊ฒ ํ๋ฉด ๊ด๋ฆฌํ ์ ์์ง?๋ฅผ ์๊ฐํ๋ค๊ฐ ๊ฐ ๋ฐฐ์ก์์๊ฒ id๊ฐ์ผ๋ก ์ฒ์์ ๋ฐฐ์ด์ ๋ฃ์ด์ค ๋ ์ธ๋ฑ์ค๊ฐ์ ๋ฃ์ด์ค ๊ฒ์ด ์๊ฐ๋ฌ๋ค.
์ด๋ฅผ ํ์ฉํด์ 14๊น์ง ์๋ ์ฌ์ด์ฆ์์ ํ๋๋ฅผ ์ ๋ด์ผ๋ก ์ ํํ์ด์ผ ํ๋๋ฐ, 4๋ก ๋๋ ๋๋จธ์ง๋ฅผ ์๊ฐํด๋ณด๋ฉด ์ธ๋ฑ์ค๊ฐ์ด ์๋ฌด๋ฆฌ ๋์ด๋๋ 03๊น์ง๋ง ์์ ๊ฒ์ด๊ณ , ์ฌ์ด์ฆ์ ๊ฒฝ์ฐ๋ 0~3๋ง์ ์๋ค๊ฐ๋ค ํ ๊ฒ์ด๋ค.
์ด๋ฅผ ํ์ฉํ์ฌ find ๊ณ ์ฐจํจ์๋ฅผ ํ์ฉํด์ ์ ๋ดํ๋ ์ฌ์ด์ฆ์ ๋ฐฐ์ก์์๊ฒ ๋ณด๋ค ์ฐ์ ์ ์ผ๋ก ๋ฐฐ์ ํด์ฃผ๋ ค ํ์์ผ๋ฉฐ, ์ถ๊ฐ์ ์ผ๋ก ๋ง์ฝ ์ ๋ดํ๋ ๋ฐฐ์ก์์ด ์๋ค ํ๋๋ผ๋ ๋จ์์ ์ฌ๊ณ ์๋ ๋ฐฐ์ก์์๊ฒ ํ์์๋ก ๋ฐฐ์ ํด์ฃผ๋ ค๊ณ ์ด๋ฌํ ๋ฐฉ์์ผ๋ก ์ค์ผ์ค๋ง์ ์ค๊ณํ๋ค.
5. Dashboard ํด๋์ค ๋ง๋ค์ด์ ํํฉ ๊ด๋ฆฌ
const EventEmitter = require("events");
class DashBoard extends EventEmitter {
static instance;
constructor() {
super();
if (DashBoard.instance) return DashBoard.instance;
this.isPending = [];
this.isClassifing = [];
this.isWaitingDeliver = [];
this.isDelivering = [];
this.isDelivered = [];
DashBoard.instance = this;
this.on("addPending", this.addPending);
this.on("addClassifying", this.addClassifying);
this.on("addWaiting", this.addWaitingDeliver);
this.on("addDelivering", this.addDelivering);
this.on("addDelivered", this.addDelivered);
}
stringify(postArr) {
return postArr
.map((post) => `${post.sender}๋์ ${post.size}๋ฌผํ`)
.join(",");
}
showState() {
console.log("----------------------------------");
console.log(
`๋ถ๋ฅ๋๊ธฐ-${this.stringify(this.isPending)}\n๋ถ๋ฅ์ค-${this.stringify(
this.isClassifing
)}\n๋ฐฐ๋ฌ๋๊ธฐ-${this.stringify(
this.isWaitingDeliver
)}\n๋ฐฐ๋ฌ์ค-${this.stringify(
this.isDelivering
)}\n๋ฐฐ๋ฌ์๋ฃ-${this.stringify(this.isDelivered)}/`
);
console.log("----------------------------------");
}
addPending(post) {
this.isPending.push(post);
this.showState();
}
deletePending(targetPost) {
this.isPending = this.isPending.filter((post) => post != targetPost);
}
addClassifying(post) {
this.deletePending(post);
this.isClassifing.push(post);
this.showState();
}
deleteClassifying(targetPost) {
this.isClassifing = this.isClassifing.filter((post) => post !== targetPost);
}
addWaitingDeliver(post) {
this.deleteClassifying(post);
this.isWaitingDeliver.push(post);
this.showState();
}
deleteWaiting(targetPost) {
this.isWaitingDeliver = this.isWaitingDeliver.filter(
(post) => post !== targetPost
);
}
addDelivering(post) {
this.deleteWaiting(post);
this.isDelivering.push(post);
this.showState();
}
addDelivered(targetPost) {
this.isDelivering = this.isDelivering.filter((post) => post !== targetPost);
this.isDelivered.push(targetPost);
this.showState();
}
}
module.exports = { DashBoard };
๋ง์ ์ ์ ๋ค ๋ง๋ค๊ณ ๋ณด๋ ํํฉ ๋ง๋ค์ด์ผ ํ๋๊ฑธ ๊น๋นกํ์๋ค. ์ด ๋ํ ๊ทธ๋ ๊ฒ ์ด๋ ค์ด ๊ฒ์ ์๋๋ ์๋กญ๊ฒ ๋ง๋ค์ด์ฃผ์๋ค.
dashboard ํด๋์ค ๋ํ EventEmitter๋ฅผ ์์ํด์ ํด๋น ํด๋์ค ๊ฐ์ฒด ์์์ ์ด๋ฒคํธ๋ฅผ ์ ์ธํด์ฃผ๊ณ , ๋ค๋ฅธ ๊ณณ์์๋ ์ด ํด๋์ค์ ์ง์
ํ์ฌ ์ด๋ฒคํธ๋ฅผ ์คํํจ์ผ๋ก์จ ๊ฐ Post๊ฐ์ฒด์ ๋ํ์ฌ ๋ถ๋ฅ๋๊ธฐ,๋ถ๋ฅ์ค,๋ฐฐ๋ฌ๋๊ธฐ,๋ฐฐ๋ฌ์ค,๋ฐฐ๋ฌ์๋ฃ ์ํ๋ฅผ ์
๋ฐ์ดํธํ ์ ์๊ฒ ํด์ฃผ๊ณ , ๋์ค์๋ ์ด๋ฌํ ๋ฐฐ์ด์ ํ์ฉํด์ ํํฉ์ ํ์ํด์ผ ํ๊ธฐ ๋๋ฌธ์ stringify๋ผ๋ ๋ฉ์๋๋ฅผ ๋ง๋ค์ด์ฃผ์ด ๋ฌธ์์ด๋ก ์ถ๋ ฅํ ์ ์๋๋ก ํด์ฃผ์๋ค.
์ด๋ฌํ dashBoard์ ๊ฒฝ์ฐ ์ฑ๊ธํค ํจํด์ ์ฌ์ฉํ์ฌ ์ด๋ค ๊ฐ์ฒด์ ์๋ ์ง ๊ฐ์ ์ธ์คํด์ค๋ฅผ ๊ณต์ ํจ์ผ๋ก์จ ์ฌ๋ฌ ๊ฐ์ ๋ฌผ๋ฅ์ผํฐ๊ฐ ๋๋ ์ง๋ ๊ฒฝ์ฐ์๋ ๊ฐ ๋ฐฐ์ก์, ๋ฌผ๋ฅ์ ๋ฑ์ด ํ๋ํ ๋๋ง๋ค ์ด๋ฒคํธ๋ฅผ ์คํ์์ผ ๊ฐ์ ์ธ์คํด์ค์ ํํฉ์ ์ต์ ํํ๋๋ก ํด์ฃผ์๋ค.