JavaScript - The Complete Guide 2022

Section 27: An Introduction to Node.js - A Different JavaScript Environment

olivia_yj 2022. 11. 8. 17:56

The goals

๐Ÿ’ช๐ŸปWhat Exactly Is Node.js

โœŒ๐ŸปWriting Node.js Code

๐Ÿ‘๐ŸปUsing Express.js

๐Ÿ‘Š๐ŸปTalking to a Database

 

 

How to use File System

const fs = require('fs');

fs.readFile('user-data.txt', (err, data) => {
  if (err) {
    console.log(err);
    return;
  }
  console.log(data.toString());
});

fs.writeFile('user-data.txt', 'username=Max', err => {
  if (err) {
    console.log(err);
  } else {
    console.log('Wrote to file!');
  }
});

 

Pure-node.js

const http = require('http');

const server = http.createServer((request, response) => {
  let body = [];
  request.on('data', chunk => {
    body.push(chunk);
  });
  request.on('end', () => {
    body = Buffer.concat(body).toString();
    let userName = 'Unknown User';
    if (body) {
      userName = body.split('=')[1];
    }
    response.setHeader('Content-Type', 'text/html');
    response.write(
      `<h1>Hi ${userName}</h1><form method="POST" action="/"><input name="username" type="text"><button type="submit">Send</button></form>`
    );
    response.end();
  });
});

server.listen(3000);

response.setHeader

 

Express.js

body-parser

 

EJS

 

Cross-Origin Resource Sharing (CORS)

๋™์ผํ•œ ์ถœ์ฒ˜๊ฐ€ ์•„๋‹Œ ๋‹ค๋ฅธ ์ถœ์ฒ˜์—์„œ ๋ฐ์ดํ„ฐ๋ฅผ ์ฃผ๊ณ  ๋ฐ›๋Š” ๊ฒƒ์„ ํ—ˆ์šฉํ•˜๋Š” ์ •์ฑ…

Cross-Origin Resource Sharing (CORS) is an HTTP-header based mechanism that allows a server to indicate any origins (domain, scheme, or port) other than its own from which a browser should permit loading resources. CORS also relies on a mechanism by which browsers make a "preflight" request to the server hosting the cross-origin resource, in order to check that the server will permit the actual request. In that preflight, the browser sends headers that indicate the HTTP method and headers that will be used in the actual request.

An example of a cross-origin request: the front-end JavaScript code served from https://domain-a.com uses XMLHttpRequest to make a request for https://domain-b.com/data.json.

For security reasons, browsers restrict cross-origin HTTP requests initiated from scripts. For example, XMLHttpRequest and the Fetch API follow the same-origin policy. This means that a web application using those APIs can only request resources from the same origin the application was loaded from unless the response from other origins includes the right CORS headers.

The CORS mechanism supports secure cross-origin requests and data transfers between browsers and servers. Modern browsers use CORS in APIs such as XMLHttpRequest or Fetch to mitigate the risks of cross-origin HTTP requests.

 

Same Origin Policy(๋™์ผ ์ถœ์ฒ˜ ์ •์ฑ…)

๋™์ผ ์ถœ์ฒ˜ ์ •์ฑ…์€ ์›น ๋ธŒ๋ผ์šฐ์ €์—์„œ ๋ณด์•ˆ์„ ๊ฐ•ํ™”ํ•˜๊ธฐ ์œ„ํ•˜์—ฌ ๋™์ผํ•œ ์ถœ์ฒ˜์—์„œ๋งŒ ๋ฆฌ์†Œ์Šค๋ฅผ ์ฃผ๊ณ  ๋ฐ›๋„๋ก ํ•˜๋Š” ์ •์ฑ…์ด๋‹ค.

๊ทธ๋ ‡๋‹ค๋ฉด "์ถœ์ฒ˜"๋Š” ๋„๋Œ€์ฒด ๋ฌด์—‡์ผ๊นŒ?

