J238-C, J204-C
์ฐ๋ฆฌ์ ์ฒดํฌํฌ์ธํธ
-
์๋ฒ
-
checkin
-
clap
-
checkout
-
summary
-
direct
-
์ฑํ (chat, finish, broadcast)
-
ํด๋ผ์ด์ธํธ
-
!history
-
checkin
-
clap
-
checkout
-
summary
-
direct
-
์ฑํ (chat, finish, broadcast)
๋ฌธ์ ํด๊ฒฐ ๊ณผ์
Telnet ์ฐ๊ฒฐ
์ฑ๋ฆฐ์ง GPT ๋ง๋ค๊ธฐ
ํต์ฌ ํฌ์ธํธ - ์์ฒญ ์๊ตฌ์ฌํญ
-
์๋ฒ๊ฐ ๋ฐ์ ๋ชจ๋ ์์ฒญ์๋ ์ ์ ํ ์๋ต์ ๋ณด๋ด์ค๋ค. (์๋ฌด๋ฐ ๋ฐ์์ด ์์ผ๋ฉด ์๋๋ค.)
-
์๋ฒ๋ ์ฌ๋ฌ ํด๋ผ์ด์ธํธ๊ฐ ๋์์ ์ฐ๊ฒฐํ ์ ์์ด์ผ ํ๋ค.
-
checkin ์์ฒญ์ ๋ฐ์ ํ์๋ ์ฐ๊ฒฐ์ ์ ์งํด์ผ ํ๋ค.
ํต์ฌ ํฌ์ธํธ - ํด๋ผ์ด์ธํธ
-
๋น๋๊ธฐ ์ ๋ ฅํ๋ฉด
-
checkin ์ฑ๊ณตํ ์๊ฐ์ ๋ณ์์ ๊ธฐ๋ก
-
chekoutํ ๋ checkout์๊ฐ - chekin ์๊ฐ โ Core Time
-
์คํ ํ ์ ๋ ฅํ ๋ช ๋ น์ ๋ชจ๋ ๊ธฐ๋ก(์๋ฒx ํด๋ผ์ด์ธํธ ์์ฒด์์)
-
์์ฒญ, ์๋ต, ๋ธ๋ก๋์บ์คํธ๋ฅผ ๋ชจ๋ ํด๋ผ์ด์ธํธ๊ฐ ๋ฐ์ ์ถ๋ ฅ
์๋ฒ
const net = require("net");
const { handleCommand } = require("./handleCommand");
const server = net.createServer((socket) => {
console.log("Client Connected");
const userSessionId = crypto.randomUUID();
socket.on("data", (data) => {
console.log(`${userSessionId} Received from client: ${data}`);
data = JSON.parse(data);
const response = handleCommand(userSessionId, data, socket);
socket.write(response);
});
socket.on("end", () => {
console.log("Client disconnected");
});
});
const port = 2024;
server.listen(port, () => {
console.log(`Server listening on port ${port}`);
});
์๋ฒ๋ net.Socket์ ํ์ฉํ์ฌ 2024ํฌํธ์ ๋ํด์ ์๋ฒ๋ฅผ ํค๊ณ , JSON ํ์์ ์ปค๋งจ๋, ๋ฐ์ดํฐ๋ก ์ด๋ฃจ์ด์ง ๊ฐ์ฒด๋ฅผ ๋ฐ์ ์ด์ ๋ํด์ ๊ฐ๊ฐ ์ฒ๋ฆฌํ๋ค. ์ด๋ฌํ ๋ฐ์ดํฐ ์ฒ๋ฆฌ ๋ฐฉ์์ ๊ธฐ์กด ํ๋ก ํธ์ ๋ฐฑ์ ๋ฐ์ดํฐ ํต์ ์ ๋ํ ๋ฐฉ์๊ณผ ๊ฑฐ์ ํก์ฌํ๋ค.
ํด๋ผ์ด์ธํธ
function checkin(campId, host, port) {
let client = new net.Socket();
client.connect(port, host, () => {});
client.on("data", (data) => {
ResponseHandler.handle(data);
});
client.on("close", () => {
process.exit();
});
client.write(RequestJson.makeCheckinRequest(campId));
historyList.push("checkin");
return client;
}
ํด๋ผ์ด์ธํธ๋ net.Socket์ ์ด์ฉํ์ฌ ์ ๋ฌ๋ host์ port์ ๋ํด ์ฐ๊ฒฐ
์ดํ write๋ก ์๋ฒ์ ์์ฒญ์ด ๊ฐํ ์๋ต์ด ๋์์ค๊ฒ ๋ ๊ฒฝ์ฐ ResponseHandler๋ฅผ ์ด์ฉํ์ฌ ์๋ต ๊ฒฐ๊ณผ ์ถ๋ ฅ
ํต์ฌ ํฌ์ธํธ - checkin
// ํด๋ผ์ด์ธํธ
> checkin J004
< checkin success to group#1
// ์๋ฒ
>> checkin J004 (success) from 127.0.0.1:12334 => session#1, group#1
const { Repository } = require("./repository");
const User = require("./user");
function checkin(userSessionId, data, socket) {
const campId = data.data;
const repository = new Repository();
numberValidCheck(campId);
const user = repository.addUser(campId, userSessionId, socket);
const groupNum = repository.joinGroup(user);
console.log(
`checkin ${user.campId} (Success) from ${socket.remoteAddress} => session#${user.indexId}, group#${user.group.groupNum}`
);
return JSON.stringify({ command: data.command, data: groupNum });
}
const numberValidCheck = (campId) => {
const idNumber = parseInt(campId.slice(1));
if (typeof idNumber !== "number" || idNumber > 256 || idNumber < 1) {
throw new Error("Invalid Id number");
}
};
module.exports = { checkin };
-
campId (J001~J256)
-
checkin โ ๊ทธ๋ฃน ํ ๋น
-
4๋ช ๊น์ง ๊ทธ๋ฃน ํ ๋น
-
๊ทธ๋ฃน์์ ๋น ์ ธ๋๊ฐ ๊ฒฝ์ฐ ์ฌํ ๋น ๊ฐ๋ฅ(ํ ๋นํ๋ ๋ฐฉ์์ ๋ํด์ ์๋ ผ)
-
checkin ์๋ต โ ๊ทธ๋ฃน ๋ฒํธ๋ฅผ ์ ์ํ์ผ๋ก ์๋ ค์ค
์ฒดํฌ์ธ์ ๊ฒฝ์ฐ ๊ฐ ์ ์ ๋ง๋ค ์ค๋ ๋ฌ๋ผ์ง๋ UUID ๊ฐ์ ๋ํด Database ๊ฐ์ฒด์ Repository๋ผ๋ ์ค๊ฐ ๊ฐ์ฒด๋ฅผ ํตํด ๊ฐฑ์ ํ๋ ๋ฐฉ์์ผ๋ก ๊ตฌํํ๋ค.
๋ํ ๊ทธ๋ฃน๋ ๊ฐ์ฒด๋ก ๋ง๋ค์ด์ฃผ์ด ๊ฐ ๊ฐ ๊ทธ๋ฃน์์ ๋จ์ ๊ณต๊ฐ์ ์ฐพ์ ํด๋นํ๋ ์บ ํผ๋ฅผ ๋ฃ์ด์ฃผ๋๋ก ํ๊ณ , ์ด ๋ํ repository์ ๋ฉ์๋๋ฅผ ํตํด ๊ฐฑ์ ํ๋ค. ๋ง์ง๋ง์๋ JSON๊ฐ์ ๋ฆฌํดํด์ฃผ์ด ํด๋ผ์ด์ธํธ์์๋ ์ฒ๋ฆฌ๊ฐ ์ฉ์ดํ๋๋ก ๊ตฌํํ๋ค.
์์ธ
-
campId ๋ฒ์ ์ด๊ณผ ์๋ฌ
-
์ฌ์ ๋ ฅ
-
checkin ์ํ์์ ๋ค์ checkin ๋ถ๊ฐ๋ฅ

