๐ŸŒณ๋ชฉํ‘œ

์š”์ฒญ ๋ฐ”๋”” ๋ฐ์ดํ„ฐ๋ฅผ ์ฒ˜๋ฆฌํ•˜๋Š” body-parser๋ฅผ ๋งŒ๋“ญ๋‹ˆ๋‹ค. ๊ทธ๋ฆฌ๊ณ  ์ด๊ฒƒ์„ ์ด์šฉํ•ด ํฌ์ŠคํŠธ ์ƒ์„ฑ API ๊ฐœ๋ฐœ์„ ์™„๋ฃŒํ•ฉ๋‹ˆ๋‹ค.

์ŠคํŠธ๋ฆผ ๋ฐ์ดํ„ฐ

์ง€๋‚œ ์‹œ๊ฐ„์— POST ๋ฉ”์†Œ๋“œ๋ฅผ ๊ฐ–๋Š” ์—”๋“œํฌ์ธํŠธ๋ฅผ ๋ผ์šฐํ„ฐ์— ์ถ”๊ฐ€ํ–ˆ์Šต๋‹ˆ๋‹ค. ๋‹ค๋งŒ ์ปจํŠธ๋กค๋Ÿฌ ํ•จ์ˆ˜๋Š” ๋น„์–ด ์žˆ๋Š” ์ฑ„๋กœ ๋‚จ๊ฒจ ๋‘์—ˆ๋Š”๋ฐ์š”. req.body ๊ฐ’์„ ๋กœ๊ทธ๋กœ ์ถœ๋ ฅํ•˜๋Š”๊ฒƒ ๊นŒ์ง€๋งŒ ์ฝ”๋”ฉํ–ˆ์Šต๋‹ˆ๋‹ค.

์ด ๋ฐ์ดํ„ฐ๋Š” ์–ด๋–ป๊ฒŒ ์ ‘๊ทผํ•  ์ˆ˜ ์žˆ์„๊นŒ์š”?

๋…ธ๋“œ ๋ฌธ์„œ์—์„œ ์š”์ฒญ ๋ฐ”๋””์— ์ ‘๊ทผํ•˜๋Š” ๋ฐฉ๋ฒ•์„ ์„ค๋ช…ํ•˜๊ณ  ์žˆ๋Š”๋ฐ์š” ์ •๋ฆฌํ•˜๋ฉด ๋‹ค์Œ ์ˆœ์„œ๋ฅผ ๋”ฐ๋ฆ…๋‹ˆ๋‹ค.

  • req๋Š” ReadableStream ์ธํ„ฐํŽ˜์ด์Šค ๊ตฌํ˜„์ฒด๋‹ค
  • ์ด๊ฒƒ์€ ์ŠคํŠธ๋ฆผ์ด๊ธฐ ๋•Œ๋ฌธ์— โ€œdataโ€์™€ โ€œendโ€ ์ด๋ฒคํŠธ๋ฅผ ์ด์šฉํ•ด์„œ ๋ฐ์ดํ„ฐ๋ฅผ ์ˆ˜์‹ ํ•  ์ˆ˜ ์žˆ๋‹ค
  • โ€œdataโ€ ์ด๋ฒคํŠธ์™€ ํ•จ๊ป˜ ๋“ค์–ด์˜จ ๋ฐ์ดํ„ฐ๋Š” Buffer ํƒ€์ž…์ด๋‹ค
  • ์ด๊ฒƒ์„ ๋ฌธ์ž์—ด๋กœ ๋ณ€ํ™˜ํ•˜๋ ค๋ฉด ๋ฐ์ดํ„ฐ๋ฅผ ๋ฐฐ์—ด๋กœ ๋“ค๊ณ  ์žˆ๋‹ค๊ฐ€ โ€œendโ€ ์ด๋ฒคํŠธ ์‹œ์ ์— ํ•ฉ์น˜๋ฉด ๋œ๋‹ค

์œ„ ์•Œ๊ณ ๋ฆฌ์ฆ˜์„ ๊ธฐ์ˆ ํ•œ ๊ฒƒ์ด ์•„๋ž˜ ์ƒ˜ํ”Œ ์ฝ”๋“œ์ž…๋‹ˆ๋‹ค.

