๐ŸŒณ๋ชฉํ‘œ

๋ฉ”์†Œ๋“œ ์ด๋ฆ„์œผ๋กœ ๋ผ์šฐํŒ…ํ•˜๋Š” ๊ธฐ๋Šฅ์„ ๊ตฌํ˜„ํ•ฉ๋‹ˆ๋‹ค.

POST ๋ฉ”์†Œ๋“œ ์š”์ฒญ

ํ™”๋ฉด์„ ์กฐ๊ธˆ ๋ณ€๊ฒฝํ–ˆ๋Š”๋ฐ์š”, ๋ธŒ๋žœ์น˜๋ฅผ ์ด๋™ํ•˜๊ณ  ํ™•์ธํ•ด ๋ณผ๊นŒ์š”?

$ git checkout -f application/get-post-spec

์„œ๋ฒ„๋ฅผ ์‹คํ–‰ํ•˜๊ณ  ๋ธŒ๋ผ์šฐ์ ธ๋กœ ์ ‘์†ํ•ฉ๋‹ˆ๋‹ค.

ํ™”๋ฉด ์ƒ๋‹จ์— ์ž…๋ ฅ ํผ์„ ๋งŒ๋“ค์—ˆ์Šต๋‹ˆ๋‹ค. ์—ฌ๊ธฐ์— ํฌ์ŠคํŠธ ์ œ๋ชฉ๊ณผ ๋‚ด์šฉ์„ ์ž…๋ ฅํ•˜๊ณ  submit ๋ฒ„ํŠผ์„ ๋ˆŒ๋Ÿฌ ๋ณผ๊นŒ์š”?

โ€œPOST /api/postsโ€ ์—”๋“œํฌ์ธํŠธ๋ฅผ ์š”์ฒญํ•˜๊ณ  ์žˆ๋„ค์š”. ์ง€๊ธˆ๊นŒ์ง€๋Š” GET ๋ฉ”์†Œ๋“œ๋งŒ ์š”์ฒญํ–ˆ์ง€๋งŒ ํผ ์ „์†ก๋ถ€ํ„ฐ๋Š” POST ๋ฉ”์†Œ๋“œ๋ฅผ ์‚ฌ์šฉํ•˜๊ธฐ ์‹œ์ž‘ํ•ฉ๋‹ˆ๋‹ค.

ํ”„๋ก ํŠธ์—”๋“œ ์ฝ”๋“œ๋ฅผ ๋” ์‚ดํŽด ๋ณผ๊นŒ์š”?

createPost({title, body}) {
  const data = `title=${title}&body=${body}`
  return http('post', '/api/posts', data)
}

submit ์ด๋ฒคํŠธ๊ฐ€ ๋ฐœ์ƒํ•˜๋ฉด createPost() ํ•จ์ˆ˜๊ฐ€ ๋™์ž‘ํ•˜๋Š”๋ฐ ๋‚ด๋ถ€์ ์œผ๋กœ POST ๋ฉ”์†Œ๋“œ๋ฅผ ์‚ฌ์šฉํ•˜๊ณ  ์žˆ๋„ค์š”.

ํ˜„์žฌ ์„œ๋ฒ„์—์„œ๋Š” ์š”์ฒญ ์ •๋ณด๋ฅผ ๋น„๊ตํ•  ๋•Œ ๊ฒฝ๋กœ๋งŒ ๋น„๊ตํ•˜๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค. ๋ฏธ๋“ค์›จ์–ด ์ฝ”๋“œ๋ฅผ ์‚ดํŽด ๋ณผ๊นŒ์š”?

if (nextMw._path) {
  const pathMatched = _req.path === nextMw._path;
  return pathMatched ? nextMw(_req, _res, next) : _run(i + 1)
}