์‰ฝ๊ฒŒ ๋งํ•˜๋ฉด URL ์ฃผ์†Œ์ด๋‹ค. (๋จผ์ € URL์˜ ๊ตฌ์„ฑ์š”์†Œ๋ฅผ ๋ชจ๋ฅด๋Š” ๋ถ„๋“ค์„ ์—ฌ๊ธฐ ์—์„œ ๋จผ์ € ์ฝ๊ณ  ์˜ค๊ธธ ๋ฐ”๋ž€๋‹ค.)

ํ•˜์ง€๋งŒ "๋™์ผํ•œ ์ถœ์ฒ˜"๋Š” ์ •ํ™•ํžˆ ๋˜‘๊ฐ™์€ URL์„ ์˜๋ฏธํ•˜๋Š” ๊ฒƒ์„ ์•„๋‹ˆ๋‹ค.

 

๋™์ผํ•œ ์ถœ์ฒ˜๋Š” URL ์ค‘์—์„œ๋„ ํ”„๋กœํ† ์ฝœ, ๋„๋ฉ”์ธ ์ฃผ์†Œ, ํฌํŠธ ๋ฒˆํ˜ธ๊ฐ€ ๊ฐ™์€ ๊ฒƒ์„ ์˜๋ฏธํ•œ๋‹ค.

์˜ˆ๋ฅผ ๋“ค๋ฉด ์•„๋ž˜์™€ ๊ฐ™๋‹ค.

 

์ถœ์ฒ˜:https://ko.wikipedia.org/wiki/%EB%8F%99%EC%9D%BC-%EC%B6%9C%EC%B2%98_%EC%A0%95%EC%B1%85


CORS

 

๋‹ค์‹œ CORS๋กœ ๋Œ์•„์™€์„œ ์ด๋Ÿฌํ•œ ๋™์ผ ์ถœ์ฒ˜ ์ •์ฑ…์ด ์žˆ๊ธฐ ๋•Œ๋ฌธ์— ์›๋ž˜๋Š” ๋‹ค๋ฅธ ์ถœ์ฒ˜์—์„œ ๋ฆฌ์†Œ์Šค๋ฅผ ๋ฐ›์•„์˜ค๋Š” ๊ฒƒ์ด ์ œํ•œ๋œ๋‹ค.

 

ํ•˜์ง€๋งŒ ๋‹ค๋ฅธ ์ถœ์ฒ˜๋กœ๋ถ€ํ„ฐ ๋ฆฌ์†Œ์Šค๋ฅผ ๋ฐ›์•„์˜ค๋Š” ๊ฒƒ์€ ํ•„์ˆ˜ ์š”์†Œ๊ฐ€ ๋˜์—ˆ๊ณ , ์ด๋Ÿฌํ•œ ๋ฌธ์ œ๋ฅผ ํ•ด๊ฒฐํ•˜๊ธฐ ์œ„ํ•ด ๋‚˜์˜จ ์ •์ฑ…์ด ๋ฐ”๋กœ CORS(๊ต์ฐจ ์ถœ์ฒ˜ ์ž์› ๊ณต์œ )์ด๋‹ค.

 

๊ทธ๋ ‡๋‹ค๋ฉด CORS๋Š” ์–ด๋–ป๊ฒŒ ์•ˆ์ „ํ•˜๊ฒŒ ๋‹ค๋ฅธ ์ถœ์ฒ˜์™€ ๋ฆฌ์†Œ์Šค๋ฅผ ๊ณต์œ ํ•˜๋Š” ๊ฒƒ์ผ๊นŒ?

 

๋ฐ”๋กœ ๋‘ ๊ฐ€์ง€ ๋ฐฉ๋ฒ•์ด ์žˆ๋Š”๋ฐ, ๋‹จ์ˆœ ์š”์ฒญ ๋ฐฉ๋ฒ•๊ณผ ์˜ˆ๋น„ ์š”์ฒญ ๋ฐฉ๋ฒ•์ด ์žˆ๋‹ค.


Header

 

