[TIL] Express.js

이재훈·2020년 10월 16일
0

JavaScript :)

목록 보기
5/5
post-thumbnail

What I learned???

  🌟 Express
     - Express 정의
     - 미들웨어

공식문서: https://expressjs.com/en/guide/routing.html

🌱   Express

     Express 정의

  Express는 웹 어플리케이션 혹은 API를 제작하기 위해 사용되어지고, node.js로 동작하는 간결한 웹 프레임워크이다.
또한 이 Express 프레임워크는 별도의 다운로드를 통해 설치를 하여야 하는데

npm install express --save

위의 명령어를 터미널에 입력하면 다운 및 설치가 가능하다.
설치에 관한 자세한 설명은 공식문서(클릭)에 있으니 살펴보길 바란다.

     간단한 서버 만들기

Express.js 설치가 선행되어져야 한다.

서버를 만든 후 Hello world를 출력해보자!
서버가 무사히 구축이 되었다면 Hello world가 보일 것이다.

(공식문서 토대로 적어보았습니다.)
const express = requir('exress');
const app = express();

const port = 3000; // 임의 변경 가능
 
var cors = require('cors'); // 필요시 설치

app.use(cors()); // 모든 요청에 대해 CORS 허용  -> npm install cors


/* 혹은
 특정 요청에 대해 CORS 허용
app.get('/products/:id', cors(), function (req, res, next) {
  res.json({msg: 'This is CORS-enabled for a Single Route'})
}) 
*/

app.get('/', (req, res) => {
  res.send('Hello World!');
});

app.listen(port, () => {
  console.log(`Example app listening at http://localhost:${port}`);
});

cors 경우 필요시 설치하면 되는데,
package.json의 dependencies에 cors가 설치가 되어있는지 확인해보면 된다.

아래 사진과 같이 Hello World!가 출력이 되면 서버가 잘 구동되고 있다는 뜻이다.

     Routing(route)

  Potter's 영/한 사전 😎
  
   Routing (route)
    1. 여정(旅程), 절차의 결정 
    2. 전달, 발송, 발송 절차

라우팅 은 애플리케이션이 특정 엔드 포인트 (URI (또는 경로) 및 특정 HTTP 요청 메서드 (GET, POST 등))에 대한 클라이언트 요청에 응답하는 방식을 결정하는 것을 의미합니다. -공식문서-

즉, 라우팅이란,
클라이언트로부터 받은 요청에 대해 어떻게 응답할 것인지 결정하는 것을 말한다.

라우트는 아래와 같이 구현된다.

  app.HTTP Method('요청 경로(path)', Route handler)
  • HTTP Method : GET, POST, PUT, DELETE (from client)
  • 요청 경로 : URL(/lower, /upper, /messages 등 분기점)
  • Route handler : 요청을 처리하는 콜백 함수
    위의 코드를 예를 들자면 아래와 같다.
  app.post('/', (req, res) => {
    res.send('Hello World!')
  });

각 라우트는 1개 이상의 handler를 가지고 있어서 알맞는 method가 떨어질 때 실행이 된다고 한다.
또한 운영하는 웹 서비스의 규모가 크고 다양한 API가 사용될 때, routing을 토해 유용하게 분기점을 구분할 수 있다고 한다.

