HJW's IT Blog

[CodeIt] 07월 4주차 본문

카테고리 없음

[CodeIt] 07월 4주차

kiki1875 2024. 7. 25. 16:15

Express 핵심 기능

Express 란?

  • 웹 서버의 기본적인 기능을 제공하는 라이브러리
  • request, response를 다룬다

미들웨어

  • express 의 request 와 response 사이에 위치하여 어떠한 동작을 하는 것
  • 모든 request 는 미들웨어를 거치게 된다
  • express 는 미들웨어의 집합
  • client 로 부터 request 를 받아 response를 만들어 다시 client 에게 반환한다
app.get('/', (req, res) => {
  res.json({ message: '안녕, 코드잇 (;' });
});
  • 최상위 경로로 request 가 들어오면 해당 콜백함수를 실행한다

미들웨어의 사용법

  • 파라미터 2개
    • (req, res) → request 객체, response 객체
  • 파라미터 3개
    • (req, res, next)
    • 하나의 route 에 여러 미들웨어가 사용되었다면, next 파라미터를 사용하여 다음 미들웨어를 실행시킨다
  • 파라미터 4개
    • (err, req, res, next)
    • 에러 핸들러
  • app.all 메소드
    • 모든 http 메소드에 대한 request 를 미들웨어로 전달한다
  • app.use 메소드
    • 해당 경로로 시작하는 모든 경로에 대응된다
app.use('/hello', (req,res) => {
  console.log('안녕, use!');
  next();
});

app.all('/hello/all', (req,res,next)=> {
  console.log("HELLO ALL");
  next();
});

app.get('/hello/all', (req,res,next)=> {
  console.log("안녕 ALL");
  res.json({ message: '안녕, codeit'});
});
  • /hello 로 시작하는 모든 라우트를 실행한다
  • 하나의 req 이 여러 미들웨어를 지나간다면 모든 미들웨어가 같은 req 객체를 사용하게 된다

에러 처리하기

  • app.use 를 사용하기에, 어떠한 http 에러가 발생하면 해당 핸들러가 실행된다.
  • 만약 특정 경로에서만 실행되게 하고 싶다면, 경로를 생략하지 않으면 된다.
app.use((err, req, res, next) => {
    console.log(err);
    res.json({message: '에러핸들러'});
})
  • 에러핸들러는 다른 라우트보다 아래에 작성하여야 한다.

내장 미들웨어

  • express.json()
    • req body 에 담긴 json 을 객체로 불러오기 위한 미들웨어
    • content type 헤더가 applicaion json 인경우 req body 를 읽어와 body 에 지정하게 된다
app.post('/products', (req, res) => {
  console.log(req.body);
  res.json({ message: 'Product 추가하기' });
});
POST <http://localhost:3000/products>
Content-Type: application/json

{
  "name" : "상품 1",
  "price" : 100,
}
  • 만약 위와 같이 post 를 보내면 console 에는 undefined 가 출력된다
  • app.use(express.json()); 를 추가해주어야 하는데
    • req 객체의 body 에 값을 담는 역할을 하기 때문에, 값을 사용하는 미들웨어보다 앞에 위치하여야 한다.
  • 해당 메소드는 실행 결과로 함수 자체를 반환한다
  • express.urlencoded()
    • content type header 가 application/x-www-form-urlencoded 형식의 데이터를 처리할 때 사용해야 한다
    • html 입력폼을 통해 서버로 입력을 보낼때 사용한다
    • key 와 value 로 된 req body 를 읽어온다
app.post('/users', (req, res) => {
  console.log(req.body);
  res.json({ message: 'User 추가하기' });
})
POST <http://localhost:3000/users>
Content-Type: application/x-www-form-urlencoded

name=codeit&age=20
  • 마찬가지로 console 에는 빈 객체가 출력된다.
  • app.use(express.urlencoded({extended: true})); 가 필요하다ㅣ
  • express.static();
    • 서버의 파일을 서버의 외부로 보낼 경우 사용

