2022 Web Development Bootcamp

Section 20: Advanced Server-Side Code: Dynamic Routes, Error Handling, Patterns - Building a More Dynamic & Realistic Backend

olivia_yj 2022. 9. 7. 22:32

The goals

๐Ÿ’ช๐ŸปDynamic Routes

โœŒ๐ŸปCustom Middleware & Error Handling

๐Ÿ‘๐ŸปOptimizing Our Code

 

Why we need Dynamic Routes

we can't make routes with speculation that how many data would be generated.

In this case, we use dynamic routes so it can generate itself while user adding data

 

res.render()

If we pass two parameters in render, it means that we can use the second item in the first file and usually we call it as a key

relativa path vs absolute path

when we use link, if we don't use '/' then it's a relative path. But if we use '/' in front of the path, then it's absolute path.

To prevent some errors in the future after modifying sturucture, it is recommended that we use abolute path with '/'.

Especially when we separate 'head' itself as an another file and share or connect to other file so we don't have to repeat, in this case we should write the path absolutely not to make an error.

req.params

It takes keys or properties form the path we define.

So, it should be the same as we set on our path. Here, we set id, so it should be params.id

 

UUId (Uniform Unique ID)

 

When URL has a specific 'id' of item and we want to show the detail of that specific item

app.get('/restaurants/:id', function (req, res) {
  const restaurantId = req.params.id
  const filePath = path.join(__dirname, 'data', 'restaurants.json');

  const fileData = fs.readFileSync(filePath);
  const storedRestaurants = JSON.parse(fileData);
  res.render('restaurant-detail', {rid: restaurantId})
});

firstly, bring the data from json file and jsonify

app.get('/restaurants/:id', function (req, res) {
  const restaurantId = req.params.id
  const filePath = path.join(__dirname, 'data', 'restaurants.json');

  const fileData = fs.readFileSync(filePath);
  const storedRestaurants = JSON.parse(fileData);

  for (const restaurant of storedRestaurants) {
    if (restaurant.id === restaurantId) {
      res.render('restaurant-detail', {rid: restaurantId})
    }
  }
});

and use for loop to check if the id of the data is the same to the data we wanna show.

And we used 'for of' loop since it's an array.

app.get('/restaurants/:id', function (req, res) {
  const restaurantId = req.params.id
  const filePath = path.join(__dirname, 'data', 'restaurants.json');

  const fileData = fs.readFileSync(filePath);
  const storedRestaurants = JSON.parse(fileData);

  for (const restaurant of storedRestaurants) {
    if (restaurant.id === restaurantId) {
      return res.render('restaurant-detail', {rid: restaurantId})
    }
  }
});

After we found the data, we should finish this funtion. So we return the value to end the execution of this code.

But, here when we render we set restaurant as a key and give the data from array, const restaurant.

Then where this key restaurant from?

This is from 'restaurant-detail' file. If this key is changed, then we need to change this for loop key also.

 

We should put render out of for loop, since we need to render '404' after checking all the item in storedRestaurant

app.get('/restaurants/:id', function (req, res) {
  const restaurantId = req.params.id
  const filePath = path.join(__dirname, 'data', 'restaurants.json');

  const fileData = fs.readFileSync(filePath);
  const storedRestaurants = JSON.parse(fileData);

  for (const restaurant of storedRestaurants) {
    if (restaurant.id === restaurantId) {
      return res.render('restaurant-detail', {
        restaurant: restaurant
      })
    }
  }
  res.render('404');
});

 

How we show error page when user input the wrong path?

It's impossible to make every possible cases as paths.

So we need to write code for all the general cases.

In this case, we can just write code for the general case and put it at the last.

So our computer will read our code from the head and when sithe the cases by the code we wrote, and left over which is not in any cases we wrote, will use this error code.

And there's no filter so it will apply for all the left over.

 

 

How to show error page for server error page

500 error code means that something went wrong on the server.

But we already put error handling code for general case, so we need more something special.

So here, we will give 4 parameters to the function and it's telling to express that it's special code and it will work everywhere if there are some cases.

 

Error Handling

Error Handling refers to how Express catches and processes errors that occur both synchronously and asynchronously. Express comes with a default error handler so you don’t need to write your own to get started.

Catching Errors

It’s important to ensure that Express catches all errors that occur while running route handlers and middleware.

Errors that occur in synchronous code inside route handlers and middleware require no extra work. If synchronous code throws an error, then Express will catch and process it. For example:

app.get('/', (req, res) => {
  throw new Error('BROKEN') // Express will catch this on its own.
})

For errors returned from asynchronous functions invoked by route handlers and middleware, you must pass them to the next() function, where Express will catch and process them. For example:

app.get('/', (req, res, next) => {
  fs.readFile('/file-does-not-exist', (err, data) => {
    if (err) {
      next(err) // Pass errors to Express.
    } else {
      res.send(data)
    }
  })
})

Starting with Express 5, route handlers and middleware that return a Promise will call next(value) automatically when they reject or throw an error. For example:

app.get('/user/:id', async (req, res, next) => {
  const user = await getUserById(req.params.id)
  res.send(user)
})

If getUserById throws an error or rejects, next will be called with either the thrown error or the rejected value. If no rejected value is provided, next will be called with a default Error object provided by the Express router.

If you pass anything to the next() function (except the string 'route'), Express regards the current request as being an error and will skip any remaining non-error handling routing and middleware functions.

 

How to use 'next' method?

 

Status codes

We can set our code specifically what status codes we wanna give, but sometimes

We are showing the error page but status code says it's okay so we need to fix this status code.

 

app.get('/restaurants/:id', function (req, res) {
  const restaurantId = req.params.id
  const filePath = path.join(__dirname, 'data', 'restaurants.json');

  const fileData = fs.readFileSync(filePath);
  const storedRestaurants = JSON.parse(fileData);

  for (const restaurant of storedRestaurants) {
    if (restaurant.id === restaurantId) {
      return res.render('restaurant-detail', {
        restaurant: restaurant
      })
    }
  }
  res.status(404).render('404');
});

 

 

Method chaining

app.use(function (req, res) {
  res.status.render('404');
})

connect the methods and use together

Status simply returns an updated response object.

So, here, technically we are still calling render on our response object, but on a slightly updated one.

 

Code refactoring

Refactoring means that "rewriting parts of the code" / "restructuring code" - always with the intention of keeping the individual code snippets short, concise and maintainable.

 

How can we use module we made in other page

module.exports = {
  getStoredRestaurants: getStoredRestaurants
}

left side is the key name we wanna use in other files, and right side is the module we wanna export. So we can't change this left sife name.

 

 

How to change the path to parent path

const filePath = path.join(__dirname, '..' ,'data', 'restaurants.json');

we put ".." it means that we will move to the parent directory from where we are now.

 

Express Router

If we wanna separate the basic code in app file and move some common code to other files, then how should we do?

 

const express = require('express');

app.get('/', function (req, res) {
  res.render('index');
});

app.get('/about', function (req, res) {
  res.render('about')
});

We brought some codes from our 'app' file cause it's basic code.

But it's based on 'app' but we can't declare here again. Because it's only for our real 'app' file.

So, in this case, we can use Express Router method.

 

const express = require('express');

const router = express.Router();

router.get('/', function (req, res) {
  res.render('index');
});

router.get('/about', function (req, res) {
  res.render('about')
});

module.exports = router;

 

So, we changed 'app' to 'router'.

 

And we should import it to use in app file then we can use like this:

 

const resData = require('./util/restaurant-data');
const defaultRoutes = require('./routes/default');

const app = express();

app.set('views', path.join(__dirname, 'views'));
app.set('view engine', 'ejs');

app.use(express.static('public'));
app.use(express.urlencoded({
  extended: false
}));

app.use('/', defaultRoutes);

 

