[TIL] Day36- Web Server(3)

공부중인 개발자·2021년 5월 31일
0

TIL

목록 보기
38/64
post-thumbnail

Achievement Goals

  • Express 라이브러리

    • express 라이브러리가 어떤 작업을 단순하게 만드는지 이해할 수 있다.
    • 미들웨어의 개념을 이해할 수 있다.
  • 서버 개발과 디버깅

    • CRUD 를 수행하는 웹 서버 개발 방법을 익힐 수 있다.
    • 서버 개발을 돕는 다양한 툴들을 익힐 수 있다.

Express 라이브러리

  • express 라이브러리가 어떤 작업을 단순하게 만드는지 이해할 수 있다.

express 라이브러리를 사용하는 예시와 그렇지 않은 예시를 들어서 작업을 단순화 차이를 알아보겠다.

if (req.method === 'POST') {
    if (req.url === '/lower') {
      let data = '';
      req.on('data', chunk => {
        data = data + chunk;
      });
      req.on('end', () => {
        data = data.toLowerCase();
        res.writeHead(201, defaultCorsHeader);
        res.end(data);
      });
    } else {
      res.writeHead(404, defaultCorsHeader);
      res.end();
    }
  }

위의 예시는 express를 이용하지 않은 경우 method가 POST 일 경우 그중 req.url이 '/lower' 일 경우를 뜻하고 POST에 사용될 data 역시 직접 Buffer를 조절해야한다.

const express = require('express')
const app = express()
const jsonParser = express.json({strict:false})
app.post('/lower', jsonParser , function(req,res){
  res.json(req.body.toLowerCase());
})

위의 예시는 express 라이브러리를 이용했고 method를 찾는 방식에서 지정된 메소드일 때 지정된 코딩을 실행하며, Buffer 역시 express라이브러리를 이용했으며 그 결과 식이 사용하지 않은 것보다 훨씬 더 단순화된것을 확인할 수 있다.



  • express에서의 라우팅

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

라우트 메소드는 HTTP 메소드 중 하나로부터 파생되며, express 클래스의 인스턴스에 연결
다음 코드는 앱의 루트에 대한 GET 및 POST 메소드에 대해 정의된 라우트의 예

// GET method route
app.get('/', function (req, res) {
  res.send('GET request to the homepage');
});

// POST method route
app.post('/', function (req, res) {
  res.send('POST request to the homepage');
});

express 가 지원하는 메소드
get, post, put, head, delete, options, trace, copy, lock, mkcol, move, purge, propfind, proppatch, unlock, report, mkactivity, checkout, merge, m-search, notify, subscribe, unsubscribe, patch, search 및 connect.

특수한 라우팅 메소드인 app.all()은 어떠한 HTTP 메소드로부터도 파생되지 않는다. 이 메소드는 모든 요청 메소드에 대해 한 경로에서 미들웨어 함수를 로드하는 데 사용

  • 라우트 경로

라우트 경로는, 요청 메소드와의 조합을 통해, 요청이 이루어질 수 있는 엔드포인트를 정의합니다. 라우트 경로는 문자열, 문자열 패턴 또는 정규식일 수 있습니다.

정규식을 기반으로 하는 라우트 경로의 예:
다음의 라우트 경로는 라우트 이름에 “a”가 포함된 모든 항목과 일치

app.get(/a/, function(req, res) {
  res.send('/a/');
});
  • 라우트 핸들러

미들웨어와 비슷하게 작동하는 여러 콜백 함수를 제공하여 요청을 처리할 수 있습니다. 유일한 차이점은 이러한 콜백은 next('route')를 호출하여 나머지 라우트 콜백을 우회할 수도 있다는 점입니다. 이러한 메커니즘을 이용하면 라우트에 대한 사전 조건을 지정한 후, 현재의 라우트를 계속할 이유가 없는 경우에는 제어를 후속 라우트에 전달할 수 있습니다.

2개 이상의 콜백 함수는 하나의 라우트를 처리할 수 있습니다(next 오브젝트를 반드시 지정해야 함).

app.get('/example/b', function (req, res, next) {
  console.log('the response will be sent by the next function ...');
  next();
}, function (req, res) {
  res.send('Hello from B!');
});

하나의 콜백 함수 배열은 하나의 라우트를 처리할 수 있습니다.

var cb0 = function (req, res, next) {
  console.log('CB0');
  next();
}

var cb1 = function (req, res, next) {
  console.log('CB1');
  next();
}

var cb2 = function (req, res) {
  res.send('Hello from C!');
}

app.get('/example/c', [cb0, cb1, cb2]);

독립적인 함수와 함수 배열의 조합은 하나의 라우트를 처리할 수 있습니다.

var cb0 = function (req, res, next) {
  console.log('CB0');
  next();
}

