Notice
Recent Posts
Recent Comments
Link
๊ด€๋ฆฌ ๋ฉ”๋‰ด

lgvv98

[Node.js] #6 ์ต์Šคํ”„๋ ˆ์Šค ์›น ์„œ๋ฒ„ ๋งŒ๋“ค๊ธฐ ๋ณธ๋ฌธ

๐Ÿ›ฐ๏ธ Node.js

[Node.js] #6 ์ต์Šคํ”„๋ ˆ์Šค ์›น ์„œ๋ฒ„ ๋งŒ๋“ค๊ธฐ

๐Ÿฅ• ์บ๋Ÿฟ๋งจ 2023. 7. 23. 14:25

์ต์Šคํ”„๋ ˆ์Šค ์›น ์„œ๋ฒ„ ๋งŒ๋“ค๊ธฐ

 

 

#4์—์„œ ์„œ๋ฒ„ ๋งŒ๋“ค๊ธฐ ๋ถˆํŽธํ–ˆ์„๊ฑฐ๋‹ค. ์ด์ œ ์ข€ ์‰ฌ์›Œ์ง€๋‹ˆ๊นŒ ์•Œ์•„๋ณด์ž.

 

 

# ์ต์Šคํ”„๋ ˆ์Šค ํ”„๋กœ์ ํŠธ ์‹œ์ž‘ํ•˜๊ธฐ

์šฐ์„  learn-express๋ฅผ ๋งŒ๋“ค์–ด๋ณด์ž.

npm init -y

์•„๋ž˜์ฒ˜๋Ÿผ ์ˆ˜์ •ํ•˜์ž.

{
  "name": "learn-express",
  "version": "0.0.1",
  "description": "์ต์Šคํ”„๋ ˆ์Šค๋ฅผ ๋ฐฐ์›Œ๋ณด์ž",
  "main": "app.js",
  "scripts": {
    "start": "nodemon app"
  },
  "keywords": [],
  "author": "",
  "license": "ISC",
  "dependencies": {
    "express": "^4.18.2"
  },
  "devDependencies": {
    "nodemon": "^3.0.1"
  }
}

๊ทธ ๋‹ค์Œ์—๋Š”

npm i express
npm i -D nodemon

 

script๊ฐ€ ์ƒ์„ฑ๋˜๋Š”๋ฐ ์ด ๋ถ€๋ถ„์— ๋ฐ˜๋“œ์‹œ start ์†์„ฑ์„ ๋„ฃ์–ด์ฃผ์–ด์•ผ ํ•œ๋‹ค. nodemon app์„ ํ•˜๋ฉด app.js๋ฅผ nodemon์œผ๋กœ ์‹คํ–‰ํ•œ๋‹ค๋Š” ์‹คํ–‰ํ•œ๋‹ค๋Š” ๋œป์ด๋‹ค.

 

์ฝ˜์†”์— rs๋ฅผ ์ž…๋ ฅํ•ด์„œ ์ˆ˜๋™์œผ๋กœ ์žฌ์‹œ์ž‘๋„ ๊ฐ€๋Šฅ.

nodemon์€ ๊ฐœ๋ฐœ์šฉ์œผ๋กœ๋งŒ ์‚ฌ์šฉํ•  ๊ฒƒ์„ ๊ถŒ์žฅ.

 

์„œ๋ฒ„์˜ ์—ญํ• ์„ ํ•  app.js์„ ์ž‘์„ฑ

const express = require('express');

const app = express();
app.set('port', process.env.PORT || 3000); // env์— ํฌํŠธ๊ฐ’ ์žˆ์œผ๋ฉด ์‚ฌ์šฉํ•˜๊ณ ์•„๋‹ˆ๋ฉด 3000๋ฒˆ
// app.set(ํ‚ค, ๊ฐ’) ํ†ตํ•ด์„œ ๋ฐ์ดํ„ฐ ์ €์žฅ
// app.get(ํ‚ค, ๊ฐ’)์œผ๋กœ ๋‚˜์ค‘์— ์ฝ์Œ

app.get('/', (req, res) => { 
    res.send('Hello World');
});

app.listen(app.get('port'), () => { 
    console.log(app.get('port'), '๋นˆ ํฌํŠธ์—์„œ ๋Œ€๊ธฐ์ค‘');
});

 

 

์œ„์—๋ฅผ html ํŽ˜์ด์ง€๋ฅผ ๋„ฃ์–ด์„œ ๋ฐ”๊ฟ”๋ณด์ž.

 

// index.html
<html>
    <head>
        <meta charset="UTF-8" />
        <title>์ต์Šคํ”„๋ ˆ์Šค ์„œ๋ฒ„</title>
    </head>
    <body>
        <h1>Express</h1>
        <p>๋ฐฐ์›Œ๋ด…์‹œ๋‹ค.</p>
    </body>
</html>

// app.js
const express = require('express');
const path = require('path');

const app = express();
app.set('port', process.env.PORT || 3000);

app.get('/', (req, res) => { 
    // res.send('Hello World');
    res.sendFile(path.join(__dirname, 'index.html'));
});

app.listen(app.get('port'), () => { 
    console.log(app.get('port'), '๋นˆ ํฌํŠธ์—์„œ ๋Œ€๊ธฐ์ค‘');
});

ํฌํฌ ํ•™๊ต ๋‹ค๋‹ ๋•Œ ์™ธ์— ์ด๊ฑธ ๋‹ค์‹œ ๋ณด๋‹ค๋‹ˆ ์˜๋กฑํ•˜๋‹ค!

 

์˜๋กฑํ•˜๋‹ค!

 

# ์ž์ฃผ ์‚ฌ์šฉํ•˜๋Š” ๋ฏธ๋“ค์›จ์–ด

 

๋ฏธ๋“ค์›จ์–ด๋Š” ์ต์Šคํ”„๋ ˆ์Šค์˜ ํ•ต์‹ฌ์ด๋‹ค.

 

๋ฏธ๋“ค์›จ์–ด๋Š” app.use์™€ ํ•จ๊ป˜ ์‚ฌ์šฉ๋œ๋‹ค.

// app.js
const express = require('express');
const path = require('path');

const app = express();
app.set('port', process.env.PORT || 3000);

// โœ…
app.use('/', (req, res, next) => {
	console.log('๋ชจ๋“  ์š”์ฒญ์— ๋‹ค ์‹คํ–‰๋œ๋‹ค.');
    next();
});

// โœ…
app.get('/', (req, res, next) => {
	console.log('GET ์š”์ฒญ์—์„œ๋งŒ ์‹คํ–‰๋œ๋‹ค.');
    next();
}, (req, res) => { 
	throw new Error('์—๋Ÿฌ๋Š” ์—๋Ÿฌ ์ฒ˜๋ฆฌ ๋ฏธ๋“ค์›จ์–ด๋กœ ๊ฐ‘๋‹ˆ๋‹ค.');
});

// โœ…
app.use((err, req, res, next) => {
	console.error(err);
    res.status(500).send(err.message);
});

app.listen(app.get('port'), () => {
  console.log(app.get('port'), '๋ฒˆ ํฌํŠธ์—์„œ ๋Œ€๊ธฐ ์ค‘');
});

 

app.use์—์„œ๋Š” req, res, nextํ•จ์ˆ˜๋ฅผ ๋„ฃ์œผ๋ฉด ๋œ๋‹ค. ๋ฏธ๋“ค์›จ์–ด๋Š” ์œ„์—์„œ๋ถ€ํ„ฐ ์•„๋ž˜๋กœ ์ˆœ์„œ๋Œ€๋กœ ์‹คํ–‰๋˜๋ฉด์„œ ์š”์ฒญ๊ณผ ์‘๋‹ต ์‚ฌ์ด์— ํŠน๋ณ„ํ•œ ๊ธฐ๋Šฅ์„ ์ถ”๊ฐ€ํ•  ์ˆ˜ ์žˆ์Œ. ์ด๋ฒˆ์—๋Š” next๋ผ๋Š” ์ƒˆ๋ฒˆ์งธ ๋งค๊ฐœ๋ณ€์ˆ˜๋ฅผ ์‚ฌ์šฉํ–ˆ๋Š”๋ฐ, ๋‹ค์Œ ๋ฏธ๋“ค์›จ์–ด๋กœ ๋„˜์–ด๊ฐ€๋Š” ํ•จ์ˆ˜. next๋ฅผ ์‹คํ–‰ํ•˜์ง€ ์•Š์œผ๋ฉด ๋‹ค์Œ ๋ฏธ๋“ค์›จ์–ด๊ฐ€ ์‹คํ–‰๋˜์ง€ ์•Š์Œ.

 

์ฃผ์†Œ๋ฅผ ์ฒซ๋ฒˆ์งธ ์ธ์ˆ˜๋กœ ๋„ฃ์–ด์ฃผ์ง€ ์•Š๋Š”๋‹ค๋ฉด ๋ฏธ๋“ค์›จ์–ด๋Š” ๋ชจ๋“  ์š”์ฒญ์—์„œ ์‹คํ–‰๋˜๊ณ , ์ฃผ์†Œ๋ฅผ ๋„ฃ๋Š”๋‹ค๋ฉด ํ•ด๋‹นํ•˜๋Š” ์š”์ฒญ์—์„œ๋งŒ ์‹คํ–‰๋œ๋‹ค๊ณ  ๋ด„.

 