(참고: https://velog.io/@naseriansuzie/imcourseTIL15)

또한 순수한 node.js로 작성한다면 아래와 같다.

const requestHandler = (req, res) => {
  if(req.url === '/mesaages') {
    if(req.method === 'GET') {
      res.end(messages)
    }
    esle if(req.method === 'POST') {
      req.on('data', (req, res) => {
        // do something!
      })
    }
  }
}

반면에 Express는 자체 라우터를 제공하므로,
라우터를 활용하면 코드를 간결하고 직관적으로 작성할 수 있다.
아래를 살펴보자.

const app = express()
// client로부터 get요청이 들어오면 app.get()이 실행
// 혹은 post요청이 들어오면 app.post() 실행

app.get('/messages', (req, res) => {
  res.send(messages)
})

app.post('/messages', (req, res) => {
  // do something!
})

     미들웨어

(출처: http://expressjs.com/en/guide/writing-middleware.html)

특징

  • 미들웨어는 Express.js에 큰 장점 중 하나로,
    요청 객체(req) 와 응답 객체(res) & 요청-응답 사이클 중간 처리 역할을 수행하는 함수로 정의한다.

  • 요청에 대한 응답을 완료하기 전까지 중간중간에 다양한 일을 처리할 수 있다.
  • 미들웨어 함수 생명주기: request - response 응답을 주기로 종료
    (res.METHOD 를 이용해 client에게 응답을 전송한다는 뜻. 응답 전송과 더불어 종료.)
  • 미들웨어 함수 우선순위: 먼저 로드되는 미들웨어 함수가 먼저 실행
    (따라서 next()를 호출하는 이유)
  • router.use() 및 router.METHOD() 함수를 사용하여 라우터 레벨 미들웨어를 로드할 수 있다.
참고: https://jinbroing.tistory.com/126)

  미들웨어 함수가 요청-응답주기를 종료하지 않으면 next()를 다음 미들웨어 함수에 제어를 전달하기 위해 호출해야한다. 그렇지 않으면 요청이 중단된다고 한다.

(내용 출처: https://expressjs.com/en/guide/using-middleware.html)

      - 자주 사용하는 미들웨어

(출처 : codestates)
  • 모든 요청에 대해 url이나 메소드를 알고자 할 때

특정 endpoint가 아닌 모든 요청에 대해 메소드와 url을 확인할 수 있다.


const myLogger = function (req, res, next) {
  console.log(`http request method - ${req.method}, url - $ req.url`);
  
  console.log('LOGGED')
  next(); // 확인했으니 다음 미들웨어 함수해서 종결하던지 다시 next를 하던지! (next를 하는 이유: 순차적으로 진행되기 때문)
}

app.use(myLogger);

말 그대로 Logger는 디버깅이나, 서버 관리에 도움이 되기 위해 console.log를 적절하게 찍어주는 역할을 한다.

  • POST 요청 등에서 쓰이는 body(payload)를 쉽게 얻어내고자 할 때
    순수 node.js로 HTTP body(payload)를 받을 때, Buffer를 조합해 복잡한 방법으로 body를 얻어냈어야 했다.
let body = [];
request.on('data', (chunk) => {
  body.push(chunk);
}).on('end', () => {
  body = Buffer.concat(body).toString();
  // body 변수에는 문자열로 payload가 담겨져 있다.
})

Express로 변환하면 아래와 같다.
body-parser 미들웨어라는 것이다.

const bodyParser = requir('body-parser')
const jsonParser = bodyParser.json()

// 생략
app.post('/api/users', jsonParser, function (req, res) { 
  // req.body에는 JSON 형태로 payload가 담겨져 있다.
})
  • 모든 요청/응답에 CORS 헤더를 붙일 때
    순수 node.js로 CORS 헤더를 붙이려면, 응답 객체의 writeHead메소드 등을 이용해 일일이 Access-Control-Allow-8 헤더를 정의해줘야만 했다.
    OPTIONS 메소드에 대한 라우팅도 구현해줘야만 했다.
const defaultCorsHeader = {
  'Access-Control-Allow-Origin': '*',
  'Access-Control-Allow-Methods': 'GET, POST, PUT, DELETE, OPTIONS',
  'Access-Control-Allow-Headers': 'Content-Type, Accept',
  'Access-Control-Max-Age': 10
}
// 생략
if(req.method === 'OPTIONS') {
  res.writeHead(201, defaultCorsHeader)
  res.end()
}

반면, Express의 cors미들웨어로 리팩토링을 해보면 아래와 같다.
짜짠!

const cors = require('cors')

// 생략
app.use(cors()); // 모든 요청에 대한 cors 허용
  • 요청 헤더에 사용자 인증 정보가 담겨있는지 확인하고 싶을 때
    아직 배우지 않았지만 추후 로그인 등 보안 관련 과정을 배우게 되면 쓰게 될 것 같다.

HTTP 요청에서 토큰(주로 사용자 인증에 쓰임)이 있는지 여부를 판단하여, 이미 로그인한 사용자일 경우, 성공 아닐 경우 에러를 보내는 미들웨어다.

  app.use((req, res, next) => {

    // 토큰 있어? 없으면 받아 줄 수 없다!
    if(req.headers.token) {
      req.isLoggedIn = true;
      next()
    }
    else {
      res.status(400).send('invalid user')
    }
  })

보통 접근 권한이 없는 웹사이트에 로그인 없이 접근을 시도하면 서버로부터 로그인 창 등으로 되돌려 보내는 경우가 위의 미들웨어의 응답인 것이다.

더 자세한 내용 및 그 외 정보들은 공식문서에서 확인하도록 하자

https://expressjs.com/en/guide/using-middleware.html

  • 애플리케이션 레벨 미들웨어 (Application-level middleware)
  • 라우터 레벨 미들웨어 (Router-level middleware)
  • 오류 처리 미들웨어 (Error-handling middleware)

🌱   Potter's tought

  일단 서버 구축하는 것 자체가 왠지 모르게 접근하기 힘들었던 것은 사실이다.
그래서 여태 블로그 작성했던 것 중 제일 많이 고민해보고 제일 많이 구글링을 했던 것 같다.

Express를 배우기 전에는 순수 node.js만을 이용해서 서버를 만들었다.
이해하고 작성 과정에 머릿속에서 정리가 안되 교통사고가 종종 일어나곤 했다.
다행이도 Express의 미들웨어를 적용하고 나니 좀 더 간결하고 직관적인 코드 작성이 가능하게 되었다.
그렇다고 node.js만으로 작성했던 코드를 경시하면 안되지만..
굳이 비교를 하자면..Express 너무 편하다.......

아무튼 Express 마저 머릿속에서 충돌나기 전에 보고 보고 또 봐야겠다.
(이미 지난 HA test에서 충돌 경험이 한 번 있었으니 재발만큼은 방지해야지..!!)

아.. 벌써 다음 스프린트인 DB가 걱정이 된다 ㅠㅠ

세상에 편한게 어디있겠는가!!
여태 그래왔듯이 피가 철철나더라도 부딪히고 굳은 살이 배겨 통증마저 무뎌질 때까지 부딪혀서 내 것으로 만들어보자!!!

profile
코딩에서 인생을 배우다.

0개의 댓글