๊ฒฝ๋กœ๋งŒ ๋น„๊ตํ•˜๊ธฐ ๋•Œ๋ฌธ์— ๋™์ผํ•œ URL ์š”์ฒญ์ผ ๊ฒฝ์šฐ ๋ฉ”์†Œ๋“œ์— ์ƒ๊ด€์—†์ด ์‘๋‹ตํ•˜๋Š” ๊ฒƒ์ด ํ˜„์žฌ ์„œ๋ฒ„์˜ ํ•œ๊ณ„์ž…๋‹ˆ๋‹ค.

ํ”„๋ก ํŠธ์—”๋“œ์—์„œ ์š”์ฒญํ•˜๋Š” POST ๋ฉ”๋„๋“œ๋ฅผ ์ง€์›ํ•˜๋ ค๋ฉด ๊ฒฝ๋กœ ๋ฟ๋งŒ ์•„๋‹ˆ๋ผ ์š”์ฒญ ๋ฉ”์†Œ๋“œ๊นŒ์ง€ ๋น„๊ตํ•ด์•ผ ๊ฒ ์ง€์š”?

๐Ÿค์‹ค์Šต - ๋ผ์šฐํŠธ ๋“ฑ๋ก ํ•จ์ˆ˜ post(), get()์„ ๋งŒ๋“ค์–ด ๋ณด์„ธ์š”

์–ดํ”Œ๋ฆฌ์ผ€์ด์…˜์˜ use() ๋ฉ”์†Œ๋“œ๋Š” ๋ผ์šฐํŠธ ๋“ฑ๋ก์„ ์œ„ํ•œ ๋…€์„์ž…๋‹ˆ๋‹ค. ๊ฒฝ๋กœ์™€ ์ปจํŠธ๋กค๋Ÿฌ ํ•จ์ˆ˜๋ฅผ ๋ฐ›์•„ ๋“ฑ๋กํ• ์ˆ˜ ์žˆ์ง€์š”. ์ด์™€ ์œ ์‚ฌํ•˜๊ฒŒ post()๋Š” ์š”์ฒญ ๋ฉ”์†Œ๋“œ POST๊นŒ์ง€ ๋“ฑ๋กํ•˜๋Š” ํ•จ์ˆ˜์ž…๋‹ˆ๋‹ค. get()๋„ ๋งˆ์ฐฌ๊ฐ€์ง€๊ตฌ์š”.

๋ฉ”์†Œ๋“œ ์ •๋ณด๊นŒ์ง€ ๋“ฑ๋กํ•˜๋Š” post()์™€ get() ๋ฉ”์†Œ๋“œ๋ฅผ ๊ตฌํ˜„ํ•ด ๋ณด์„ธ์š”.

ํžŒํŠธ: ๊ฒฝ๋กœ ์ •๋ณด๋ฅผ _path์— ์ €์žฅํ•œ ๊ฒƒ์ฒ˜๋Ÿผ _method๋ž€ ์ด๋ฆ„์œผ๋กœ ์ €์žฅ

๐Ÿคํ’€์ด

๊ทธ๋Ÿผ ๊ฐ™์ด ํ’€์–ด ๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค.

์–ดํ”Œ๋ฆฌ์ผ€์ด์…˜ ๋ฉ”์†Œ๋“œ๋กœ ์ถ”๊ฐ€ํ•˜๋‹ˆ๊น src/Application.js ์ฝ”๋“œ๋ฅผ ์ˆ˜์ •ํ•ฉ๋‹ˆ๋‹ค. ๋‘ ๋ถ€๋ถ„์œผ๋กœ ๋‚˜๋ˆ ์„œ ์„ค๋ช…ํ• ๊ฒŒ์š”.

const get = (path, fn) => {
  if (!path || !fn) throw Error('path and fn is required')
  fn._method = 'get'
  use(path, fn)
}