app.use(๋ฏธ๋“ค์›จ์–ด): ๋ชจ๋“  ์š”์ฒญ์—์„œ ๋ฏธ๋“ค์›จ์–ด ์‹คํ–‰

app.use('/abc', ๋ฏธ๋“ค์›จ์–ด): abc๋กœ ์‹œ์ž‘ํ•˜๋Š” ์š”์ฒญ์—์„œ ๋ฏธ๋“ค์›จ์–ด ์‹คํ–‰

app.post('/abc', ๋ฏธ๋“ค์›จ์–ด): abc๋กœ ์‹œ์ž‘ํ•˜๋Š” POST ์š”์ฒญ์—์„œ ๋ฏธ๋“ค์›จ์–ด ์‹คํ–‰

 

app.use๋‚˜ app.get ๊ฐ™์€ ๋ผ์šฐํ„ฐ์— ๋ฏธ๋“ค์›จ์–ด๋ฅผ ์—ฌ๋Ÿฌ๊ฐœ๋ฅผ ์žฅ์ฐฉํ•  ์ˆ˜ ์žˆ๋‹ค.

app.get ๋ผ์šฐํ„ฐ์— ๋ฏธ๋“ค์›จ์–ด๊ฐ€ ๋‘ ๊ฐœ ์—ฐ๊ฒฐ๋˜์–ด ์žˆ์Œ. ๋‹ค๋งŒ ์ด๋•Œ๋„ next๋ฅผ ํ˜ธ์ถœํ•ด์•ผ ๋‹ค์Œ ๋ฏธ๋“ค์›จ์–ด๋กœ ๋„˜์–ด๊ฐˆ ์ˆ˜ ์žˆ๋‹ค.

 

์—๋Ÿฌ์ฒ˜๋ฆฌ!! ๋งค๊ฐœ๋ณ€์ˆ˜๋Š” ๋„ค ๊ฐœ๋‹ค. ๋ชจ๋“  ๋งค๊ฐœ๋ณ€์ˆ˜๋ฅผ ์‚ฌ์šฉํ•˜์ง€ ์•Š๋”๋ผ๋„ ๋งค๊ฐœ๋ณ€์ˆ˜๊ฐ€ ๋ฐ˜๋“œ์‹œ ๋„ค ๊ฐœ์—ฌ์•ผ ํ•œ๋‹ค. 

res.status ๋ฉ”์„œ๋“œ๋กœ HTTP ์ƒํƒœ ์ฝ”๋“œ๋ฅผ ์ง€์ •ํ•  ์ˆ˜ ์žˆ๋”ฐ. ๊ธฐ๋ณธ๊ฐ’์€ 200์ด๋ฉฐ ์‹ค๋ฌด์—์„œ๋Š” ์ง์ ‘ ์—๋Ÿฌ ์ฒ˜๋ฆฌ ๋ฏธ๋“ค์›จ์–ด๋ฅผ ์—ฐ๊ฒฐํ•ด์ฃผ๋Š”๊ฒŒ ์ข‹๋‹ค. ์—๋Ÿฌ์ฒ˜๋ฆฌ ๋ฏธ๋“ค์›จ์–ด๋Š” ํŠน๋ณ„ํ•œ ๊ฒฝ์šฐ ์•„๋‹ˆ๋ฉด ๊ฐ€์žฅ ์•„๋ž˜์— ์œ„ใ…Šํ•˜๋„๋ก ํ•œ๋‹ค.

 

๋ฏธ๋“ค์›จ์–ด๋ฅผ ํ†ตํ•ด ์š”์ฒญ๊ณผ ์‘๋‹ต์— ๋Œ€ํ•œ ๊ธฐ๋Šฅ์„ ์ถ”๊ฐ€ํ•  ์ˆ˜ ์žˆ๊ณ , ์‹ค๋ฌด์— ์ž์ฃผ ์‚ฌ์šฉํ•˜๋Š” ํŒจํ‚ค์ง€๋“ค์„ ์„ค์น˜ํ•ด๋ด…์‹œ๋‹ค.

npm i morgan cookie-parser express-session dotenv

 

dotenv ํŒจํ‚ค์ง€๋Š” .env ํŒŒ์ผ์„ ์ฝ์–ด์„œ precess.env๋กœ ๋งŒ๋“ญ๋‹ˆ๋‹ค. process.env.COOKIE_SECRET์— cookiesecret ๊ฐ’์ด ํ• ๋‹น๋œ๋‹ค. 

ํ‚ค=๊ฐ’ ํ˜•์‹์œผ๋กœ ์ถ”๊ฐ€ํ•˜๋ฉด ๋œ๋‹ค. process.env๋ฅผ ๋ณ„๋„์˜ ํŒŒ์ผ๋กœ ๊ด€๋ฆฌํ•˜๋Š”๊ฑด ๋ณด์•ˆ๊ณผ ์„ค์ •์˜ ํŽธ์˜์„ฑ

๋น„๋ฐ€ ํ‚ค๋“ค์„ ์†Œ์Šค ์ฝ”๋“œ์— ๊ทธ๋Œ€๋กœ ์ ์–ด๋‘๋ฉด ์†Œ์Šค ์ฝ”๋“œ๊ฐ€ ์œ ์ถœ๋˜์—ˆ์„ ๋•Œ๋„ ํ‚ค๋„ ๊ฐ™์ด ์œ ์ถœ ๋”ฐ๋ผ์„œ .env ๊ฐ™์€ ๋ณ„๋„์˜ ํŒŒ์ผ์— ๋น„๋ฐ€ํ‚ค๋ฅผ ์ ์–ด๋‘๊ณ  ๊ด€๋ฆฌํ•จ ์†Œ์Šค์ฝ”๋“œ๊ฐ€ ์œ ์ถœ๋˜๋”๋ผ๋„ .envํŒŒ์ผ๋งŒ ์ž˜ ๊ด€๋ฆฌํ•˜๋ฉด ์ง€ํ‚ฌ ์ˆ˜ ์žˆ๋‹ค.

 

// .env
COOKIE_SECRET=cookiesecret

 

์•„๋ž˜ ์ฝ”๋“œ๋ฅผ ์ž‘์„ฑํ•ด๋ณด์ž

// app.js
const express = require('express');
const morgan = require('morgan');
const cookieParser = require('cookie-parser');
const session = require('express-session');
const dotenv = require('dotenv');
const path = require('path');

dotenv.config(); // โœ… ์„ค์ •
const app = express();
app.set('port', process.env.PORT || 3000);

app.use(morgan('dev'));
app.use('/', express.static(path.join(__dirname, 'public')));
app.use(express.json());
app.use(express.urlencoded({ extended: false }));
app.use(cookieParser(process.env.COOKIE_SECRET));
app.use(session({
  resave: false,
  saveUninitialized: false,
  secret: process.env.COOKIE_SECRET,
  cookie: {
    httpOnly: true,
    secure: false,
  },
  name: 'session-cookie',
}));

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

try {
  fs.readdirSync('uploads');
} catch (error) {
  console.error('uploads ํด๋”๊ฐ€ ์—†์–ด uploads ํด๋”๋ฅผ ์ƒ์„ฑํ•ฉ๋‹ˆ๋‹ค.');
  fs.mkdirSync('uploads');
}
const upload = multer({
  storage: multer.diskStorage({
    destination(req, file, done) {
      done(null, 'uploads/');
    },
    filename(req, file, done) {
      const ext = path.extname(file.originalname);
      done(null, path.basename(file.originalname, ext) + Date.now() + ext);
    },
  }),
  limits: { fileSize: 5 * 1024 * 1024 },
});
app.get('/upload', (req, res) => {
  res.sendFile(path.join(__dirname, 'multipart.html'));
});
app.post('/upload', upload.single('image'), (req, res) => {
  console.log(req.file);
  res.send('ok');
});

app.get('/', (req, res, next) => {
  console.log('GET / ์š”์ฒญ์—์„œ๋งŒ ์‹คํ–‰๋ฉ๋‹ˆ๋‹ค.');
  next();
}, (req, res) => {
  throw new Error('์—๋Ÿฌ๋Š” ์—๋Ÿฌ ์ฒ˜๋ฆฌ ๋ฏธ๋“ค์›จ์–ด๋กœ ๊ฐ‘๋‹ˆ๋‹ค.')
});
app.use((err, req, res, next) => {
  console.error(err);
  res.status(500).send(err.message);
});

app.listen(app.get('port'), () => {
  console.log(app.get('port'), '๋ฒˆ ํฌํŠธ์—์„œ ๋Œ€๊ธฐ ์ค‘');
});

 

# morgan

morgan ์—ฐ๊ฒฐ ํ›„, ๊ธฐ์กด ๋กœ๊ทธ ์™ธ์— ์ถ”๊ฐ€์ ์ธ ๋กœ๊ทธ๋ฅผ ๋ณผ ์ˆ˜ ์žˆ์Œ.

