Notice
Recent Posts
Recent Comments
Link
ยซ   2024/05   ยป
์ผ ์›” ํ™” ์ˆ˜ ๋ชฉ ๊ธˆ ํ† 
1 2 3 4
5 6 7 8 9 10 11
12 13 14 15 16 17 18
19 20 21 22 23 24 25
26 27 28 29 30 31
Archives
Today
Total
๊ด€๋ฆฌ ๋ฉ”๋‰ด

lgvv98

[Node.js] #4 http ๋ชจ๋“ˆ๋กœ ์„œ๋ฒ„ ๋งŒ๋“ค๊ธฐ ๋ณธ๋ฌธ

๐Ÿ›ฐ๏ธ Node.js

[Node.js] #4 http ๋ชจ๋“ˆ๋กœ ์„œ๋ฒ„ ๋งŒ๋“ค๊ธฐ

๐Ÿฅ• ์บ๋Ÿฟ๋งจ 2023. 7. 22. 17:45

http ๋ชจ๋“ˆ๋กœ ์„œ๋ฒ„ ๋งŒ๋“ค๊ธฐ

 

#์š”์ฒญ๊ณผ ์‘๋‹ต ์ดํ•ดํ•˜๊ธฐ

 

์ž ์ด์ œ๋ถ€ํ„ฐ ์„œ๋ฒ„๋ฅผ ๋งŒ๋“ค์–ด๋ณด์ž

์„œ๋ฒ„์—์„œ๋Š” ์š”์ฒญ์˜ ๋‚ด์šฉ์„ ์ฝ๊ณ  ์ฒ˜๋ฆฌํ•œ ๋’ค ํด๋ผ์ด์–ธํŠธ์— ์‘๋‹ต์„ ๋ณด๋‚ธ๋‹ค.

 

๊ทธ๋Ÿฌ๋‹ˆ๊นŒ ์ผ๋‹จ ์š”์ฒญ์„ ๋ฐ›๋Š” ๋ถ€๋ถ„๊ณผ ์‘๋‹ต์„ ๋ณด๋‚ด๋Š” ๋ถ€๋ถ„์ด ์žˆ์–ด์•ผ ํ•œ๋‹ค.

const http = require('http');

http.createServer((req, res) => {
  // ์—ฌ๊ธฐ์— ์–ด๋–ป๊ฒŒ ์‘๋‹ตํ•  ์ง€ ์ ์–ด์ค๋‹ˆ๋‹ค.
});

 

 

http ์„œ๋ฒ„๊ฐ€ ์žˆ์–ด์•ผ ์›น ๋ธŒ๋ผ์šฐ์ €์˜ ์š”์ฒญ์„ ์ฒ˜๋ฆฌํ•  ์ˆ˜ ์žˆ์œผ๋ฏ€๋กœ http ๋ชจ๋“ˆ์  ์‚ฌ์šฉํ–ˆ๋‹ค.

http๋ชจ๋“ˆ์—๋Š” createServer ๋ฉ”์„œ๋“œ๊ฐ€ ์žˆ๋‹ค.

 

์š”์ฒญ์ด ๋“ค์–ด์˜ฌ ๋•Œ๋งˆ๋‹ค ์ฝœ๋ฐฑ ํ•จ์ˆ˜๊ฐ€ ์‹คํ–‰๋œ๋‹ค.

const http = require('http');

http.createServer((req, res) => {
  res.writeHead(200, { 'Content-Type': 'text/html; charset=utf-8' });
  res.write('<h1>Hello Node!</h1>');
  res.end('<p>Hello Server!</p>');
})
  .listen(8080, () => { // ์„œ๋ฒ„ ์—ฐ๊ฒฐ
    console.log('8080๋ฒˆ ํฌํŠธ์—์„œ ์„œ๋ฒ„ ๋Œ€๊ธฐ ์ค‘์ž…๋‹ˆ๋‹ค!');
  });
  
  // ์ถœ๋ ฅ๊ฒฐ๊ณผ
8080๋ฒˆ ํฌํŠธ์—์„œ ์„œ๋ฒ„ ๋Œ€๊ธฐ ์ค‘์ž…๋‹ˆ๋‹ค!

์ด๋ ‡๊ฒŒํ•˜๋ฉด 8080ํฌํŠธ์—์„œ ์‘๋‹ต์˜ค๊ธฐ๋ฅผ ๊ธฐ๋‹ค๋ฆผ.

res๊ฐ์ฒด๋ฅผ ๋ณด์ž.

 

writeHead๋Š” ์‘๋‹ต์— ๋Œ€ํ•œ ์ •๋ณด๋ฅผ ๊ธฐ๋กํ•˜๋Š” ๋ฉ”์„œ๋“œ

์ฒซ ๋ฒˆ์งธ ์ธ์ˆ˜๋กœ ์„ฑ๊ณต์ ์ธ ์š”์ฒญ์ž„์„ ์˜๋ฏธํ•˜๋Š” 200์„

๋‘ ๋ฒˆ์งธ ์ธ์ˆ˜๋กœ ์‘๋‹ต์— ๋Œ€ํ•œ ์ •๋ณด๋ฅผ ๋ณด๋‚ด๋Š”๋ฐ ์ฝ˜ํ…์ธ ์˜ ํ˜•์‹์ด HTML์ž„์„ ๊ฐ€๋ฅดํ‚ค๊ณ  ์žˆ์Œ. ๋˜ํ•œ ํ•œ๊ธ€ ํ‘œ์‹œ๋ฅผ ์œ„ํ•ด charset์„ uft-8๋กœ ์ง€์ •.

์ด ์ •๋ณด๊ฐ€ ๊ธฐ๋ก๋˜๋Š” ๋ถ€๋ถ„์„ header๋ผ๊ณ  ํ•œ๋‹ค.

 

write๋ฉ”์„œ๋“œ์—๋Š”

์ฒซ ๋ฒˆ์งธ ์ธ์ˆ˜๋Š” ํด๋ผ์ด์–ธํŠธ๋กœ ๋ณด๋‚ผ ๋ฐ์ดํ„ฐ๋‹ค.

์ง€๊ธˆ์€ HTML๋ฌธ์ž์—ด์„ ๋ณด๋ƒˆ์ง€๋งŒ ๋ฒ„ํผ๋ฅผ ๋ณด๋‚ผ ์ˆ˜๋„ ์žˆ๋‹ค.

๋˜ํ•œ ์—ฌ๋Ÿฌ ๋ฒˆ ํ˜ธ์ถœํ•ด์„œ ๋ฐ์ดํ„ฐ๋ฅผ ์—ฌ๋Ÿฌ ๊ฐœ ๋ณด๋‚ด๋„ ๋œ๋‹ค.

๋ฐ์ดํ„ฐ๊ฐ€ ๊ธฐ๋ก๋˜๋Š” ๋ถ€๋ถ„์„ body๋ผ๊ณ  ํ•œ๋‹ค.

 

end๋ฉ”์„œ๋“œ๋Š” ์‘๋‹ต์„ ์ข…๋ฃŒํ•˜๋Š” ๋ฉ”์„œ๋“œ์ด๋‹ค. 

