TIL - Express

김수지·2019년 12월 8일
0

TILs

목록 보기
15/39

Today What I Learned

Javascript를 배우고 있습니다. 매일 배운 것을 이해한만큼 정리해봅니다.


1. Express 개념 정리

  1. Express란?

    • Express는 Node.js 환경에서 동작하는 웹 애플리케이션 프레임워크으로 미들웨어를 붙여서 사용할 수 있는 것과 라우팅 기능을 제공하는 장점이 있다.
    • node.js 기반이며 npm을 통해 다운 받을 수 있다.
    • 기존에 bare node.js에서는 http.createserver 기능을 통해 서버를 생성하였으나, express 프레임워크에서는 express의 instance를 만들어 서버를 사용한다.
    • Express에서 에러 처리는 매개변수가 4개(err, req, res, next)인 미들웨어 함수를 사용하고, 이를 이용해 에러 발생 시 console.err(err.stack) 형식을 취한다.
  2. Middleware란?

    • 미들웨어는 요청 객체(req), 응답 객체(res) 사이에서 중간 처리 역할을 수행한다.
    • 미들웨어를 통해 요청에 대한 응답 처리 전까지 다양한 일을 처리할 수 있다.
    • 실제로 body parser나 cors 처리 등은 http를 이용한 서버 구축에서 꽤 긴 문장을 차지했는데, 이러한 미들웨어를 사용하면서 코드가 굉장히 깔끔하고 짧게 작성되었고 payload를 파싱해서 보여주거나 cors 요청에 손쉽게 응답할 수 있었다.
      image.png[출처: express 홈페이지]
  3. Routing?

    • 클라이언트로부터 받은 요청에 어떻게 응답할 것인지를 결정하는 행위
    • Route handler는 요청을 처리하는 콜백함수이다.
    • 각 라우트는 1개 혹은 1개 이상의 라우트 핸들러 함수를 가지고 있어서 해당하는 method가 인지되었을 때 실행된다.
      image.png [출처: https://poiemaweb.com/express-basics]
    • 운영하는 웹 서비스의 규모가 크고 다양한 api가 사용될 때 routing을 통해 유용하게 분기점을 구분할 수 있다.

2. express로 서버 리팩토링 하기

  1. node.js와 서버에 대해서 배우는 과정에서 서버는 분기를 잘 해준다는 점이 매우 매력적이었다. 물론 클라이언트에서도 다양한 함수를 통해 이벤트 발생 시 핸들링을 해주지만 서버단에서의 라우팅이나 요청 대응은 뭔가 더 체계적이고 안정감 있게 지원을 해주는 느낌이었다고 해야 하나? 아무튼... Express로 리팩토링 하기
  2. 중점적으로 익힌 내용
    • 미들웨어, 라우팅이 적용된 서버 리팩토링 : http를 이용한 서버를 구축하면서 서버 구축의 기본적인 개념과 요소를 배웠다면 이번에는 이들을 편리하고 빠르게 대체해줄 수 있는 프레임워크를 통해 리팩토링 해보는 것이 목표였다.
  3. 고전했던 부분
    • 라우팅 적용: 몇일 전 내가 구축했던 chatter-box 클라이언트는 단일 패스로 구성되어서 서버로 요청을 하더라도 분기점이 딱히 필요하지 않았다. 상황이 이렇다 보니 라우팅의 필요성을 크게 느끼지 못했고, express 서버 내 method로 대응하는 것과 express.Router를 이용한 분기 처리 후 method에 따른 대응 코드를 작성해주는 것을 크게 구분하지 못했다. 개념을 확실히 하기 위해서 페어들에게도 질문하고, 엔지니어와의 시간에 직접 질문을 했다. 한 개의 웹서비스 내 다양한 패스를 통해 로그인/로그아웃/조회 등 다양한 api를 주고 받아야 할 수 있다는 예시를 듣고 나서 라우팅의 필요성과 정확한 개념을 이해하게 되었다. 앞으로는 개념 학습을 하면서 실제 서비스 구현의 예제도 함께 찾아봐야겠다.

3. Code Review

  1. 전 날 작성했던 chatter box server는 크게 basic-server.js(server creation이 담김), request-handler.js(서버에 요청이 도달했을 때 핸들러 함수를 담음 - 이 파일이 메인이었음), 그리고 data.js(db storage creation 대신 사용했던 데이터 파일)로 구성되어 있었다.
  2. express 프레임워크를 사용하면서 basic-server.js에서는 기존의 server creation과 에러 대응과 routing을 구현했다. request-handler 대신 route.js를 만들어서 서버에 도달해 path 기준으로 라우팅 된 get, post 요청에 대응하는 함수를 구현했다. 그리고 똑같이 data.js를 db 성격으로 사용하였다.
  3. Express부터 배웠다면 http.createserver 방식은 별로 쳐다보고 싶지 않았을 것 같다. 특히 body parsing 같은 경우는 express 4.16버전 이후부터는 내장 모듈로 제공된다고 하는데, chunk를 모아 buffer에서 다시 객체로 파싱해주는 작업이 얼마나 자주 일어나는지 직접 손으로 쳐보고 나서 더 깊이 공감할 수 있어서 좋았다.
    좋은 배움이었으나 앞으로는 시간 효율을 위해서라도 그냥 express만 쓰고 싶다...ㅎㅎㅎ
  • basic-server.js
const express = require("express");
const app = express();

const bodyParser = require("body-parser");
const cors = require("cors");
const route = require("./route");

const PORT = 3001;
const ip = "127.0.0.1";

app.use(cors()); // 미들웨어로 cors 대응
app.use(bodyParser.json()); // 미들웨어로 req payload 파싱 처리
app.use("/classes/messages", route); // path routing
app
  .use((req, res) => {
    res.status(404).send("no such a matching address"); // 잘못된 페이지 요청 에러 처리
  })
  .use((err, req, res) => {
    console.err(err.stack);
    res.statsu(500).send("internal server error"); // 내부 서버 오류 처리
  });

app.listen(PORT, () => {
  // 서버 작동
  console.log(`server listen on ${ip} : ${PORT}`);
})
  • route.js
const { storage } = require("./data.js");
let { idNum, date } = require("./data.js");

const express = require("express");
const router = express.Router();

router.use((req, res, next) => {
  console.log(`http method is ${req.method}, url is ${req.url}`);
  next();
});

router
  .route("/")
  .get((req, res) => {
    res.status(200).send(storage);
  })
  .post((req, res) => {
    if (req.body.text === "" || req.body.username === "") {
      // 메시지나 이름이 입력되지 않았을 때 에러 처리
      console.log(req.body.username, req.body.text);
      res.status(400).send();
    } else {
      date = new Date();
      console.log("post", req.body);
      req.body["date"] = date;
      req.body["id"] = idNum;
      storage.results.push(req.body);
      res.status(201).end(JSON.stringify({ id: idNum }));
      idNum++;
    }
  });
module.exports = router;
  • data.js
const storage = { results: [] };

let idNum = 0;
let date = "";

module.exports = { storage, idNum, date };
profile
선한 변화와 사회적 가치를 만들고 싶은 체인지 메이커+개발자입니다.

0개의 댓글