프론트엔드 개발/Node.js

Web Server 기초. GET, POST, PUT, DELETE (Express 활용)

하이고니 2023. 2. 7. 21:24

공항 리스트, 비행편 리스트, 예약 리스트를 GET, POST, PUT, DELETE 할 수 있는 서버를 만들어보자

 

app.js

 

const express = require('express');				// (1)
const cors = require('cors');
const app = express();

const port = 3001;						// (2)

const flightRouter = require('./router/flightRouter');		// (3)
const bookRouter = require('./router/bookRouter');
const airportRouter = require('./router/airportRouter');

app.use(cors());						// (4)
app.use(express.json());

app.use('/flight', flightRouter);				// (5)
app.use('/book', bookRouter);
app.use('/airport', airportRouter);

app.get('/', (req, res) => {					// (6)
  res.status(200).send('Welcome, States Airline!');
});

app.use((req, res, next) => {					// (7)
  res.status(404).send('Not Found!');
});

app.use((err, req, res, next) => {				// (8)
  console.error(err.stack);
  res.status(500).send({
    message: 'Internal Server Error',
    stacktrace: err.toString()
  });
});

app.listen(port, () => {					// (9)
  console.log(`[RUN] StatesAirline Server... | http://localhost:${port}`);
});

module.exports = app;

 

(1) 맨 위의 세 줄은 express를 사용하면서 그냥 고정적으로 쓰는 코드라고 생각하면 된다.

(2) port는 임의로 지정.

(3) 세 개의 라우터가 등장하는데, 이건 잠시 후에 설명하겠다.

(4) cors와 express.json을 모든 url에서 사용하겠다는 코드.

(5) 세 개의 라우터를 각각의 url에서 사용하겠다는 코드.

 

(6) localhost:3001/ 로 접속하면 'Welcome, States Airline!'이 출력된다.

(7) 지정되지 않은 경로로 접속하면 404 Not Found

(8) 500 에러도 자주 뜨던데 이거 뭔지 잘 모르겠다.

 

(9) 지정된 포트로 오는 요청을 항상 귀담아 듣겠소

 

 

Router

 

airportRouter.js

 

const { findAll } = require('../controller/airportController');
const express = require('express');
const router = express.Router();	// (1)

router.get('/', findAll);		// (2)

module.exports = router;

 

(1) 라우터 기능을 사용하려면 입력해야 하는 코드

(2) localhost:3001/airport 로 접속하면 findAll 함수 작동(특정 엔드포인트를 지정해주는 것이 아니면 모든 비행편 보여준다는 뜻인 듯)

 

bookRouter.js

 

const { 
    	findAll, 
    	findByPhone, 
    	findByPhoneAndFlightId, 
    	create, 
    	deleteByBookingId 
      } = require('../controller/bookController');
    
const express = require('express');
const router = express.Router();

router.get('/', findAll);
router.get('/:phone', findByPhone);
router.get('/:phone/:flight_uuid', findByPhoneAndFlightId);
router.post('/', create);
router.delete('/:booking_uuid', deleteByBookingId);

module.exports = router;

 

- GET 요청 3가지, POST 요청, DELETE 요청

 

flightRouter.js

 

const { findAll, findById, update } = require('../controller/flightController');
const express = require('express');
const router = express.Router();

router.get('/', findAll);
router.get('/:uuid', findById);
router.put('/:uuid', update);

module.exports = router;

 

- GET 요청 2가지, PUT 요청

 

 

Repository

 

airportList.js

 

module.exports = [
  {
    name: '제주',
    code: 'CJU'
  },
  {
    name: '인천',
    code: 'ICN'
  },
  {
    name: '부산',
    code: 'PUS'
  },
  {
    name: '광주',
    code: 'KWJ'
  },
  {
    name: '방콕',
    code: 'BKK'
  },
  {
    name: '세부',
    code: 'CEB'
  },
  {
    name: '하노이',
    code: 'HAN'
  },
  {
    name: '오사카',
    code: 'KIX'
  },
  {
    name: '하얼빈',
    code: 'HRB'
  },
  {
    name: '웨이하이',
    code: 'WEH'
  },
  {
    name: '홍콩',
    code: 'HKG'
  }
];

 

