Web Server 기초(express)

HanSungUk·2022년 6월 22일
0

백엔드

목록 보기
1/2

Web Server 기초(express)

현재 코드스테이츠 강의를 통해 프론트엔드를 학습하고 있습니다.
본 포스트는 해당 강의에 대한 내용 정리를 목적으로 합니다.

학습목표

  • Express로 간단한 서버를 구현할 수 있다.
  • 미들웨어를 이해할 수 있다.
  • 미들웨어를 이용할 수 있다.
  • 미들웨어를 구현할 수 있다.

1. Express 시작하기

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

Express로 구현한 서버가 Node.js HTTP 모듈로 작성한 서버와 다른 점은 다음과 같습니다.

  1. 미들웨어를 추가할 수 있다.
  2. 라우터를 제공한다.

1. Express 설치

npm install express

2. 간단한 웹 서버 만들기

const express = require('express')
const app = express()
const port = 3000

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

app.listen(port, ()=>{
	console.log(`Example app listening on port ${port}`)
})

앱은 서버를 시작하며 3000번 포트에서 연결을 청취합니다. 앱은 루트 URL(/) 또는 라우트에 대한 요청에 'Hello World!'로 응답합니다. 다른 모든 경로에 대해서는 404 Not Found로 응답합니다.

3. 라우팅: 메서드와 url에 따라 분기(Routing)하기

메서드와 url(/lower, /upper 등)로 분기점을 만드는 것을 라우팅(Routing)이라고 합니다.
클라이언트는 특정한 HTTP 요청 메서드(GET, POST 등)와 함께 서버의 특정 URI(또는 경로)로 HTTP 요청을 보냅니다.
라우팅은 클라이언트의 요청에 해당하는 Endpoint에 따라 서버가 응답하는 방법을 결정하는 것입니다.

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는 라우트가 일치할 때 실행되는 함수입니다.

2. 미들웨어(Middleware)

미들웨어는 자동차 공장의 공정과 비슷합니다.
컨베이어 벨트 위에 올라가 있는 요청(Request)에 필요한 기능을 더하거나, 문제가 발견된 불량품을 밖으로 걷어내는 역할을 합니다.

미들웨어를 사용하는 상황은 다음과 같습니다.

  1. POST 요청 등에 포함된 body(payload)를 구조화할 때
  2. 모든 요청/응답에 CORS 헤더를 붙여야 할 때
  3. 모든 요청에 대해 url이나 메서드를 확인할 때
  4. 요청 헤더에 사용자 인증 정보가 담겨있는지 확인할 때

1. POST 요청 등에 포함된 body(payload)를 구조화할 때

Node.js로 HTTP body(payload)를 받을 때에는 Buffer를 조합해서 다소 복잡한 방식으로 body를 얻을 수 있습니다.
네트워크 상의 chunk를 합치고, buffer를 문자열로 변환하는 작업이 필요합니다.

let body=[];
request
      .on("data", (chunk) => {
        // Buffer 형태의 데이터를 배열에 담는다.
        body.push(chunk);
      })
      .on("end", () => {
        console.log(body);
        // Buffer 형태의 데이터를 문자열로 풀어준뒤 배열에 담는다.
        body = Buffer.concat(body).toString();
		// body 변수에는 문자열 형태로 payload가 담겨져 있습니다.
});

Express v4.16.0부터는 Express 내장 미들웨어인 express.json()을 사용합니다.

const jsonParser = express.json({ strict: false });

// POST 메서드와 '/upper' PATH는 위 node.js 예제와 연관되지 않습니다. 
// HTTP body(payload)를 jsonParser로 쉽게 받을 수 있다는 부분이 포인트 입니다.
app.post("/upper", jsonParser, (req, res) => {
  
})

express.json([options])에서 options의 strict은 배열과 객체만 받아들이도록 설정하거나 해제하는 기능을 합니다 비활성화(false)가 되면 JSON.parse가 허용하는 모든 항목을 수락합니다.

2. 모든 요청/응답에 CORS 헤더를 붙일 때

Node.js HTTP 모듈을 이용한 코드에 CORS 헤더를 붙이려면, 응답 객체의 writeHead메서드를 이용할 수 있습니다. Node.js에서는 이 메서드 등을 이용하여 라우팅마다 헤더를 매번 넣어주어야 합니다. 그 뿐만 아니라, 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()
}

cors 미들웨어를 사용하면 이 과정을 간단하게 처리할 수 있습니다.

// npm으로 cors를 설치
npm install cors
const cors = require('cors');

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

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

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

위 그림은 endpoint가 /이면서, 클라이언트로부터 GET요청을 받았을 때 적용되는 미들웨어입니다. 파라미터의 순서에 유의해야 합니다. req, res는 우리가 잘 아는 요청(request), 응답(response)이고 next는 다음 미들웨어를 실행하는 역할을 합니다.
만약 특정 endpoint가 아니라, 모든 요청에 동일한 미들웨어를 적용하려면 어떻게 해야 할까요? 바로 메서드 app.use를 사용합니다.

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);

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

다음은 HTTP 요청에서 토큰이 있는지를 판단하여, 이미 로그인한 사용자일 경우 성공, 아닐 경우 에러를 보내는 미들웨어 예제입니다.

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

0개의 댓글