let body = []
request.on('data', (chunk) => {
  body.push(chunk)
}).on('end', () => {
  body = Buffer.concat(body).toString();
  // ์ด ์‹œ์ ์— body๋Š” ์ „์ฒด ์š”์ฒญ ๋ฐ์ดํ„ฐ๋ฅผ ๋ฌธ์ž์—ด ํ˜•ํƒœ๋กœ ๊ฐ€์ง€๊ณ  ์žˆ๋‹ค
  // (at this point, `body` has the entire request body stored in it as a string)
});

API ์ปจํŠธ๋กค๋Ÿฌ ํ•จ์ˆ˜์—์„œ ์š”์ฒญ ๋ฐ”๋””์— ์‰ฝ๊ฒŒ ์ ‘๊ทผํ•˜๋ ค๋ฉด ์ข‹๊ฒ ๋Š”๋ฐ ๋งค ์š”์ฒญ๋งˆ๋‹ค ์œ„ ์ฝ”๋”ฉ์„ ํ•˜๋Š”๊ฑด ๋ฏธ๋ จํ•œ ๋ฐฉ๋ฒ•์ฒ˜๋Ÿผ ๋ณด์ž…๋‹ˆ๋‹ค.

๋งŒ์•ฝ ์ปจํŠธ๋กค๋Ÿฌ๊นŒ์ง€ ์˜ค๊ธฐ ์ „์— ๋ฏธ๋ฆฌ ๋ฐ”๋”” ๋ฐ์ดํ„ฐ๋ฅผ ํŒŒ์‹ฑํ•˜์—ฌ req.body์— ๋‹ด์•„ ๋†“๋Š”๋‹ค๋ฉด ์–ด๋–จ๊นŒ์š”? ์ดํ›„ ๋ชจ๋“  ์ปจํŠธ๋กค๋Ÿฌ์—์„œ๋Š” ๊ฐ„๋‹จํžˆ req.body๋ฅผ ์ด์šฉํ•˜๋ฉด ๋ฐ์ดํ„ฐ์— ์‰ฝ๊ฒŒ ์ ‘๊ทผํ•  ์ˆ˜ ์žˆ์„ ๊ฒƒ ๊ฐ™๋„ค์š”.

๐Ÿค์‹ค์Šต - body-parser๋ฅผ ๋งŒ๋“ค์–ด ๋ณด์„ธ์š”

req.path์™€ req.query๋„ ์ด๋Ÿฐ ๋ฐฉ์‹์œผ๋กœ ๋ฐ์ดํ„ฐ๋ฅผ ๋ฏธ๋ฆฌ ๊ฐ€๊ณตํ–ˆ์—ˆ์ฃ ? ์ด๊ฒƒ๊ณผ ๋น„์Šทํ•˜๊ฒŒ req.body์—๋„ ๋ฏธ๋ฆฌ ๊ฐ€๊ณต๋œ ์š”์ฒญ ๋ฐ”๋””๋ฅผ ์ €์žฅํ•ด ๋ณด์„ธ์š”.

๐Ÿคํ’€์ด

๊ฐ™์ด ํ’€์–ด๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค. ๋ฐ”๋”” ํŒŒ์„œ๋ฅผ ๋ฏธ๋“ค์›จ์–ด ํ•จ์ˆ˜๋กœ ๋งŒ๋“ค๊ธฐ๋กœ ํ• ๊ฒŒ์š”. middlewares ํด๋”์— body-parser.js ํŒŒ์ผ์„ ๋งŒ๋“ค์–ด ์•„๋ž˜ ์ฝ”๋“œ๋ฅผ ์ž…๋ ฅํ•ฉ๋‹ˆ๋‹ค.