์š”์ฒญ ๋ฐฉ๋ฒ•์€ ์š”์ฒญํ•˜๋Š” ํ—ค๋”์™€ ์‘๋‹ตํ•˜๋Š” ํ—ค๋”๋ฅผ ํ†ตํ•ด์„œ ์ด๋ฃจ์–ด ์ง„๋‹ค.

 

์š”์ฒญ ํ—ค๋”

 

1. Access-Control-Request-Method

 

์š”์ฒญ์„ ํ•  ๋•Œ ์–ด๋–ค ๋ฉ”์„œ๋“œ๋ฅผ ์‚ฌ์šฉํ•  ๊ฒƒ์ธ์ง€๋ฅผ ์•Œ๋ ค์ฃผ๋Š” ๊ฒƒ์ด๋‹ค.

 

2. Access-Control-Request-Headers

 

์š”์ฒญ์„ ํ•  ๋•Œ ์–ด๋–ค ํ—ค๋”๋ฅผ ์‚ฌ์šฉํ•  ๊ฒƒ์ธ์ง€ ์•Œ๋ ค์ฃผ๋Š” ๊ฒƒ์ด๋‹ค.

 

์‘๋‹ต ํ—ค๋”

 

1. Access-Control-Allow-Origin

 

๋ฆฌ์†Œ์Šค์— ์ ‘๊ทผํ•  ์ˆ˜ ์žˆ๋„๋ก ํ—ˆ์šฉํ•˜๋Š”์ง€๋ฅผ ์•Œ๋ ค์ฃผ๋Š” ๊ฒƒ์ด๋‹ค.

 

2. Access-Control-Expose-Headers

 

๋ธŒ๋ผ์šฐ์ €์—๊ฒŒ ์ ‘๊ทผํ•  ์ˆ˜ ์žˆ๋Š” ๋ฆฌ์ŠคํŠธ๋“ค์„ ์•Œ๋ ค์ฃผ๋Š” ๊ฒƒ์ด๋‹ค.

 

3. Access-Control-Max-Age

 

์บ์‹ฑ๋˜๋Š” ์‹œ๊ฐ„์„ ์•Œ๋ ค์ฃผ๋Š” ๊ฒƒ์ด๋‹ค.

 

4. Access-Control-Allow-Credentials

 

ํฌ๋ ˆ๋ด์…œ์ด true์ผ ๋•Œ ์š”์ฒญํ• ์ง€์— ๋Œ€ํ•œ ๊ฒƒ์„ ์•Œ๋ ค์ฃผ๋Š” ๊ฒƒ์ด๋‹ค.

 

5. Access-Control-Allow-Methods

 

ํ—ˆ์šฉ๋˜๋Š” ๋ฉ”์„œ๋“œ๋ฅผ ์•Œ๋ ค์ฃผ๋Š” ๊ฒƒ์ด๋‹ค.

 

6. Access-Control-Allow-Headers

 

์‚ฌ์šฉ ๊ฐ€๋Šฅํ•œ HTTP ํ—ค๋”๋ฅผ ์•Œ๋ ค์ฃผ๋Š” ๊ฒƒ์ด๋‹ค.

 

 

์ด์ œ ํ—ค๋”์— ๋Œ€ํ•ด ์•Œ์•„ ๋ณด์•˜์œผ๋‹ˆ ๋ณธ๊ฒฉ์ ์œผ๋กœ ์š”์ฒญ์— ๋Œ€ํ•ด ๋‹ค๋ค„๋ณด๋„๋ก ํ•˜์ž.


Preflight Request (์˜ˆ๋น„ ์š”์ฒญ)

 

์˜ˆ๋น„ ์š”์ฒญ์€ ๋ง ๊ทธ๋Œ€๋กœ ๋ฏธ๋ฆฌ ์š”์ฒญ์„ ๋ณด๋‚ด๋ณด๊ณ , ์•ˆ์ „ํ•œ์ง€๋ฅผ ํŒ๋‹จํ•œ ๋’ค์— ๋ณธ๊ฒฉ์ ์œผ๋กœ ์š”์ฒญ์„ ํ•˜๋Š” ๋ฐฉ์‹์ด๋‹ค.

 