use() ๋ฉ”์†Œ๋“œ์ฒ˜๋Ÿผ ๊ฒฝ๋กœ์™€ ์ปจํŠธ๋กค๋Ÿฌ ํ•จ์ˆ˜๋ฅผ ์ธ์ž๋กœ ์ทจํ•ฉ๋‹ˆ๋‹ค. ์ธ์ž๊ฐ€ ํ•„์ˆ˜๋กœ ๋“ค์–ด์™”๋Š”์ง€ ์ ๊ฒ€ํ•˜๊ณ  ๊ทธ๋ ‡์ง€ ์•Š์œผ๋ฉด ์˜ˆ์™ธ๋ฅผ ๋˜์ ธ ํ”„๋กœ๊ทธ๋žจ์„ ์ค‘์ง€์‹œํ‚ต๋‹ˆ๋‹ค.

๋ฏธ๋“ค์›จ์–ด์ธ ์ปจํŠธ๋กค๋Ÿฌ ํ•จ์ˆ˜์˜ _method ์†์„ฑ์— โ€˜getโ€™ ๋ฌธ์ž์—ด์„ ํ• ๋‹นํ•˜์—ฌ ์š”์ฒญ ๋ฉ”์†Œ๋“œ๋ฅผ ์ €์žฅํ•ฉ๋‹ˆ๋‹ค. ๊ทธ๋ฆฌ๊ณ  ๊ฒฝ๋กœ์™€ ์ปจํŠธ๋กค๋Ÿฌ๋ฅผ ๋ผ์šฐํŠธ ๋“ฑ๋ก ํ•จ์ˆ˜์ธ use() ๋ฉ”์†Œ๋“œ ์ธ์ž๋กœ ์ „๋‹ฌํ•ด ์ฃผ์—ˆ์Šต๋‹ˆ๋‹ค.

const post = (path, fn) => {
  if (!path || !fn) throw Error('path and fn is required')
  fn._method = 'post'
  use(path, fn)
}

return {
  // ...
   get,
   post,
}

post()๋„ ๋ฉ”์†Œ๋“œ ์ด๋ฆ„๋งŒ ๋‹ค๋ฅด์ง€ ๋กœ์ง์€ ์™„์ „ํžˆ ๋™์ผํ•ฉ๋‹ˆ๋‹ค.

์ด์ œ ๋ฏธ๋“ค์›จ์–ด๋ฅผ ์‹คํ–‰ํ•  ๋•Œ ์ด ์ •๋ณด๋ฅผ ๋น„๊ตํ•ด์•ผ๊ฒ ์ฃ ? src/Middleware.js ํŒŒ์ผ๋กœ ์ด๋™ํ•ฉ๋‹ˆ๋‹ค.

  if (nextMw._path) {
    const pathMatched = _req.path === nextMw._path &&
      _req.method.toLowerCase() === (nextMw._method || 'get');

    return pathMatched ? nextMw(_req, _res, next) : _run(i + 1)
  }

๋“ฑ๋ก๋œ ๊ฒฝ๋กœ๊ฐ€ ์žˆ์„ ๊ฒฝ์šฐ์— ๊ทธ๊ฒƒ๊ณผ ์š”์ฒญ ๊ฒฝ๋กœ๋ฅผ ๋น„๊ตํ•˜๋Š” ๋กœ์ง์„ ๊ฐœ์„ ํ•ฉ๋‹ˆ๋‹ค. ๊ฒฝ๋กœ ๋ฟ๋งŒ์•„๋‹ˆ๋ผ ๋“ฑ๋กํ•œ ๋ฉ”์†Œ๋“œ ์ด๋ฆ„๋„ ํ•จ๊ป˜ ๋น„๊ตํ•˜๋Š” ๊ฒƒ์ด์ฃ . ๋งŒ์•ฝ ๋“ฑ๋กํ•œ ๋ฉ”์†Œ๋“œ๊ฐ€ ์—†์œผ๋ฉด ๊ธฐ๋ณธ๊ฐ’์ธ โ€œgetโ€์„ ๋“ฑ๋กํ•œ ๊ฒƒ์œผ๋กœ ํ•ฉ๋‹ˆ๋‹ค. ๋Œ€์†Œ๋ฌธ์ž์™€ ๋ฌด๊ด€ํ•˜๊ฒŒ ๋™์ž‘ํ•˜๋„๋ก ํ•˜๋ ค๊ณ  ์†Œ๋ฌธ์ž๋กœ ๋ณ€ํ™˜ํ•˜์—ฌ ๋น„๊ตํ•œ ๊ฒƒ์„ ๋ˆˆ์—ฌ๊ฒจ ๋ณด์‹œ๊ธฐ ๋ฐ”๋ž๋‹ˆ๋‹ค.

