'리액트를 다루는 기술' 21장, 백엔드 프로그래밍: Node.js의 Koa 프레임워크

Jake_Young·2020년 9월 12일
0
post-thumbnail

😄 Koa

  • Node.js 환경에서 웹 서버를 구축할 때는 보통 Express, Hapi, Koa 등의 웹 프레임워크를 사용한다.
  • Koa, Next generation web framework for node.js
  • Express는 미들웨어, 라우팅, 템플릿, 파일 호스팅 등의 다양한 기능이 자체적으로 내장되어 있음
  • Koa는 미들웨어 기능만 갖추고 있으며 나머지는 다른 라이브러리를 적용하여 사용한다.
  • Koa가 Express보다 훨씬 가볍다.
  • Koa는 Async/await 문법을 정식으로 지원하기 때문에 비동기 작업을 더 편하게 관리할 수 있다.

😎 Middleware

  • Koa의 미들웨어의 배열로 구성되어 있다.
  • app.use 함수는 미들웨어 함수를 애플리케이션에 등록한다.
  • 미들웨어 함수는 (ctx, next) => { } 구조로 작성된다.
  • ctx는 Context의 줄임말로 웹 요청과 응답에 관한 정보를 지니고 있다.
  • next는 현재 처리 중인 미들웨어의 다음 미들웨어를 호출하는 함수이다.
  • next를 호출하지 않으면, 그다음 미들웨어를 처리하지 않는다.
  • next 함수는 Promise를 반환한다.
  • 이 점이 Koa가 Express와 차별화되는 부분이다.
  • Koa는 async/await를 정식으로 지원한다(Express는 오류 처리가 제대로 되지 않아 3rd 라이브러리가 필요하다)
// index.js
const Koa = require('koa');

const app = new Koa();

app.use(async (ctx, next) => {
  console.log(ctx.url);
  console.log(1);
  if (ctx.query.authorized !== '1') {
    ctx.status = 401;
    return;
  }
  await next();
  console.log('END');
});

app.use((ctx, next) => {
  console.log(2);
  next();
});

app.use((ctx) => {
  ctx.body = 'hello world';
});

app.listen(4000, () => {
  console.log('Listening to port 4000');
});

😜 Nodemon

  • 서버 코드에 변경사항이 있을 때마다 서버를 자동으로 재시작 시켜준다.
  • yarn add --dev nodemon
  • 실행은 nodemon --watch src/ src/index.js로 한다.
  • src 폴더 아래에 변경사항이 생기면 src/index.js를 재시작하라는 의미이다.

😍 Koa-router

  • parameter는 ctx.params에서 찾을 수 있다
  • parameter는 url에 :name 처럼 적을 수 있다
  • :name? 마지막 '?'는 name이 선택사항임을 가리킨다
  • query는 ctx.query로 찾을 수 있다
// index.js
...

const Router = require('koa-router');
const router = new Router();

...

router.get('/about/:name?', (ctx) => {
  const { name } = ctx.params;

  ctx.body = name ? `${name}의 소개` : '소개';
});

router.get('/posts', (ctx) => {
  const { id } = ctx.query;

  ctx.body = id ? `포스트 #${id}` : '포스트 아이디가 없음이야~';
});

...

😱 Route 모듈화

// index.js
const Koa = require('koa');
const Router = require('koa-router');

const api = require('./api');

const app = new Koa();
const router = new Router();

router.use('/api', api.routes());

app.use(router.routes()).use(router.allowedMethods());

app.listen(4000, () => {
  console.log('Listening to port 4000');
});

// api/index.js
const Router = require('koa-router');
const api = new Router();

api.get('/test', (ctx) => {
  ctx.body = '성공!';
});

module.exports = api;

🤓 REST API

// src/api/posts/index.js
const Router = require('koa-router');
const posts = new Router();

const printInfo = (ctx) => {
  ctx.body = {
    method: ctx.method,
    path: ctx.path,
    params: ctx.params,
  };
};

posts.get('/', printInfo);
posts.post('/', printInfo);
posts.get('/:id', printInfo);
posts.delete('/:id', printInfo);
posts.put('/:id', printInfo);
posts.patch('/:id', printInfo);

module.exports = posts;

// src/api/index.js
const Router = require('koa-router');
const posts = require('./posts');

const api = new Router();

api.use('/posts', posts.routes());

module.exports = api;

🧐 Koa-bodyparser

  • 이 미들웨어는 POST/PUT/PATCH 같은 메서드의 Request Body에 JSON 형식으로 데이터를 넣어주면 이를 파싱하여 서버에서 사용할 수 있게 한다.
// index.js
...

const bodyParser = require('koa-bodyparser');

...

// router 적용 전에 실행시킨다.
app.use(bodyParser());

app.use(router.routes()).use(router.allowedMethods());

...

🥶 REST API2

// src/api/posts/posts.ctrl.js
let postId = 1;

const posts = [
  {
    id: 1,
    title: 'title',
    body: 'contents',
  },
];

exports.write = (ctx) => {
  const { title, body } = ctx.request.body;
  postId += 1;
  const post = { id: postId, title, body };
  posts.push(post);
  ctx.body = post;
};

exports.list = (ctx) => {
  ctx.body = posts;
};

exports.read = (ctx) => {
  const { id } = ctx.params;
  const post = posts.find((p) => p.id.toString() === id);
  if (!post) {
    ctx.status = 404;
    ctx.body = {
      message: 'post doesnt exist',
    };
    return;
  }
  ctx.body = post;
};

exports.remove = (ctx) => {
  const { id } = ctx.params;
  const index = posts.findIndex((p) => p.id.toString() === id);
  if (index === 1) {
    ctx.status = 404;
    ctx.body = {
      message: 'post doesnt exist',
    };
    return;
  }
  posts.splice(index, 1);
  ctx.status = 204;
};

exports.replace = (ctx) => {
  const { id } = ctx.params;
  const index = posts.findIndex((p) => p.id.toString() === id);
  if (index === -1) {
    ctx.status = 404;
    ctx.body = {
      message: 'post doesnt exist',
    };
    return;
  }
  posts[index] = {
    id,
    ...ctx.request.body,
  };
  ctx.body = posts[index];
};

exports.update = (ctx) => {
  const { id } = ctx.params;
  const index = posts.findIndex((p) => p.id.toString() === id);
  if (index === 1) {
    ctx.status = 404;
    ctx.body = {
      message: 'post doesnt exist',
    };
    return;
  }
  posts[index] = {
    ...posts[index],
    ...ctx.request.body,
  };

  ctx.body = posts[index];
};

// src/api/posts/index.js
const Router = require('koa-router');
const postsCtrl = require('./posts.ctrl');

const posts = new Router();

posts.get('/', postsCtrl.list);
posts.post('/', postsCtrl.write);
posts.get('/:id', postsCtrl.read);
posts.delete('/:id', postsCtrl.remove);
posts.put('/:id', postsCtrl.replace);
posts.patch('/:id', postsCtrl.update);

module.exports = posts;
profile
자바스크립트와 파이썬 그리고 컴퓨터와 네트워크

0개의 댓글