혹시나 잘못된 개념 전달이 있다면 댓글 부탁드립니다. 저의 성장의 도움이 됩니다

오늘의 Checkpoint

Express

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

  • 미들웨어
  • 라우터

설치 후 사용

npm install express

서버 생성

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

// HTTP method가 GET이고, Endpoint가 '/' 일 경우
app.get('/', (req, res) => {
  res.send('Hello World!')
})

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

라우팅

요청 메서드와 Endpoint 경로에 따라 수행되는 작업을 나누는 과정

app.METHOD(PATH, HANDLER)
// app : express의 인스턴스
// METHOD : 요청의 HTTP 메서드
// PATH : 서버의 경로 Endpoint
// HANDLER : METHOD와 Endpoint가 일치할 경우 실행되는 함수(=라우트 핸들러)
//           함수의 기본 전달인자는 request, response
//           추가로 next를 전달(콜백함수)할 경우 METHOD의 전달인자로 next에 해당하는 함수를 추가

app.METHOD(PATH, MIDDLEWARE, HANDLER)


// 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!');
});
// HTTP method가 POST이고, Endpoint가 '/' 일 경우
app.post('/', function (req, res) {
  res.send('Got a POST request');
});

// HTTP method가 DELETE이고, Endpoint가 '/user' 일 경우
app.delete('/user', function (req, res) {
  res.send('Got a DELETE request at /user');
});

// 모든 HTTP method에 Endpoint가 '/secret' 일 경우
app.all('/secret', function (req, res, next) {
  console.log('Accessing the secret section ...');
  next(); // pass control to the next handler
});

express.Router()

express.Router클래스를 통해 모듈식으로 사용할 수 있는 핸들러 설정 가능
-> 미들웨어

// birds.js 파일
var express = require('express');
var router = express.Router();

// middleware that is specific to this router
router.use(function timeLog(req, res, next) {
  console.log('Time: ', Date.now());
  next();
});

router.get('/', function(req, res) {
  res.send('Birds home page');
});

router.get('/about', function(req, res) {
  res.send('About birds');
});

module.exports = router;


// birds.js 파일에 설정한 router를 다른 파일에서 사용
var birds = require('./birds');
...
app.use('/birds', birds);

미들웨어

Middleware
request 객체와 response 객체를 전달받아 개발자가 의도한 작업을 하기 전에 특정한 작업을 수행하는 함수
ex. POST요청에서 body를 파싱하는 작업을 수행 -> body-parser 미들웨어

  • 타인이 작성한 미들웨어 사용 -> 모듈 설치 후 사용
  • 직접 작성하여 사용

- 요청에 포함된 Payload 추출

POST 요청 등에 포함된 body를 사용할 수 있도록 파싱
-> 파싱 후, 함수 내부에서 req.body 로 body를 이용할 수 있음

  • body-parser (서드파티 미들웨어)

    • 설치 : npm install body-parser
    • 호출 : require('body-parser')
    const bodyParser = require('body-parser');
     const jsonParser = bodyParser.json();
    
     app.post('/users', jsonParser, function (req, res) {/* 생략 */})
  • ⭐️ express.json()
    : body를 json으로 변환하여 반환하는 함수
    기존의 body-parser 기능을 하는 미들웨어가 express의 내장 미들웨어 함수로 대체되어 사용 가능

    express.json(options);
    // options : 파싱의 조건 명시(생략 가능 -> 배열이나 객체만 파싱 가능)
    
     express.json({ strict : false }); 
    // 파싱할 대상이 배열이나 객체가 아닐 경우도 파싱 가능하게 설정

    // 설치 할 필요없이 바로 사용 가능
    const jsonParser = express.json();
    
     app.post('/users', jsonParser, function (req, res) {/* 생략 */})
// Node.js만을 사용한 동일한 작업 비교용
let body = [];
request.on('data', (chunk) => {
  body.push(chunk);
}).on('end', () => {
  body = Buffer.concat(body).toString();
  /* 생략 */
});