var cb1 = function (req, res, next) {
  console.log('CB1');
  next();
}

app.get('/example/d', [cb0, cb1], function (req, res, next) {
  console.log('the response will be sent by the next function ...');
  next();
}, function (req, res) {
  res.send('Hello from D!');
});
  • 미들웨어를 자주사용하는 4가지

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

var app = express();

app.use(function (req, res, next) {
  console.log('Time:', Date.now());
  next();
});

마운트 경로가 없는 미들웨어 함수 - 매 요청을 수신할 때 마다 작동

2.POST 요청 등에 포함된 body(payload)를 구조화할 때(쉽게 얻어내고자 할 때)
위에 나온 express 가 단순화 할 때 예시를 보면 body의 구조화를 쉽게 하는 것을 볼 수 있다.

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

기존 - writeHead,end 메소드 사용

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 사용

//1. 모든 요청/응답에 CORS헤더를 붙일 때
const cors = require('cors')

app.use(cors())

//2. 특정 메소드에만 붙일 때
const cors = require('cors')
app.get('/products/:id', cors(), function (req, res, next) {
  res.json({msg: 'This is CORS-enabled for a Single Route'})
})

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

인증 정보 확인 미들웨어 구현
http 요청에서 토큰이 있는지 여부를 판단, 이미 로그인했다면 성공, 아닐경우 에러를 보내는 미들웨어



app.use((req, res, next) => {
  // 토큰이 있는 경우만 받아준다.
  if(req.headers.token){
    req.isLoggedIn = true;
    next()
  } else {
    res.status(400).send('invalid user')
  }
})

미들웨어는 상위 미들웨어에서 send로 응답을 전송하게 되면 그 외 미들웨어는 작동하지 않는다. 또한 next() 를 통해 다음 미들웨어로 보내지 않는다면 무한 로딩에 걸릴 수 있다.(확인요망 확실치않음)

서버 개발과 디버깅

  • CRUD 를 수행하는 웹 서버 개발 방법을 익힐 수 있다.

먼저 CRUD 를 수행하기 위해 필요한 것은 각각에 맞는 메소드가 필요하며 메소드를 만들기 위해 필요한 것은 라우터와 컨트롤러 등 많은것이 필요하다.

웹 서버를 개발 할때 주로 사용하는 app.js 프레임워크는 이렇게 되어있다.

//외부모듈
const express = require('express')

//내부모듈

//전역변수
const app = express();
const port = 81;

//라우트 모듈

//실행 로직
app.use(cors());
//use 란? 우리가 서버를 실행하기전에 use의 인자를 express에 등록하는것
app.use(express.json())

app.get('/', function(req, res) {
res.status(200).send("Welcome!");
})
//express 가 알아서 등록을해준다?
//get은 use를 바탕으로 구현한 것(use는 express에게 알려주는 것)

//=> app.listen 서버를 실행시켜주는 역할
// app.listen(port, callback() => {
console.log('start server')
})

이렇게 크게 다섯가지로 나열해서 작성해야 일반적인 app.js 작성이며 특히

app.listen(port, callback() => {
    console.log('start server')

위의 listen은 서버를 실행해주는 역할을 하며 이것이 없다면 서버는 작동하지 않는다.



  • 서버 개발을 돕는 다양한 툴들을 익힐 수 있다.

서버 개발에 도움이 되는 다양한 툴은
postman / nodemon / express / node debug 등을 사용해봤으며

postman의 경우 GUI로 서버에게 직접 메소드를 요청할 수 있고 응답을 받을 수도 있다.

nodemon의 경우 원래 서버의 코드를 바꿀 때 마다 서버를 껐다켰다 해야하지만 nodemon을 이용하면 저장 시 자동으로 서버새로고침을 해준다.

node debug의 경우 툴이 맞나 싶긴 하지만
평소에 CLI 에 node app.js 나 nodemon app.js 를 쳐서 서버를 활성화 했지만
node --inspect app.js 나 nodemon --inspect app.js 를 치게 되면 크롬 개발자도구에 새로운 버튼이 활성화 된다.

초록색 node 아이콘을 클릭해보면

이렇게 뜨는데 app.js 에서 console.log를 찍어서 확인 할 수 있다.


그 외 수업시간에 배운 내용은 스프린트에서 중요한 것은 문제를 100프로 모두 맞추는게 중요한 것이 아니라 app.js / Router.js /Controller.js 를 나눠서 라우팅을 하는 것 따로 각종 메소드에 대한 응답을 하는 법 따로 마지막으로 app에서 활성화(?) 하는 것을 따로 하면서 분할을 통해
서버를 공부하면서 체계적으로 분할된 앱에 대한 확인을 잘 하는 것이 중요하다고 했음

서버를 알게 되니 솔직히 재밌다는 생각이 들었다.

profile
열심히 공부하자

0개의 댓글