๋งŒ์•ฝ ์ธ์ˆ˜๊ฐ€ ์žˆ๋‹ค๋ฉด ๊ทธ ๋ฐ์ดํ„ฐ๋„ ํด๋ผ์ด์–ธํŠธ๋กœ ๋ณด๋‚ด๊ณ  ์‘๋‹ต์„ ์ข…๋ฃŒ

์œ„ ์˜ˆ์ œ๋Š” res.write์—์„œ write๋กœ ๋ฐ”๋””๋ฌธ์„ end๋กœ ์ € ๋ฌธ๊ตฌ๋ฅผ ๋ณด๋‚ด๋ฉด์„œ ์‘๋‹ต์ด ์ข…๋ฃŒ๋œ ๊ฒƒ์ด๋‹ค.

๋ธŒ๋ผ์šฐ์ €๋Š” ์‘๋‹ต ๋‚ด์šฉ์„ ๋ฐ›์•„์„œ ๋ Œ๋”๋งํ•ฉ๋‹ˆ๋‹ค.

 

๋…ธ๋“œ์„œ๋ฒ„

 

listen ๋ฉ”์„œ๋“œ์— ์ฝœ๋ฐฑ ํ•จ์ˆ˜๋ฅผ ๋„ฃ๋Š” ๋Œ€์‹ ,ใ„ท ใ…์Œ๊ณผ ๊ฐ™์ด ์„œ๋ฒ„์— listening ์ด๋ฒคํŠธ ๋ฆฌ์Šค๋„ˆ๋ฅผ ๋ถ™์—ฌ๋„ ๋ฉ๋‹ˆ๋‹ค. ์ถ”๊ฐ€๋กœ error ๋ฆฌ์Šค๋„ˆ๋„ ๋ถ™์—ฌ๋ดค์Šต๋‹ˆ๋‹ค.

 

const http = require('http');

const server = http.createServer((req, res) => {
  res.writeHead(200, { 'Content-Type': 'text/html; charset=utf-8' });
  res.write('<h1>Hello Node!</h1>');
  res.end('<p>Hello Server!</p>');
});
server.listen(8080);

server.on('listening', () => {
  console.log('8080๋ฒˆ ํฌํŠธ์—์„œ ์„œ๋ฒ„ ๋Œ€๊ธฐ ์ค‘์ž…๋‹ˆ๋‹ค!');
});
server.on('error', (error) => {
  console.error(error);
});

์„œ๋ฒ„๋Š” ์ฐธ๊ณ ๋กœ ๋ณ€๊ฒฝ์‚ฌํ•ญ์„ ์ฆ‰๊ฐ ๋ฐ˜์˜ํ•˜์ง€ ์•Š์Œ. ์ข…๋ฃŒํ–ˆ๋‹ค๊ฐ€ ๋‹ค์‹œ ์‹คํ–‰ํ•ด์•ผ ํ•œ๋‹ค.

 

const http = require('http');

http.createServer((req, res) => {
  res.writeHead(200, { 'Content-Type': 'text/html; charset=utf-8' });
  res.write('<h1>Hello Node!</h1>');
  res.end('<p>Hello Server!</p>');
})
  .listen(8080, () => { // ์„œ๋ฒ„ ์—ฐ๊ฒฐ
    console.log('8080๋ฒˆ ํฌํŠธ์—์„œ ์„œ๋ฒ„ ๋Œ€๊ธฐ ์ค‘์ž…๋‹ˆ๋‹ค!');
  });

http.createServer((req, res) => {
  res.writeHead(200, { 'Content-Type': 'text/html; charset=utf-8' });
  res.write('<h1>Hello Node!</h1>');
  res.end('<p>Hello Server!</p>');
})
  .listen(8081, () => { // ์„œ๋ฒ„ ์—ฐ๊ฒฐ
    console.log('8081๋ฒˆ ํฌํŠธ์—์„œ ์„œ๋ฒ„ ๋Œ€๊ธฐ ์ค‘์ž…๋‹ˆ๋‹ค!');
  });
  
  // ๋งŒ์•ฝ ํฌํŠธ ๋ฒˆํ˜ธ๊ฐ€ ๊ฐ™๋‹ค๋ฉด ์„œ๋ฒ„๊ฐ€ ์ฃฝ๋Š”๋‹ค.

์„œ๋ฒ„๋ฅผ ์—ฌ๋Ÿฌ๊ฐœ  ๋งŒ๋“ค ์ˆ˜๋„ ์žˆ๋‹ค.

์„œ๋ฒ„ ํฌํŠธ๊ฐ€ ๊ฐ™์œผ๋ฉด ์„œ๋ฒ„๊ฐ€ ์ฃฝ๋Š”๋‹ค.

 

์‹ค๋ฌด์—์„œ ์„œ๋ฒ„๋ฅผ ์—ฌ๋Ÿฌ๊ฐœ ๋„์šฐ๋Š” ์ผ์€ ๋“œ๋ฌผ๋‹ค. 

write์™€ end์— ์ผ์ผํžˆ HTML์„ ์ ๋Š”๊ฑฐ๋Š” ๋น„ํšจ์œจ ์ ์ด๋ฏ€๋กœ HTML ํŒŒ์ผ์„ ๋งŒ๋“ค์–ด ๋‘๋Š”๊ฒƒ์ด ๋ฐ”๋žŒ์งํ•˜๋‹ค

๊ทธ HTML ํŒŒ์ผ์€ fs๋ชจ๋“ˆ๋กœ ์ฝ์–ด์„œ ์ „์†กํ•  ์ˆ˜ ์žˆ๋‹ค.

 

// server2.html
<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8" />
    <title>Node.js ์›น ์„œ๋ฒ„</title>
</head>
<body>
    <h1>Node.js ์›น ์„œ๋ฒ„</h1>
    <p>๋งŒ๋“ค ์ค€๋น„๋˜์…จ๋‚˜์š”?</p>
</body>
</html>

// server2.js
const http = require('http');
const fs = require('fs').promises;

http.createServer(async (req, res) => {
  try {
    const data = await fs.readFile('./server2.html');
    res.writeHead(200, { 'Content-Type': 'text/html; charset=utf-8' });
    res.end(data);
  } catch (err) {
    console.error(err);
    res.writeHead(500, { 'Content-Type': 'text/plain; charset=utf-8' });
    res.end(err.message);
  }
})
  .listen(8081, () => {
    console.log('8081๋ฒˆ ํฌํŠธ์—์„œ ์„œ๋ฒ„ ๋Œ€๊ธฐ ์ค‘์ž…๋‹ˆ๋‹ค!');
  });

์š”์ฒญ ๋“ค์–ด์˜ค๋ฉด ๋จผ์ € fs ๋ชจ๋“ˆ๋กœ HTML ํŒŒ์ผ์„ ์ฝ์Šต๋‹ˆ๋‹ค.

data์— ์ €์žฅ๋œ ๋ฒ„ํผ๋ฅผ ๊ทธ๋Œ€๋กœ ํด๋ผ์ด์–ธํŠธ์— ๋ณด๋‚ด๋ฉด ๋œ๋‹ค.