ํต์ฌ ํฌ์ธํธ - checkout
// ํด๋ผ์ด์ธํธ
> checkout
< checkout (disconnected)
> Core time = 11min 32sec
// ์๋ฒ
>> checkout from session#2(J005) - disconnected
const { Repository } = require("./repository");
function checkout(user, userSessionId) {
const repository = new Repository();
console.log(
`checkout from session#${user.indexId}(${user.campId}) - disconnected`
);
repository.deleteUser(userSessionId);
return JSON.stringify({ command: "checkout", data: true });
}
module.exports = { checkout };
-
์ด์ ์ checkin ํ๋ ๊ทธ๋ฃน์์ ํด์ฅ
-
๊ทธ๋ฃน์ ๋ค๋ฅธ ์บ ํผ๊ฐ ๋จ์์๋ค๋ฉด, ํด๋น ๊ทธ๋ฃน ์บ ํผ๋ค์๊ฒ ํด์ฅ ๋ฉ์์ง ์ ๋ฌ
-
chekout ์์ฒญ ํ ์๋ต์ ๋ฐ์ผ๋ฉด ์ฐ๊ฒฐ์ ๋๊ธฐ
-
chekout ์์ด TCP ์ฐ๊ฒฐ์ด ๋๊ฒจ๋ checkout ์ฒ๋ฆฌ
์ฒดํฌ์์์์ ์ ๊ฒฝ์จ์ผ ํ ์ ์ ๊ธฐ์กด์ ์ ์ ์ค์ธ ์บ ํผ๋ฅผ ๋ณด๊ดํ๋ database์ user๊ฐ์ฒด์ ๋ํด ์ญ์ ๋ฅผ ํจ๊ณผ ๋์์ ๊ทธ๋ฃน์์ ๋ํ ์ ๊ฑฐํด์ผ ํ๋ค๋ ์ ์ด์๋ค. ์ด๋ฅผ ์ ์ํ์ฌ repository๋ฅผ ํตํด ์ ๋ณด๋ฅผ ๊ฐฑ์ ํ๊ณ , error๊ฐ ๋์ ธ์ง์ง ์๋ ์ด์ true๊ฐ๋ง ๋ฐ์ดํฐ๋ก ๋ฆฌํดํ์ฌ ์ฑ๊ณต ์ฌ๋ถ๋ฅผ ์๋ฆฌ๋๋ก ํ๋ค.

