Nodejs REST

REST

: REpresentational State Transfer์˜ ์ค„์ž„๋ง์ด๋ฉฐ, ์„œ๋ฒ„์˜ ์ž์›์„ ์ •์˜ํ•˜๊ณ  ์ž์›์— ๋Œ€ํ•œ ์ฃผ์†Œ๋ฅผ ์ง€์ •ํ•˜๋Š” ๋ฐฉ๋ฒ•์„ ๊ฐ€๋ฅดํ‚ค๋Š” ๊ฒƒ, ์ผ์ข…์˜ ์•ฝ์†

REST์—์„œ๋Š” ์ฃผ์†Œ ์™ธ์—๋„ HTTP ์š”์ฒญ ๋ฉ”์„œ๋“œ๋ผ๋Š” ๊ฒƒ์„ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค.

  • GET : ์„œ๋ฒ„ ์ž์›์„ ๊ฐ€์ ธ์˜ค๊ณ ์ž ํ•  ๋•Œ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค. ์š”์ฒญ์˜ ๋ณธ๋ฌธ์— ๋ฐ์ดํ„ฐ๋ฅผ ๋„ฃ์ง€ ์•Š์Šต๋‹ˆ๋‹ค. ๋ฐ์ดํ„ฐ๋ฅผ ์„œ๋ฒ„๋กœ ๋ณด๋‚ด์•ผ ํ•œ๋‹ค๋ฉด ์ฟผ๋ฆฌ์ŠคํŠธ๋ง์„ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค.
  • POST : ์„œ๋ฒ„์— ์ž์›์„ ์ƒˆ๋กœ ๋“ฑ๋กํ•˜๊ณ ์ž ํ•  ๋•Œ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค. ์š”์ฒญ์˜ ๋ณธ๋ฌธ์— ์ƒˆ๋กœ ๋“ฑ๋กํ•  ๋ฐ์ดํ„ฐ๋ฅผ ๋„ฃ์–ด ๋ณด๋ƒ…๋‹ˆ๋‹ค.
  • PUT : ์„œ๋ฒ„์˜ ์ž์›์„ ์š”์ฒญ์— ๋“ค์–ด ์žˆ๋Š” ์ž์›์œผ๋กœ ์น˜ํ™˜ํ•˜๊ณ ์ž ํ•  ๋•Œ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค. ์š”์ฒญ์˜ ๋ณธ๋ฌธ์— ์น˜ํ™˜ํ•  ๋ฐ์ดํ„ฐ๋ฅผ ๋„ฃ์–ด๋ณด๋ƒ…๋‹ˆ๋‹ค.
  • PATCH : ์„œ๋ฒ„ ์ž์›์˜ ์ผ๋ถ€๋งŒ ์ˆ˜์ •ํ•˜๊ณ ์ž ํ•  ๋•Œ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค. ์š”์ฒญ์˜ ๋ณธ๋ฌธ์— ์ผ๋ถ€ ์ˆ˜์ •ํ•  ๋ฐ์ดํ„ฐ๋ฅผ ๋„ฃ์–ด ๋ณด๋ƒ…๋‹ˆ๋‹ค.
  • DELECT : ์„œ๋ฒ„์˜ ์ž์›์„ ์‚ญ์ œํ•˜๊ณ ์ž ํ•  ๋•Œ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค. ์š”์ฒญ์˜ ๋ณธ๋ฌธ์— ๋ฐ์ดํ„ฐ๋ฅผ ๋„ฃ์ง€ ์•Š์Šต๋‹ˆ๋‹ค.
  • OPTIONS : ์š”์ฒญ์„ ํ•˜๊ธฐ ์ „์— ํ†ต์‹  ์˜ต์…˜์„ ์„ค๋ช…ํ•˜๊ธฐ ์œ„ํ•ด ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค.

HTTP ๋ฐฉ์‹์„ ์‚ฌ์šฉํ•˜๋ฉด ํด๋ผ์ด์–ธํŠธ๊ฐ€ ๋ˆ„๊ตฌ๋“  ์ƒ๊ด€์—†์ด ๊ฐ™์€ ๋ฐฉ์‹์œผ๋กœ ์„œ๋ฒ„์™€ ์†Œํ†ตํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