์ด์ „์—๋Š” ๋ฌธ์ž์—ด์„ ๋ณด๋ƒˆ์ง€๋งŒ, ์ €๋ ‡๊ฒŒ ๋ฒ„ํผ๋ฅผ ๋ณด๋‚ผ ์ˆ˜๋„ ์žˆ๋‹ค.

์˜ˆ๊ธฐ์น˜ ๋ชปํ•œ ์—๋Ÿฌ๊ฐ€ ๋ฐœ์ƒํ•œ ๊ฒฝ์šฐ์—๋Š” ์—๋Ÿฌ ๋ฉ”์‹œ์ง€๋ฅผ ์‘๋‹ต

์—๋Ÿฌ ๋ฉ”์‹œ์ง€๋Š” ์ผ๋ฐ˜ ๋ฌธ์ž์—ด์ด๋ฏ€๋กœ text/plain ์‚ฌ์šฉ

 

HTTP ์ƒํƒœ์ฝ”๋“œ ๊ฐ„๋‹จ์ •๋ฆฌ

- 2XX: ์„ฑ๊ณต์•Œ๋ฆฌ๋Š” ์ฝ”๋“œ 200(์„ฑ๊ณต), 201(์ž‘์„ฑ๋จ)

- 3XX: ๋ฆฌ๋‹ค์ด๋ ‰์…˜(๋‹ค๋ฅธ ํŽ˜์ด์ง€ ์ด๋™)์„ ์•Œ๋ฆฌ๋Š” ์ฝ”๋“œ ์–ด๋–ค ์ฃผ์†Œ๋ฅผ ์ž…๋ ฅํ–ˆ๋Š”๋ฐ ๋‹ค๋ฅธํŽ˜์ด์ง€๋กœ ๋„˜์–ด๊ฐˆ ๋•Œ

301(์˜๊ตฌ์ด๋™) 302(์ž„์‹œ์ด๋™)

304(์ˆ˜์ •๋˜์ง€ ์•Š์Œ): ์š”์ฒญ์˜ ์‘๋‹ต์œผ๋กœ ์บ์‹œ๋ฅผ ์‚ฌ์šฉ

- 4XX: ์š”์ฒญ์˜ค๋ฅ˜ ์š”์ฒญ ์ž์ฒด์— ์˜ค๋ฅ˜

400(์ž˜๋ชป๋œ ์š”์ฒญ) 401(๊ถŒํ•œ ์—†์Œ) 403(๊ธˆ์ง€๋จ) 404(์ฐพ์„ ์ˆ˜ ์—†์Œ)

- 5XX: ์„œ๋ฒ„ ์˜ค๋ฅ˜๋ฅผ ๋‚˜ํƒ€๋ƒ„ ์š”์ฒญ์€ ์ œ๋Œ€๋กœ ์™”์ง€๋งŒ ์„œ๋ฒ„์— ์˜ค๋ฅ˜๊ฐ€ ๋ฐœ์ƒ

res.writeHead๋กœ ํด๋ผ์ด์–ธํŠธ์— ์ง์ ‘ ๋ณด๋‚ด๋Š” ๊ฒฝ์šฐ๋Š” ๊ฑฐ์˜ ์—†๊ณ , ์˜ˆ๊ธฐ์น˜ ๋ชปํ•œ ์—๋Ÿฌ๊ฐ€ ๋ฐœ์ƒํ•˜๋ฉด์„œ ์„œ๋ฒ„๊ฐ€ ์•Œ์•„์„œ 5XX๋Œ€ ์ฝ”๋“œ๋ฅผ ๋ณด๋‚ธ๋‹ค.

500(๋‚ด๋ถ€ ์„œ๋ฒ„ ์˜ค๋ฅ˜) 502(๋ถˆ๋Ÿ‰ ๊ฒŒ์ดํŠธ์›จ์ด) 503(์„œ๋น„์Šค๋ฅผ ์‚ฌ์šฉํ•  ์ˆ˜ ์—†์Œ)

 

์š”์ฒญ ๊ณผ์ •์—์„œ ์˜ค๋ฅ˜ ๋ฐœ์ƒํ–ˆ๋‹ค๊ณ  ์‘๋‹ต์„ ๋ณด๋‚ด์ง€ ์•Š์œผ๋ฉด ์•ˆ๋œ๋‹ค. ์š”์ฒญ์ด ์„ฑ๊ณตํ–ˆ๋“  ์‹คํŒจํ–ˆ๋“  ์‘๋‹ต์„ ํด๋ผ์ด์–ธํŠธ๋กœ ๋ณด๋‚ด์„œ ์š”์ฒญ์ด ๋งˆ๋ฌด๋ฆฌ ๋˜์—ˆ์Œ์„ ์•Œ๋ฆฐ๋‹ค.

์‘๋‹ต์„ ๋ณด๋‚ด์ง€ ์•Š๋Š”๋‹ค๋ฉด ํด๋ผ์ด์–ธํŠธ๋Š” ์„œ๋ฒ„๋กœ๋ถ€ํ„ฐ ์‘๋‹ต์ด ์˜ค๊ธธ ํ•˜์—ผ์—†์ด ๊ธฐ๋‹ค๋ฆฌ๋‹ค๊ฐ€ ์‹œ๊ฐ„์ดˆ๊ณผ๋ฅผ ๋‚ด์•ผํ•œ๋‹ค.

 

 

#REST์™€ ๋ผ์šฐํŒ… ์‚ฌ์šฉํ•˜๊ธฐ

REST๋ž€?

REpresentational State Transfer์˜ ์ค„์ž„๋ง๋กœ ์„œ๋ฒ„์˜ ์ž์› ์ •์˜ํ•˜๊ณ  ์ž์›์— ๋Œ€ํ•œ ์ฃผ์†Œ๋ฅผ ์ง€์ •ํ•˜๋Š” ๋ฐฉ๋ฒ•์„ ๊ฐ€๋ฆฌํ‚จ๋‹ค.

์ผ์ข…์˜ ์•ฝ์†์ด๋ผ๊ณ  ๋ด๋„ ๋ฌด๋ฐฉ.

์ž์›์ด๋ผ๊ณ  ํ•ด์„œ ๊ผญ ํŒŒ์ผ์ผ ํ•„์š”๋Š” ์—†๊ณ  ์„œ๋ฒ„๊ฐ€ ํ–‰ํ•  ์ˆ˜ ์žˆ๋Š” ๊ฒƒ๋“ค์„ ํ†ตํ‹€์–ด์„œ ์˜๋ฏธํ•œ๋‹ค๊ณ  ๋ณด๋ฉด ๋œ๋‹ค.

 

- get: ์„œ๋ฒ„ ์ž์› ๊ฐ€์ ธ์˜ฌ ๋•Œ, ๋ฐ”๋”” ๋„ฃ์ง€ ์•Š๊ณ  ํ€ด๋ฆฌ์ŠคํŠธ๋ง ์‚ฌ์šฉ

