[TIL] Express

ㅜㅜ·2022년 10월 14일
1

Today I learn

목록 보기
33/77
post-thumbnail

어제 수업하면서 구글로 node.js 서버 관련한 내용을 찾아봤는데, 'Express라는 것도 배울 것 같군...?' 그렇게 생각했었다.

그리고 역시나 오늘은 Express와 함께 구르는 날이었던 것이다... 🫠
제출 과제는 월요일까지 하는 거라 오늘은 간단하게 개념 학습한 내용 + 공식 문서 보면서 알아들은(맞겠지?🤔) 내용을 조금 정리해보려고 한다.



Express

: Node.js 환경에서 웹 서버, 또는 API 서버를 제작하기 위해 사용되는 프레임워크.

‘미들웨어를 추가할 수 있다 + 라우터를 제공한다’는 점에서 Node.js HTTP 모듈로 작성한 서버와 다름.

한 마디로 말하자면 node.js를 그냥 사용하는 것보다 Express를 사용하면 더 편리하게 서버를 구축할 수 있는 듯?

❓미들웨어 (middleware)

: 요청 객체(req), 응답 객체(res), 애플리케이션의 요청-응답 주기 중 그 다음의 미들웨어 함수에 대한 액세스 권한을 갖는 함수. (그 다음의 미들웨어 함수는 일반적으로 next라는 이름의 변수로 표시됨)

미들웨어는 요청에 필요한 기능을 더하거나, 문제가 발견된 불량품을 밖으로 걷어내는 역할을 함.

추상적이기는 하지만 일단 미들웨어는 '함수'인 것 같았고, 객체들에 접근할 수 있는 권한을 가지고 특정 기능을 하는 함수이구나! 라고 이해했다.

❓미들웨어를 사용하는 상황

  1. POST 요청 등에 포함된 body(payload)를 구조화할 때 (쉽게 얻어내고자 할 때)

    : node.js로 HTTP body를 받을 땐 Buffer를 조합해 복잡한 방식으로 body를 얻게 된다.

    body-parser 미들웨이 사용시 이 과정을 간단하게 처리 가능한데, Express v4.16.0부터는 body-parser설치하지 않고 Express 내장 미들웨어인 express.json() 사용.

    express.json()은 JSON부분만 파싱해 미들웨어를 반환하는데, Conetent-Type 헤더가 request와 옵션이 일치하지 않으면 비어있는 오브젝트로 남거나 오류가 발생한다.

    express.json([options]) 속에 options를 strict로 하면 배열과 객체만 허용하는 것을 활성화하게 됨. (strict는 기본값이 true임) strict가 비활성화 상태일 때는 JSON.parse가 허용하는 모든 항목들을 수용하게 된다.

    과제에서는 strict를 false로 설정해주어야 하는데 그 이유는 원시데이터 타입도 제이슨 형태로 parsing 해주도록 설정하기 위함. (배열과 객체만이 아니라)


  1. 모든 요청/응답에 CORS 헤더를 붙여야 할 때

    : node.js HTTP 모듈을 이용한 코드에 CORS 헤더를 붙이려면 응답 객체의 writeHead 매서드를 이용하는데, 매번 라우팅마다 헤더를 넣어주어야 하고, OPTIONS 매서드에 대한 라우팅도 따로 구현해야함.

    Express에서는 cors 미들웨어를 사용할 수 있음.

//모든 요청에 대한 CORS 허용.
const cors = require('cors');

// 생략
app.use(cors());

--------------------------------------
//아래는 특정 요청에 대해 CORS 허용.
const cors = require('cors')

// 생략
app.get('/products/:id', cors(), function (req, res, next) {
  res.json({msg: 'This is CORS-enabled for a Single Route'})
})


  1. 모든 요청에 대해 url이나 매서드를 확인할 때

: 로거(Logger)는 말 그대로 console.log로 어떠한 로그를 출력하는 기능을 하는데, 디버깅이나 서버 관리에 도움이 된다. 3번 제목에서 알 수 있듯이 모든 요청에 대해 url, method를 확인하고 싶을 때 로거 미들웨어를 만들어 볼 수 있을 것이다.

(모든 요청에 동일한 미들웨어를 적용할 때 app.use를 사용할 수 있음.)

//개념 예시 
//모든 요청에 대해 콘솔에 LOGGED가 출력될 것임. 
const express = require('express');
const app = express();

const myLogger = function (req, res, next) {
  console.log('LOGGED');
  next();
};

app.use(myLogger);

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

app.listen(3000);

_______

//과제에서는 콘솔에 모든 요청들의 매서드, url, body가 출력되도록 아래와 같이 작성함.

const myLogger = function (req, res, next) {
  console.log(req.method, req.url);
  console.log(req.body);
  next();
};
//my Logger 미드웨이는 요청의 매서드, url, body를 콘솔에 나타냄.
//이런 로거는 보통 현재 데이터를 확인하거나, 디버깅에 사용함.