POST ๋ฉ”์†Œ๋“ค๋ฅผ ์ง€์›ํ•˜๋Š” ์—”๋“œํฌ์ธํŠธ ๋งŒ๋“ค๊ธฐ

๊ทธ๋Ÿผ ์ด๋ฅผ ๋ฐ”ํƒ•์œผ๋กœ ํฌ์ŠคํŠธ ์ƒ์„ฑ API๋ฅผ ๋งŒ๋“ค์–ด ๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค.

ํฌ์ŠคํŠธ ๊ด€๋ จ API ์ปจํŠธ๋กค๋Ÿฌ ํ•จ์ˆ˜๋ฅผ ์ •์˜ํ•œ routes/api/post.js ํŒŒ์ผ์— ๋กœ์ง์„ ์ถ”๊ฐ€ํ•ฉ๋‹ˆ๋‹ค.

const create = () => (req, res, next) => {
  debug(`create() ${req.body}`)
}

module.exports = {
  index,
  create,
}

์ƒ์„ฑ์„ ์˜๋ฏธํ•˜๋Š” create๋ž€ ์ด๋ฆ„์œผ๋กœ ํ•จ์ˆ˜๋ฅผ ๋งŒ๋“ค์—ˆ์Šต๋‹ˆ๋‹ค. ์‹ค์ œ ๋กœ์ง์€ ์—†๊ณ  ๋กœ๊ทธ๋งŒ ๊ธฐ๋กํ•˜๊ณ  ์žˆ๊ตฌ์š”. ์™ธ๋ถ€์—์„œ ๋ผ์šฐํŠธ ๋“ฑ๋ก์„ ์œ„ํ•ด ๋ชจ๋“ˆ๋กœ ๋…ธ์ถœ์‹œ์ผฐ์Šต๋‹ˆ๋‹ค.

app.js์—์„œ ์ด ์ปจํŠธ๋กค๋Ÿฌ ํ•จ์ˆ˜๋ฅผ ๋“ฑ๋กํ•˜๊ฒ ์Šต๋‹ˆ๋‹ค.

app.get('/api/posts', apiPost.index()) // use() ์˜€๋˜ ๊ฒƒ์„ get() ์œผ๋กœ ๋ช…ํ™•ํžˆ ๋“ฑ๋ก
app.post('/api/posts', apiPost.create()); // post()๋กœ ๋“ฑ๋ก
app.use(errors.error404());
// ...

use()๋กœ ๋“ฑ๋กํ–ˆ๋˜ ํฌ์ŠคํŠธ ์กฐํšŒ ์—”๋“œํฌ์ธํŠธ๋Š” get() ๋ฉ”์†Œ๋“œ๋กœ ์˜๋ฏธ๋ฅผ ๋” ๋ช…ํ™•ํ•˜๊ฒŒ ๊ฐœ์„ ํ–ˆ์Šต๋‹ˆ๋‹ค. ๋ฟ๋งŒ ์•„๋‹ˆ๋ผ post() ๋ฉ”์†Œ๋“œ๋กœ ํฌ์ŠคํŠธ ์ƒ์„ฑ ์—”๋“œํฌ์ธํŠธ๊นŒ์ง€ ์ถ”๊ฐ€ํ–ˆ๊ตฌ์š”.

์ •๋ฆฌ

  • get(), post() ๋ฉ”์†Œ๋“œ๋ฅผ ๋งŒ๋“ค์–ด ๋” ๋ช…ํ™•ํ•˜๊ฒŒ ์—”๋“œํฌ์ธํŠธ๋ฅผ ๋“ฑ๋กํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

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