- post: ์„œ๋ฒ„์— ์ž์›์„ ์ƒˆ๋กœ ๋“ฑ๋กํ•˜๊ณ ์ž ํ• ๋•Œ, ์š”์ฒญ์˜ ๋ณธ๋ฌธ์— ์ƒˆ๋กœ ๋“ฑ๋กํ•  ๋ฐ์ดํ„ฐ๋ฅผ ๋„ฃ์–ด ๋ณด๋‚ธ๋‹ค.

- put: ์„œ๋ฒ„ ์ž์›์˜ ์ผ๋ถ€๋งŒ ์ˆ˜์ •ํ•˜๊ณ ์ž ํ• ๋•Œ. ์š”์ฒญ์˜ ๋ณธ๋ฌธ์— ์น˜ํ™˜ํ•  ๋ฐ์ดํ„ฐ๋ฅผ ๋„ฃ์–ด ๋ณด๋‚ธ๋‹ค.

- patch: ์„œ๋ฒ„ ์ž์›์˜ ์ผ๋ถ€๋งŒ ์ˆ˜์ •ํ•˜๊ณ ์ž ํ• ๋•Œ. ์š”์ฒญ์˜ ๋ณธ๋ฌธ์— ์ผ๋ถ€ ์ˆ˜์ •ํ•  ๋ฐ์ดํ„ฐ๋ฅผ ๋„ฃ์–ด ๋ณด๋‚ธ๋‹ค.

- delete: ์„œ๋ฒ„์˜ ์ž์›์„ ์‚ญ์ œํ•˜๊ณ ์ž ํ• ๋•Œ, ์š”์ฒญ์˜ ๋ณธ๋ฌธ์— ๋ฐ์ดํ„ฐ๋ฅผ ๋„ฃ์ง€ ์•Š๋Š”๋‹ค.

- options: ์š”์ฒญ์„ ํ•˜๊ธฐ ์ „์— ํ†ต์‹  ์˜ต์…˜์„ ์„ค๋ช…ํ•˜๊ธฐ ์œ„ํ•ด ์‚ฌ์šฉ

 

์ฃผ์†Œ ํ•˜๋‚˜๊ฐ€ ์š”์ฒญ ๋ฉ”์†Œ๋“œ ์—ฌ๋Ÿฌ๊ฐœ๋ฅผ ๊ฐ€์งˆ ์ˆ˜ ์žˆ์Œ.

 

์ด์ œ๋Š” REST๋ฅผ ์‚ฌ์šฉํ•œ ์ฃผ์†Œ ์ฒด๊ณ„๋กœ RESTfulํ•œ ์›น ์„œ๋ฒ„๋ฅผ ๋งŒ๋“ค์–ด๋ณด์ž.

REST๋ฅผ ๋”ฐ๋ฅด๋Š” ์„œ๋ฒ„๋ฅผ 'RESTful'ํ•˜๋‹ค๊ณ  ํ‘œํ˜„ํ•œ๋‹ค.

 

// restFront.css
a { color: blue; text-decoration: none; }

// restFront.html
<!DOCTYPE html>
<html lang="ko">
<head>
  <meta charset="utf-8" />
  <title>RESTful SERVER</title>
  <link rel="stylesheet" href="./restFront.css" />
</head>
<body>
<nav>
  <a href="/">Home</a>
  <a href="/about">About</a>
</nav>
<div>
  <form id="form">
    <input type="text" id="username">
    <button type="submit">๋“ฑ๋ก</button>
  </form>
</div>
<div id="list"></div>
<script src="https://unpkg.com/axios/dist/axios.min.js"></script>
<script src="./restFront.js"></script>
</body>
</html>

async function getUser() { // ๋กœ๋”ฉ ์‹œ ์‚ฌ์šฉ์ž ๊ฐ€์ ธ์˜ค๋Š” ํ•จ์ˆ˜
  try {
    const res = await axios.get('/users');
    const users = res.data;
    const list = document.getElementById('list');
    list.innerHTML = '';
    // ์‚ฌ์šฉ์ž๋งˆ๋‹ค ๋ฐ˜๋ณต์ ์œผ๋กœ ํ™”๋ฉด ํ‘œ์‹œ ๋ฐ ์ด๋ฒคํŠธ ์—ฐ๊ฒฐ
    Object.keys(users).map(function (key) {
      const userDiv = document.createElement('div');
      const span = document.createElement('span');
      span.textContent = users[key];
      const edit = document.createElement('button');
      edit.textContent = '์ˆ˜์ •';
      edit.addEventListener('click', async () => { // ์ˆ˜์ • ๋ฒ„ํŠผ ํด๋ฆญ
        const name = prompt('๋ฐ”๊ฟ€ ์ด๋ฆ„์„ ์ž…๋ ฅํ•˜์„ธ์š”');
        if (!name) {
          return alert('์ด๋ฆ„์„ ๋ฐ˜๋“œ์‹œ ์ž…๋ ฅํ•˜์…”์•ผ ํ•ฉ๋‹ˆ๋‹ค');
        }
        try {
          await axios.put('/user/' + key, { name });
          getUser();
        } catch (err) {
          console.error(err);
        }
      });
      const remove = document.createElement('button');
      remove.textContent = '์‚ญ์ œ';
      remove.addEventListener('click', async () => { // ์‚ญ์ œ ๋ฒ„ํŠผ ํด๋ฆญ
        try {
          await axios.delete('/user/' + key);
          getUser();
        } catch (err) {
          console.error(err);
        }
      });
      userDiv.appendChild(span);
      userDiv.appendChild(edit);
      userDiv.appendChild(remove);
      list.appendChild(userDiv);
      console.log(res.data);
    });
  } catch (err) {
    console.error(err);
  }
}

// restFront.js
window.onload = getUser; // ํ™”๋ฉด ๋กœ๋”ฉ ์‹œ getUser ํ˜ธ์ถœ
// ํผ ์ œ์ถœ(submit) ์‹œ ์‹คํ–‰
document.getElementById('form').addEventListener('submit', async (e) => {
  e.preventDefault();
  const name = e.target.username.value;
  if (!name) {
    return alert('์ด๋ฆ„์„ ์ž…๋ ฅํ•˜์„ธ์š”');
  }
  try {
    await axios.post('/user', { name });
    getUser();
  } catch (err) {
    console.error(err);
  }
  e.target.username.value = '';
});

// about.html
<!DOCTYPE html>
<html>
<head>
  <meta charset="utf-8" />
  <title>RESTful SERVER</title>
  <link rel="stylesheet" href="./restFront.css" />
</head>
<body>
<nav>
  <a href="/">Home</a>
  <a href="/about">About</a>
</nav>
<div>
  <h2>์†Œ๊ฐœ ํŽ˜์ด์ง€์ž…๋‹ˆ๋‹ค.</h2>
  <p>์‚ฌ์šฉ์ž ์ด๋ฆ„์„ ๋“ฑ๋กํ•˜์„ธ์š”!</p>
</div>
</body>
</html>

// restServer.js
const http = require('http');
const fs = require('fs').promises;

const users = {}; // ๋ฐ์ดํ„ฐ ์ €์žฅ์šฉ