์•„๋ž˜์™€ ๊ฐ™์ด ์˜ˆ๋น„ ์š”์ฒญ์„ ๋ณด๋‚ด๊ณ  ๊ทธ์— ๋Œ€ํ•œ ์‘๋‹ต์„ ๋ฐ›์€ ๋’ค ์‹ค์ œ ์š”์ฒญ์„ ๋ณด๋‚ด๊ณ  ์‘๋‹ต๋ฐ›๊ฒŒ ๋œ๋‹ค.

 

 

 

์กฐ๊ธˆ ๋” ๊ตฌ์ฒด์ ์œผ๋กœ ๋งํ•˜๋ฉด ํ—ค๋”์— Access-Control-Request-Method๋ฅผ ํ†ตํ•ด ์š”์ฒญํ•˜๋Š” HTTP ๋ฉ”์„œ๋“œ GET,POST,PUT,DELETE ์ค‘ ํ•˜๋‚˜์˜ ๋ฉ”์„œ๋“œ์™€ Access-Control-Request-Headers๋ฅผ ํ†ตํ•ด OPTIONS๋ผ๋Š” ํ—ค๋”๋ฅผ ๋„ฃ๊ณ  ์š”์ฒญ์„ ๋ณด๋‚ธ๋‹ค.

 

์ด ๋•Œ ์˜ˆ๋น„๋กœ ํ™•์ธํ•˜๋Š” ๊ฒƒ ๋ฟ์ด๊ธฐ ๋•Œ๋ฌธ์— ๋ฐ”๋””์— ์•„๋ฌด๊ฒƒ๋„ ์ž‘์„ฑํ•˜์ง€ ์•Š๊ณ  ํ—ค๋”๋งŒ ๋ณด๋‚ธ๋‹ค,

 

ํ•ด๋‹น ๋ฉ”์„œ๋“œ์™€ ํ—ค๋”๊ฐ€ ์œ ํšจํ•˜๋‹ค๋ฉด ์„œ๋ฒ„๋Š” ์‘๋‹ต ํ—ค๋”๋ฅผ ํ†ตํ•ด ์ ‘๊ทผ ๊ฐ€๋Šฅํ•œ์ง€(Access-Control-Allow-Origin), ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋Š” ๋ฆฌ์†Œ์Šค์˜ ๋ฆฌ์ŠคํŠธ(Access-Control-Expose-Headers), ์บ์‹ฑ ๋˜๋Š” ์‹œ๊ฐ„(Access-Control-Max-Age) ๋“ฑ์„ ์•Œ๋ ค์ฃผ๋Š” ๊ฒƒ์ด๋‹ค.


Simple Request (๋‹จ์ˆœ ์š”์ฒญ)

 

๋‹จ์ˆœ ์š”์ฒญ์€ ์œ„์˜ ์˜ˆ๋น„ ์š”์ฒญ๊ณผ๋Š” ๋‹ฌ๋ฆฌ ์„œ๋ฒ„์— ๋ฐ”๋กœ ๋ณธ๊ฒฉ์ ์œผ๋กœ ์š”์ฒญ์„ ์‹œ์ž‘ํ•œ๋‹ค.

 

๊ทธ๋ ‡๋‹ค๋ฉด ๋ฏธ๋ฆฌ ํ™•์ธํ•˜์ง€๋„ ์•Š๊ณ  ์–ด๋–ป๊ฒŒ ์•ˆ์ „ํ•˜๊ฒŒ ๋ฆฌ์†Œ์Šค๋ฅผ ์š”์ฒญํ•˜๋Š” ๊ฒƒ์ผ๊นŒ?

 

๊ทธ ๋ฐฉ๋ฒ•์€ ์กฐ๊ธˆ ๊นŒ๋‹ค๋กœ์šด ์กฐ๊ฑด๋“ค์„ ๊ฑฐ๋Š” ๊ฒƒ์ด๋‹ค.

 