ํต์ฌ ํฌ์ธํธ - Summary
// ํด๋ผ์ด์ธํธ
> summary day4
< keywords are "Heap, Stack"
// ์๋ฒ
>> summary from session#2(J005) : day19 => 'Network, Server'
function summary(user, data) {
if (!day.hasOwnProperty(data.data) || !data.data)
throw new Error("404 Day Not Found");
console.log(`summary from session#${user.indexId}(${user.campId})`);
return JSON.stringify({ command: "summary", data: `\"${day[data.data]}\"` });
}
const day = Object.freeze({
day1: "IDE,node",
day2: "Linux,System",
day3: "XML,JSON",
day4: "Heap,Stack",
day6: "Object,Class",
day7: "File Path, UnitTest",
day8: "Immutable, Closure",
day9: "Event, Publisher",
day11: "Async,EventLoop",
day13: "Git, Object",
day16: "HTTP, SQL",
day18: "Network, Server",
});
module.exports = { summary };
-
summary ์์ฒญ์ ๋ณด๋ด์ ํค์๋ ๋ฐ๊ธฐ
-
๋ฐ์ดํฐ โ day ๋ช ๋ฒ์งธ ๋ฏธ์ ์ธ์ง ์ ์ํ์ผ๋ก ๋ฐ๊ธฐ
-
์๋ฒ โ ์ ์ํ์ ํ์ธํด์ ์๋ต
summary๊ฐ์ ๊ฒฝ์ฐ ์ด๋ฏธ ์ฃผ์ด์ง๋ ๊ฐ๋ค์ด ๊ณ ์ ๋์ด ์์ผ๋ฏ๋ก, ์ด๋ฅผ ์์์ฒ๋ฆฌ ํด์ฃผ๊ณ ๊ฐ์ ธ๋ค๊ฐ ์ธ ์ ์๊ฒ๋ ํด ์ฃผ์๋ค. ํด๋นํ์ง ์์ ๋์์ด ๋์ค๊ฒ ๋๋ค๋ฉด ์๋ฌ๋ฅผ ๋์ ธ์ฃผ์๋ค.