http.createServer(async (req, res) => {
  try {
    if (req.method === 'GET') {
      if (req.url === '/') {
        const data = await fs.readFile('./restFront.html');
        res.writeHead(200, { 'Content-Type': 'text/html; charset=utf-8' });
        return res.end(data);
      } else if (req.url === '/about') {
        const data = await fs.readFile('./about.html');
        res.writeHead(200, { 'Content-Type': 'text/html; charset=utf-8' });
        return res.end(data);
      } else if (req.url === '/users') {
        res.writeHead(200, { 'Content-Type': 'application/json; charset=utf-8' });
        return res.end(JSON.stringify(users));
      }
      // /๋„ /about๋„ /users๋„ ์•„๋‹ˆ๋ฉด
      try {
        const data = await fs.readFile(`.${req.url}`);
        return res.end(data);
      } catch (err) {
        // ์ฃผ์†Œ์— ํ•ด๋‹นํ•˜๋Š” ๋ผ์šฐํŠธ๋ฅผ ๋ชป ์ฐพ์•˜๋‹ค๋Š” 404 Not Found error ๋ฐœ์ƒ
      }
    } else if (req.method === 'POST') {
      if (req.url === '/user') {
        let body = '';
        // ์š”์ฒญ์˜ body๋ฅผ stream ํ˜•์‹์œผ๋กœ ๋ฐ›์Œ
        req.on('data', (data) => {
          body += data;
        });
        // ์š”์ฒญ์˜ body๋ฅผ ๋‹ค ๋ฐ›์€ ํ›„ ์‹คํ–‰๋จ
        return req.on('end', () => {
          console.log('POST ๋ณธ๋ฌธ(Body):', body);
          const { name } = JSON.parse(body);
          const id = Date.now();
          users[id] = name;
          res.writeHead(201, { 'Content-Type': 'text/plain; charset=utf-8' });
          res.end('ok');
        });
      }
    } else if (req.method === 'PUT') {
      if (req.url.startsWith('/user/')) {
        const key = req.url.split('/')[2];
        let body = '';
        req.on('data', (data) => {
          body += data;
        });
        return req.on('end', () => {
          console.log('PUT ๋ณธ๋ฌธ(Body):', body);
          users[key] = JSON.parse(body).name;
          res.writeHead(200, { 'Content-Type': 'text/plain; charset=utf-8' });
          return res.end('ok');
        });
      }
    } else if (req.method === 'DELETE') {
      if (req.url.startsWith('/user/')) {
        const key = req.url.split('/')[2];
        delete users[key];
        res.writeHead(200, { 'Content-Type': 'text/plain; charset=utf-8' });
        return res.end('ok');
      }
    }
    res.writeHead(404);
    return res.end('NOT FOUND');
  } catch (err) {
    console.error(err);
    res.writeHead(500, { 'Content-Type': 'text/plain; charset=utf-8' });
    res.end(err.message);
  }
})
  .listen(8082, () => {
    console.log('8082๋ฒˆ ํฌํŠธ์—์„œ ์„œ๋ฒ„ ๋Œ€๊ธฐ ์ค‘์ž…๋‹ˆ๋‹ค');
  });

restServer.js๊ฐ€ ํ•ต์‹ฌ

 

res.end ์•ž์— return์„ ๋ถ™์ด๋Š” ์ด์œ ๋Š” end๋ฅผ ํ˜ธ์ถœํ•˜๋ฉด ํ•จ์ˆ˜๊ฐ€ ์ข…๋ฃŒ๋œ๋‹ค๊ณ  ์ฐฉ๊ฐํ•˜๊ณค ํ•œ๋‹ค. ๋…ธ๋“œ๋„ ์ผ๋ฐ˜์ ์ธ ์ž๋ฐ”์Šคํฌ๋ฆฝํŠธ ๋ฌธ๋ฒ•์„ ๋”ฐ๋ฅด๋ฏ€๋กœ return์„ ๋ถ™์ด์ง€ ์•Š๋Š” ํ•œ ํ•จ์ˆ˜๊ฐ€ ์ข…๋ฃŒ๋˜์ง€ ์•Š๋Š”๋‹ค. ๋”ฐ๋ผ์„œ ๋‹ค์Œ์— ์ฝ”๋“œ๊ฐ€ ์ด๋Ÿฌ์ง€๋Š” ๊ฒฝ์šฐ์—๋Š” return๋กœ ์ข…๋ฃŒํ•œ๋‹ค.

 

๋งŒ์•ฝ end๊ฐ€ ์—ฌ๋Ÿฌ ๋ฒˆ ์‹คํ–‰๋œ๋‹ค๋ฉด Error๊ฐ€ ๋ฐœ์ƒํ•œ๋‹ค.

 

ํ•ด๋‹น ์˜ˆ์ œ์—์„œ๋Š” ๋ฐ์ดํ„ฐ๊ฐ€ ๋ฉ”๋ชจ๋ฆฌ์— ์ €์žฅ๋˜์–ด์„œ ์„œ๋ฒ„ ์ข…๋ฃŒํ•˜๋ฉด ์†Œ์‹ค๋œ๋‹ค๋Š”๊ฑฐ, 7,8 ์žฅ์—์„œ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ๋‹ค๋ฃฐ๊ฑฐ์ž„.

 

# ์ฟ ํ‚ค์™€ ์„ธ์…˜ ์ดํ•ดํ•˜๊ธฐ

ํด๋ผ์ด์–ธํŠธ์—๊ฒŒ ๋ณด๋‚ด๋Š” ์š”์ฒญ์—๋Š” ํ•œ๊ฐ€์ง€ ํฐ ๋‹จ์ ์ด ์žˆ๋Š”๋ฐ, ๋ฐ”๋กœ ๋ˆ„๊ฐ€ ๋ณด๋‚ด๋Š”์ง€ ๋ชจ๋ฅธ๋‹ค๋Š” ๊ฒƒ์ด๋‹ค.

๋ฌผ๋ก  ์š”์ฒญ์„ ๋ณด๋‚ด๋Š” IP์ฃผ์†Œ๋‚˜ ๋ธŒ๋ผ์šฐ์ €์˜ ์ •๋ณด๋ฅผ ๋ฐ›์•„์˜ฌ ์ˆ˜๋Š” ์žˆ๋‹ค. ํ•˜์ง€๋งŒ ์—ฌ๋Ÿฌ ์ปดํ“จํ„ฐ๊ฐ€ ๊ณตํ†ต์œผ๋กœ IP์ฃผ์†Œ๋ฅผ ๊ฐ–๊ฑฐ๋‚˜ ํ•œ ์ปดํ“จํ„ฐ๋ฅผ ์—ฌ๋Ÿฌ์‚ฌ๋žŒ์ด ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋‹ค.

 

๋กœ๊ทธ์ธ์„ ๊ตฌํ˜„ํ•˜๋ ค๋ฉด ์ฟ ์ผ€์™€ ์„ธ์…˜์„ ์•Œ๊ณ  ์žˆ์–ด์•ผ ํ•œ๋‹ค.

 