1. Access-Control-Request-Method๋ฅผ ํ†ตํ•ด ์š”์ฒญํ•  ๋•Œ ๋ฉ”์„œ๋“œ๋Š” HTTP ๋ฉ”์„œ๋“œ๊ฐ€ ์•„๋‹Œ GET,HEAD,POST ์ค‘ ํ•˜๋‚˜์—ฌ์•ผ ํ•œ๋‹ค.

 

2. Access-Control-Request-Headers ํ†ตํ•ด ์š”์ฒญ์„ ๋ณด๋‚ผ ๋•Œ Accept  Accept-Language,Content-Language, Content-TypeDPR, Downlink, Save-Data, Viewport-Width ์ค‘ ํ•˜๋‚˜์—ฌ์•ผ ํ•œ๋‹ค.

 

3. Content-Type์„ ์‚ฌ์šฉํ•  ๊ฒฝ์šฐ application/x-www-form-urlencoded, multipart/form-data, text/plain ์ค‘ ํ•˜๋‚˜์—ฌ์•ผ ํ•œ๋‹ค.

 

์ด๋ ‡๊ฒŒ ๊นŒ๋‹ค๋กœ์šด ์กฐ๊ฑด์„ ๊ฑธ๊ณ  ํ•ด๋‹น ์กฐ๊ฑด์— ๋ถ€ํ•ฉํ•˜๋‹ค๋ฉด ์•ˆ์ „ํ•œ ์š”์ฒญ์ด๋ผ ์ธ์‹ํ•˜๊ณ  ๋ฐ์ดํ„ฐ๋ฅผ ์‘๋‹ตํ•˜๋Š” ํ˜•์‹์ด๋‹ค.

 

NodeJS ์˜ค๋ฅ˜ ์ฒ˜๋ฆฌํ•˜๊ธฐ

์ด ์„น์…˜์˜ ์™„์„ฑ๋œ ์ฝ”๋“œ๋Š” ์ž˜๋ชป๋œ ID(ํŠน์ˆ˜ MongoDB ObjectId ์œ ํ˜•์œผ๋กœ ๋ณ€ํ™˜ํ•  ์ˆ˜ ์—†์Œ)๋กœ /my-place/:id๋ฅผ ๋ฐฉ๋ฌธํ•˜๋ ค๊ณ  ํ•˜๋ฉด ์ถฉ๋Œํ•ฉ๋‹ˆ๋‹ค.

๋ฌผ๋ก  ์ด์ „ ๊ฐ•์˜์—์„œ ๋ฐฐ์šด ๊ฒƒ๊ณผ ์œ ์‚ฌํ•œ ๋ฐฉ์‹์œผ๋กœ ์˜ค๋ฅ˜ ์ฒ˜๋ฆฌ๋ฅผ ์ถ”๊ฐ€ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

  • ๋™๊ธฐ ์ฝ”๋“œ์˜ ๊ฒฝ์šฐ try-catch (๋˜๋Š” async/await)
  • (async/ await์„ ์‚ฌ์šฉํ•˜์ง€ ์•Š๋Š”) ํ”„๋กœ๋ฏธ์Šค ๊ธฐ๋ฐ˜ ์ฝ”๋“œ์—์„œ๋Š” then() / catch()

์˜ˆ์‹œ:

router.get('/location/:lid', (req, res, next) => {
  const locationId = req.params.lid;
 
  client.connect(function(err, client) {
    const db = client.db('locations');
 
    // Insert a single document
    db.collection('user-locations').findOne(
      {
        _id: new mongodb.ObjectId(locationId)
      },
      function(err, doc) {
        // if (err) {}
        if (!doc) {
          return res.status(404).json({ message: 'Not found!' });
        }
        res.json({ address: doc.address, coordinates: doc.coords });
      }
    );
  });
});

์œ„ ์˜ˆ์‹œ๋Š” ์•„๋ž˜์™€ ๊ฐ™์ด ๊ฐœ์„ ๋  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