flightList.js

 

module.exports = [
  {
    uuid: 'af6fa55c-da65-47dd-af23-578fdba40bed',
    departure: 'ICN',
    destination: 'CJU',
    departure_times: '2021-12-02T12:00:00',
    arrival_times: '2021-12-03T12:00:00'
  },
  {
    uuid: 'af6fa55c-da65-47dd-af23-578fdba40byd',
    departure: 'ICN',
    destination: 'PUS',
    departure_times: '2021-12-03T12:00:00',
    arrival_times: '2021-12-03T12:00:00'
  },
  {
    uuid: 'af6fa55c-da65-47dd-af23-578fdba48bed',
    departure: 'ICN',
    destination: 'CJU',
    departure_times: '2021-12-03T12:00:00',
    arrival_times: '2021-12-04T12:00:00'
  },
  {
    uuid: 'af6fa55c-da65-47dd-af23-578fdbr40bed',
    departure: 'ICN',
    destination: 'CJU',
    departure_times: '2021-12-03T12:00:00',
    arrival_times: '2021-12-04T12:00:00'
  },
  {
    uuid: 'af6fa55c-da65-47dd-af23-578fd7a40bed',
    departure: 'ICN',
    destination: 'BKK',
    departure_times: '2021-12-02T12:00:00',
    arrival_times: '2021-12-03T12:00:00'
  },
  {
    uuid: 'af6fa55c-da65-47dd-af23-578fdba40bod',
    departure: 'ICN',
    destination: 'CJU',
    departure_times: '2021-12-02T12:00:00',
    arrival_times: '2021-12-03T12:00:00'
  },
  {
    uuid: 'af6fa55c-da65-47dd-af23-578fdba44bed',
    departure: 'ICN',
    destination: 'CJU',
    departure_times: '2021-12-03T12:00:00',
    arrival_times: '2021-12-03T12:00:00'
  },
  {
    uuid: 'af6fa55c-da65-47dd-af23-578fdba42bed',
    departure: 'CJU',
    destination: 'ICN',
    departure_times: '2021-12-03T12:00:00',
    arrival_times: '2021-12-04T12:00:00'
  },
  {
    uuid: 'af6fa55c-da65-47dd-af23-578fdba41bed',
    departure: 'CJU',
    destination: 'ICN',
    departure_times: '2021-12-03T12:00:00',
    arrival_times: '2021-12-03T12:00:00'
  },
  {
    uuid: 'af6fa55c-da65-47dd-af23-578fdba99bed',
    departure: 'CJU',
    destination: 'ICN',
    departure_times: '2021-12-03T12:00:00',
    arrival_times: '2021-12-04T12:00:00'
  },
  {
    uuid: 'af6fa55c-da65-47dd-af23-578fdba50bed',
    departure: 'CJU',
    destination: 'ICN',
    departure_times: '2021-12-02T12:00:00',
    arrival_times: '2021-12-03T12:00:00'
  }
];

 

 

Controller

airportController

 

const airports = require('../repository/airportList');

module.exports = {
  
  findAll: (req, res) => {

    if (req.query.query !== undefined) {
      const filteredAirports = airports.filter((airport) => 
        airport.code.includes(req.query.query.toUpperCase())
      );
      return res.status(200).json(filteredAirports);
    }
    res.json(airports);
  }
};

 

GET 요청 /airport?query={query} 을 수행한다.

 

GET 요청의 URI가 localhost:3001/airport?query=cju 라면

airports(공항 리스트 배열)의 요소(객체) 중 code(키 값)가 'CJU'인 것만 필터링해서 응답한다. 

 

return res.status(200).json(filteredAirports);