๋ˆ„๊ตฌ์ธ์ง€ ๊ธฐ์–ตํ•˜๊ธฐ ์œ„ํ•ด ์„œ๋ฒ„๋Š” ์š”์ฒญ์— ๋Œ€ํ•œ ์‘๋‹ต์„ ํ•  ๋•Œ ์ฟ ํ‚ค๋ผ๋Š” ๊ฒƒ์„ ๊ฐ™์ด ๋ณด๋ƒ„.

์ฟ ํ‚ค๋Š” ์œ ํšจ ๊ธฐ๊ฐ„์ด ์žˆ์œผ๋ฉฐ name=lgvv์ฒ˜๋Ÿผ ๋‹จ์ˆœํ•œ 'ํ‚ค-๊ฐ’'์ด๋‹ค.

์„œ๋ฒ„๋กœ๋ถ€ํ„ฐ ์ฟ ํ‚ค๊ฐ€ ์˜ค๋ฉด ์›น ๋ธŒ๋ผ์šฐ์ €๋Š” ์ฟ ํ‚ค๋ฅผ ์ €์žฅํ•ด๋’€๋‹ค๊ฐ€ ๋‹ค์Œ์— ์š”์ฒญํ•  ๋•Œ๋งˆ๋‹ค ์ฟ ํ‚ค๋ฅผ ๋™๋ด‰ํ•ด์„œ ๋ณด๋ƒ„

์„œ๋ฒ„๋Š” ์š”์ฒญ์— ์žˆ๋Š” ์ฟ ํ‚ค๋ฅผ ์ฝ์–ด์„œ ๋ˆ„๊ตฌ์ธ์ง€ ํŒ๋‹จํ•จ.

 

๋ธŒ๋ผ์šฐ์ €๋Š” ์ฟ ํ‚ค๋ฅผ ์•Œ์•„์„œ ์ž๋™์œผ๋กœ ๋™๋ด‰ํ•ด์„œ ๋ณด๋‚ด์คŒ.

์„œ๋ฒ„์—์„œ ๋ธŒ๋ผ์šฐ์ €๋กœ ๋ณด๋‚ผ๋•Œ๋งˆ ์ฝ”๋“œ ์ž‘์„ฑํ•˜๋ฉด ๋œ๋‹ค.

 

์ฟ ํ‚ค๋Š” ์š”์ฒญ์˜ ํ—ค๋”์— ๋‹ด๊ฒจ ํ•จ๊ผ ์ „์†ก๋œ๋‹ค. ํ—ค์–ด(Set-Cookie) ์—ฌ๋ถ€์— ๋”ฐ๋ผ ์ฟ ํ‚ค๋ฅผ ์ €์žฅํ•œ๋‹ค.

const http = require('http');

http.createServer((req, res) => {
  console.log(req.url, req.headers.cookie);
  res.writeHead(200, { 'Set-Cookie': 'mycookie=test' });
  res.end('Hello Cookie');
})
  .listen(8083, () => {
    console.log('8083๋ฒˆ ํฌํŠธ์—์„œ ์„œ๋ฒ„ ๋Œ€๊ธฐ ์ค‘์ž…๋‹ˆ๋‹ค!');
  });

 

 

์ฟ ํ‚ค๋Š” ๋ฌธ์ž์—ด ํ˜•์‹์œผ๋กœ ์กด์žฌ

name=lgvv;year=2000 ํ˜•ํƒœ๋กœ ์กด์žฌ. ์ฟ ํ‚ค ๊ฐ„์—๋Š” ์„ธ๋ฏธ์ฝœ๋ก ์„ ๋„ฃ์–ด ๊ฐ๊ฐ์„ ๊ตฌ๋ถ„

 

createServer ๋ฉ”์„œ๋“œ์˜ ์ฝœ๋ฐฑ์—์„œ๋Š” req ๊ฐ์ฒด์— ๋‹ด๊ฒจ ์žˆ๋Š” ์ฟ ํ‚ค๋ฅผ ๊ฐ€์ ธ์˜จ๋‹ค. ์ฟ ํ‚ค๋Š” req.headers.cookie์— ๋“ค์–ด์žˆ์Œ. req.headers ๋ฉ”์„œ๋“œ๋ฅผ ์‚ฌ์šฉ. ์กฐ๊ธˆ ์ „์— ์ฟ ํ‚ค๋Š” ์š”์ฒญ๊ณผ ์‘๋‹ต์˜ ํ—ค๋”๋ฅผ ํ†ตํ•ด ์˜ค๊ฐ„๋‹ค.

 

์‘๋‹ต์˜ ํ—ค๋”์— ์ฟ ํ‚ค๋ฅผ ๊ธฐ๋กํ•ด์•ผ ํ•œ๋‹ค. res.writeHead๋ฅผ ์ž‘์„ฑ Set-Cookie๋Š” ๋ธŒ๋ผ์šฐ์ €ํ•œํ…Œ ๋‹ค์Œ๊ณผ ๊ฐ™์€ ๊ฐ’์˜ ์ฟ ํ‚ค๋ฅผ ์ €์žฅํ•˜๋ผ๋Š” ์˜๋ฏธ.

 

ํŒŒ๋น„ํ”์ด๋ž‘ ์›น ์‚ฌ์ดํŠธ์— ํƒญ์— ๋ณด์ด๋Š” ์ด๋ฏธ์ง€๋ฅผ ๋งํ•จ.

์šฐ์ธก ์•„์ด์ฝ˜

 

๋‹ค์Œ์—๋Š” ๊ทธ ์ฟ ํ‚ค๊ฐ€ ๋‚˜์ธ์ง€ ์‹๋ณ„ํ•ด์ฃผ๋Š” ๋ฐฉ๋ฒ•์„ ์•Œ์•„๋ณด์ž.

// cookie2.html
<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8" />
    <title>์ฟ ํ‚ค&์„ธ์…˜ ์ดํ•ดํ•˜๊ธฐ</title>
</head>
<body>
<form action="/login">
    <input id="name" name="name" placeholder="์ด๋ฆ„์„ ์ž…๋ ฅํ•˜์„ธ์š”" />
    <button id="login">๋กœ๊ทธ์ธ</button>
</form>
</body>
</html>

// cookie2.js
const http = require('http');
const fs = require('fs').promises;
const url = require('url');
const qs = require('querystring');

const parseCookies = (cookie = '') =>
  cookie
    .split(';')
    .map(v => v.split('='))
    .reduce((acc, [k, v]) => {
      acc[k.trim()] = decodeURIComponent(v);
      return acc;
    }, {});