3000๋ฒˆ ํฌํŠธ์—์„œ ๋Œ€๊ธฐ ์ค‘
๋ชจ๋“  ์š”์ฒญ์— ๋‹ค ์‹คํ–‰๋œ๋‹ค.
GET / ์š”์ฒญ์—์„œ๋งŒ ์‹คํ–‰๋ฉ๋‹ˆ๋‹ค.
Error: ์—๋Ÿฌ๋Š” ์—๋Ÿฌ ์ฒ˜๋ฆฌ ๋ฏธ๋“ค์›จ์–ด๋กœ ๊ฐ‘๋‹ˆ๋‹ค.
// ์—๋Ÿฌ ์Šคํƒ ํŠธ๋ ˆ์ด์Šค ์ƒ๋žต
GET / 500 6.332 ms - 50

 

๋งจ ์•„๋ž˜ ๋กœ๊ทธ๋Š” morgan ๋ฏธ๋“ค์›จ์–ด์—์„œ ๋‚˜์˜ค๋Š” ๊ฒƒ์ด๋‹ค. ์š”์ฒญ๊ณผ ์‘๋‹ต์— ๋Œ€ํ•œ ์ •๋ณด๋ฅผ ์ฝ˜์†”์— ๊ธฐ๋ก

morgan ๋ฏธ๋“ค์›จ์–ด๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™์ด ์‚ฌ์šฉ

app.use(morgan('dev'));

 

์ธ์ˆ˜๋กœ dev ์™ธ์— combined, common, short, tiny ๋“ฑ์„ ๋„ฃ์„ ์ˆ˜ ์žˆ๋‹ค. 

๊ฐœ๋ฐœํ™˜๊ฒฝ์€ dev, ๋ฐฐํฌํ™˜๊ฒฝ์€ combined

 

 # static

static ๋ฏธ๋“ค์›จ์–ด๋Š” ์ •์ ์ธ ํŒŒ์ผ๋“ค์„ ์ œ๊ณตํ•˜๋Š” ๋ผ์šฐํ„ฐ ์—ญํ• ์„ ํ•œ๋‹ค.

๊ธฐ๋ณธ์ ์œผ๋กœ ์ œ๊ณต๋˜๊ธฐ์— ๋”ฐ๋กœ ์„ค์น˜ํ•  ํ•„์š” ์—†์ด express ๊ฐ์ฒด ์•ˆ์—์„œ ๊บผ๋‚ด ์žฅ์ฐฉํ•˜๋ฉด ๋œ๋‹ค.

 

app.use('์š”์ฒญ ์ •๋ณด', express.static('์‹ค์ œ ๊ฒฝ๋กœ'));