이 부분은 그냥 GET 요청 공식이라고 생각하고 외워두자.

 

 

bookController.js

 

const { v4: uuid } = require('uuid');
let booking = [];

module.exports = {
  findAll: (req, res) => {
    return res.status(200).json(booking);
  },

  findByPhone: (req, res) => {
    const { phone } = req.params;
    if (req.params.phone !== undefined) {
      const bookFiltered = booking.filter((el) => 
        el.phone === req.params.phone
      )
      return res.status(200).json(bookFiltered);
    }
  },

  findByPhoneAndFlightId: (req, res) => {
    const { phone, flight_uuid } = req.params;

    if (req.params.phone !== undefined && req.params.flight_uuid !== undefined) {
      const phoneUuidFiltered = booking.filter((el) => 
        el.phone === req.params.phone &&
          el.flight_uuid === req.params.flight_uuid
      )
      return res.status(200).json(phoneUuidFiltered);
    }
    res.json(req.params);
  },

  create: (req, res) => {

    const booking_uuid = uuid();
    const { flight_uuid } = req.body;
    const { name } = req.body;
    const { phone } = req.body;

    const newBook = {
      "booking_uuid": booking_uuid,
      "flight_uuid": flight_uuid,
      "name": name,
      "phone": phone,
    }
    booking.push(newBook);
    res.status(201).json(booking);
  },

  deleteByBookingId: (req, res) => {
    
      const index = booking.findIndex((el) => {
        return el.booking_uuid === req.params.booking_uuid;
      });
      if(index === -1) return res.status(404).json('예약되지 않은 항공편입니다.');
      const { booking_uuid } = booking[index];
      booking.splice(index, 1);
      return res.status(200).json({ booking_uuid });
    }
};

 

너무 기니까 하나씩 뜯어서 볼게용

 

1.

findAll: (req, res) => res.status(200).json(booking)

 

그냥 예약 전체 목록 보여줘라

 

2.

findByPhone: (req, res) => {
  const { phone } = req.params;
  if (req.params.phone !== undefined) {
    const bookFiltered = booking.filter((el) => 
      el.phone === phone
    )
    return res.status(200).json(bookFiltered);
  }
}

 

URI가 localhost:3001/book/010-1234-5678 일 때,

req.params{ phone: '010-1234-5678' } 이다. 왜 그럴까?

 

진짜 왜 그렇지?

왜긴 왜야 프론트에서 요청할 때 그렇게 했겠지..

 

예약 목록 중에서 phone(키 값)이 변수 phone(req.params.phone)과 같은 것만 필터링한다.

 

3.

create: (req, res) => {

  const booking_uuid = uuid();
  const { flight_uuid } = req.body;
  const { name } = req.body;
  const { phone } = req.body;

  const newBook = {
    "booking_uuid": booking_uuid,
    "flight_uuid": flight_uuid,
    "name": name,
    "phone": phone,
  }
  booking.push(newBook);   
  res.status(201).json(booking);
}

 

예약 생성.

uuid()는 임의의 id를 생성해주는 모듈이다.

newBook이라는 새로운 객체를 만들어서 booking(예약 목록 배열)에 push해준다.

 

4.

deleteByBookingId: (req, res) => {
    
    const index = booking.findIndex((el) => 
      el.booking_uuid === req.params.booking_uuid
    );
    if(index === -1) return res.status(404).json('예약되지 않은 항공편입니다.');
    const { booking_uuid } = booking[index];
    booking.splice(index, 1);
    return res.status(200).json({ booking_uuid });
    }
    
};

예약 삭제.

findIndex 메서드를 활용해서 예약 목록의 booking_uuid 중,

req.params.booking_uuid와 같은 것의 인덱스를 찾는다.

 

그 인덱스의 booking_uuid 요소를 리턴한다.

 

 

flightController.js

 

const flights = require('../repository/flightList');
const fs = require('fs');