const bodyParser = () => (req, res, next) => {
  let body = []

  req.on('data', chunk => {
    body.push(chunk)
    console.log('data', chunk)
  })

  req.on('end', () => {
    body = Buffer.concat(body).toString()
    console.log('end', body)
  }
}

module.exports = bodyParser;

์ด๋ฒคํŠธ ๊ธฐ๋ฐ˜์œผ๋กœ ์ŠคํŠธ๋ฆผ ๋ฐ์ดํ„ฐ ๋ฐ”๋””๋ฅผ ์ฒ˜๋ฆฌํ•˜๋Š” ์ฝ”๋“œ๋Š” ์ƒ˜ํ”Œ ์ฝ”๋“œ์—์„œ ๊ทธ๋Œ€๋กœ ๋ฐฐ๊ปด ์™”์Šต๋‹ˆ๋‹ค. ๋‹ค๋งŒ ๊ทธ ์‹œ์ ์— ๋ฐ์ดํ„ฐ๊ฐ€ ๊ฐ ๊ฐ ์–ด๋–ค ๋ชจ์Šต์œผ๋กœ ๋ณ€ํ•˜๋Š”์ง€ ํ™•์ธํ•˜๊ธฐ ์œ„ํ•ด ํ„ฐ๋ฏธ๋„์— ์ถœ๋ ฅํ–ˆ์Šต๋‹ˆ๋‹ค.

๋ฏธ๋“ค์›จ์–ด๋ฅผ ์šฐ๋ฆฌ ์–ดํ”Œ๋ฆฌ์ผ€์ด์…˜์— ์ถ”๊ฐ€ํ•ด ๋ณด์ง€์š”. app.js๋ฅผ ์ˆ˜์ •ํ•ฉ๋‹ˆ๋‹ค.

const bodyParser = require('./middlewares/body-parser')

app.use(logger())
app.use(bodyParser()) // body-parser๋ฅผ ์ถ”๊ฐ€

์„œ๋ฒ„๋ฅผ ์žฌ๊ตฌ๋™ํ•˜๊ณ  ํผ์„ ๋‹ค์‹œ ์ „์†กํ•ด ๋ณผ๊นŒ์š”?

โ€œdataโ€ ์ด๋ฒคํŠธ๊ฐ€ ๋ฐœ์ƒํ•  ๋•Œ๋Š” ๋ฒ„ํผ๊ฐ’์ด ์ถœ๋ ฅ๋˜์—ˆ์Šต๋‹ˆ๋‹ค. ๋ฐ์ดํ„ฐ๋ฅผ ๋ชจ๋‘ ์ˆ˜์‹ ํ•œ โ€œendโ€ ์ด๋ฒคํŠธ๊ฐ€ ๋ฐœ์ƒํ•  ๋•Œ๋Š” ๋ฒ„ํผ๋ฅผ ๋ฌธ์ž์—ด๋กœ ๋ณ€๊ฒฝํ•˜์—ฌ โ€œtitle=asd&body=sdfโ€๋ผ๋Š” ๊ฐ’์ด ์ถœ๋ ฅ๋˜์—ˆ๋„ค์š”.

๊ฐ€๋งŒํžˆ ๋ณด๋ฉด ์ฟผ๋ฆฌ์ŠคํŠธ๋ง๊ณผ ๊ตฌ์กฐ๊ฐ€ ๋˜‘๊ฐ™๋„ค์š”? ๋„ค, ๊ทธ๋ ‡์Šต๋‹ˆ๋‹ค. ์ฟผ๋ฆฌ์ŠคํŠธ๋ง์„ ์˜ค๋ธŒ์ ํŠธ๋กœ ํŒŒ์‹ฑํ•œ ๊ฒƒ์ฒ˜๋Ÿผ, ์ด ๋ฌธ์ž์—ด๋„ ์ž๋ฐ”์Šคํฌ๋ฆฝํŠธ ๊ฐ์ฒด๋กœ ํŒŒ์‹ฑํ•œ ๋’ค req.body์— ๋„ฃ์–ด๋‘๋ฉด ์‚ฌ์šฉํ•˜๊ธฐ ํŽธ๋ฆฌํ•˜๊ฒ ๋„ค์š”.

body-parser๋ฅผ ๋” ๊ฐœ๋ฐœํ•ด ๋ณด์ฃ .

   req.on('end', () => {
    body = Buffer.concat(body).toString();

    body = body.split('&').reduce((body, pair) => {
      if (!pair) return body;
      const frg = pair.split('=');
      body[frg[0]] = frg[1];
      return body;
    }, {});

    req.body = body;
    next();
  })

ํŠน์ • ๋ฌธ์ž๋ฅผ ๊ธฐ์ค€์œผ๋กœ ํŒŒ์‹ฑํ•˜๋Š” ๋ถ€๋ถ„์€ ์ฟผ๋ฆฌ์ŠคํŠธ๋ง ํŒŒ์‹ฑ๊ณผ ๊ฐ™์€ ๋กœ์ง์ž…๋‹ˆ๋‹ค. ํŒŒ์‹ฑํ•œ ๊ฒฐ๊ณผ body์— ์˜ค๋ธŒ์ ํŠธ ํ˜•ํƒœ๋กœ ๋ฐ์ดํ„ฐ๊ฐ€ ๋‹ด๊ธฐ๊ฒ ์ง€์š”. ๊ทธ๋Ÿฌ๋ฉด req.body์— ์ด ๊ฐ์ฒด๋ฅผ ์ €์žฅํ•ฉ๋‹ˆ๋‹ค.

๋งˆ์ง€๋ง‰์—” ๋‹ค์Œ ๋ฏธ๋“ค์›จ์–ด๋ฅผ ์‹คํ–‰ํ•ด ์ฃผ๊ธฐ ์œ„ํ•ด next() ํ•จ์ˆ˜๋ฅผ ํ˜ธ์ถœํ•ฉ๋‹ˆ๋‹ค.

body-parser๋Š” ์ „์ฒด ๊ตฌ์กฐ๋„ ์ค‘ ์šฐ์ธก ํ•˜๋‹จ์˜ ์จ๋“œํŒŒํ‹ฐ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ ์„น์…˜์— ์œ„์น˜ํ•˜๋Š” ๋…€์„์ž…๋‹ˆ๋‹ค.

๐Ÿค์‹ค์Šต - ํฌ์ŠคํŠธ ์ถ”๊ฐ€ API ๊ฐœ๋ฐœ์„ ์™„์„ฑํ•˜์„ธ์š”

req.body ๋ฐ์ดํ„ฐ๋ฅผ ์ด์šฉํ•ด POST /api/posts ์—”๋“œํฌ์ธํŠธ๋ฅผ ๋งˆ์ ธ ๊ตฌํ˜„ํ•ด ๋ณด์„ธ์š”. ์ฝ”๋“œ๋ฅผ ๋ฏธ์ณ ์ž‘์„ฑํ•˜์ง€ ๋ชปํ•˜์‹  ๋ถ„์€ ์•„๋ž˜ ๋ธŒ๋žœ์น˜๋กœ ์ด๋™ํ•œ ๋’ค ์‹ค์Šต์„ ์ง„ํ–‰ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

$ git checkout -f middleware/body-parser

ํžŒํŠธ: 201 ์‘๋‹ต, ์ƒˆ๋กœ์šด ๋ฐ์ดํ„ฐ๋ฅผ ์‘๋‹ต

๐Ÿคํ’€์ด

์ž˜ ํ’€์–ด ๋ณด์…จ๋‚˜์š”? ๊ทธ๋Ÿผ ๊ฐ™์ด ์ง„ํ–‰ํ•ด ๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค.

routers/api/post.js ํŒŒ์ผ์„ ๋งˆ์ ธ ์ˆ˜์ •ํ•˜์ง€์š”. ๋‘ ๋ถ€๋ถ„์œผ๋กœ ๋‚˜๋ˆ  ์„ค๋ช…ํ•˜๊ฒ ์Šต๋‹ˆ๋‹ค.

const create = () => (req, res, next) => {
  const {title, body} = req.body
  const post = {title, body}

  if (!post.title || !post.body) {
    return res.status(400).send('parameter error')
  }

๊ฐ์ฒด ํ•ด์ฒด ๋ฌธ๋ฒ•์œผ๋กœ title๊ณผ body๋ฅผ ๊ฐ ์ƒ์ˆ˜๊ฐ’์œผ๋กœ ๊ฐ€์ ธ์˜ต๋‹ˆ๋‹ค. ๊ทธ๋ฆฌ๊ณ  ๊ธฐ์กด ๋ฐ์ดํ„ฐ ํ˜•์‹์— ๋งž๊ฒŒ ์žฌ ๊ฐ€๊ณตํ•ด์„œ post ๊ฐ์ฒด๋ฅผ ๋งŒ๋“ญ๋‹ˆ๋‹ค.

๋งŒ์•ฝ title์ด๋‚˜ body ๊ฐ’ ์ค‘ ์–ด๋Š ํ•˜๋‚˜๋ผ๋„ ๋ถ€์กฑํ•˜๋ฉด ํŒŒ๋ผ๋งคํ„ฐ ์—๋Ÿฌ๋ฅผ ์˜๋ฏธํ•˜๋Š” 400๋ฒˆ ์ƒํƒœ์ฝ”๋“œ๋ฅผ ์‘๋‹ตํ•˜๊ณ  ํ•จ์ˆ˜๋ฅผ ์ข…๋ฃŒํ•ฉ๋‹ˆ๋‹ค.

  posts = [post].concat(posts)

  res.status(201).json(post)
}

ํฌ์ŠคํŠธ ์ถ”๊ฐ€์— ํ•„์š”ํ•œ ๋ฐ์ดํ„ฐ๊ฐ€ ํ™•๋ณด๋˜๋ฉด ํฌ์ŠคํŠธ๋ฅผ ๋‹ด๊ณ  ์žˆ๋Š” ๋ฐฐ์—ด ๋งจ ์•ž์— ์ถ”๊ฐ€ํ•ฉ๋‹ˆ๋‹ค.

๊ทธ๋ฆฌ๊ณ  ๋ฆฌ์†Œ์Šค ์ƒ์„ฑ์„ ์˜๋ฏธํ•˜๋Š” 201 ์ƒํƒœ์ฝ”๋“œ์™€ ์ƒ์„ฑ๋œ ํฌ์ŠคํŠธ ๊ฐ์ฒด๋ฅผ ์‘๋‹ต ๋ฐ”๋””๋กœ ์ „๋‹ฌํ•ฉ๋‹ˆ๋‹ค.

๊ทธ๋Ÿผ ์—ฌ๊ธฐ๊นŒ์ง€ ์ฝ”๋”ฉ์„ ๋งˆ์นœ ๋’ค ์„œ๋ฒ„๋ฅผ ์žฌ๊ตฌ๋™ ํ•ฉ์‹œ๋‹ค. ๋ธŒ๋ผ์šฐ์ ธ๋ฅผ ํ†ตํ•ด ํฌ์ŠคํŠธ ์ƒ์„ฑ ํผ์„ ์ „์†กํ•ด ๋ณผ๊นŒ์š”?

์ž…๋ ฅํ•œ post4๊ฐ€ ๋งจ ์ƒ๋‹จ์— ์ถ”๊ฐ€๋˜์—ˆ์Šต๋‹ˆ๋‹ค.

์ •๋ฆฌ

  • ์ด๋ฒคํŠธ๋ฅผ ์ด์šฉํ•ด ์ŠคํŠธ๋ฆผ ๋ฐ์ดํ„ฐ๋ฅผ ์ฒ˜๋ฆฌํ•˜์˜€์Šต๋‹ˆ๋‹ค.
  • ์š”์ฒญ ๋ฐ”๋””๋ฅผ ํŒŒ์‹ฑํ•˜์—ฌ API ์ปจํŠธ๋กค๋Ÿฌ์—์„œ ์†์‰ฝ๊ฒŒ ์‚ฌ์šฉํ• ์ˆ˜ ์žˆ๋„๋ก ํ•˜์˜€์Šต๋‹ˆ๋‹ค.
  • ํฌ์ŠคํŠธ ์ถ”๊ฐ€ API๋ฅผ ์™„์„ฑํ•˜์˜€์Šต๋‹ˆ๋‹ค.

๋ชฉ์ฐจ ๋ฐ”๋กœ๊ฐ€๊ธฐ