ํต์ฌ ํฌ์ธํธ - chat(์ฑํ ๋ฐฉ ๋ง๋ค๊ธฐ)
// ํด๋ผ์ด์ธํธ
> chat maxCount=2
< broadcast from server, "์ฑํ
์ด ์์๋์์ต๋๋ค"
//ํด๋ผ์ด์ธํธ - ๋ค๋ฅธ ํด๋ผ์ด์ธํธ์๊ฒ chat์ ํตํด ์ฑํ
๋ฐฉ์ ๋ง๋ค๊ณ ๋ธ๋ก๋์บ์คํธ ๋ฐ์์ ๋
< broadcast from J005, "๋ฐ๊ฐ์ต๋๋ค"
// ์๋ฒ
>> chat from session#1(J004)
function chat(user) {
if (!user.group) throw new Error("404 Group not found");
user.group.chatStart();
return JSON.stringify({ command: "chat", data: true });
}
module.exports = { chat };
-
๊ฐ์ ๊ทธ๋ฃน์ ์๋ ์ฌ๋๋ค๊ณผ ๋ธ๋ก๋์บ์คํธ
-
์์ฒญ ๋ฐ์ดํฐ โ maxCount(int)
-
๋ฉ์์ง ๊ฐ์ < maxCount
์์ธ
-
๋ฉ์์ง ๊ฐ์๊ฐ MaxCount๋ฅผ ๋์ผ๋ฉด ์๋ก์๊ฒ ์ ๋ฌ๋์ง ์์
ํต์ฌ ํฌ์ธํธ - finish
//ํด๋ผ์ด์ธํธ -> ์์์ ๋ฃ๊ธฐ
//์๋ฒ
>> finish from session#1(J004)
function finish() {
if (!user.group) throw new Error("404 Group not found");
user.group.chatFinish();
return JSON.stringify({ command: "finish", data: true });
}
module.exports = { finish };
-
์ฑํ ์์ฒญ์ ๋ณด๋ธ ์บ ํผ๊ฐ finish๋ฅผ ๋ณด๋ด๋ฉด ์ฑํ ๋ฉ์ถ๊ธฐ
-
๋ค์ ๋ธ๋ก๋์บ์คํธ ๋ถ๊ฐ๋ฅ
ํต์ฌ ํฌ์ธํธ - broadcast(์ฑํ ๋ฉ์์ง ๋ณด๋ด๊ธฐ)
๋ณด๋ผ ๋
//ํด๋ผ์ด์ธํธ
> broadcast "๋ฐ๊ฐ์ต๋๋ค"
//์๋ฒ
>> broadcast from session#2(J005) => "๋ฐ๊ฐ์ต๋๋ค"
class Database {
_instance = null;
constructor() {
if (this._instance === null) {
this._instance = this;
this.user = {};
this.groups = [];
this.clap = 0;
this.currsessionId = 0;
}
return this._instance;
}
getNewSessionId() {
this.currsessionId++;
return this.currsessionId;
}
}
const getInstance = () => {
if (this.database == undefined) {
this.database = new Database();
}
return this.database;
};
module.exports = { getInstance };
๋ฐ์ ๋
//ํด๋ผ์ด์ธํธ
< broadcast from J004, "์ค๋ํ๋๋ค์"
//์๋ฒ
>> broadcast to group#1 => text="๋ฐ๊ฐ์ต๋๋ค", from="J005"
-
๋ธ๋ก๋์บ์คํธ ์์ฒญ์ ๋ณด๋ด๋ฉด chat ์งํ์ค์ธ ๊ทธ๋ฃน ๋ชจ๋์๊ฒ ๋ธ๋ก๋์บ์คํธ
-
์์ฒญ ๋ฐ์ดํฐ โ text(string)
ํต์ฌ ํฌ์ธํธ - direct
๋ณด๋ผ ๋
//ํด๋ผ์ด์ธํธ
> direct to J004 "๋ง์ง๋ง์ด๋ ํ๋ด์"
< direct (success)
//์๋ฒ
>> direct from session#2(J005) => to="J004", text="๋ง์ง๋ง์ด๋ ํ๋ด์"
๋ฐ์ ๋
//ํด๋ผ์ด์ธํธ
< direct from J005, "๋ง์ง๋ง์ด๋ ํ๋ด์"
//์๋ฒ
broadcast to session#1(J004) => text="๋ง์ง๋ง์ด๋ ํ๋ด์"
-
์ง์ ํน์ ํ ์บ ํผ์๊ฒ ๋ฉ์์ง๋ฅผ ๋ณด๋ผ ์ ์๋ ๊ธฐ๋ฅ
-
์์ฒญ ๋ฐ์ดํฐ โ campId(string), text(string)
์์ธ
-
์์ ํ ๋์ ์บ ํผ๊ฐ ์ฒดํฌ์ธ ์ํ์ผ๋ฉด ๋ณด๋ด์ง ์๊ธฐ
-
์ฒดํฌ์ธ์ ํ ์ํ๋ผ๋ฉด text ๋ฉ์์ง ์ ๋ฌ
ํต์ฌ ํฌ์ธํธ - clap
//ํด๋ผ์ด์ธํธ
> clap
< clap count is 1
//์๋ฒ
>> clap from session#1(J004) => 1
const { Repository } = require("./repository");
function clap() {
const repository = new Repository();
repository.addClap();
console.log("clap!");
return JSON.stringify({ command: "clap", data: repository.getClap() });
}
module.exports = { clap };
-
๋ชจ๋ ํด๋ผ์ด์ธํธ๊ฐ ๋ณด๋ด๋ ์์ฒญ ํ์๋ฅผ ๋์ ํ๊ธฐ ์ํ ๊ธฐ๋ฅ
-
์์ฒญํ ๋๋ง๋ค ํ๋์ฉ ๊ฐ์ ๋์ ํด์ ์ซ์ ์๋ต
-
ํ ํด๋ผ์ด์ธํธ์์ ๋ฐ๋ณตํด์ ์์ฒญ ๊ฐ๋ฅ