router.get('/location/:lid', (req, res, next) => {
  const locationId = req.params.lid;
 
  client.connect(function(err, client) {
    const db = client.db('locations');
    
    // ์ถ”๊ฐ€๋œ ๋ถ€๋ถ„
    let locationId;
    try {
        locationId = new mongodb.ObjectId(locationId);
    } catch (error) {
        // ๋‹ค๋ฅธ ์ฝ”๋“œ๊ฐ€ ์‹คํ–‰๋˜์ง€ ์•Š๋Š”์ง€ ํ™•์ธํ•˜๊ธฐ ์œ„ํ•œ return ๋ฌธ
        return res.status(500).json({message: 'Invalid id!'}); 
    }
    // ์ถ”๊ฐ€๋œ ์ฝ”๋“œ์˜ ๋งˆ์ง€๋ง‰
 
 
    // ๋‹จ์ผ ๋ฌธ์„œ ์‚ฝ์ž…
    db.collection('user-locations').findOne(
      {
        _id: locationId // ์œ—๋ถ€๋ถ„์˜ ์ฝ”๋“œ์— ์˜ค๋ฅ˜๊ฐ€ ์—†๋‹ค๋ฉด ์—ฌ๊ธฐ๊นŒ์ง€ ๋„๋‹ฌ
 
      },
      function(err, doc) {
        // if (err) {}
        if (!doc) {
          return res.status(404).json({ message: 'Not found!' });
        }
        res.json({ address: doc.address, coordinates: doc.coords });
      }
    );
  });
});
 

์—ฌ๊ธฐ์„œ ์ค‘์š”ํ•œ ์ ์€ ๋ธŒ๋ผ์šฐ์ € ์ธก JavaScript์™€ ๋™์ผํ•œ ์˜ค๋ฅ˜ ์ฒ˜๋ฆฌ ๋„๊ตฌ๊ฐ€ ์žˆ๋‹ค๋Š” ๊ฒ๋‹ˆ๋‹ค.

 

 

 

Sources

https://expressjs.com/

 

Express - Node.js web application framework

Fast, unopinionated, minimalist web framework for Node.js $ npm install express --save

expressjs.com

https://ejs.co/

 

EJS -- Embedded JavaScript templates

Simple syntax JavaScript code in simple, straightforward scriptlet tags. Just write JavaScript that emits the HTML you want, and get the job done!

ejs.co

https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS

 

Cross-Origin Resource Sharing (CORS) - HTTP | MDN

Cross-Origin Resource Sharing (CORS) is an HTTP-header based mechanism that allows a server to indicate any origins (domain, scheme, or port) other than its own from which a browser should permit loading resources. CORS also relies on a mechanism by which

developer.mozilla.org

https://fomaios.tistory.com/entry/Network-CORS%EB%9E%80-feat-%EB%B3%B4%EC%95%88HTTP

 

[Network] CORS๋ž€? (feat. ๋ณด์•ˆ,HTTP) (What is a CORS?)

CORS๋ž€? CORS๋Š” Cross-Origin Resource Sharing์˜ ์•ฝ์ž๋กœ ์ง์—ญํ•˜๋ฉด "๊ต์ฐจ ์ถœ์ฒ˜ ๋ฆฌ์†Œ์Šค ๊ณต์œ " ์ด๋‹ค. ์ข€ ๋” ์‰ฝ๊ฒŒ ๋งํ•˜๋ฉด ๋™์ผํ•œ ์ถœ์ฒ˜๊ฐ€ ์•„๋‹Œ ๋‹ค๋ฅธ ์ถœ์ฒ˜์—์„œ ๋ฐ์ดํ„ฐ๋ฅผ ์ฃผ๊ณ  ๋ฐ›๋Š” ๊ฒƒ์„ ํ—ˆ์šฉํ•˜๋Š” ์ •์ฑ…์ด๋‹ค. ๊ทธ๋ ‡๋‹ค

fomaios.tistory.com