http.createServer(async (req, res) => {
  const cookies = parseCookies(req.headers.cookie); // { mycookie: 'test' }
  // ์ฃผ์†Œ๊ฐ€ /login์œผ๋กœ ์‹œ์ž‘ํ•˜๋Š” ๊ฒฝ์šฐ
  if (req.url.startsWith('/login')) {
    const { query } = url.parse(req.url);
    const { name } = qs.parse(query);
    const expires = new Date();
    // ์ฟ ํ‚ค ์œ ํšจ ์‹œ๊ฐ„์„ ํ˜„์žฌ์‹œ๊ฐ„ + 5๋ถ„์œผ๋กœ ์„ค์ •
    expires.setMinutes(expires.getMinutes() + 5);
    res.writeHead(302, {
      Location: '/',
      'Set-Cookie': `name=${encodeURIComponent(name)}; Expires=${expires.toGMTString()}; HttpOnly; Path=/`,
    });
    res.end();
  // name์ด๋ผ๋Š” ์ฟ ํ‚ค๊ฐ€ ์žˆ๋Š” ๊ฒฝ์šฐ
  } else if (cookies.name) {
    res.writeHead(200, { 'Content-Type': 'text/plain; charset=utf-8' });
    res.end(`${cookies.name}๋‹˜ ์•ˆ๋…•ํ•˜์„ธ์š”`);
  } else {
    try {
      const data = await fs.readFile('./cookie2.html');
      res.writeHead(200, { 'Content-Type': 'text/html; charset=utf-8' });
      res.end(data);
    } catch (err) {
      res.writeHead(500, { 'Content-Type': 'text/plain; charset=utf-8' });
      res.end(err.message);
    }
  }
})
  .listen(8084, () => {
    console.log('8084๋ฒˆ ํฌํŠธ์—์„œ ์„œ๋ฒ„ ๋Œ€๊ธฐ ์ค‘์ž…๋‹ˆ๋‹ค!');
  });

 

์ด ๊ฒฝ์šฐ์—๋Š” ์ฟ ํ‚ค๊ฐ€ ์•ฑ๋‹จ์—์„œ ๋…ธ์ถœ๋˜์–ด์„œ ์œ„ํ—˜ํ•จ

const http = require('http');
const fs = require('fs').promises;
const url = require('url');
const qs = require('querystring');

const parseCookies = (cookie = '') =>
  cookie
    .split(';')
    .map(v => v.split('='))
    .reduce((acc, [k, v]) => {
      acc[k.trim()] = decodeURIComponent(v);
      return acc;
    }, {});

const session = {};

http.createServer(async (req, res) => {
  const cookies = parseCookies(req.headers.cookie);
  if (req.url.startsWith('/login')) {
    const { query } = url.parse(req.url);
    const { name } = qs.parse(query);
    const expires = new Date();
    expires.setMinutes(expires.getMinutes() + 5);
    const uniqueInt = Date.now();
    session[uniqueInt] = {
      name,
      expires,
    };
    res.writeHead(302, {
      Location: '/',
      'Set-Cookie': `session=${uniqueInt}; Expires=${expires.toGMTString()}; HttpOnly; Path=/`,
    });
    res.end();
  // ์„ธ์…˜์ฟ ํ‚ค๊ฐ€ ์กด์žฌํ•˜๊ณ , ๋งŒ๋ฃŒ ๊ธฐ๊ฐ„์ด ์ง€๋‚˜์ง€ ์•Š์•˜๋‹ค๋ฉด
  } else if (cookies.session && session[cookies.session].expires > new Date()) {
    res.writeHead(200, { 'Content-Type': 'text/plain; charset=utf-8' });
    res.end(`${session[cookies.session].name}๋‹˜ ์•ˆ๋…•ํ•˜์„ธ์š”`);
  } else {
    try {
      const data = await fs.readFile('./cookie2.html');
      res.writeHead(200, { 'Content-Type': 'text/html; charset=utf-8' });
      res.end(data);
    } catch (err) {
      res.writeHead(500, { 'Content-Type': 'text/plain; charset=utf-8' });
      res.end(err.message);
    }
  }
})
  .listen(8085, () => {
    console.log('8085๋ฒˆ ํฌํŠธ์—์„œ ์„œ๋ฒ„ ๋Œ€๊ธฐ ์ค‘์ž…๋‹ˆ๋‹ค!');
  });

์ข€ ์ž˜๋ผ์ง„๊ฒŒ ์ฟ ํ‚ค์— ์ด๋ฆ„ ๋‹ด์•„์„œ ๋ณด๋‚ด๋Š” ๋Œ€์‹  uniqueInt๋ผ๋Š” ์ˆซ์ž๊ฐ’์„ ๋ณด๋ƒ„. ์‚ฌ์šฉ์ž์˜ ์ด๋ฆ„๊ณผ ๋งŒ๋ฃŒ ์‹œ๊ฐ„์€ uniqueInt ์†์„ฑ๋ช… ์•„๋ž˜์— ์žˆ๋Š” session์ด๋ผ๋Š” ๊ฐ์ฒด์— ๋Œ€์‹  ์ €์žฅํ•จ.

 

# https์™€ http2

 

https ๋ชจ๋“ˆ์€ ์›น ์„œ๋ฒ„์— SSL ์•”ํ˜ธํ™”๋ฅผ ์ถ”๊ฐ€.

GET, POST ํ•  ๋•Œ ๋ฐ์ดํ„ฐ๋ฅผ ์•”ํ˜ธํ™”ํ•ด์„œ ์ค‘๊ฐ„์— ์ฑ„๊ฐ€๋„ ํ™•์ธํ•  ์ˆ˜ ์—†๊ฒŒ ๋งŒ๋“ค์–ด๋ฒ„๋ฆผ.

๋กœ๊ทธ์ธ์ด๋‚˜ ๊ฒฐ์ œ์—์„œ ํ•„์ˆ˜๋กœ ํ•„์š”ํ•œ ์ด์œ .

 

const http = require('http');

http.createServer((req, res) => {
  res.writeHead(200, { 'Content-Type': 'text/html; charset=utf-8' });
  res.write('<h1>Hello Node!</h1>');
  res.end('<p>Hello Server!</p>');
})
  .listen(8080, () => { // ์„œ๋ฒ„ ์—ฐ๊ฒฐ
    console.log('8080๋ฒˆ ํฌํŠธ์—์„œ ์„œ๋ฒ„ ๋Œ€๊ธฐ ์ค‘์ž…๋‹ˆ๋‹ค!');
  });

์ธ์ฆ ๊ธฐ๊ด€์—์„œ SSL์„ ๊ตฌ์ž…ํ•ด์•ผ ํ•˜๋Š”๋ฐ, Let's Encrpyt ๊ฐ™์€ ๊ธฐ๊ด€์—์„œ ๋ฌด๋ฃŒ๋กœ ๋ฐœ๊ธ‰ํ•ด์ฃผ๊ธฐ๋„ ํ•จ.

 

const https = require('https');
const fs = require('fs');

https.createServer({
  cert: fs.readFileSync('๋„๋ฉ”์ธ ์ธ์ฆ์„œ ๊ฒฝ๋กœ'),
  key: fs.readFileSync('๋„๋ฉ”์ธ ๋น„๋ฐ€ํ‚ค ๊ฒฝ๋กœ'),
  ca: [
    fs.readFileSync('์ƒ์œ„ ์ธ์ฆ์„œ ๊ฒฝ๋กœ'),
    fs.readFileSync('์ƒ์œ„ ์ธ์ฆ์„œ ๊ฒฝ๋กœ'),
  ],
}, (req, res) => {
  res.writeHead(200, { 'Content-Type': 'text/html; charset=utf-8' });
  res.write('<h1>Hello Node!</h1>');
  res.end('<p>Hello Server!</p>');
})
  .listen(443, () => {
    console.log('443๋ฒˆ ํฌํŠธ์—์„œ ์„œ๋ฒ„ ๋Œ€๊ธฐ ์ค‘์ž…๋‹ˆ๋‹ค!');
  });