ํ์ต ๋ฉ๋ชจ
๊ฐ์ ํ๊ธฐ ์ฒดํฌํฌ์ธํธ
- ๋ชจ๋ ๊ธฐ๋ฅ ์์ฑ โ 2024-08-08
- ํด๋ผ์ด์ธํธ์ readline ๊ตฌ์กฐ ๊ฐ์ โ 2024-08-08
- http Request && response ๊ตฌ์กฐ๋ก ๋ฐ์ดํฐ ๋ณด๋ด๊ธฐ โ 2024-08-08
- Error ํธ๋ค๋ง โ ํด๋ผ์ด์ธํธ์ ์๋ฌ ์ ์ก ๊ฐ์ โ 2024-08-08
ํด๋ผ์ด์ธํธ์ readline ๊ตฌ์กฐ ๊ฐ์
const RequestHandler = require("./requestHandler");
const readline = require("readline");
const rl = readline.createInterface({
input: process.stdin,
output: process.stdout,
});
let client = null;
const port = 2024;
const host = "localhost";
let startTime = 0;
rl.on("line", (line) => {
const order = line.trim().split(" ");
if (order[0] == "!history") {
RequestHandler.history();
} else if (!client) {
if (order[0] == "checkin") {
startTime = Date.now();
client = RequestHandler.checkin(order[1], host, port);
} else {
console.log("์๋ชป๋ ๋ช
๋ น์
๋๋ค");
}
} else {
if (order[0] == "clap") {
RequestHandler.clap(client);
} else if (order[0] == "checkout") {
RequestHandler.checkout(client);
printTime(startTime, Date.now());
} else if (order[0] == "summary") {
RequestHandler.summary(client, order[1]);
} else if (order[0] == "direct") {
//RequestHandler.direct(client);
} else if (order[0] == "chat") {
} else if (order[0] == "finish") {
} else if (order[0] == "broadcast") {
} else {
console.log("์๋ชป๋ ๋ช
๋ น์
๋๋ค");
}
}
});
function printTime(startTime, endTime) {
let time = parseInt((endTime - startTime) / 1000);
console.log(`Core time = ${parseInt(time / 60)}min ${time % 60}sec`);
}
๊ธฐ์กด ์ฝ๋์ ๊ฒฝ์ฐ readline ๋ด์์ ์ด๋ป๊ฒ ์ฒ๋ฆฌํ ์ง์ ๋ํด ๋ณด๋ค ๊ตฌ์กฐ๋ฅผ ์ ํ์ ํ๊ธฐ ์ํด readline ๋ด์์ ๋ช ๋ น์ด๋ฅผ ์ฒ๋ฆฌํ๋ค๋ณด๋ ์๋ฌด๋๋ if else ๋ฌธ์ ๋ณด๋ค ๋จ๋ฐํ๋ ๊ฒฝ์ฐ๊ฐ ์์๋ค. ๋ํ ํด๋ผ์ด์ธํธ๊ฐ ์๋ ๊ฒฝ์ฐ์ ๋ํด์๋ ๋ฐ๋ก ์๋ฒ์ ๋ช ๋ น์ด๋ฅผ ์ฒ๋ฆฌํ๋ฉด ์๋๊ธฐ ๋๋ฌธ์ ์ด๋ฅผ ๋ง๋ค๋ณด๋ ๋ค์ํ ์์ธ ์ํฉ์ ๋ํด ์ฒ๋ฆฌํ๊ธฐ ์ํด if else๋ฌธ์ ์ผ์ง๋ง ์ด๋ฅผ switch/case๋ฌธ์ ํตํด ๋ณด๋ค ๊ตฌ์กฐ์ ์ผ๋ก ์ ๋ฆฌํ ์ ์์ ๊ฒ ๊ฐ์๋.
const RequestHandler = require("./requestHandler");
//ํด๋ผ์ด์ธํธ ๊ฐ์ฒด
let client;
//์ ์ ์๊ฐ์ ๊ตฌํ๊ธฐ ์ํ startTime
let startTime;
const PORT = 2024;
const HOST = "localhost";
function commandHandler(line) {
const [command, ...data] = line.trim().split(" ");
console.log(command, data);
if (!client && command !== "checkin") {
console.log("์ฒดํฌ์ธ์ ์งํํด์ผ ๋ช
๋ น์ด๊ฐ ๊ฐ๋ฅํฉ๋๋ค.");
} else {
switch (command) {
case "!history":
RequestHandler.history();
break;
case "checkin":
startTime = Date.now();
client = RequestHandler.checkin(data[0], HOST, PORT);
break;
case "checkout":
RequestHandler.checkout(client);
printTime(startTime, Date.now());
break;
case "summary":
RequestHandler.summary(client, data[0]);
break;
case "clap":
RequestHandler.clap(client);
break;
case "direct":
RequestHandler.direct(client, data[0], data[1]);
break;
case "broadcast":
RequestHandler.broadcast(client, data[0]);
break;
case "finish":
RequestHandler.finish(client);
break;
default:
console.log("์๋ชป๋ ๋ช
๋ น์ด์
๋๋ค.");
break;
}
}
}
function printTime(startTime, endTime) {
let time = parseInt((endTime - startTime) / 1000);
console.log(`Core time = ${parseInt(time / 60)}min ${time % 60}sec`);
}
module.exports = { commandHandler };๋ฐ๋ผ์ client์ commandHandler๋ฅผ ๋ฐ๋ก ๋ง๋ค๊ณ , ์ด์ ๋ํด์ readline์ ํด๋ก์ ๋ก ๋๊ฒจ์ฃผ์๋ค. ์ด ํด๋ก์ ์์๋ ๊ฐ ํด๋ผ์ด์ธํธ์ ๋ํด ๊ฐ์ฒด๋ฅผ ๊ด๋ฆฌํ๊ณ , ๋ช ๋ น์ด์ ๋ํด ์ฒ๋ฆฌํ๋ ๊ธฐ์กด์ ์๋ ์ฝ๋ฐฑํจ์๋ฅผ ๋ฐ๋ก ๋ชจ๋ํ์์ผ๋๊ณ ๊ธฐ์กด์ ๋ฌธ๋ฒ์ ์ด์ง ๋ณํํ ์ ๋์ด๋ค. ์ด๋ฅผ ํตํด ๋์ค์ ๋ณด๋ค ๊ตฌ์กฐ์ ์ผ๋ก ํ์ธ์ด ํธํ๊ณ , ๋ช ๋ น์ด ์ถ๊ฐ๊ฐ ๋ณด๋ค ์ฉ์ดํ๋ค.
const { commandHandler } = require("./commandHandler");
const readline = require("readline");
const rl = readline.createInterface({
input: process.stdin,
output: process.stdout,
});
rl.on("line", commandHandler);
๋ํ ๊ธฐ์กด์ ์๋ client์ readline๋ถ๋ถ์ด ๋งค์ฐ ๊ฐ์ํ๋์ด ๋ช ๋ น์ด์ ๋ฐ์ดํฐ์ ํ๋ฆ ๋ณ๋ก ๋ณด๋ค ํ์ ์ด ์ฉ์ดํ๊ฒ ๊ฐ์ ๋์๋ค๊ณ ์๊ฐํ๋ค.
HTTP request & response ๊ตฌ์กฐ ์งํค๊ธฐ
function makeCheckinRequest(campId) {
return JSON.stringify({
command: "checkin",
data: campId,
});
}
function makeClapRequest() {
return JSON.stringify({
command: "clap",
});
}
function makeCheckoutRequest() {
return JSON.stringify({
command: "checkout",
});
}
function makeSummaryRequest(day) {
return JSON.stringify({
command: "summary",
data: day,
});
}
function makeChatRequest(cnt) {
return JSON.stringify({
command: "chat",
data: cnt,
});
}์ด์ ์๋ ๊ทธ๋ฅ jsonํ์์ผ๋ก command & data์ ํ์์ผ๋ก ๋ณด๋๋๋ฐ, ์ด๋ด ๋๋ง๋ค command์ ์ญํ ์์ฒด๊ฐ ํ๋์ http ์์ฒญ์ ๋ณด๋ด๋ ๊ฒ์ด ์๋, ๋ฐ์ดํฐ๋ง ๋ฐ์์ ์ด๋ฅผ ์ฒ๋ฆฌํด์ ์คํํ๋ ๋๋์ด ๋ค์๋ค. ์ฐ๋ฆฌ์ ๋ฏธ์ ์์๋ ํ์ตํด์ผ ํ ๋ถ๋ถ์ด http request & response์ ๋ํ ๋ถ๋ถ๋ ์์๊ธฐ ๋๋ฌธ์ ์ด๋ฌํ ๋ฐ์ดํฐ๋ฅผ ์๋ฒ์ ๋ณด๋ด๋ ๊ฒ์ด ํ์์ ๋ง์ง ์๋ ๊ฒ ๊ฐ์๋ค. ๋ฐ๋ผ์ ์ด๋ฅผ ๊ธฐ๋ณธ์ ์ธ http ์์ฒญ์ ๊ตฌ์กฐ๋ฅผ ๋ง๋ค์ด ์๋ฒ์ ๋ณด๋ด๋ ๋ก์ง์ ๋ฐ๋ก ์ค์ ํ์ฌ ์์ฒญ ๋ฐ ์๋ตํ๋ ๊ฒ์ด ์กฐ๊ธ ๋ ์ ํฉํ ๋ฐฉ์์ด๋ผ๊ณ ์๊ฐํ๋ค.
const httpRequest = (path, data = {}, method = "POST") => {
const request = {
method: method,
path: path,
version: "HTTP/1.1",
headers: {
"Content-Type": "application/json",
"Content-Length": JSON.stringify(data).length,
},
body: {
data: data,
},
};
return JSON.stringify(request);
};
module.exports = {
httpRequest,
};๋ฐ๋ผ์ ๊ธฐ์กด HTTP ์์ฒญ์ ์ผ๋ถ๋ถ์ ๋ฐ๋ผํ์ฌ ๋น์ทํ ์์ ํ ํ๋ฆฟ์ ๋ฐ์ดํฐ๋ฅผ ๋ด์ ๋ณด๋ด๋๋ก ํ๋ค. ์ฌ๊ธฐ์ path์ ๊ฒฝ์ฐ ๊ธฐ์กด์ ์์ฒญํ๋ ๋ช ๋ น์ด๋ค์ ์๋ฏธํ๋ฉฐ, ๋ฐ์ดํฐ์ ๊ฒฝ์ฐ requestHandler์์ readline์ ํตํด ๋ฐ์ ๋ฐ์ดํฐ๋ฅผ ์ฒ๋ฆฌํ์ฌ ๋๊ฒจ์ฃผ์ด JSON ํ์์ ํ์คํ๋ ๋ฐ์ดํฐ๋ฅผ ์ป๊ฒ ๋๊ณ , ์ด๋ฅผ ์๋ฒ์ ๋ณด๋ธ๋ค.
const httpSuccessResponse = (path, data = {}, method = "POST") => {
const request = {
result: "SUCCESS",
method: method,
path: path,
version: "HTTP/1.1",
headers: {
"Content-Type": "application/json",
"Content-Length": JSON.stringify(data).length,
},
body: {
data: data,
},
};
return JSON.stringify(request);
};
const httpFailResponse = (path, error = "", method = "POST") => {
const request = {
result: "ERROR",
method: method,
path: path,
version: "HTTP/1.1",
headers: {
"Content-Type": "application/json",
"Content-Length": JSON.stringify(error).length,
},
body: {
error: error,
},
};
return JSON.stringify(request);
};
module.exports = {
httpFailResponse,
httpFailResponse,
};์๋ฒ์์๋ ๋ฐ์ ์๋ต์๋ํด ์ฒ๋ฆฌ๋ฅผ ํ๊ณ ์๋ต ๊ฒฐ๊ณผ์ ๋ฐ๋ผ ๋ ๊ฐ์ง์ ์๋ต์ ๋ณด๋ผ ์ ์๋๋ก ํ์๋ค. FAIL์ ๊ฒฝ์ฐ ์ FAIL์ด ์ด๋ฃจ์ด์ก๋์ง์ ๋ํ ์ด์ ๋ฅผ ๋ด์ ๋ณด๋ผ ์ ์๋๋ก ํ์๋ค.
์๋ฌ ํธ๋ค๋ง
function throwServerError(errorCode, path, message) {
throw Object.assign(new Error(message), {
code: errorCode,
path: path,
});
}
module.exports = { throwServerError };๊ธฐ์กด์ ์๋ฒ ์๋ฌ๋ค์ ๊ทธ์ ์๋ฌ๋ฅผ ๋์ ธ์ฃผ๊ธฐ๋ง ํ๊ณ ์ด์ ๋ํด ๋ฐ๋ก ์ฒ๋ฆฌํด์ฃผ์ง ์์ ์๋ฒ์์๋ง ์ ๋๋ก ์๋ฌ๊ฐ ๋จ๊ณ , ํด๋ผ์ด์ธํธ์์๋ ์๋ฌ์ ๋ํด ํธ๋ค๋ง์ ๋ฐ๋ก ํด์ฃผ์ง ์์๋ค.
๋ฐ๋ผ์ ์ด๋ฌํ ์๋ฌ๋ฅผ ๋์ ธ์ฃผ๋ ๊ณผ์ ์์ ์๋ฒ์์ ์ด ์๋ฌ๋ฅผ ๋ฐ์ ์ ์ ํ http Response๋ก ๋ฐ๊ฟ์ค ํ error ๊ด๋ จ ์ ๋ณด๋ฅผ ๋ด์ ์๋ต์ ๋ณด๋ด์ค ํด๋ผ์ด์ธํธ์์ ์ด๋ฅผ ์ฒ๋ฆฌํ ์ ์๋๋ก ํด์คฌ๋ค. ์๋ฌ์ ๊ฐ์ ๊ฒฝ์ฐ ์ฝ๋์ ์ด๋ค ๋ช ๋ น์ด๋ฅผ ์คํํ์ ๋, ์ด๋ค ์๋ฌ๊ฐ ๋ด๋์ง๋ฅผ ์์์ผ ํ๊ธฐ ๋๋ฌธ์ ์์ ๊ฐ์ด ๊ธฐ์กด Error์ ์๋ก์ด property๋ฅผ ์ถ๊ฐํ์ฌ ์๋ฌ๋ฅผ ๋ฐ์ ์ฒ๋ฆฌํด์ฃผ๋๋ก ํ๋ค.
socket.on("data", (request) => {
console.log(`Received from client: ${request}`);
request = JSON.parse(request);
const data = request.body.data;
const path = request.path;
try {
handleCommand(userSessionId, path, data, socket);
} catch (error) {
socket.write(httpFailResponse(error.path, error.code, error.message));
}
});์๋ฒ๊ฐ ์๋ฌ๋ฅผ ํธ๋ค๋งํ๋ ๋ก์ง๋ํ ๋ฐ๊ฟ์ฃผ์๋ค. ์๋ฒ๊ฐ ๋ฐ์ดํฐ๋ฅผ ๋ฐ์ผ๋ฉด handleCommand๋ฅผ ํตํด ๋ฐ์ดํฐ๊ฐ ๊ฐ๊ฒ ๋๊ณ , ์ด๋ ๊ฒ ๊ฐ ๋ฐ์ดํฐ๊ฐ ์ ํจ์ฑ ๊ฒ์ฆ ์ค์ ์๋ฌ๊ฐ ๋ฐ์ํ๋ค๋ฉด ์์ ์๋ฌ๋ฅผ ๋์ ธ์ฃผ์ด ์๋ฒ์ ์ต์์์ธ ํด๋น ์ฝ๋์์ ๋ฐ์ socket.write๋ก ๋ฐ์ ์ด๋ฅผ http response ํ์์ผ๋ก ์ฒ๋ฆฌํ์ฌ ํด๋ผ์ด์ธํธ๋ก ๋ณด๋ผ ์ ์๋๋ก ํ์๋ค.