서드파티 미들웨어

  • cookie-parser
    • request 로 전달받은 쿠키를 쉽게 파싱할 수 있게 하는 미들웨어
  • morgan
    • npm install morgan
    • 서버로 들어온 리퀘스트를 로그로 남기는 미들웨어이다
    import express from 'express';
    import morgan from 'morgan';
    
    const app = express();
    
    app.use(morgan('tiny'));
    
    app.get('/hello', (req, res) => {
      return res.json({ message: '안녕, 코드잇 (;' });
    });
    
    app.listen(3000, () => {
      console.log('Server is listening on port 3000');
    });
    
    GET <http://localhost:3000/hello>
    
    GET /hello 200 34 - 2.595 ms
    
  • cors
    • Cross Origin Resource Sharing
    • 웹사이트가 다른 도메인에 있는 리소스에 접근할 수 있도록 http 헤더를 통해 제어
    • npm install cors
  • multer
    • content type 이 multipart/form-data 인 리퀘스트를 다루는 미들웨어
import express from 'express';
import multer from 'multer';

const app = express();

const upload = multer({ dest: 'uploads/' });

app.post('/profile', upload.single('avatar'), function (req, res, next) {
  // ...
});

app.listen(3000, () => {
  console.log('Server is listening on port 3000');
});


라우트 중복 제거하기

  • app.route();
  • 중복되는 라우트를 하나로 묶어 표현할 수 있다.
  • 가장 위에 작성해야 한다
  • 중복된 경로를 첫 argument 로 넘긴다
app.route('/products')
  .get((req, res) => {
    res.json({ message: 'Product 목록 보기' });
  })
  .post((req, res) => {
    res.json({ message: 'Product 추가하기' });
  });
  
app.route('/products/:id')
  .patch((req, res) => {
    res.json({ message: 'Product 수정하기' });
  })
  .delete((req, res) => {
    res.json({ message: 'Product 삭제하기' });
  });
  • express.Router();
    • 같은 주제의 여러 라우트를 묶어 하나의 모듈로 만들고
    • 그렇게 생성된 여러 모듈을 app 객체에 연결하는 방식을 많이 사용
    • 이때 사용하는것이 해당 미들웨어
    • 다음은 express.Router 를 사용하여 위 코드를 간결하게 만든 예시이다
    import express from 'express';
    
    const app = express();
    
    const productRouter = express.Router(); 
    
    app.use(express.json());
    
    productRouter.route('/')
      .get((req, res) => {
        res.json({ message: 'Product 목록 보기' });
      })
      .post((req, res) => {
        res.json({ message: 'Product 추가하기' });
      });
      
    productRouter.route('/:id')
      .patch((req, res) => {
        res.json({ message: 'Product 수정하기' });
      })
      .delete((req, res) => {
        res.json({ message: 'Product 삭제하기' });
      });
    
    app.use('/products', productRouter);
    
    app.listen(3000, () => {
      console.log('Server is listening on port 3000');
    }); 
    
  • 이전에 다루었던 use 메소드를 라우터에도 사용할 수 있는데, 이를 라우터 레벨 미들웨어라 한다 → 특정 라우터에만 적용 할 수 있는 미들웨어
productRouter.use((req,res,next) => {
  console.log("product router middleware");
  next();
});


파일과 multipart/form-data

  • 파일을 text 로 인코딩하여 body 에 encoding 할 수 있다
    • 하지만 용량이 증가하기에 효율 x
  • form 을 통해 보낼 수 있다 (application/x-www-form-urlencoded)
    • 단순 text 이기에 사진과 같은 content 를 전송할 수 없다
    • 사진과 같은 form이 있을 때, 두가지 content type header 가 있어야 한다
    • image/jpeg , application/x-www-form-urlencoded
    • 위 두 타입의 데이터를 한번에 보내는 법은 다음과 같다
  • multipart/form-data
    • 각각의 데이터 type 그대로 전송된다
    • npm install multer

multer 사용하기

const upload = multer({ dest: 'uploads/'});

app.post('/files', upload.single('attachment'), (req, res) => {
	
});
POST <http://localhost:3000/files>
Content-Type: multipart/form-data; boundary=Boundary01234567890123456789

--Boundary01234567890123456789
Content-Disposition: form-data; name="attachment"; filename="hello.txt"
Content-Type: text/plain

Hello!
--Boundary01234567890123456789--
  • 위 post 를 실행하게 되면, uploads 폴더 내에 파일이 저장되게 된다.
  • 이때 random 한 name 이 저장되게 되는데, original name 은 따로 저장된다
app.use('/files', express.static('uploads'));
  • upload 폴더의 파일들에 접근 가능한 route 를 생성하게 된다