- CORS 적용

  • cors (서드파티 미들웨어)
    : 모든 요청에 CORS를 적용할 수 있는 미들웨어
    -> 기존 Node.js로 작업시 라우팅마다 헤더를 수정해줘야하는 번거로움을 한번에 해결 가능

    • 설치 : npm install cors

    • 호출 : require('cors')

      const cors = require('cors');
      
       // 모든 요청에 CORS 허용 
       app.use(cors()); 
      
       // 특정 요청에 CORS 허용 
       app.get('/products/:id', cors(), function (req, res, next) {
         res.json({msg: 'This is CORS-enabled for a Single Route'})
       })
// Node.js만을 사용한 동일한 작업 비교용
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); // <--- CORS 허용을 위해 헤더 설정
  res.end()
}

- 요청의 HTTP 메서드와 Endpoint 확인

-> 직접 미들웨어를 작성하여 사용

  • 특정 요청에 적용 -> app.METHOD() ( METHOD는 요청의 HTTP 메서드 )
  • 모든 요청에 적용 -> app.use()
  • next
    : 미들웨어의 3번째 전달인자로 다음에 수행되는 콜백함수
    -> 미들웨어 작성시 의도한 기능을 수행 후, 마지막에 next() 를 추가하여 다음 작업이 실행되게 설정

logger 미들웨어 만들기

const express = require('express');
const app = express();

// logger 미들웨어 생성
const myLogger = function (req, res, next) {
  console.log(`http request method is ${req.method}, Endpoint is ${req.url}`);
  next();
};

// app.use(myLogger); // <--- 모든 요청에 적용
// app.get('/', function (req, res) {
//   res.send('Hello World!');
// });

app.get('/', myLogger, function (req, res) { // <--- 특정 요청에 미들웨어 적용
  res.send('Hello World!');
});

app.listen(3000);

logger 미들웨어 만들고 적용


- 요청 헤더의 인증정보 확인

-> 직접 미들웨어를 작성하여 사용

// 모든 요청에 토큰이 있는 경우만 다음 콜백함수 실행
// ex. 로그인을 하지 않았다면 미들웨어가 요청한 작업 수행을 못하게 막음  
app.use((req, res, next) => {
  if(req.headers.token){
    req.isLoggedIn = true;
    next();
  } else {
    res.status(400).send('invalid user')
  }
});

응답

  • res.send()
    : 데이터를 포함하여 응답하여 끝낼때 사용
    -> content-type 헤더를 입력받은 데이터에 맞게 적용하여 전달
  • ⭐️ res.json()
    : 데이터를 JSON으로 변환하여 응답
    -> content-type 헤더를 application/JSON 으로 적용하여 전달
    // json 형태로 응답
    res.send(JSON.stringify(req.body));
    res.json(req.body);
  • res.end()
    : 데이터 전달 없이 응답을 끝냄
    res.end()
     res.status(404).end()



참고

Query parameter vs Path parameter

GET 메서드의 경우 payload 대신 URI의 query parameter, path parameter로 필요한 리소스 전달

  • query parameter
    : GET 메서드에서 필터처럼 조건으로 사용되며 URL의 ? 뒷부분
    ex. GET /39th?age=25 -> 특정한 조건으로 필터링
    • req.query -> { age : "25" }

  • path parameter
    : GET 메서드에서 유일한 값을 지정할 때 사용
    ex. GET /people/49 -> id가 49인 대상 지목
    • Endpoint : /:id
    • req.params -> { id : "49" }



오늘의 나

개선점 및 리마인드

  • 큰 그림
    웹서버 부분에 이해도가 낮은것 같아서 주말에 이 공부를 하려고 했는데, 페어분 얘기 들으니까 서버 보다 직접 프로젝트를 만들어보는게 더 좋지 않을까 하는 생각도 든다. 수업 들은 내용이라도 소화 시키자라는 마음으로 임했는데, 이게 좋은건 아닐수도 있겠다는 생각이 든다. 블로그 정리와 수업내용에만 집중하는게 최선은 아닐수도 있겠다. 고민좀 해야겠다.

**

0개의 댓글