์ด ์˜๋ฏธ๋Š” ์ฆ‰ ์„œ๋ฒ„์™€ ํด๋ผ์ด์–ธํŠธ๊ฐ€ ๋ถ„๋ฆฌ๋˜์–ด์žˆ๋‹ค๋Š” ์†Œ๋ฆฌ์ž…๋‹ˆ๋‹ค. ์ถ”ํ›„ ํด๋ผ๋ฆฌ์–ธํŠธ์— ๊ตฌ์• ๋˜์ง€ ์•Š๋Š”๋‹ค๋Š” ๋œป์ด๊ธฐ๋„ ํ•ฉ๋‹ˆ๋‹ค.

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(201, { 'Content-Type': 'application/json; charset=utf-8' });
        return res.end(JSON.stringify(users)); // JSON๋ฅผ ๋ฌธ์ž์—ด๋กœ ๋ณ€ํ™˜
      }
      // /๋„ /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) => { // .push ์ด์šฉ์‹œ ๋ฒ„ํผํ˜•์‹์œผ๋กœ ์‚ฌ์šฉํ•˜๊ณ  end์—์„œ ๋ฌธ์ž์—ด์„ ํ•ฉ์ณ์„œ ์‚ฌ์šฉ
          body += data; // ์—ฌ๊ธฐ์„œ ์ด๋ฏธ ์ŠคํŠธ๋ฆฌ๋ฐํ˜•์‹์œผ๋กœ ํ•ฉ์นจ
        });
        // ์š”์ฒญ์˜ body๋ฅผ ๋‹ค ๋ฐ›์€ ํ›„ ์‹คํ–‰๋จ
        return req.on('end', () => {
          console.log('POST ๋ณธ๋ฌธ(Body):', body);
          const { name } = JSON.parse(body); // ๋ฌธ์ž์—ด์„ JSON์œผ๋กœ ๋ณ€ํ™˜
          // { name } : ๋””์Šค๋Ÿญ์ณ๋ง : body.name์„ ๋„ฃ์–ด์ค€๊ฒƒ
          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); // ์•ž์—์„œ ์•„๋ฌด๊ฒƒ๋„ ํ•ด๋‹นํ•˜์ง€ ์•Š์•˜์„ ๊ฒฝ์šฐ NOT FOUND์—๋Ÿฌ
    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๋ฒˆ ํฌํŠธ์—์„œ ์„œ๋ฒ„ ๋Œ€๊ธฐ ์ค‘์ž…๋‹ˆ๋‹ค');
  });

์œ„์˜ ์ฝ”๋“œ์— ์ฃผ์„๋ฌธ์„ ๊ฑฐ์˜๋‹ค ์ ์–ด๋†“์•˜์ง€๋งŒ ์กฐ๊ธˆ๋” ์„ค๋ช…์„ ํ•ด๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค.

req.method๋กœ HTTP์š”์ฒญ ๋ฉ”์„œ๋“œ๋ฅผ ๊ตฌ๋ถ„ํ•˜๊ณ , req.url๋กœ ์š”์ฒญ์ฃผ์†Œ๋ฅผ ๊ตฌ๋ถ„ํ•ฉ๋‹ˆ๋‹ค.

๋˜ ๋‹ค๋ฅธ HTTP์š”์ฒญ ๋ฉ”์†Œ๋“œ๋ฅผ ์‚ฌ์šฉํ•˜๊ณ ์‹ถ์œผ๋ฉด else if๋ฅผ ํ†ตํ•ด ์‚ฌ์šฉ์„ ํ•˜๋ฉด๋ฉ๋‹ˆ๋‹ค.

res.end ์•ž์— return์ด ์žˆ๋Š” ์ด์œ ๋Š” ํ•จ์ˆ˜๋ฅผ ์ข…๋ฃŒ์‹œํ‚ค๊ธฐ ์œ„ํ•ด์„œ ์ž…๋‹ˆ๋‹ค.

users ๋Š” ๊ฐœ์ฒด๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ์‚ฌ์šฉ์ž ์ •๋ณด๋ฅผ ์ €์žฅํ–ˆ์Šต๋‹ˆ๋‹ค.

stream์œผ๋กœ ๋˜์–ด์žˆ๋Š” ๋ฐ์ดํ„ฐ๋Š” ์ŠคํŠธ๋ฆผ ํ˜•์‹์œผ๋กœ ์ „๋‹ฌ๋˜๋ฉฐ, on์„ ํ†ตํ•ด ๋ฐ›์€ ๋ฐ์ดํ„ฐ๋Š” ๋ฌธ์ž์—ด์ด๋ฏ€๋กœ JSON.parseํ•˜๋Š” ๊ณผ์ •์ด ํ•„์š”ํ•ฉ๋‹ˆ๋‹ค.

Leave a comment