app.use('/', express.static(path.join(__dirname, 'public'));

 

ํ•จ์ˆ˜์˜ ์ธ์ˆ˜๋กœ ์ •์  ํŒŒ์ผ๋“ค์ด ๋‹ด๊ฒจ ์žˆ๋Š” ํด๋”๋ฅผ ์ง€์ •ํ•˜๋ฉด ๋ฉ๋‹ˆ๋‹ค. 

์˜ˆ๋ฅผ ๋“ค์–ด public/stylesheet/style.css๋Š” http://localhost:3000/stylesheets/style.css๋กœ ์ ‘๊ทผํ•  ์ˆ˜ ์žˆ์Œ.

 

์‹ค์ œ ์„œ๋ฒ„์˜ ํด๋” ๊ฒฝ๋กœ์—๋Š” public์ด ๋“ค์–ด ์žˆ์ง€๋งŒ ์š”์ฒญ ์ฃผ์†Œ์—๋Š” ์—†๋Š”๋ฐ ์š”์ฒญ ๊ฒฝ๋กœ๊ฐ€ ๋‹ค๋ฅด๋ฏ€๋กœ ์™ธ๋ถ€์ธ์ด ์„œ๋ฒ„์˜ ๊ตฌ์กฐ๋ฅผ ์‰ฝ๊ฒŒ ํŒŒ์•…ํ•  ์ˆ˜ ์žˆ์Œ.

 

๋˜ํ•œ, fs.readFile์„ ํŒŒ์ผ์„ ์ง์ ‘ ์ฝ์–ด์„œ ์ „์†กํ•  ํ•„์š”๊ฐ€ ์—†์Œ. ๋งŒ์•ฝ ์š”์ฒญ ๊ฒฝ๋กœ์— ํ•ด๋‹นํ•˜๋Š” ํŒŒ์ผ์ด ์—†์œผ๋ฉด ์•Œ์•„์„œ ๋‚ด๋ถ€์ ์œผ๋กœ next๋ฅผ ํ˜ธ์ถœ ํŒŒ์ผ ๋ฐœ๊ฒฌํ•˜๋ฉด ๋ฏธ๋“ค์›จ์–ด๋Š” ์‹คํ–‰์•ˆ๋ผ ์‘๋‹ต์œผ๋กœ ํŒŒ์ผ ๋ณด๋‚ด๊ณ  next๋ฅผ ํ˜ธ์ถœํ•˜์ง€ ์•Š์Œ.

 

 #  body-parser

์š”์ฒญ์˜ ๋ณธ๋ฌธ์— ์žˆ๋Š” ๋ฐ์ดํ„ฐ๋ฅผ ํ•ด์„ํ•ด์„œ req.body ๊ฐ์ฒด๋กœ ๋งŒ๋“ค์–ด์ค€๋‹ค. 

๋ณดํ†ต ํผ ๋ฐ์ดํ„ฐ๋‚˜ AJAX ์š”์ฒญ์˜๋ฐ์ดํ„ฐ๋ฅผ ์ฒ˜๋ฆฌ. ๋‹จ, ๋ฉ€ํ‹ฐํŒŒํŠธ(์ด๋ฏธ์ง€, ๋™์˜์ƒ, ํŒŒ์ผ) ๋ฐ์ดํ„ฐ ์ฒ˜๋ฆฌํ•˜์ง€ ๋ชปํ•จ.

์ด ๊ฒฝ์šฐ์—๋Š” ๋’ค์— ๋‚˜์˜ค๋Š” multer ๋ชจ๋“ˆ์„ ์‚ฌ์šฉํ•˜๋ฉด ๋œ๋‹ค.

 

body-parser๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™์ด ์‚ฌ์šฉํ•˜๋ฉด ๋œ๋‹ค.

app.use(express.join());
app.use(express.urlencoded({ extended: false }));

 

 

์•„๋ž˜๋Š” ์š”์ฒญ ๋ฐ์ดํ„ฐ์˜ ์ข…๋ฅ˜๋‹ค.

const bodyParser = require('body-parser');

app.use(bodyParser.raw());
app.use(bodyParser.text());

์š”์ฒญ ๋ฐ์ดํ„ฐ ์ข…๋ฅ˜์— ๋Œ€ํ•ด ์‚ดํŽด๋ณด์ž.

JSON์€ JSONํ˜•์‹์— ๋”ฐ๋ผ URL-encoded๋Š” ์ฃผ์†Œ ํ˜•์‹์œผ๋กœ ๋ฐ์ดํ„ฐ๋ฅผ ๋ณด๋‚ด๋Š” ๋ฐฉ์‹ ํผ ์ „์†ก์€ URL-encoded ๋ฐฉ์‹์„ ์ฃผ๋กœ ์‚ฌ์šฉ

urlencoded ๋ฉ”์„œ๋“œ๋ฅผ ๋ณด๋ฉด { extended: false }๋ผ๋Š” ์˜ต์…˜์ด ๋“ค์–ด ์žˆ๋‹ค.

์ด ์˜ต์…˜์ด false์ด๋ฉด ๋…ธ๋“œ์˜ querystring ๋ชจ๋“ˆ์„ ์‚ฌ์šฉํ•ด ์ฟผ๋ฆฌ์ŠคํŠธ๋ง์„ ํ•ด์„ํ•˜๊ณ , qs ๋ชจ๋“ˆ์€ npm์„ ํ†ตํ•ด ์‚ฌ์šฉํ•˜๋Š” ๋ชจ๋“ˆ

 

POST์™€ PUT์š”์ฒญ์—์„œ ๋ณธ๋ฌธ ๋ฐ›์œผ๋ฉด req.on('data') req.end('data) ํ–ˆ๋˜๊ฑฐ ๊ธฐ์–ต๋‚จ?

๋ฐ”๋”” ํŒŒ์„œ ์‚ฌ์šฉํ•˜๋ฉด ์•ˆํ•ด๋„ ๋ผ

 

 #  cookie-parser

์š”์ฒญ์— ๋™๋ด‰๋œ ์ฟ ๋ฆฌ๋ฅผ ํ•ด์„ํ•ด req.cookies ๊ฐ์ฒด๋กœ ๋งŒ๋“ ๋‹ค.

 

app.use(cookieParser(๋น„๋ฐ€ ํ‚ค));

 

์˜ˆ๋ฅผ๋“ค์–ด name=lgvv ์ฟ ํ‚ค๋ฅผ ๋ณด๋ƒˆ๋‹ค๋ฉด, { name: 'lgvv' }๊ฐ€ ๋œ๋‹ค. ์œ ํšจ ๊ธฐ๊ฐ„์ด ์ง€๋‚œ ์ฟ ํ‚ค๋Š” ์•Œ์•„์„œ ๊ฑธ๋Ÿฌ๋‚ธ๋‹ค.

์ฒซ๋ฒˆ์งธ์ธ์ˆ˜๋กœ ๋น„๋ฐ€ํ‚ค๋ฅผ ๋„ฃ์–ด์ค„ ์ˆ˜ ์žˆ๋‹ค.

 

res.cookie('name', 'lgvv', { 
	expires: new Date(Date.now() + 90000),
    httpOnly: true,
    secure: true,
});

res.clearCookie('name', 'lgvv', { httpOnly: true, secure: true });

 

 ์ฟ ํ‚ค๋ฅผ ์ง€์šฐ๋ ค๋ฉด ํ‚ค ๊ฐ’ ์™ธ์— ์˜ต์…˜๋งˆ์ €๋„ ์ •ํ™•ํžˆ ์ผ์น˜ํ•ด์•ผ ๋งŒ๋“œ๋ ์ง„๋‹ค. ๋‹จ expires๋‚˜ maxAge ์˜ต์…˜์€ ์ผ์น˜ํ•  ํ•„์š” ์—†์Œ.

์˜ต์…˜ ์ค‘์—๋Š” signed๋ผ๋Š” ์˜ต์…˜์ด ์žˆ๋Š”๋ฐ, ์ด๋ฅผ true๋กœ ์„ค์ •ํ•˜๋ฉด ์ฟ ํ‚ค ๋’ค์— ์„œ๋ช…์ด ๋ถ™๋Š”๋‹ค. ๋‚ด ์„œ๋ฒ„๊ฐ€ ์ฟ ํ‚ค๋ฅผ ๋งŒ๋“ค์—ˆ๋‹ค๋Š” ๊ฒƒ์„ ๊ฒ€์ฆํ•  ์ˆ˜ ์žˆ์œผ๋ฏ€๋กœ ๋Œ€๋ถ€๋ถ„์˜ ๊ฒฝ์šฐ ์„œ๋ช… ์˜ต์…˜์„ ์ผœ๋‘๋Š” ๊ฒƒ์ด ์ข‹๋‹ค. ์„œ๋ช…์„ ์œ„ํ•œ ๋น„๋ฐ€ ํ‚ค๋Š” cookieParser ๋ฏธ๋“ค์›จ์–ด์— ์ธ์ˆ˜๋กœ ๋„ฃ์€ process.env.COOKIE_SECRET์ด ๋ฉ๋‹ˆ๋‹ค.

 

 #  express-session

์„ธ์…˜ ๊ด€๋ฆฌ์šฉ ๋ฏธ๋“ค์›จ์–ด. ๋กœ๊ทธ์ธ ๋“ฑ์˜ ์ด์œ ๋กœ ์„ธ์…˜์„ ๊ตฌํ˜„ํ•˜๊ฑฐ๋‚˜ ํŠน์ • ์‚ฌ์šฉ์ž๋ฅผ ์œ„ํ•œ ๋ฐ์ดํ„ฐ ์ž„์‹œ์ ์œผ๋กœ ์ €์žฅํ•ด๋‘˜ ๋•Œ ๋งค์šฐ ์œ ์šฉ. ์„ธ์…˜์€ ์‚ฌ์šฉ์ž๋ณ„๋กœ req.session ๊ฐ์ฒด ์•ˆ์— ์œ ์ง€๋œ๋‹ค.

 

app.use(session({
	resave: false, // โœ… ์š”์ฒญ์ด ๋“ค์–ด์˜ฌ ๋•Œ ์„ธ์…˜์— ์ˆ˜์ •์‚ฌํ•ญ ์ƒ๊ธฐ์ง€ ์•Š๋”๋ผ๋„ ์„ธ์…˜์„ ๋‹ค์‹œ ์ €์žฅํ• ์ง€ ์„ค์ •
    saveUninitialized: false, // โœ… ์„ธ์…˜์— ์ €์žฅํ•  ๋‚ด์—ญ์ด ์—†๋”๋ผ๋„ ์„ธ์…˜์„ ์žฌ์‹œ์ž‘ํ• ์ง€ ์„ค์ •
    secret: process.env.COOKIE_SECRET, // โœ… ์„ธ์…˜ ๊ด€๋ฆฌ์‹œ ํด๋ผ์ด์–ธํŠธ์— ์ฟ ํ‚ค
    cookie: { // โœ… ์ผ๋ฐ˜์ ์ธ ์ฟ ํ‚ค ์˜ต์…˜์„ ์ œ๊ณต
    	httpOnly: true, // โœ… ํด๋ผ์ด์–ธํŠธ์—์„œ ์ฟ ํ‚ค ํ™•์ธ ๋ชปํ•˜๊ฒŒ
        secure: false, // โœ… https์ ์šฉ์—ฌ๋ถ€
    },
	name: 'session-cookie', // โœ… env ๊ฐ’
}));

์˜ˆ์ œ์—๋Š” ์—†์ง€๋งŒ store๋ผ๋Š” ์˜ต์…˜์ด ์žˆ๋Š”๋ฐ ๋ฉ”๋ชจ๋ฆฌ๊ฐ€ ์ดˆ๊ธฐํ™”๋˜์–ด ์„ธ์…˜์ด ๋ชจ๋‘ ์‚ฌ๋ผ์ง€๋”๋ผ๋„ store์— ๋ฐ๋ฒ ๋ฅผ ์—ฐ๊ฒฐํ•ด ์„ธ์…˜์„ ์œ ์ง€ํ•˜๋Š”๊ฒƒ์ด ์ข‹๋‹ค.

๋ณดํ†ต ๋ ˆ๋””์Šค๊ฐ€ ์“ฐ์ž„.

store.session.name = 'lgvv'; // ์„ธ์…˜ ๋“ฑ๋ก
req.sessionID; // ์„ธ์…˜ ์•„์ด๋”” ํ™•์ธ
req.session.destroy(); // ์„ธ์…˜ ๋ชจ๋‘ ์ œ๊ฑฐ

 

 #  ๋ฏธ๋“ค์›จ์–ด์˜ ํŠน์„ฑ ํ™œ์šฉํ•˜๊ธฐ

๋ฏธ๋“ค์›จ์–ด๋ฅผ ์ง์ ‘ ๋งŒ๋“ค์–ด๋ณด๊ธฐ๋„ ํ–ˆ๊ณ , ๋‹ค๋ฅธ ์‚ด๋งˆ์ด ๋งŒ๋“  ๋ฏธ๋“ค์›จ์–ด ํŒจํ‚ค์ง€๋ฅผ ์„ค์น˜ํ•ด ์žฅ์ฐฉํ•ด๋ณด๊ธฐ๋„ ํ•จ.

์ด๋ฒˆ์—๋Š” ๊ทธ ํŠน์„ฑ์„ ์ •๋ฆฌํ•ด ๋ณผ ์˜ˆ์ •.

 

app.use((req, res, next) => { 
	console.log('๋ชจ๋“  ์š”์ฒญ์— ๋‹ค ์‹คํ–‰๋œ๋‹ค.');
    next();
});

๋ฏธ๋“ค์›จ์–ด๋Š” req, res, next๋ฅผ ๊ฐ–๋Š” ํ•จ์ˆ˜๋กœ์จ app.use๋‚˜ app.get, app.post ๋“ฑ์œผ๋กœ ์žฅ์ฐฉํ•œ๋‹ค. ํŠน์ •ํ•œ ์ฃผ์†Œ์˜ ์š”์ฒญ์—๋งŒ ๋ฏธ๋“ค์›จ์–ด๊ฐ€ ์‹คํ–‰๋˜๊ฒŒ ํ•˜๋ ค๋ฉด ์ฒซ๋ฒˆ์งธ ์ธ์ˆ˜๋กœ ์ฃผ์†Œ๋ฅผ ๋„ฃ์œผ๋ฉด ๋œ๋‹ค.

 

app.use(
	morgan('dev');
    express.static('/', path.join(__dirname, 'public');
	express.json();
    express.urlencoded({ extended: false }),
    cookeParser(precess.env.COOKIE_SECRET),
);

 

์œ„์™€ ๊ฐ™์ด ์—ฌ๋Ÿฌ๊ฐœ์˜ ๋ฏธ๋“ค์›จ์–ด๋ฅผ ์žฅ์ฐฉํ•  ์ˆ˜ ์žˆ์œผ๋ฉฐ, ๋‹ค์Œ ๋ฏธ๋“ค์›จ์–ด๋กœ ๋„˜์–ด๊ฐ€๋ ค๋ฉด ํ•จ์ˆ˜๋ฅผ ํ˜ธ์ถœํ•ด์•ผ ํ•œ๋‹ค.

์œ„ ๋ฏธ๋“ค์›จ์–ด๋“ค์€ ๋‚ด๋ถ€์ ์œผ๋กœ next()๋ฅผ ํ˜ธ์ถœํ•˜๊ณ  ์žˆ์œผ๋ฏ€๋กœ ์—ฐ๋‹ฌ์•„ ์“ธ ์ˆ˜ ์žˆ๋‹ค.

 

next๋ฅผ ํ˜ธ์ถœํ•˜์ง€ ์•Š๋Š” ๋ฏธ๋“ค์›จ์–ด๋Š” res.send๋‚˜ res.sendFile ๋“ฑ์˜ ๋ฉ”์„œ๋“œ๋กœ ์‘๋‹ต์œผ ๋ณด๋‚ด์•ผ ํ•œ๋‹ค.

 

express.static๊ณผ ๊ฐ™์€ ๋ฏธ๋“ค์›จ์–ด๋Š” ์ •์  ํŒŒ์ผ์„ ์ œ๊ณตํ•  ๋•Œ next ๋Œ€์‹  res.sendFile ๋ฉ”์„œ๋“œ๋กœ ์‘๋‹ต์„ ๋ณด๋ƒ…๋‹ˆ๋‹ค.

๋”ฐ๋ผ์„œ ์ •์  ํŒŒ์ผ์„ ์ œ๊ณตํ•˜๋Š” ๊ฒฝ์šฐ expree.json์ด๋‚˜ express.urlencoded, cookieParser ๋ฏธ๋“ค์›จ์–ด๋Š” ์‹คํ–‰๋˜์ง€ ์•Š๋Š”๋‹ค.

 

๋ฏธ๋“ค์›จ์–ด ์žฅ์ฐฉ ์ˆœ์„œ์— ๋”ฐ๋ผ ์–ด๋–ค ๋ฏธ๋“ค์›จ์–ด๋Š” ์‹คํ–‰๋˜์ง€ ์•Š์„์ˆ˜๋„ ์žˆ๋‹ค.

next์— ์ธ์ˆ˜๋ฅผ ๋„ฃ์„์ˆ˜๋„ ์žˆ์Œ

next('route')๋ผ๋Š” ์ธ์ˆ˜๋ฅผ ๋„ฃ์œผ๋ฉฐ ๋‹ค์Œ ๋ผ์šฐํ„ฐ์˜ ๋ฏธ๋“ค์›จ์–ด๋กœ ๋ฐ”๋กœ ์ด๋™ํ•˜๊ณ , ๊ทธ ์™ธ์˜ ์ธ์ˆ˜๋ฅผ ๋„ฃ๋Š”๋‹ค๋ฉด ๋ฐ”๋กœ ์—๋Ÿฌ ์ฒ˜๋ฆฌ ๋ฏธ๋“ค์›จ์–ด๋กœ ์ด๋™.

 

next(error) ๋‹ค์Œ ์—๋Ÿฌ ํ•ธ๋“ค๋Ÿฌ๋กœ ๋ณด๋ƒ„

 

(err, req, res, enxt) => { }

 

๋ฏธ๋“ค์›จ์–ด ๊ฐ„ ๋ฐ์ดํ„ฐ๋ฅผ ์ „๋‹ฌํ•˜๋Š” ๋ฐฉ๋ฒ•๋„ ์žˆ์Œ. ์„ธ์…˜์„ ์‚ฌ์šฉํ•œ๋‹ค๋ฉด req.session ๊ฐ์ฒด์— ๋ฐ์ดํ„ฐ๋ฅผ ๋„ฃ์–ด๋„ ๋˜์ง€๋งŒ, ์„ธ์…˜์ด ์œ ์ง€๋˜๋Š” ๋™์•ˆ์— ๋ฐ์ดํ„ฐ๋„ ๊ณ„์† ์œ ์ง€๋œ๋‹ค๋Š” ๋‹จ์ ์ด ์žˆ๋‹ค.

๋งŒ์•ฝ ์š”์ฒญ์ด ๋๋‚  ๋•Œ ๊นŒ์ง€๋งŒ ๋ฐ์ดํ„ฐ๋ฅผ ์œ ์ง€ํ•˜๊ณ  ์‹ถ๋‹ค๋ฉด res.locals ๊ฐ์ฒด์— ๋ฐ์ดํ„ฐ๋ฅผ ๋„ฃ์–ด๋‘๋ฉด ๋œ๋‹ค.

app.use((req, res, next) => { 
	res.locals.data = '๋ฐ์ดํ„ฐ ๋„ฃ๊ธฐ';
    next();
}, (req, res, next) => { 
	console.log(res.locals.data); // ๋ฐ์ดํ„ฐ ๋ฐ›๊ธฐ
    next();
});

์š”์ฒญ์ด ์ฒ˜๋ฆฌ๋˜๋Š” ๋™์•ˆ res.locals ๊ฐ์ฒด๋ฅผ ํ†ตํ•ด ๋ฏธ๋“ค์›จ์–ด ๊ฐ„์— ๋ฐ์ดํ„ฐ๋ฅผ ๊ณต์œ ํ•  ์ˆ˜ ์žˆ์Œ.

์ƒˆ๋กœ์šด ์š”์ฒญ์ด ๋“ค์–ด์˜ค๋ฉด res.locals๋Š” ์ดˆ๊ธฐํ™” ๋œ๋‹ค.

 

app.set๊ณผ์˜ res.locals์˜ ์ฐจ์ด.

app.get, req.app.get์œผ๋กœ ์–ด๋””์„œ๋“ ์ง€ ๋ฐ์ดํ„ฐ๋ฅผ ๊ฐ€์ ธ์˜ฌ ์ˆ˜ ์žˆ์Œ. ํ•˜์ง€๋งŒ app.set์„ ํ•˜์ง€ ์•Š๊ณ ์„œ res.locals ๊ฐ์ฒด์— ๋ฐ์ดํ„ฐ๋ฅผ ๋„ฃ์–ด์„œ ๋ฏธ๋“ค์›จ์–ด๋กœ ์ „๋‹ฌํ•˜๋Š” ์ด์œ ๊ฐ€ ์žˆ์Œ. app.set์€ ์ต์Šคํ”„๋ ˆ์Šค์—์„œ ์ „์—ญ์ ์œผ๋กœ ์‚ฌ์šฉ๋˜๋ฏ€๋กœ ํ•˜๋‚˜์˜ ์š”์ฒญ ์•ˆ์—์„œ๋งŒ ์œ ์ง€๋˜์–ด์•ผ ํ•˜๋Š” ๊ฐ’์„ ๋„ฃ๊ธฐ์—๋Š” ๋ถ€์ ์ ˆํ•˜๋‹ค. app.set์€ ์•ฑ ์ „์ฒด์˜ ์„ค์ •์„ ๊ณต์œ ํ•  ๋•Œ ์‚ฌ์šฉํ•˜๋ฉด ๋œ๋‹ค.

res.locals ๊ฐ์ฒด๋Š” ํ•˜๋‚˜์˜ ์š”์ฒญ ์•ˆ์—์„œ๋งŒ ์œ ์ง€๋˜๋ฏ€๋กœ res.locals ๊ฐ์ฒด๋ฅผ ํ†ตํ•ด ์š”์ฒญ์— ์ข…์†๋˜๋Š” ๋ฐ์ดํ„ฐ๋ฅผ ์ „๋‹ฌํ•˜๋Š” ๊ฒƒ์ด ์ข‹๋‹ค.

 

๋ฏธ๋“ค์›จ์–ด ์•ˆ์— ๋ฏธ๋“ค์›จ์–ด๋ฅผ ๋„ฃ๋Š” ์œ ์šฉํ•œ ๋ฐฉ์‹

app.use(morgan('dev'));
// or
app.use((req, res, next) => { 
	morgan('dev')(req, res, next);
});

 

์ด ํŒจํ„ด์ด ์œ ์šฉํ•œ๊ฑด ๊ธฐ์กด ๋ฏธ๋“ค์›จ์–ด ๊ธฐ๋Šฅ ํ™•์žฅ ์˜ˆ๋ฅผ ๋“ค์–ด ๋ถ„๊ธฐ ์ฒ˜๋ฆฌ๋„ ๊ฐ€๋Šฅ

 

์•„๋ž˜์ฝ”๋“œ ๋ณด์ž

 

app.use((req, rex, next) => { 
	if (precess.env.NODE_ENV === 'production') { 
    	morgan('combined')(req, res, next);
    } else { 
    	morgan('dev')(req, res, next);
    }
});

 

์กฐ๊ฑด๋ฌธ์— ๋”ฐ๋ผ ๋ถ„๊ธฐ๋„ ๊ฐ€๋Šฅ

 

 #  multer

 

์ด๊ฑด ๋‹ค์†Œ ์–ด๋ ค์šด๋ฐ ์ด๋ฏธ์ง€๋‚˜ ์˜์ƒ ๋“ฑ์„ ๋น„๋กฏํ•œ ๋ฉ€ํ‹ฐํŒŒํŠธ ์ด๋ฏธ์ง€ ํŒŒ์ผ์„ ์—…๋กœ๋“œํ•  ๋–„ ์‚ฌ์šฉํ•˜๋Š” ๋ฏธ๋“ค์›จ์–ด

<form id="form" action="/upload" method="post" enctype="multipart/form-data">
  <input type="file" name="image1" />
  <input type="file" name="image2" />
  <input type="text" name="title" />
  <button type="submit">์—…๋กœ๋“œ</button>
</form>

์ด๊ฑด ์ง์ ‘ ํŒŒ์‹ฑํ•˜๊ธฐ ๊นŒ๋‹ค๋กœ์›Œ์„œ multer ๋ฏธ๋“ค์›จ์–ด ์‚ฌ์šฉํ•˜๋ฉด ํŽธ๋ฆฌํ•จ.

 

npm i multer

 

multer ํŒจํ‚ค์ง€ ์•ˆ์—๋Š” ์—ฌ๋Ÿฌ ์ข…๋ฅ˜์˜ ๋ฏธ๋“ค์›จ์–ด๊ฐ€ ๋“ค์–ด์žˆ๋‹ค.

const multer = require('multer');

const upload = multer({
	storage: multer.diskStorage({ 
    	destination(req, file, done) { // โœ… ์–ด๋–ค ์ด๋ฆ„์œผ๋กœ ์–ด๋””์— ์ €์žฅํ• ์ง€
        	done(null, 'uploads/'); // โœ… ์—๋Ÿฌ๊ฐ€ ์žˆ๋‹ค๋ฉด error๋ฅผ ๋„ฃ๊ธฐ, ๋‘๋ฒˆ์งธ ์ธ์ˆ˜๋Š” ์‹ค์ œ ๊ฒฝ๋กœ๋‚˜ ํŒŒ์ผ์ด๋ฆ„
        },
        filename(req, file, done) { 
        	const ext = path.extname(file.originalname);
            done(null, path.basename(file.originalname, ext) + Date.now() + ext); // โœ… [ํŒŒ์ผ๋ช… + ํ˜„์žฌ์‹œ๊ฐ„.ํ™•์žฅ์ž]
        },
    }),
    limits: { fileSize: 5 * 1024 * 1024 }, // โœ… 5MB๋กœ ์šฉ๋Ÿ‰์ œํ•œ
});

์œ„ ์ฝ”๋“œ ์˜ฌ๋ฐ”๋ฅด๊ฒŒ ์ž‘๋™ํ•˜๋ ค๋ฉด upload ํด๋”๊ฐ€ ๋ฐ˜๋“œ์‹œ ์กด์žฌํ•ด์•ผ ํ•œ๋‹ค.

์—†๋‹ค๋ฉด ์ง์ ‘ ๋งŒ๋“ค์–ด์ฃผ๊ฑฐ๋‚˜ fs๋ชจ๋“ˆ ์‚ฌ์šฉํ•ด์„œ ์„œ๋ฒ„ ์ƒ์„ฑํ•  ๋•Œ ์ƒ์„ฑํ•ด์•ผ ํ•œ๋‹ค.

 

const fs = require('fs');

try {
	fs.readdirSync('uploads');
} catch (error) { 
	console.error('uploads ํด๋”๊ฐ€ ์—†์–ด ํด๋”๋ฅผ ์ƒ์„ฑ');
    fs.mkdirSync('uploads');
}

์„ค์ •์ด ๋๋‚˜๋ฉด upload ๋ณ€์ˆ˜๊ฐ€ ์ƒ๊ธฐ๋Š”๋ฐ, ์—ฌ๊ธฐ์— ๋‹ค์–‘ํ•œ ์ข…๋ฅ˜์— ๋ฏธ๋“ค์›จ์–ด๊ฐ€ ์žˆ๋‹ค.

๋จผ์ € ํŒŒ์ผ์„ ํ•˜๋‚˜๋งŒ ์—…๋กœ๋“œํ•˜๋Š” ๊ฒฝ์šฐ ์‹ฑ๊ธ€ ๋ฏธ๋“ค์›จ์–ด๋ฅผ ์‚ฌ์šฉํ•œ๋‹ค.

app.post('/upload', upload.single('image'),  (req, res) => { 
 	console.log(req.file, req.body);
    res.send('ok');
});

single ๋ฏธ๋“ค์›จ์–ด๋ฅผ ๋ผ์šฐํ„ฐ ๋ฏธ๋“ค์›จ์–ด ์•ž์— ๋„ฃ์–ด๋‘๋ฉด multer ์„ค์ •์— ๋”ฐ๋ผ ํŒŒ์ผ ์—…๋กœ๋“œ ํ›„ req.file ๊ฐ์ฒด๊ฐ€ ์ƒ์„ฑ๋œ๋‹ค.

 

req.file ๊ฐ์ฒด๋Š” ์•„๋ž˜์ฒ˜๋Ÿผ ์ƒ๊น€

 

๋ฉ€ํ‹ฐํŒŒํŠธํผ์—์„œ

์ด๋ฒˆ์— ๋ฏธ๋“ค์›จ์–ด๋Š” single ๋Œ€์‹  array๋ฅผ ์‚ฌ์šฉํ•ด๋ณด์ž

app.post('/upload', upload.array('many'),  (req, res) => { 
 	console.log(req.file, req.body);
    res.send('ok');
});

 

์—…๋กœ๋“œ ๊ฒฐ๊ณผ๋„ req.file๋Œ€์‹  req.files ๋ฐฐ์—ด์— ๋“ค์–ด ์žˆ๋‹ค.

ํŒŒ์ผ์„ ์—ฌ๋Ÿฌ ๊ฐœ ์—…๋กœ๋“œํ•˜์ง€๋งŒ input ํƒœ๊ทธ๋‚˜ ํผ ๋ฐ์ดํ„ฐ์˜ ํ‚ค๊ฐ€ ๋‹ค๋ฅธ ๊ฒฝ์šฐ์—๋Š” fileds ๋ฏธ๋“ค์›จ์–ด๋ฅผ ์‚ฌ์šฉํ•œ๋‹ค

<form id="form" action="/upload" method="post" enctype="multipart/form-data">
  <input type="file" name="image1" />
  <input type="file" name="image2" />
  <input type="text" name="title" />
  <button type="submit">์—…๋กœ๋“œ</button>
</form>

fields ๋ฏธ๋“ค์›จ์–ด์˜ ์ธ์ˆ˜๋กœ input ํƒœ๊ทธ์˜ name์„ ๊ฐ๊ฐ ์ ๋Š”๋‹ค.

 

app.post('/upload',
	upload.fields([{ name: 'image1' }, { name: 'image2' }]),  (req, res) => { 
 	console.log(req.file, req.body);
    res.send('ok');
});

์—…๋กœ๋“œ ๊ฒฐ๊ณผ๋„ req.files.image1, req.files.image2๋กœ ๋”ฐ๋กœ ๋“ค์–ด์žˆ์Œ.

 

ํŠน์ˆ˜ํ•œ ๊ฒฝ์šฐ์ง€๋งŒ ํŒŒ์ผ ์—†์ด๋„ ๋ฉ€ํ‹ฐํŒŒํŠธ ํ˜•์‹์œผ๋กœ ์˜ฌ๋ฆฌ๊ธฐ๋„ ํ•จ

 

app.post('/upload', upload.none(),  (req, res) => { 
 	console.log(req.body);
    res.send('ok');
});

ํŒŒ์ผ ์—…๋กœ๋“œํ•˜์ง€ ์•Š์•„์„œ ๋ฐ”๋””๋งŒ ์กด์žฌํ•œ๋‹ค.

 

์‹ค์ œ๋กœ multer์˜ˆ์ œ ์‹ค์Šตํ•˜๋ ค๋ฉด app.js์ˆ˜์ •

 

// multipart.html
<form id="form" action="/upload" method="post" enctype="multipart/form-data">
  <input type="file" name="image1" />
  <input type="file" name="image2" />
  <input type="text" name="title" />
  <button type="submit">์—…๋กœ๋“œ</button>
</form>

// app.js
const express = require('express');
const morgan = require('morgan');
const cookieParser = require('cookie-parser');
const session = require('express-session');
const dotenv = require('dotenv');
const path = require('path');

dotenv.config();
const app = express();
app.set('port', process.env.PORT || 3000);

app.use(morgan('dev'));
app.use('/', express.static(path.join(__dirname, 'public')));
app.use(express.json());
app.use(express.urlencoded({ extended: false }));
app.use(cookieParser(process.env.COOKIE_SECRET));
app.use(session({
  resave: false,
  saveUninitialized: false,
  secret: process.env.COOKIE_SECRET,
  cookie: {
    httpOnly: true,
    secure: false,
  },
  name: 'session-cookie',
}));

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

try {
  fs.readdirSync('uploads');
} catch (error) {
  console.error('uploads ํด๋”๊ฐ€ ์—†์–ด uploads ํด๋”๋ฅผ ์ƒ์„ฑํ•ฉ๋‹ˆ๋‹ค.');
  fs.mkdirSync('uploads');
}
const upload = multer({
  storage: multer.diskStorage({
    destination(req, file, done) {
      done(null, 'uploads/');
    },
    filename(req, file, done) {
      const ext = path.extname(file.originalname);
      done(null, path.basename(file.originalname, ext) + Date.now() + ext);
    },
  }),
  limits: { fileSize: 5 * 1024 * 1024 },
});
app.get('/upload', (req, res) => {
  res.sendFile(path.join(__dirname, 'multipart.html'));
});
app.post('/upload', upload.single('image'), (req, res) => {
  console.log(req.file);
  res.send('ok');
});

app.get('/', (req, res, next) => {
  console.log('GET / ์š”์ฒญ์—์„œ๋งŒ ์‹คํ–‰๋ฉ๋‹ˆ๋‹ค.');
  next();
}, (req, res) => {
  throw new Error('์—๋Ÿฌ๋Š” ์—๋Ÿฌ ์ฒ˜๋ฆฌ ๋ฏธ๋“ค์›จ์–ด๋กœ ๊ฐ‘๋‹ˆ๋‹ค.')
});
app.use((err, req, res, next) => {
  console.error(err);
  res.status(500).send(err.message);
});

app.listen(app.get('port'), () => {
  console.log(app.get('port'), '๋ฒˆ ํฌํŠธ์—์„œ ๋Œ€๊ธฐ ์ค‘');
});

์ž˜ ๋‚˜์˜จ๋‹ค.

 

 # Router ๊ฐ์ฒด๋กœ ๋ผ์šฐํŒ… ๋ถ„๋ฆฌํ•˜๊ธฐ

 

์š”์ฒญ ๋ฉ”์„œ๋“œ์™€ ์ฃผ์†Œ๋ณ„๋กœ ๋ถ„๊ธฐ ์ฒ˜๋ฆฌ ํ•˜๋Š๋ผ ์ฝ”๋“œ๊ฐ€ ๋งค์šฐ ๋ณต์žก

if๋ฌธ์œผ๋กœ ๋ถ„๊ธฐํ•˜๋ฉด์„œ ์ฝ”๋”ฉํ–ˆ๊ธฐ ๋•Œ๋ฌธ์— ๋ณด๊ธฐ๋„ ์–ด๋ ค์›€.

app.js์—์„œ app.get ๊ฐ™์€ ๋ฉ”์„œ๋“œ๊ฐ€ ๋ผ์šฐํ„ฐ ๋ถ€๋ถ„์ด๋‹ค. ๋ผ์šฐํ„ฐ๋ฅผ ๋งŽ์ด ์—ฐ๊ฒฐํ•˜๋ฉด app.js ์ฝ”๋“œ๊ฐ€ ๋งค์šฐ ๊ธธ์–ด์ง€๋ฏ€๋กœ ์ต์Šคํ”„๋ ˆ์Šค์—์„œ๋Š” ๋ผ์šฐํ„ฐ๋ฅผ ๋ถ„๋ฆฌํ•  ์ˆ˜ ์žˆ๋Š” ๋ฐฉ๋ฒ•์„ ์ œ๊ณต

routes ํด๋”๋ฅผ ๋งŒ๋“ค๊ณ  ๊ทธ ์•ˆ์— index.js์™€ user.js๋ฅผ ์ž‘์„ฑ

 

/// routes/index.js
const express = require('express');

const router = express.Router();

// GET / ๋ผ์šฐํ„ฐ
router.get('/', (req, res) => {
  res.send('Hello, Express'); // โœ… ์ด๊ฑฐ๋ฅผ ๋ณด๋‚ธ๋‹ค
});

module.exports = router; // โœ… ์ด๊ฑฐ ๋‹ฌ์•„์ค˜์•ผ ํ•œ๋‹ค.

///routes.user.js
const express = require('express');

const router = express.Router();

// GET /user ๋ผ์šฐํ„ฐ
router.get('/', (req, res) => {
  res.send('Hello, User'); // โœ… ์ด๊ฑฐ๋ฅผ ๋ณด๋‚ธ๋‹ค
});

module.exports = router; // โœ… ์ด๊ฑฐ ๋‹ฌ์•„์ค˜์•ผ ํ•œ๋‹ค.

/// app.js
const express = require('express');
const morgan = require('morgan');
const cookieParser = require('cookie-parser');
const session = require('express-session');
const dotenv = require('dotenv');
const path = require('path');

dotenv.config();
const indexRouter = require('./routes'); // โœ… ์—ฐ๊ฒฐํ•  ๊ฒฝ๋กœ
const userRouter = require('./routes/user'); // โœ… ์—ฐ๊ฒฐํ•  ๊ฒฝ๋กœ

const app = express();
app.set('port', process.env.PORT || 3000);

app.use(morgan('dev'));
app.use('/', express.static(path.join(__dirname, 'public')));
app.use(express.json());
app.use(express.urlencoded({ extended: false }));
app.use(cookieParser(process.env.COOKIE_SECRET));
app.use(session({
  resave: false,
  saveUninitialized: false,
  secret: process.env.COOKIE_SECRET,
  cookie: {
    httpOnly: true,
    secure: false,
  },
  name: 'session-cookie',
}));

app.use('/', indexRouter); // โœ… url ์„ค์ •
app.use('/user', userRouter); // โœ… url ์„ค์ •

app.use((req, res, next) => {
  res.status(404).send('Not Found');
});

app.use((err, req, res, next) => {
  console.error(err);
  res.status(500).send(err.message);
});

app.listen(app.get('port'), () => {
  console.log(app.get('port'), '๋ฒˆ ํฌํŠธ์—์„œ ๋Œ€๊ธฐ ์ค‘');
});

์ด๋ ‡๊ฒŒ ๋งŒ๋“ค์–ด์ง„ index.js์™€ user.js๋ฅผ app.use๋ฅผ ํ†ตํ•ด app.js์— ์—ฐ๊ฒฐํ•œ๋‹ค

์—๋Ÿฌ์ฒ˜๋ฆฌ ๋ฏธ๋“ค์›จ์–ด ์œ„์— 404์ƒํƒœ ์ฝ”๋“œ ์‘๋‹ตํ•˜๋Š” ๋ฏธ๋“ค์›จ์–ด๋ฅผ ์ถ”๊ฐ€

 

indexRouter๋ฅผ ./routes๋กœ requireํ•  ์ˆ˜ ์žˆ๋Š” ์ด์œ ๋Š” index.js๋Š” ์ƒ๋žตํ•  ์ˆ˜ ์žˆ์Œ

require('./routes/index.js')์™€ require('routes')์™€ ๊ฐ™๋‹ค

 

์ด์ „์ ˆ์—์„œ next('route') ์•Œ์•„๋ณด์ž

์ด ๊ธฐ๋Šฅ์€ ๋ผ์šฐํ„ฐ์— ์—ฐ๊ฒฐ๋œ ๋‚˜๋จธ์ง€ ๋ฏธ๋“ค์›จ์–ด๋“ค์„ ๊ฑด๋„ˆ๋›ฐ๊ณ  ์‹ถ์„๋•Œ ์‚ฌ์šฉ.

 

router.get('/', (req, res, next) => { 
	next('rotue');
}, (req, res, next) => { 
	console.log('์‹คํ–‰๋˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค');
    next();
}, (req, res, next) => { 
	console.log('์‹คํ–‰๋˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค');
    next();
});

router.get('/', (req, res) => { 
	console.log('์‹คํ–‰๋œ๋‹ค.');
	res.send('hello express');
});

๋ผ์šฐํ„ฐ ์—ฌ๋Ÿฌ๊ฐœํŠผ next๋ฅผ ํ˜ธ์ถœํ•˜๋ฉด ๋‹ค์Œ ๋ฏธ๋“ค์›จ์–ด ์‹คํ–‰๋œ๋‹ค.

์ฒซ๋ฒˆ์งธ ๋ผ์šฐํ„ฐ์˜ next()๋Œ€์‹  next('route')๋ฅผ ํ˜ธ์ถœํ•ด์„œ ๋Œ€์‹  ์ด ์ฃผ์†Œ์™€ ์ผ์น˜ํ•˜๋Š” ๊ฑธ๋กœ ์ด๋™

 

๋ผ์šฐํ„ฐ ์ฃผ์†Œ์—๋Š” ์ •๊ทœํ‘œํ˜„์‹์„ ๋น„๋กฏํ•œ ํŠน์ˆ˜ ํŒจํ„ด์„ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Œ.

์—ฌ๋Ÿฌ ๊ฐ€์ง€ ํŒจํ„ด์ด ์žˆ์ง€๋งŒ, ์ž์ฃผ ์“ฐ์ด๋Š” ํŒจํ„ด ํ•˜๋‚˜๋งŒ ์•Œ์•„๋ณด์ž.

 

router.get('/user/:id', (res, req) => { 
	console.log(req.params, req.query);
});

๋ฌธ์ž ๊ทธ๋Œ€๋กœ :id๋ฅผ ์˜๋ฏธํ•˜๋Š” ๊ฒƒ์ด ์•„๋‹˜. ์ด ๋ถ€๋ถ„์—๋Š” ๋‹ค๋ฅธ ๊ฐ’์„ ๋„ฃ์„ ์ˆ˜ ์žˆ์Œ

์˜ˆ๋ฅผ ๋“ค๋ฉด /user/123, /user/1 ๋“ฑ์˜ ์š”์ฒญ๋„ ์ด ๋ผ์šฐํ„ฐ๊ฐ€ ์ฒ˜๋ฆฌํ•จ.

์ด ๋ฐฉ์‹์˜ ์žฅ์ ์€ :id์ด๋ฉด ํ•ด๋‹นํ•˜๋Š” 1์ด๋‚˜ 123์„ ์กฐํšŒํ• ์ˆ˜ ์žˆ๋‹ค๋Š” ์  req.params ๊ฐ์ฒด ์•ˆ์— ๋“ค์–ด ์žˆ๋‹ค.

:id์ด๋ฉด req.params.id๋กœ :type์ด๋ฉด req.params.type์œผ๋กœ ์กฐํšŒํ•  ์ˆ˜ ์žˆ๋‹ค.

 

๋‹จ, ์ด ํŒจํ„ด ์‚ฌ์šฉํ•  ๋•Œ ์ฃผ์˜์ . ์ผ๋ฐ˜ ๋ผ์šฐํ„ฐ๋ณด๋‹ค ๋’ค์— ์œ„์น˜ํ•ด์•ผ ํ•จ.

๋‹ค์–‘ํ•œ ๋ผ์šฐํ„ฐ๋ฅผ ์•„์šฐ๋ฅด๋Š” ์™€์ผ๋“œ ์นด๋“œ ์—ญํ• ์ด๋ผ ์ผ๋ฐ˜ ๋ผ์šฐํ„ฐ ๋ณด๋‹ค ๋’ค์— ์žˆ์–ด์•ผ ๋ฐฉํ•ดํ•˜์ง€ ์•Š์Œ.

router.get('/user/:id', (req, res) => { 
	console.log('์–˜๋งŒ ์‹คํ–‰๋ฉ๋‹ˆ๋‹ค.');
});

router.get('/user/like', (req, res) => { 
	console.log('์‹คํ–‰๋˜์ง€ ์•Š๋Š”๋‹ค.');
});

/user/like์™€ ๊ฐ™์€ ๋ผ์šฐํ„ฐ๋Š” /user/:id ๊ฐ™์€ ๋ผ์šฐํŠธ ๋งค๊ฐœ๋ณ€์ˆ˜ ์œ„์— ๋‘์–ด์•ผ ํ•จ.

์ฃผ์†Œ์— ์ฟผ๋ฆฌ์ŠคํŠธ๋ง ์“ฐ๋Š” ๊ฒฝ์šฐ๋„ ์žˆ์Œ.

 

/user/123?limit=5&skip=10

req.params์™€ req.query๊ฐ์ฒด๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™์Œ

{ id: '123' } { limit: '5', skip: '10' }

app.js์—์„œ ์—๋Ÿฌ ์ฒ˜๋ฆฌ ๋ฏธ๋“ค์›จ์–ด ์œ„์— ๋„ฃ์–ด๋‘” ๋ฏธ๋“ค์›จ์–ด๋Š” ์ผ์น˜ํ•˜๋Š” ๋ผ์šฐํ„ฐ๊ฐ€ ์—†์„ ๋•Œ 404์ƒํƒœ ์ฝ”๋“œ๋ฅผ ์‘๋‹ตํ•˜๋Š” ์—ญํ• .

 

app.use((req, res, next) => { 
	res.status(404).send('Not Found');
});

 

์ด ๋ฏธ๋“ค์›จ์–ด๋ฅผ ์ œ๊ฑฐํ•˜๊ณ  localhost:3000/abc์— ์ ‘์†ํ•˜๋ฉด 404์ƒํƒœ์™€ ํ•จ๊ป˜ ๋ฉ”์‹œ์ง€๊ฐ€ ์‘๋‹ต๋œ๋‹ค.

 

๋ผ์šฐํ„ฐ์—์„œ ์ž์ฃผ ์“ฐ์ด๋Š” ํ™œ์šฉ๋ฒ•์œผ๋กœ app.route๋‚˜ router.route๊ฐ€ ์žˆ๋‹ค.

router.get('/abc', (req, res) => { 
	res.send('GET /abc');
});

router.post('/abc', (req, res) => { 
	res.send('POST /abc');
});

// ์•„๋ž˜์ฒ˜๋Ÿผ ๋ฌถ๊ธฐ๋„ ๊ฐ€๋Šฅ
router.route('/abc')
	.get((req, res) => { 
		res.send('GET /abc');
	}).post((req, res) => { 
		res.send('POST /abc');
	});

 

 # req, res ๊ฐ์ฒด ์‚ดํŽด๋ณด๊ธฐ

 

์ต์Šคํ”„๋ ˆ์Šค์˜ req, res ๊ฐ์ฒด๋Š” http ๋ชจ๋“ˆ์˜ req, res ๊ฐ์ฒด๋ฅผ ํ™•์žฅํ•œ ๊ฒƒ์ด๋‹ค. ๊ธฐ์กด http ๋ชจ๋“ˆ์˜ ๋ฉ”์„œ๋“œ๋„ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๊ณ , ์ต์Šคํ”„๋ ˆ์Šค๊ฐ€ ์ถ”๊ฐ€ํ•œ ๋ฉ”์„œ๋“œ๋‚˜ ์†์„ฑ์„ ์‚ฌ์šฉํ•  ์ˆ˜๋„ ์žˆ๋‹ค.

 

 

์ฒด์ด๋‹์„ ํ†ตํ•ด ์ฝ”๋“œ์–‘์„ ์ค„์ผ ์ˆ˜ ์žˆ๋‹ค.

res
	.status(201)
    .cookie('test', 'test')
    .redirect('/admin');

 

 # ํ…œํ”Œ๋ฆฟ ์—”์ง„ ์‚ฌ์šฉํ•˜๊ธฐ

 

HTML์€ ์ •์ ์ž„. ๊ทธ๋ž˜์„œ ๋Œ€ํ‘œ์  ํ…œํ”Œ๋ฆฟ์—”์ง„์ธ pug์™€ ๋„Œ์ ์Šค ์•Œ์•„๋ณผ ์˜ˆ์ •.

 

 

 # ํผ๊ทธ(์ œ์ด๋“œ), ๋„Œ์ ์Šค๋Š”  ์ฑ…์„ ๋ณ„๋„๋กœ ์‚ดํŽด๋ณด์ž.

๊ทธ๋ ‡๊ฒŒ ์–ด๋ ต์ง€ ์•Š์Œ. ๋ฌธ๋ฒ•์— ๋Œ€ํ•œ ๋ถ€๋ถ„.

 

์˜ˆ์ „ ์ด๋ฆ„์ธ ์ œ์ด๋“œ(Jade)๋กœ ๋” ์œ ๋ช…ํ•จ. ๋ฃจ๋น„ ์‚ฌ์šฉํ•ด ๋ณด์•˜๋‹ค๋ฉด ๋ฌธ๋ฒ•์ด ๋น„์Šทํ•ด์„œ ๋น ๋ฅด๊ฒŒ ์ ์‘ํ•  ์ˆ˜ ์žˆ์Œ.

 

ํผ๊ทธ ์„ค์น˜ํ•˜๊ธฐ

npm i pug

 

์ต์Šคํ”„๋ ˆ์Šค์™€ ์—ฐ๊ฒฐํ•˜๋ ค๋ฉด ๋‹ค์Œ ๋ถ€๋ถ„์ด ์žˆ์–ด์•ผ ํ•จ

/// app.js

...
app.set('port', process.env.PORT || 3000);
app.set('views', path.join(__dirname, 'views')); // โœ…
app.set('view engine', 'pug'); // โœ…

app.use(morgan('dev'));
...

 

 

views๋Š” ํ…œํ”Œ๋ฆฟ ํŒŒ์ผ๋“ค์ด ์œ„์น˜ํ•œ ํด๋”๋ฅผ ์ง€์ •ํ•˜๋Š” ๊ฒƒ. res.render ๋ฉ”์„œ๋“œ๊ฐ€ ์ด ํด๋” ๊ธฐ์ค€์œผ๋กœ ํ…œํ”Œ๋ฆฟ ์—”์ง„์„  ์ฐพ์•„์„œ ๋ Œ๋”๋ง ํ•จ.

re.render('index')๋ผ๋ฉด views/index.pug๋ฅผ ๋ Œ๋”๋งํ•œ๋‹ค. res.render('admin/main')์ด๋ผ๋ฉด views/admin/main.pug๋ฅผ ๋ Œ๋”๋ง

 

view engine์€ ์–ด๋– ํ•œ ์ข…๋ฅ˜์˜ ํ…œํ”Œ๋ฆฟ ์—”์ง„์„ ์‚ฌ์šฉํ• ์ง€๋ฅผ ๋‚˜ํƒ€๋‚ธ๋‹ค. ํ˜„์žฌ pug๋กœ ์„ค์ •๋˜์–ด ์žˆ์œผ๋ฏ€๋กœ ๊ทธ๋Œ€๋กœ ์‚ฌ์šฉํ•˜๋ฉด ์•ˆ๋œ๋‹ค.

 

 

 

 

Comments