Koa 프레임워크 접하기

오형근·2022년 4월 14일
0

Study

목록 보기
1/7
post-thumbnail

벨로퍼트 님의 "리액트를 다루는 기술" 21챕터에 대한 내용이다.

Express의 단점을 보완한 Koa 프레임워크를 통해 node 기반 백엔드를 구축하는 방법을 배운다.

Koa의 특징

Express와 다르게 Koa는 미들웨어의 배열로 구성되어 있어 미들웨어 기능만을 가지고 있다. 따라서 라우팅, 파일 호스팅 등등의 다양한 기능들은 모두 라이브러리를 적용하여야 한다.

Koa는 우리가 사용하고픈 기능들만 불러와서 서버를 만들 수 있어 Express에 비해 훨씬 가볍다.

또한 async/await 문법을 정식으로 지원하기 때문에 비동기 작업을 편하게 처리할 수 있다!


Koa 코드 톺아보기

Koa의 미들웨어 함수는 다음과 같은 구조로 이루어져 있다.

(ctx, next) => {
}

ctxContext의 줄임말로 웹 요청과 응답에 관한 정보를 가진다. next는 현재 처리 중인 미들웨어의 다음 미들웨어를 호출한다.
만일 미들웨어에서 next를 사용하지 않으면 아래와 같은 형태로 next를 전달하지 않아도 좋다. 일반적으로 다음 미들웨어가 필요없는 라우트 미들웨어를 설정할 때 이러한 구조로 작성한다.

미들웨어는 app.use를 사용해 등록되는 순서대로 처리한다.
이때 next를 호출하지 않으면 해당 미들웨어까지만 실행하고 그 아래 미들웨어는 모두 무시된다.

다음과 같은 설정으로 쿼리 파라미터를 이용한 조작도 가능하다.

app.use((ctx, next) => {
    console.log(ctx.url); //context 내부의 url을 호출. 현재 페이지에 대한 url을 불러온다.
    console.log(1);
    if (ctx.query.authorized !== "1") {
        ctx.status = 401; // Unauthorized
        return; // url 뒤에 ?authorized=1이 있어야 올바른 body를 호출함.
    }
    next();
});

또한 next함수는 Promise를 반환한다. 이는 Express와 차별화되는 부분인데,
Promise는 다음에 처리할 미들웨어가 끝나야 완료된다. 이러한 특징을 이용하면 미들웨어 간의 실행 순서를 쉽게 조정할 수 있을 것이다.

async/await

위에 언급한 것처럼 Koaasync/await을 정식으로 지원한다. 다음 코드를 살펴보자.

app.use(async (ctx, next) => {
    console.log(ctx.url); //context 내부의 url을 호출. 현재 페이지에 대한 url을 불러온다.
    console.log(1);
    if (ctx.query.authorized !== "1") {
        ctx.status = 401; // Unauthorized
        return;
    }
    await next(); // 뒤의 미들웨어를 실행한 뒤 END를 찍는다.
    console.log("END"); // 미들웨어를 실행한 뒤 작업을 수행. Koa의 미들웨어는 Promise를 반환하고 이 Promise는 다음에 처리할 미들웨어가 끝나야만 반환된다.
});

Koa-router 사용하기

Koa는 내장 라우터 기능이 없으므로 라이브러리를 적용해야한다.

$ yarn add 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 인스턴스에 라우터 적용 -> 그래야 app과 router가 연동된다.
app.use(router.routes()).use(router.allowedMethods());

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

파라미터와 쿼리

라우트의 파라미터를 설정하는 것은 일반적인 형식과 비슷하다.
/about/:name과 같은 형식으로 라우트 경로를 설정한다.
파라미터가 조건부로 존재한다면/about/:name?과 같은 형식으로 설정한다.
이렇게 설정된 파라미터는 함수의 ctx.params 객체를 통해 조회할 수 있다.

쿼리 문자열을 자동으로 객체 형태로 파싱해 주므로 별도의 파싱 함수를 돌릴 필요가 없다!!!(문자열 형태의 쿼리 문자열 조회에는 ctx.querystring을 사용한다!)

다음 예시를 살펴보자.

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/:name?", ctx => {
    const { name } = ctx.params;
    // name의 존재 여부에 따라 다른 결과 출력
    ctx.body = name ? `${name}의 소개` : "소개";
});

router.get("/posts", ctx => {
    const { id } = ctx.query;
    // id의 존재 여부에 따라 다른 결과 출력
    ctx.body = id ? `포스트 #${id}` : "포스트 아이디가 없습니다.";
});

// app 인스턴스에 라우터 적용 -> 그래야 app과 router가 연동된다.
app.use(router.routes()).use(router.allowedMethods());

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

위에서 name은 파라미터로 불러왔고, id는 쿼리했다. 이처럼 파라미터와 쿼리는 둘 다 주소를 통해 특정 값을 받아올 때 사용하지만, 용도가 조금 다르다.

파라미터는 처리할 작업의 카테고리를 받아오거나, 고유 ID 혹은 이름으로 특정 데이터를 조회할 때 사용한다.

쿼리는 옵션에 관련된 정보를 받아온다. 예를 들어 여러 항목을 리스팅하는 API라면, 어떤 조건을 만족하는 항목을 보여줄지 또는 어떤 기준으로 정렬할지를 정해야 할 때 쿼리를 사용한다.

라우트 모듈화

애플리케이션을 제작할 때 라우트 경로가 아주 많아지고 복잡해질 가능성이 크다.
이러한 경우 특정 용도나 목적에 따라 라우트를 분류하고 코드를 작게 쪼개는 작업은 필수적인데, Koa를 이용한 라우트 모듈화가 어떻게 이루어지는지 알아보자.

src/api/index.js

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()); // api 라우트 적용

// app 인스턴스에 라우터 적용 -> 그래야 app과 router가 연동된다.
app.use(router.routes()).use(router.allowedMethods());

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

위의 코드 예시처럼 src 디렉토리에 api 디렉토리를 추가로 만들고, 그곳에서 Router를 이용해 새로운 api를 제작한다. 이후 module.exports를 이용해 export하면 이후 src 디렉토리에서 라우터를 적용할 수 있게 된다.


지금까지 Koa 프레임워크에 대한 특징과 짧은 예시들을 살펴보았다.

앞으로 계속 Koa에 익숙해지는 시간을 가지면서 백엔드에 적응해보자.

profile
https://nohv.site

0개의 댓글