http2 ์‚ฌ์šฉํ•˜๋ฉด ์†๋„๋„ ๋” ๊ฐœ์„ ๋œ๋‹ค.

http1.1์—์„œ๋„ ํŒŒ์ดํ”„๋ผ์ธ ๊ธฐ์ˆ ์„ ์ ์šฉํ•˜๋ฏ€๋กœ ์ €์ •๋„๋กœ ์ฐจ์ด๊ฐ€ ๋‚˜์ง€๋Š” ์•Š์ง€๋งŒ http/2๊ฐ€ ๋” ํšจ์œจ์ ์ธ ๊ฒƒ์€ ๋ถ„๋ช…

 

 

์•„๋ž˜๋Š” http/2๋ฅผ ์ ์šฉํ•œ๊ฑฐ์ž„.

const http2 = require('http2');
const fs = require('fs');

http2.createSecureServer({ // ์—ฌ๊ธฐ๋งŒ ๋ฐ”๊พธ๋ฉด ๋œ๋‹ค.
  cert: fs.readFileSync('๋„๋ฉ”์ธ ์ธ์ฆ์„œ ๊ฒฝ๋กœ'),
  key: fs.readFileSync('๋„๋ฉ”์ธ ๋น„๋ฐ€ํ‚ค ๊ฒฝ๋กœ'),
  ca: [
    fs.readFileSync('์ƒ์œ„ ์ธ์ฆ์„œ ๊ฒฝ๋กœ'),
    fs.readFileSync('์ƒ์œ„ ์ธ์ฆ์„œ ๊ฒฝ๋กœ'),
  ],
}, (req, res) => {
  res.writeHead(200, { 'Content-Type': 'text/html; charset=utf-8' });
  res.write('<h1>Hello Node!</h1>');
  res.end('<p>Hello Server!</p>');
})
  .listen(443, () => {
    console.log('443๋ฒˆ ํฌํŠธ์—์„œ ์„œ๋ฒ„ ๋Œ€๊ธฐ ์ค‘์ž…๋‹ˆ๋‹ค!');
  });

์ฝ”๋“œ๋Š” ๋˜‘๊ฐ™์€๋ฐ ์ €๊ธฐ๋งŒ ๋‹ค๋ฅด๋‹ค!

 

# Cluster

 

cluster ๋ชจ๋“ˆ์€ ๊ธฐ๋ณธ์ ์œผ๋กœ ์‹ฑ๊ธ€ ํ”„๋กœ์„ธ์Šค๋กœ ๋™์ž‘ํ•˜๋Š” ๋…ธ๋“œ๊ฐ€ CPU ์ฝ”์–ด๋ฅผ ๋ชจ๋‘ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๊ฒŒ ํ•ด์ฃผ๋Š” ๋ชจ๋“ˆ.

์š”์ฒญ์ด ๋“ค์–ด์˜ค๋ฉด ๋ณ‘๋ ฌ๋กœ ์‹คํ–‰๋œ ์„œ๋ฒ„์˜ ๊ฐœ์ˆ˜๋งŒํผ ์š”์ฒญ์ด ๋ถ„์‚ฐ๋˜๊ฒŒ ํ•  ์ˆ˜ ์žˆ์Œ.

์„œ๋ฒ„์— ๋ฌด๋ฆฌ๊ฐ€ ๊ทธ๋งŒํผ ๋œ ์ƒ๊น€.

 

๋ฉ”๋ชจ๋ฆฌ๋ฅผ ๊ณต์œ ํ•˜์ง€ ๋ชปํ•˜๋Š” ๋‹จ์ ๋„ ์กด์žฌ ๋”ฐ๋ผ์„œ ์„ธ์…˜์„ ๋ฉ”๋ชจ๋ฆฌ์— ์ €์žฅํ•˜๋Š” ๊ฒฝ์šฐ ๋ฌธ์ œ๊ฐ€ ๋  ์ˆ˜ ์žˆ์Œ. ์ด๋Š” ๋ ˆ๋””์Šค ๋“ฑ์˜ ์„œ๋ฒ„๋ฅผ ๋„์ž…ํ•ด ํ•ด๊ฒฐํ•  ์ˆ˜ ์žˆ์Œ.

 

const cluster = require('cluster');
const http = require('http');
const numCPUs = require('os').cpus().length;

if (cluster.isMaster) {
  console.log(`๋งˆ์Šคํ„ฐ ํ”„๋กœ์„ธ์Šค ์•„์ด๋””: ${process.pid}`);
  // CPU ๊ฐœ์ˆ˜๋งŒํผ ์›Œ์ปค๋ฅผ ์ƒ์‚ฐ
  for (let i = 0; i < numCPUs; i += 1) {
    cluster.fork();
  }
  // ์›Œ์ปค๊ฐ€ ์ข…๋ฃŒ๋˜์—ˆ์„ ๋•Œ
  cluster.on('exit', (worker, code, signal) => {
    console.log(`${worker.process.pid}๋ฒˆ ์›Œ์ปค๊ฐ€ ์ข…๋ฃŒ๋˜์—ˆ์Šต๋‹ˆ๋‹ค.`);
    console.log('code', code, 'signal', signal);
    cluster.fork();
  });
} else {
  // ์›Œ์ปค๋“ค์ด ํฌํŠธ์—์„œ ๋Œ€๊ธฐ
  http.createServer((req, res) => {
    res.writeHead(200, { 'Content-Type': 'text/html; charset=utf-8' });
    res.write('<h1>Hello Node!</h1>');
    res.end('<p>Hello Cluster!</p>');
    setTimeout(() => { // ์›Œ์ปค ์กด์žฌ๋ฅผ ํ™•์ธํ•˜๊ธฐ ์œ„ํ•ด 1์ดˆ๋งˆ๋‹ค ๊ฐ•์ œ ์ข…๋ฃŒ
      process.exit(1);
    }, 1000);
  }).listen(8086);

  console.log(`${process.pid}๋ฒˆ ์›Œ์ปค ์‹คํ–‰`);
}

์›Œ์ปค ์Šค๋ ˆ๋“œ๋ž‘ ๋น„์Šทํ•จ. ํ•˜์ง€๋งŒ ํ”„๋กœ์„ธ์Šค์ž„

 

์š”์ฒญ์ด ๋“ค์–ด์˜ค๋ฉด ๋งŒใ„ท๋ฅด์–ด์ง„ ์›Œ์ปค ํ”„๋กœ์„ธ์Šค์— ์š”์ฒญ์„ ๋ถ„๋ฐฐํ•จ.

 

์š”์ฒญํ•˜๋Š” ์ฃผ์†Œ ๋งŽ์•„์ง€๋ฉด if๋ฌธ ๋งŽ์•„์ ธ์„œ ๊ด€๋ฆฌ ๋ณต์žกํ•ด์ง

Express ๋ชจ๋“ˆ์„ ์ด์ œ ์•Œ์•„๋ณด์ž #5์—์„œ

Comments