업데이트:

태그: ,

카테고리:

Velopert

koa프레임워크란

express를 개발한 팀이 개발한 프레임워크이다.
express에서 고치고 싶던 문제를 고친 프레임워크, express는 다양한 기능들이 기본적으로 내장된 프레임워크였는데, koa는 필요한 기능만 만들어서 서버를 만들 수 있기 때문에 훨씬 가볍다.

설치

(공식홈페이지)[https://koajs.com/]

node v7.6.0이상이 필요하다.

설치 명령어는 npm i koa

이후, 실행하고자하는 서버가 열린 곳에서 node 디렉터리명으로 서버를 실행한다.

기본 사용법

서버시작

koa의 사용법은 express의 사용법과 비슷하다.

  1. koa를 import(require)하고,
  2. koa객체를 새로 만들어 app을 정의하고
  3. use로 미들웨어, listen으로 포트열기

이렇게 사용된다.

const koa = require("koa");

const app = new koa();

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

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

미들웨어

koa 앱은 미들웨어의 배열로 구성되어있다. app.use함수는 미들웨어 함수를 애플리케이션에 등록한다.

ctx

미들웨어 함수는 (ctx, next) => {} 이렇게 구성되어있다.

ctx 는 Context의 줄임말로, 웹 요청과 응답에 관한 정보를 가지고 있다.
express에선 (req,res)로 요청과 응답에 관한 파라미터가 나뉘어있었다면, koa는 ctx 파라미터 안에 모두 담겨있다.

next는 현재 처리 중인 미들웨어의 다음 미들웨어를 호출하는 함수이고, 역시 next 함수를 호출하지 않으면 다음 미들웨어를 호출하지 않는다.

next

koa의 next()는 다음 미들웨어 함수를 호출하는데, 이때 Promise를 반환한다.
따라서 next함수가 반환하는 Promise는 다음에 처리해야할 미들웨어가 끝나야 완료된다.

app.use((ctx, next) => {
  console.log(ctx.url);
  console.log(1);
  if (ctx.query.authorized !== "1") {
    ctx.status = 401;
    return;
  }
  next().then(() => {
    console.log("end");
  });
});
app.use((ctx, next) => {
  console.log(2);
  next();
});
app.use((ctx, next) => {
  console.log(3);
  next();
});
  1. console.log(1)이 출력.
  2. next()로 다음 미들웨어 함수를 호출, 호출된 미들웨어 함수들의 호출이 끝나야 console.log(‘end’)실행
  3. console.log(2)
  4. next()로 다음 미들웨어
  5. console.log(3)
  6. next()로 다음 미들웨어가 호출되어야하지만, 마지막 미들웨어이므로, console.log(‘end’) 실행

async/await

Koa는 async/await문법을 정식으로 지원한다. 따라서 .then으로 처리했던 함수를 변경할 수 있다.

app.use(async (ctx, next) => {
  //함수 앞에 async
  console.log(ctx.url);
  console.log(1);
  if (ctx.query.authorized !== "1") {
    ctx.status = 401;
    return;
  }
  await next(); //비동기처리를 하고자하는 작업 앞에 await
  console.log("end");
});

koa-router

koa에서 라우터를 사용하기 위해선 별도의 모듈 설치가 필요하다.(다른점!)

npm i koa-router 설치

const Koa = require("koa");
const Router = require("koa-router");

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

router.get("/", (ctx) => {
  ctx.body = "";
});
router.get("/about", (ctx) => {
  ctx.body = "소개";
});

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

app.listen(4000, () => {
  console.log(`listening on 4000`);
});

router를 new Router();로 선언하고, 이 라우터에 메서드별로 동작을 할당할 수 있다.

라우트 파라미터, 쿼리

사용법은 express와 동일하다.

/about/:name방식으로 콜론을 붙이는 방식으로 파라미터를 설정하며, ctx.params(express의 req.params와 동일)로 조회한다.

router.get("/about/:name?", (ctx) => {
  const { name } = ctx.params;
  ctx.body = name ? `${name}의 소개` : "소개";
});

URL 쿼리는 /posts/?id=10 방식으로 설정하며 ctx.query에서 조회할 수 있다. 쿼리 문자열을 자동으로 객체형태로 파싱해주기 때문에 따로 파싱을 할 필요가 없다고 한다.

router.get("/posts", (ctx) => {
  const { id } = ctx.query;
  ctx.body = id ? `포스트 # ${id}` : "포스트아이디 존재하지 않음";
});

REST API

웹 어플리케이션을 만들기 위해선 DB에 정보를 입력하고 읽어와야한다.
그런데 웹 브라우저에서 DB에 직접 접속해 데이터를 변경하면 보안상 문제가 되기 때문에 REST API를 사용한다.

rest

  1. 클라이언트의 CRUD요청
  2. 서버는 필요한 로직에 따라 DB에 접근해 요청을 처리한다.

자세한건 (Meetup!)[https://meetup.toast.com/posts/92]참고바람.

rest api를 요약하자면

  • 클라이언트의 요청을 HTTP 메서드별로 구분하고
  • 각 라우터에 알맞게 적용한다.


Http 메서드 종류

REST API는 클라이언트의 요청 종류에 따라 다른 HTTP 메서드를 사용한다.
HTTP 메서드의 종류에는

  • GET : 조회
  • POST : 등록, 인증(로그인)
  • DELETE : 삭제
  • PUT : 데이터를 새 정보로 통째로 교체
  • PATCH : 업데이트

가 있다.


REST API를 설계할때는 주소와 메서드에 따라 어떤 역할을 하는지 쉽게 알 수 있게 해야한다.
가령, 노마드 코더의 wetube 라우터를 보면,

-Global router-
GET    / -> Home 조회
GET /join -> 가입페이지 조회
POST /join -> 가입한 유저의 데이터 등록
GET /login -> 로그인 페이지 조회
POST /login -> 로그인 정보 등록
GET /search -> search페이지 조회
GET /search/:id -> 특정 비디오 조회

-User router-
PATCH /users/:id/edit -> 유저 데이터 수정
DELETE /users/:id/delete -> 유저 데이터 삭제

-Video router-
GET /videos -> 비디오 나열 페이지 조회
GET /videos/upload -> 비디오 업로드 페이지 조회
POST /videos/upload/:id -> 특정 비디오 업로드
GET /videos/:id -> 특정 비디오 조회
PATCH /videos/:id/edit -> 특정 비디오 업데이트
DELETE /videos/:id/delete -> 특정 비디오 삭제
POST /videos/:id/comment -> 특정 비디오에 덧글 등록
GET /videos/:id/comment -> 특정 비디오에 덧글 조회
DELETE /videos/:id/comment/:commentId -> 특정 포스트의 특정 덧글 삭제

이렇게 REST API 규칙을 적용해 표현할 수 있을 것이다.

라우트 모듈화

라우트 별로 나누어서 가독성이 좋게 변경한다.
테스트 모듈을 작성하면, 아래 코드와 같다.

const Router = require("koa-router");
const api = new Router();

api.get("/test", (ctx) => {
  ctx.body = "라우터 모듈화 테스트";
});

module.exports = api;

src 디렉터리에서 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 on 4000`);
});

POSTMAN을 활용한 REST API요청 테스팅

postman이란 프로그램은 REST API 요청 테스팅을 쉽게 할 수 있게 해준다.

이에 앞서, 테스팅 라우트를 삭제하고 posts 라우터를 구현한다.

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;
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 인스턴스에 라우터 적용
app.use(router.routes()).use(router.allowedMethods());

app.listen(4000, () => {
  console.log(`listening on 4000`);
});

스크린샷 2021-12-27 오후 6 48 36

이렇게 다양한 method의 request를 테스트할 수 있다.

컨트롤러 설정

라우트 처리 함수만 모아놓은 파일을 컨트롤러라고 한다.
DB를 연결하기 전이므로 JS의 배열기능으로 임시로 CRUD를 구현한다.

이 전에, koa-bodyParser 미들웨어를 적용해야 Request로 날라온 데이터를 파싱해 서버에서 사용할 수 있다.

npm i koa-bodyParser

그리고 적용

const Koa = require("koa");
const Router = require("koa-router");
const bodyParser = require("koa-bodyparser");

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

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

// 라우터 설정
router.use("/api", api.routes());

// 라우터 적용 전 bodyParser적용
app.use(bodyParser());

//app 인스턴스에 라우터 적용
app.use(router.routes()).use(router.allowedMethods());

app.listen(4000, () => {
  console.log(`listening on 4000`);
});

댓글남기기