app.use(myLogger);
//모든 요청에 myLogger라는 동일한 미드웨이를 적용하기 위함


  1. 요청 헤더에 사용자 인증 정보가 담겨있는지 확인할 때

    : 로그인 없이 웹 사이트 접근 시도했을 때 로그인 창으로 되돌려 보내는 경우와 같이 서버에서 요청에 포함된 데이터를 통해 미들웨어가 요구하는 조건에 맞지 않으면 불량품으로 판단해 돌려보내도록 구현 가능.

//예시코드
app.use((req, res, next) => {
  // 토큰이 있는지 확인, 없으면 받아줄 수 없음.
  if(req.headers.token){
    req.isLoggedIn = true;
    next();
  } else {
    res.status(400).send('invalid user')
  }
})

//token(토큰)은 주로 사용자 인증에 사용 




❓라우팅

: URI(또는 경로) 및 특정한 HTTP 요청 매서드(GET, POST 등)인 특정 엔드포인트에 대한 클라이언트 요청에 애플리케이션이 응답하는 방법을 결정하는 것.

예를 들어 과제에서처럼 매서드와 url(/lower,/upper)로 분기점을 만드는 것을 라우팅이라고 함!

node.js에서 라우팅을 구현하려면 과제에서 구현했던 것처럼 if else if문을 사용해 구현해줄 수 있는데, Express는 프레임워크 자체에서 라우터 기능을 제공함.

//Express로 라우터 구현 
const router = express.Router()

router.get('/lower', (req, res) => {
 res.send(data);
})

router.post('/lower', (req, res) => {
 //do something
})

각 라우트는 하나 이상의 핸들러 함수를 가질 수 있으며, 이러한 함수는 라우트가 일치될 때 실행된다.

app.METHOD(PATH, HANDLER)

//app은 express의 인스턴스
//METHOD는 HTTP 요청 매서드
//PATH는 서버에서의 경로
//HANDLER는 라우트가 일치할 때 실행되는 함수 

❓ 애플리케이션 레벨 미들웨어 & 라우터 레벨 미들웨어

위 라우터 예시에 보면 첫번째 예시는 express.Router()를 이용해 router.get ~ 과 같은 방식으로 라우터를 사용하고, 두번째 예시에서는 express.Router()를 이용하지 않고 app.METHOD(PATH,HANDLER)와 같은 방식으로 라우터를 사용한다. 두 가지의 차이점이 무엇인지 궁금했는데 공식 문서에 애플리케이션 레벨 미들웨어 & 라우터 레벨 미들웨어라고 설명이 되어 있었다. Express 미들웨어 공식 문서

애플리케이션 레벨 미들웨어는 express()로 생성할 수 있는 app 객체의 app.use()나 app.METHOD()(ex:app.post) 함수를 이용해 미들웨어를 app 인스턴스에 바인딩하는 미들웨어를 말하고, 라우터 레벨 미들웨어는 express.Router()로 생성할 수 있는 router 인스턴스에 미들웨어가 바인딩되는 것을 말한다고 한다.

바인딩에 관한 부분을 제외하면 에플리케이션 레벨과 라우터 레벨 미들웨어는 동일한 방식으로 작동한다고 한다.

그리고 공식 문서의 라우터 부분 중 express.Router 부분을 보면 express.Router 클래스를 사용하면 모듈을 만들 수 있고, 그 모듈은 다른 곳에서 export & import 해서 사용할 수 있는 것 같다.

(*아직 마운트에 대한 개념이 확실하진 않아서 이해한 것이 틀릴 수도 있을 것 같다)

실제 과제에서는 아래와 같이 작성했는데 아래와 같은 방법이 애플리케이션 레벨 미들웨어인 것 같았다.

const app = express();
//중략

app.get("/", (req, res) => {
  console.log(req.method, req.url);
  res.send("Hello World!");
});
//라우팅 위해 필요한 구조가 app.METHOD(PATH, HANDLER)
//얘는 upper나 lower 같은 url을 붙이지 않은 상태에 나타나는 화면
//get 요청을 처리해서 "Hello World!"라는 응답을 보냄.

app.post("/upper", (req, res) => {
  res.json(req.body.toUpperCase());
});
//toUpperCase 버튼을 눌렀을 때 /upper 라는 url로 요청이 가고
//요청으로 받은 body부분을 대문자로 바꾸고,
//res.json()매서드를 통해 json 문자열로 변환해서 헤드에 Content-Type:application/json으로 셋팅
//body인자에 저장해 res.send()를 호출해서 응답을 보냄

app.post("/lower", (req, res) => {
  res.json(req.body.toLowerCase());
});
profile
다시 일어나는 중

0개의 댓글