This will be EVERY request. Every request starts with "/" since every request is at least targeting <your-domain>/something (even if it's just <your-domain>/).

 

When we use this, if we set it as 'app.use('/restaurants', defaultRoutes), then in this case, in default file all the routes work as '/restaurants/~' so we don't use like this.

 

Query Parameters

Array.prototype.sort()

The sort() method sorts the elements of an array in place and returns the reference to the same array, now sorted. The default sort order is ascending, built upon converting the elements into strings, then comparing their sequences of UTF-16 code units values.

The time and space complexity of the sort cannot be guaranteed as it depends on the implementation.

Syntax

// Functionless
sort()

// Arrow function
sort((a, b) => { /* … */ } )

// Compare function
sort(compareFn)

// Inline compare function
sort(function compareFn(a, b) { /* … */ })

Parameters

compareFn Optional

Specifies a function that defines the sort order. If omitted, the array elements are converted to strings, then sorted according to each character's Unicode code point value.

a
The first element for comparison.

b

 

The second element for comparison.

 

 

In JavaScript, we can use the ">" and "<" operators not just on numbers but also on strings!

E.g. "Tornado" > "Weather" yield "true"

 

router.get('/restaurants', function (req, res) {
  const storedRestaurants = resData.getStoredRestaurants();

  storedRestaurants.sort(function(resA, resB) {
    if (resA.name > resB.name) {
      return 1
    } 
      return -1
    }
  );

 

If we define button in <form> but there's no other items then?

It will automatically submit the data

 

    <form action="/restaurants" method="GET">
      <input type="hidden" value="asc" name="order">
      <button class="btn">Change Order</button>
    </form>

But if we just submit this form, there would be no data. So we put 'input' tag there and set type as 'hidden'.

So, user would not be able to input some data but we can set as developers.

So here we set 'value' as 'asc' which means ascending.

So we will reload this page with some slight change.

 

 

In the Server-side code, we can access to the query parameter value, and change the sorting based on the query parameter value

 

router.get('/restaurants', function (req, res) {
  let order = req.query.order
  
  if (order !== 'asc' & order !== 'desc') {
    order = 'asc';
  }

 

We can use this code to change our sorting code.

 

 <form action="/restaurants" method="GET">
      <input type="hidden" value="<%= nextOrder %>" name="order">
      <button class="btn">Change Order</button>
 </form>

Since we fix our code like this, every time when we click the button, it changes the data would be submitted by the form.

 

Query parameter vs Route parameter in Dynamic routes

"๋™์  ๋ผ์šฐํŠธ"์˜ ๋ผ์šฐํŠธ ๋งค๊ฐœ๋ณ€์ˆ˜

์ด ์„น์…˜์—์„œ๋Š” ๋ผ์šฐํŠธ ๋งค๊ฐœ๋ณ€์ˆ˜๋ฅผ ํ™œ์šฉํ•˜์—ฌ URL ๊ฒฝ๋กœ์—์„œ ๋™์  ๊ฐ’์„ ์ถ”์ถœํ•˜๋Š” "๋™์  ๋ผ์šฐํŠธ"์— ๋Œ€ํ•ด ๋ฐฐ์› ์Šต๋‹ˆ๋‹ค.

์˜ˆ๋ฅผ ๋“ค์–ด:

router.get('/restaurants/:id', ...)

์ด ์˜ˆ์—์„œ id๋Š” ์ด URL/๊ฒฝ๋กœ๋ฅผ ๋ฐฉ๋ฌธํ•  ๋•Œ ๋‹ค๋ฅธ ๊ฐ’์„ ์œ ์ง€ํ•˜๋Š” ๋ผ์šฐํŠธ ๋งค๊ฐœ๋ณ€์ˆ˜์ž…๋‹ˆ๋‹ค. ์˜ˆ๋ฅผ ๋“ค์–ด, ์‚ฌ์šฉ์ž๊ฐ€ /restaurants/r1์„ ์ž…๋ ฅํ•˜๋ฉด id๋Š” r1๊ณผ ๊ฐ™์Šต๋‹ˆ๋‹ค.

๋ผ์šฐํŠธ ๋งค๊ฐœ๋ณ€์ˆ˜๋Š” ํ•˜๋‚˜์˜ ๋‹จ์ผ ๊ฒฝ๋กœ๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ๊ตฌ์ฒด์ ์ธ ๋ผ์šฐํŠธ ๋งค๊ฐœ๋ณ€์ˆ˜ ๊ฐ’์— ๋”ฐ๋ผ ๋‹ค๋ฅธ ๋ฐ์ดํ„ฐ๋ฅผ ๋กœ๋“œํ•  ์ˆ˜ ์žˆ์œผ๋ฏ€๋กœ ๋งค์šฐ ์œ ์šฉํ•ฉ๋‹ˆ๋‹ค.

๋ผ์šฐํŠธ ๋งค๊ฐœ๋ณ€์ˆ˜(์œ„์˜ ์˜ˆ์—์„œ:id)๊ฐ€ URL ๊ฒฝ๋กœ์˜ ํ•ต์‹ฌ ๋ถ€๋ถ„์ž„์„ ์ดํ•ดํ•˜๋Š” ๊ฒƒ์ด ์ค‘์š”ํ•ฉ๋‹ˆ๋‹ค. ์˜ˆ๋ฅผ ๋“ค์–ด ์œ„์˜ ๊ฒฝ๋กœ์—์„œ๋Š” /restaurants๋งŒ ์ฒ˜๋ฆฌ๋˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. ๋ผ์šฐํŠธ ๋งค๊ฐœ๋ณ€์ˆ˜์— ๋Œ€ํ•œ ๊ฐ’์ด ์—†๊ธฐ ๋•Œ๋ฌธ์ž…๋‹ˆ๋‹ค.

 

์ฟผ๋ฆฌ ๋งค๊ฐœ๋ณ€์ˆ˜

๋˜ํ•œ ์ด ์„น์…˜์—์„œ "์ฟผ๋ฆฌ ๋งค๊ฐœ๋ณ€์ˆ˜"๋ผ๋Š” ๊ฐœ๋…์— ๋Œ€ํ•ด์„œ๋„ ๋ฐฐ์› ์Šต๋‹ˆ๋‹ค.

"์ฟผ๋ฆฌ ๋งค๊ฐœ๋ณ€์ˆ˜"์™€ "๋ผ์šฐํŠธ ๋งค๊ฐœ๋ณ€์ˆ˜"๋ฅผ ํ˜ผ๋™ํ•˜๊ธฐ ์‰ฝ์ง€๋งŒ ์ด๋“ค์€ ์„œ๋กœ ๋‹ค๋ฅธ ๋ฌธ์ œ๋ฅผ ํ•ด๊ฒฐํ•˜๋Š” ๊ทผ๋ณธ์ ์œผ๋กœ ๋‹ค๋ฅธ ๊ฐœ๋…์ž…๋‹ˆ๋‹ค.

"๋ผ์šฐํŠธ ๋งค๊ฐœ๋ณ€์ˆ˜"(์œ„ ์ฐธ์กฐ)๊ฐ€ ์„ ํƒ ์‚ฌํ•ญ์ด ์•„๋‹ˆ๊ณ  ๋ผ์šฐํŠธ ์ •์˜์˜ ํ•ต์‹ฌ ๋ถ€๋ถ„์ธ ๊ฒฝ์šฐ(์ฆ‰, ๋ผ์šฐํŠธ ๋งค๊ฐœ๋ณ€์ˆ˜์— ๊ฐ’์ด ์ œ๊ณต๋˜์ง€ ์•Š์œผ๋ฉด ๋กœ๋“œ๊ฐ€ ํ™œ์„ฑํ™”๋˜์ง€ ์•Š์Œ) "์ฟผ๋ฆฌ ๋งค๊ฐœ๋ณ€์ˆ˜"๋Š” ์™„์ „ํžˆ ์„ ํƒ ์‚ฌํ•ญ์ž…๋‹ˆ๋‹ค!

"์ฟผ๋ฆฌ ๋งค๊ฐœ๋ณ€์ˆ˜"๋Š” ์ผ๋ฐ˜์ ์œผ๋กœ URL ๊ฒฝ๋กœ์— ์ถ”๊ฐ€ ์ •๋ณด๋ฅผ ์ถ”๊ฐ€ํ•˜๋Š” ๋ฐ ์‚ฌ์šฉ๋ฉ๋‹ˆ๋‹ค.

์˜ˆ๋ฅผ ๋“ค์–ด:

/restaurants?order=asc

์—ฌ๊ธฐ์„œ "order" ์ฟผ๋ฆฌ ๋งค๊ฐœ๋ณ€์ˆ˜๋Š” "asc" ๊ฐ’์œผ๋กœ ์ถ”๊ฐ€๋ฉ๋‹ˆ๋‹ค(์ฟผ๋ฆฌ ๋งค๊ฐœ๋ณ€์ˆ˜๋Š” ํ•ญ์ƒ ?๊ธฐํ˜ธ๋ฅผ ํ†ตํ•ด "์ฃผ ๊ฒฝ๋กœ"์™€ ๋ถ„๋ฆฌ๋จ).

๊ธฐ๋ณธ์ ์œผ๋กœ ์ฟผ๋ฆฌ ๋งค๊ฐœ๋ณ€์ˆ˜๋Š” ์•„๋ฌด ์ž‘์—…๋„ ์ˆ˜ํ–‰ํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค!

์›น์‚ฌ์ดํŠธ ๋ฐฉ๋ฌธ์ž๋Š” ์›ํ•˜๋Š” ๋งŒํผ ์ถ”๊ฐ€ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๋งํฌ๋ฅผ ํ†ตํ•ด ์ถ”๊ฐ€ํ•˜๊ฑฐ๋‚˜ ์ด์ „ ๊ฐ•์˜์—์„œ์™€ ๊ฐ™์ด GET ์š”์ฒญ์„ ํ†ตํ•ด ์–‘์‹์„ ์ œ์ถœํ•˜์—ฌ ์ถ”๊ฐ€ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค(์ฐธ๊ณ : GET ์–‘์‹ ๋Œ€์‹  ์ด์ „ ๊ฐ•์˜์—์„œ ์ฟผ๋ฆฌ ๋งค๊ฐœ๋ณ€์ˆ˜๋กœ ๋งํฌ๋ฅผ ๊ตฌ์„ฑํ•  ์ˆ˜๋„ ์žˆ์—ˆ์Šต๋‹ˆ๋‹ค. - ํ•˜์ง€๋งŒ ์ˆจ๊ฒจ์ง„ ์ž…๋ ฅ ํ•„๋“œ์— ๋Œ€ํ•œ ์•„์ด๋””์–ด๋ฅผ ์†Œ๊ฐœํ•˜๊ณ  ์‹ถ์—ˆ์–ด์š”.)

์„œ๋ฒ„ ์ธก์—์„œ ์ถ”๊ฐ€ ์ž‘์—…์„ ์ˆ˜ํ–‰ํ•˜๊ธฐ ์œ„ํ•ด ์ด๋Ÿฌํ•œ ์„ ํƒ์  ์ฟผ๋ฆฌ ๋งค๊ฐœ๋ณ€์ˆ˜๋ฅผ ์ฒ˜๋ฆฌํ•  ์ˆ˜ ์žˆ๋Š” ์ฝ”๋“œ๋ฅผ ์ถ”๊ฐ€ํ•˜๋Š” ๊ฒƒ์€ ๊ฐœ๋ฐœ์ž์—๊ฒŒ ๋‹ฌ๋ ค ์žˆ์Šต๋‹ˆ๋‹ค. ์˜ˆ๋ฅผ ๋“ค์–ด, ๋ฐฐ์—ด์˜ ํ•ญ๋ชฉ ์ˆœ์„œ๋ฅผ ๋ณ€๊ฒฝํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค(๋งˆ์ง€๋ง‰ ๊ฐ•์˜) ํ•ญ๋ชฉ์„ ํ•„ํ„ฐ๋งํ•˜๊ฑฐ๋‚˜ ๋‹ค๋ฅธ ์ž‘์—…์„ ์ˆ˜ํ–‰ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

๋ผ์šฐํŠธ ๋งค๊ฐœ๋ณ€์ˆ˜์™€ ์ฟผ๋ฆฌ ๋งค๊ฐœ๋ณ€์ˆ˜

์œ„์—์„œ ์„ค๋ช…ํ•œ ๊ฒƒ์ฒ˜๋Ÿผ ์ฟผ๋ฆฌ ๋งค๊ฐœ๋ณ€์ˆ˜๋Š” ์„ ํƒ ์‚ฌํ•ญ์ด๋ฉฐ ๊ฒฝ๋กœ ๋ผ์šฐํŠธ์˜ ํ•ต์‹ฌ ๋ถ€๋ถ„์ด ์•„๋‹ˆ์ง€๋งŒ ๋ผ์šฐํŠธ ๋งค๊ฐœ๋ณ€์ˆ˜๋Š” ํ•„์ˆ˜์‚ฌํ•ญ์ž…๋‹ˆ๋‹ค!

๋ผ์šฐํŠธ ๋งค๊ฐœ๋ณ€์ˆ˜๋Š” ํ™œ์„ฑํ™”๋˜์–ด์•ผ ํ•˜๋Š” ๊ฒฝ๋กœ๋ฅผ ๊ฒฐ์ •ํ•˜๋Š” ๋ฐ ์‚ฌ์šฉ๋˜๋ฉฐ ๋ผ์šฐํŠธ ๋งค๊ฐœ๋ณ€์ˆ˜์— ๋Œ€ํ•œ ๊ตฌ์ฒด์ ์ธ ๊ฐ’(์˜ˆ: ์‹๋‹น ID)์„ ์–ป๊ธฐ ์œ„ํ•ด ๋ผ์šฐํŠธ ๋‚ด๋ถ€์—์„œ ๊ตฌ๋ฌธ ๋ถ„์„๋  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

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

 
 
 
 
 
 
 

 

 

Sources

https://yohanpro.com/posts/nodejs/error-handling

 

(NodeJS) Express ์—๋Ÿฌ ํ•ธ๋“ค๋งํ•˜๊ธฐ - Yohan's Developer Diary

์—๋Ÿฌ๊ฐ€ ๋ฐœ์ƒํ•  ๊ฒฝ์šฐ ์–ด๋–ป๊ฒŒ ๊ณตํ†ต๋กœ์ง์œผ๋กœ ์ฒ˜๋ฆฌ๋ฅผ ํ•ด์ฃผ์–ด์•ผ ํ•˜๋Š”๊ฐ€? express๋ฅผ ์ด์šฉํ•˜๋ฉด ๋ฏธ๋“ค์›จ์–ด๋ฅผ app.use()๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ์‰ฝ๊ฒŒ ๋“ฑ๋กํ•  ์ˆ˜ ์žˆ๋‹ค. ์ด๋ฅผ ์ด์šฉํ•˜๋ฉด ์—๋Ÿฌ๋ฅผ ์ฒ˜๋ฆฌํ•˜๋Š” ๋ฏธ๋“ค์›จ์–ด๋„ ์‰ฝ๊ฒŒ ์‚ฌ

yohanpro.com

https://jeonghwan-kim.github.io/node/2017/08/17/express-error-handling.html

 

์—๋Ÿฌ ์ฒ˜๋ฆฌ๋ฅผ ์œ„ํ•œ ์ต์Šคํ”„๋ ˆ์Šค ๊ฐ€์ด๋“œ

์›๋ฌธ: http://thecodebarbarian.com/80-20-guide-to-express-error-handling.html ์ต์Šคํ”„๋ ˆ์Šค์˜ ์—๋Ÿฌ ์ฒ˜๋ฆฌ ๋ฏธ๋“ค์›จ์–ด๋Š” HTTP ์‘๋‹ต ๋กœ์ง์„ ๊ฒฌ๊ณ ํ•˜๊ฒŒ ๋งŒ๋“œ๋Š” ํŒŒ์›Œํ’€ํ•œ ๋„๊ตฌ์ž…๋‹ˆ๋‹ค. ์•„๋ž˜๋Š” ์ต์Šคํ”„๋ ˆ์Šค ์ฝ”๋“œ๋กœ ์ž‘์„ฑํ•œ ์ฝ”๋“œ

jeonghwan-kim.github.io

http://expressjs.com/en/guide/error-handling.html

 

Express error handling

Error Handling Error Handling refers to how Express catches and processes errors that occur both synchronously and asynchronously. Express comes with a default error handler so you don’t need to write your own to get started. Catching Errors It’s impor

expressjs.com

https://stackoverflow.com/questions/13133071/express-next-function-what-is-it-really-for

 

Express next function, what is it really for?

Have been trying to find a good description of what the next() method does. In the Express documentation it says that next('route') can be used to jump to that route and skip all routes in between,...

stackoverflow.com

https://velog.io/@yjs_177076/next%EC%9D%98-%EC%82%AC%EC%9A%A9%EB%B2%95

 

next์˜ ์‚ฌ์šฉ๋ฒ•

๐Ÿ˜ต‍๐Ÿ’ซExpress์—์„œ ์‚ฌ์šฉํ•˜๋Š” ๋ฏธ๋“ค์›จ์–ด ํ•จ์ˆ˜๋ฏธ๋“ค์›จ์–ด ํ•จ์ˆ˜๋Š” ์š”์ฒญ ์˜ค๋ธŒ์ ํŠธ(req), ์‘๋‹ต ์˜ค๋ธŒ์ ํŠธ (res), ๊ทธ๋ฆฌ๊ณ  ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์˜ ์š”์ฒญ-์‘๋‹ต ์ฃผ๊ธฐ ์ค‘ ๊ทธ ๋‹ค์Œ์˜ ๋ฏธ๋“ค์›จ์–ด ํ•จ์ˆ˜ ๋Œ€ํ•œ ์•ก์„ธ์Šค ๊ถŒํ•œ์„ ๊ฐ–

velog.io

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/sort

 

Array.prototype.sort() - JavaScript | MDN

The sort() method sorts the elements of an array in place and returns the reference to the same array, now sorted. The default sort order is ascending, built upon converting the elements into strings, then comparing their sequences of UTF-16 code units val

developer.mozilla.org