module.exports = {
  findAll: (req, res) => {
    const { departure_times, arrival_times, destination, departure } = req.query;
    
    if(departure_times !== undefined && arrival_times !== undefined) {
      const timesFiltered = flights.filter((el) => {
        return (el.departure_times === departure_times &&
                el.arrival_times === arrival_times)
      })
      return res.status(200).json(timesFiltered);
    }
    if(departure !== undefined && destination !== undefined) {
      const locationFiltered = flights.filter((el) => {
        return (el.departure === departure &&
                el.destination === destination);
      })
      return res.status(200).json(locationFiltered);
    }
    return res.json(flights);
  },

  findById: (req, res) => {
    const { uuid } = req.params;
    // TODO:
    if(req.params.uuid !== undefined) {
      const uuidFiltered = flights.filter((el) => 
         el.uuid === req.params.uuid
      )
      return res.status(200).json(uuidFiltered)
    }
  },


  update: (req, res) => {
    const { uuid } = req.params;
    const bodyData = req.body;
    let index;

    if(uuid !== undefined){
      index = flights.findIndex((el) => el.uuid === uuid);
      console.log(index);
      flights[index] = {
        ...flights[index],
        ...bodyData,
      }
      console.log(flights);
    }
    
    return res.status(201).json(flights[index]);
  }
};

이것도 끊어서 한 번 볼까용?

 

1.

findAll: (req, res) => {
  const { departure_times, arrival_times, destination, departure } = req.query;
 
  if(departure_times !== undefined && arrival_times !== undefined) {
    const timesFiltered = flights.filter((el) => {
      return (el.departure_times === departure_times &&
              el.arrival_times === arrival_times)
    })
    return res.status(200).json(timesFiltered);
  }
  if(departure !== undefined && destination !== undefined) {
    const locationFiltered = flights.filter((el) => {
      return (el.departure === departure &&
              el.destination === destination);
    })
    return res.status(200).json(locationFiltered);
  }
  return res.json(flights);
}

 

위에서 계속 봐서 이제 좀 지겹죠?

하지만 우리는 계속 봐야 합니다 이것을

 

URI에 무엇이 실려오냐에 따라 두가지 경우로 나뉜다.

 

1) 출발 시간, 도착 시간이 포함되어 있을 때

 

비행편의 목록 중 자신의 departure_times와 arrival_times가 departure_times(req.query.departure_times), arrival_times(req.query.arrival_times)와 같은 것을 필터링한다.

 

2) 출발지, 도착지가 포함되어 있을 때

 

비행편의 목록 중 자신의 departure, destination이 departure(req.query.departure), destination(req.query.destination)와 같은 것을 필터링한다.

 

 

2.

findById: (req, res) => {
  const { uuid } = req.params;

  if(uuid !== undefined) {
    const uuidFiltered = flights.filter((el) => el.uuid === uuid);
    return res.status(200).json(uuidFiltered);
  }
}

 

비행편의 목록 중 자신의 uuid가 uuid(req.params.uuid)와 같은 것을 필터링한다.

 

3. PUT

update: (req, res) => {
  const { uuid } = req.params;
  const bodyData = req.body;
  let index;
  // 원본 배열이 수정되어야 한다
  if(uuid !== undefined){
    index = flights.findIndex((el) => el.uuid === uuid);
    flights[index] = {
      ...flights[index],
      ...bodyData,
    }
  }
  return res.status(201).json(flights[index]);
}

 

비행편의 목록 중 자신의 uuid가 <code>uuid(req.params.uuid)</code>와 같은 것을 찾아 그 인덱스를 저장한다.

비행편의 목록 중 그 인덱스를 가진 것을 수정한다. (스프레드 문법 이용. 뒤의 키 값이 앞의 것과 같다면 덮어 쓴다.)

'프론트엔드 개발 > Node.js' 카테고리의 다른 글

Node.js 이벤트, eventEmitter  (0) 2023.02.06
Stream, Pipe  (0) 2023.02.06
Buffer  (0) 2023.02.06