Boot Camp/code states

[ Code States ] StatesAirline Server 과제

2023. 4. 7. 00:57
목차
  1. 과제 요구 사항
  2.  
  3. 통과해야 할 테스트
  4. 내가 구현한  방법
  5. 알게 된 지식 - 요청 객체와 응답 객체 (req, res)
StatesAirline Server 과제

- cors가 무엇인지 알아보고 node.js를 이용하여 서버를 구축한다.

- mini-node server를 공식 문서를 참고하여 직접 만들어보고 express로 리팩토링해 본 후,

지난 스프린트에서 사용한StatesAirline의 API Server를 직접 구현하면서 라우팅하는 방법을 학습한다.


과제 요구 사항

Bare Minimum Requirements
statesairline/controller/flightController.js와 statesairline/controller/bookController.js 에 코드를 작성하세요.
Express 공식문서에서 req.query , req.params를 사용하는 방법을 확인하세요.
Query와 Params를 기준으로 데이터를 필터링하는 코드를 작성해야 합니다.
예약 데이터는 controller/bookController.js 안에 작성된 let booking = []; 배열에 저장해야 합니다.
Flight API -> 항공편 수정은 Advanced Challenges입니다.

Advanced Challenges
Advanced 콘텐츠의 문제를 해결하려면, 충분한 컨텍스트가 필요할 수 있습니다.
Bare minimum requirements를 완료했다면 도전하세요.
생성한 데이터를 수정할 수 없다면, 매번 데이터를 지우고 다시 생성해야 합니다.
이런 불편을 서비스에서 제거하려면, 데이터를 수정할 수 있는 기능을 추가하면 됩니다.
Advanced 콘텐츠에서는 PUT 요청에 따라 항공편을 수정하는 기능을 구현합니다.

1. 목표
Flight API -> 항공편 수정에서 정의한 API 요청을 수행하는 코드를 작성하세요.
Advanced Challenges에 있는 모든 테스트를 통과해야 합니다.


2. 참고 내용
flight.uuid는 변경되면 안 됩니다.flight JSON의 일부만 수정할 수 있어야 합니다.

 

통과해야 할 테스트


내가 구현한  방법

1. 코드의 흐름을 파악

위의 테스트 목록을 보면 flight Router, Book Router의 파일을 구현해야하는 것으로 보인다.

두 파일을 살펴보자.

 

flight Router

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;

Book Router

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

//Optional
router.delete('/:booking_uuid', deleteByBookingId);

module.exports = router;

위 두 파일을 보면, 라우터(Router) 모듈을 사용하여 경로에 대한 HTTP GET  및 HTTP PUT 요청을 처리하기 위해 각 함수를 호출하는 라우터를 설정하고 있는 것을 알 수 있다.

 

즉, 이렇게 설정된 라우터는 Express 애플리케이션에서 해당 URL에 대한 요청이 들어올 경우,

flightController와 bookController모듈의 함수들을 호출하여 요청에 따른 항공편 정보를 처리하는 역할을 하는 것이다.

저 파일에서는 수정해야 할 로직이 없을 것 같으므로 flightController, bookController 파일로 이동해보자.

 

flightController

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

module.exports = {
  // [GET] /flight
  // 요청 된 파라미터 departure_times, arrival_times 값과 동일한 값을 가진 항공편 데이터를 조회합니다.
  // 요청 된 파라미터 departure, destination 값과 동일한 값을 가진 항공편 데이터를 조회합니다.
  findAll: (req, res) => {
    const { departure_times, arrival_times, destination, departure } = req.query;
    // TODO:

    return res.json(flights);
  },
  // [GET] /flight/:uuid
  // 요청 된 uuid 값과 동일한 uuid 값을 가진 항공편 데이터를 조회합니다.
  findById: (req, res) => {
    const { uuid } = req.params;
    // TODO:

  },

  // Advanced
  // [PUT] /flight/:uuid 요청을 수행합니다.
  // 요청 된 uuid 값과 동일한 uuid 값을 가진 항공편 데이터를 요쳥 된 Body 데이터로 수정합니다.
  update: (req, res) => {
    const { uuid } = req.params;
    const bodyData = req.body;
     // TODO:
  }
};

 

bookController 

// POST /book에서 사용할 uuid입니다.
const { v4: uuid } = require('uuid');
// 항공편 예약 데이터를 저장합니다.
let booking = [];

module.exports = {
  // [GET] /book 요청을 수행합니다.
  // 전체 예약 데이터를 조회합니다.
  findAll: (req, res) => {
    return res.status(200).json(booking);
  },
  // [GET] /book/:phone 요청을 수행합니다.
  // 요청 된 phone과 동일한 phone 예약 데이터를 조회합니다.
  findByPhone: (req, res) => {
    const {phone} = req.params;

  },
  // [GET] /book/:phone/:flight_uuid 요청을 수행합니다.
  // 요청 된 id, phone과 동일한 uuid, phone 예약 데이터를 조회합니다.
  findByPhoneAndFlightId: (req,res) => {
    const {phone, flight_uuid} = req.params;
    // TODO:
  },
  // [POST] /book 요청을 수행합니다.
  // 요청 된 예약 데이터를 저장합니다.
  create: (req, res) => {
    // POST /book에서 사용할 booking_uuid입니다.
    const booking_uuid = uuid();
    // TODO:
  },

  // Optional
  // [DELETE] /book/:booking_uuid 요청을 수행합니다.
  // 요청 된 id, phone 값과 동일한 예약 데이터를 삭제합니다.
  deleteByBookingId: (req, res) => {
    const {booking_uuid} = req.params;
    // TODO:
  }
};

위의 두 파일을 봤을 때, 각 함수마다 달린 주석에는 구현해야 할 로직들이 의사코드로 작성이 되어있는 것을 볼 수 있다.

따라서, 결론적으로는 순서로만 봤을 때 로직은 이런 순서로 되어있는 것으로 생각하면 쉽다.

app -> flight Router  -> flightController 

app -> Book Router -> bookController 

 

2. 테스트에 맞게 함수의 로직을 구현

flight Router

 

- GET /flight?departure_times=2021-12-03T12:00:00&arrival_times=2021-12-03T12:00:00를  입력하면 조건에 해당하는 객체를 응답으로 보냅니다.

- GET /flight?departure=CJU&destination=ICN 을 입력하면 조건에 해당하는 객체를 응답으로 보냅니다.

// [GET] /flight
// 요청 된 파라미터 departure_times, arrival_times 값과 동일한 값을 가진 항공편 데이터를 조회합니다.
// 요청 된 파라미터 departure, destination 값과 동일한 값을 가진 항공편 데이터를 조회합니다.
findAll: (req, res) => {
	// req.query : GET 방식으로 넘어오는 데이터,쿼리스트링의 정보를 가져온다.
    const { departure_times, arrival_times, destination, departure } =
      req.query;
    // list 변수에 항공편 데이터를 복사해서 저장
    let list = flights;
    // 요청받아온 departure_times, arrival_times 데이터가 들어올 때
    // 항공편 데이터에 있는 정보와 같다면 같은 값을 필터로 걸러서 list에 저장
    if (departure_times && arrival_times) {
      list = flights.filter(
        (el) =>
          departure_times === el.departure_times &&
          arrival_times === el.arrival_times
      );
    }
    // 요청받아온 departure, destination 데이터가 들어올 때
    // 항공편 데이터에 있는 정보와 같다면 같은 값을 필터로 걸러서 list에 저장
    if (departure && destination) {
      list = flights.filter(
        (el) => departure === el.departure && destination === el.destination
      );
    }
	// list를 json 형식으로 변환하여 리턴
    return res.json(list);
  }

 

- GET /flight/:uuid 요청의 응답 객체는 `uuid, departure, destination, departure_times, arrival_times`를 포함해야 합니다.

// [GET] /flight/:uuid
// 요청 된 uuid 값과 동일한 uuid 값을 가진 항공편 데이터를 조회합니다.
findById: (req, res) => {
	// 요청받은 파라미터 uuid를 가져온다.
    const { uuid } = req.params;
    // 항공편 데이터를 list 변수에 저장한다.
    let list = flights;
    // uuid 파라미터가 들어올 때, 항공편 데이터에 있는 값이랑 동일하다면 같은 값을 찾아서 list에 저장
    if (uuid) {
      list = flights.filter((el) => uuid === el.uuid);
    }
    // json으로 변환한 list를 리턴한다.
   return res.json(list);
}

 

Advanced Challenges

- PUT /flight/:uuid 요청의 업데이트 된 객체를 응답으로 보냅니다.

- PUT /flight/:uuid 요청의 일부 데이터만 업데이트 된 객체를 응답으로 보냅니다.

 

// Advanced
  // [PUT] /flight/:uuid 요청을 수행합니다.
  // 요청 된 uuid 값과 동일한 uuid 값을 가진 항공편 데이터를 요쳥 된 Body 데이터로 수정합니다.
  update: (req, res) => {
    // 요청된 파라미터 가져오기
    const { uuid } = req.params;
    // 요청된 본문 가져오기
    const bodyData = req.body;
    // 요청된 본문의 uuid 속성만 제외하고 나머지 속성들만 넣어서 새로운 객체를 생성하여 updatedData에 저장
    const updatedData = Object.keys(bodyData)
      .filter((key) => key !== 'uuid')
      .reduce((obj, key) => {
        obj[key] = bodyData[key];
        return obj;
      }, {});

    // 요청된 uuid와 모든 항공편 데이터에서 같은 uuid의 위치를 찾아 flightIndex에 저장
    const flightIndex = flights.findIndex((flight) => flight.uuid === uuid);
    // updatedFlight에 모든 항공편 데이터에서 찾은 uuid와 요청된 수정 값을 저장
    const updatedFlight = { ...flights[flightIndex], ...updatedData };
    // flights의 동일한 uuid키의 값에 updatedFlight값을 넣어서 수정한다.
    flights[flightIndex] = updatedFlight;
    // 수정된 값을 json으로 변환하여 리턴
    return res.json(updatedFlight);
  }

 

Book Router

 

- POST /book 요청시, uuid, name, phone 데이터가 booking 배열에 객체 형태로 저장되어야 합니다.

// [POST] /book 요청을 수행합니다.
// 요청 된 예약 데이터를 저장합니다.
create: (req, res) => {
    // 요청된 본문을 해석한 객체
    const { flight_uuid, name, phone } = req.body;
    const booking_uuid = uuid();
    // 요청 된 예약 데이터를 객체 형식으로 담아서 예약 정보를 저장할 배열에 넣는다.
    const newBooking = { booking_uuid, flight_uuid, name, phone };
    booking.push(newBooking);
    return res.status(201).json(newBooking);
}

 

- GET /book/:phone 요청은 특정 예약자 전화번호에 대한 예약 데이터를 응답으로 보냅니다.

// [GET] /book/:phone 요청을 수행합니다.
// 요청 된 phone과 동일한 phone 예약 데이터를 조회합니다.
findByPhone: (req, res) => {
    const { phone } = req.params;
    // 요청된 phone과 예약정보가 담긴 booking 안에 있는 phone과 같다면 filter를 통해 같은 것만 걸러줌
    const result = booking.filter((booking) => booking.phone === phone);
    // 응답시 HTTP 상태 코드를 지정하고 phone과 동일한 예약 데이터를 json 형식으로 변환하여 리턴
    return res.status(200).json(result);
}

 

- GET /book/:phone/:flight_uuid 요청은 특정 항공편의 예약자 전화번호에 대한 예약 데이터를 응답으로 보냅니다.

// [GET] /book/:phone/:flight_uuid 요청을 수행합니다.
// 요청 된 id, phone과 동일한 uuid, phone 예약 데이터를 조회합니다.
findByPhoneAndFlightId: (req, res) => {
    // 요청 받은 라우트 매개변수에 대한 정보를 가져옴
    const { phone, flight_uuid } = req.params;
    // 요청된 id와 phone을 가지고 있는 예약 데이터 안에서 같은지 둘다 확인하여 filter로 찾아서 변수에 저장
    const result = booking.filter(
      (booking) =>
        booking.phone === phone && booking.flight_uuid === flight_uuid
    );
    // 응답시 HTTP 상태 코드를 지정하고 id,phone과 동일한 예약 데이터를 json 형식으로 변환하여 리턴
    return res.status(200).json(result);
}

 

- 테스트 통과 목록은 아니지만 구현하라는 함수 : deleteByBookingId

// Optional
// [DELETE] /book/:booking_uuid 요청을 수행합니다.
// 요청 된 id, phone 값과 동일한 예약 데이터를 삭제합니다.
deleteByBookingId: (req, res) => {
    // 요청된 booking_uuid를 가져옴
    const { booking_uuid } = req.params;
    // 예약된 정보에서 booking_uuid 값과 같은 정보를 찾아서 위치를 찾아 index 변수에 저장
    const index = booking.findIndex(
      (booking) => booking.booking_uuid === booking_uuid
    );
    // 위치가 -1이 아니라면 정보가 같은게 있으므로 splice 이용해서 예약 데이터를 삭제한다.
    if (index !== -1) {
      booking.splice(index, 1);
      // send() -> 본문을 보내지 않음을 의미(body 본문)
      return res.status(204).send();
    } else {
      // 동일한 예약 정보가 없으면 찾을 수 없다는 문구 json 형식으로 리턴
      return res.status(404).json({ error: 'Booking not found' });
    }
}

 

알게 된 지식 - 요청 객체와 응답 객체 (req, res)

 

req (요청객체)

  • req.get(헤더 이름): 헤더의 값을 가져온다. req.get('Content-type')
  • req.body: body-parser 미들웨어가 만드는 요청의 본문을 해석한 객체이다. POST 방식으로 넘어오는 데이터를 담는다.
  • req.params: 라우트 매개변수에 대한 정보가 담긴다.
  • req.query: GET방식으로 넘어오는 데이터, 쿼리스트링의 정보가 담긴다.
  • req.route : 현재 라우트에 관한 정보. 디버깅용.

res (응답 객체)

  • res.status(코드) / res.sendStatus(코드): 응답 시의 HTTP 상태 코드를 지정한다.
  • res.end(): 데이터 없이 응답을 보낸다.
  • res.json(JSON): JSON 형식의 응답을 보낸다.
  • res.send(body), res.send(status, body) : 클라이언트에 응답을 보냄. 상태 코드는 옵션

 

과제 진행에 큰 도움을 받은 자료

 

[EXPRESS] 📚 요청 객체와 응답 객체 (req, res) 정리

응답 객체 - response res.app: 똑같이 res 객체를 통해 app 객체에 접근한다. res.app.get('')같이 사용 가능. res.set(헤더, 값) / res.setHeader(헤더, 값): 응답의 헤더를 설정한다. req.get()이 헤더값을 가져오는거

inpa.tistory.com

 

'Boot Camp > code states' 카테고리의 다른 글

[ Code States ] Section 2 / KDT 회고  (0) 2023.04.10
[ Code States ] Section 2 / 기술 면접 준비  (0) 2023.04.10
[ Code States ] Refactor Express 과제  (0) 2023.04.06
[ Code States ] Mini Node Server 과제  (0) 2023.04.06
코드스테이츠 OT - [ 메타인지적 학습법 / 앞으로의 나의 다짐 ]  (0) 2023.03.23
  1. 과제 요구 사항
  2.  
  3. 통과해야 할 테스트
  4. 내가 구현한  방법
  5. 알게 된 지식 - 요청 객체와 응답 객체 (req, res)
'Boot Camp/code states' 카테고리의 다른 글
  • [ Code States ] Section 2 / KDT 회고
  • [ Code States ] Section 2 / 기술 면접 준비
  • [ Code States ] Refactor Express 과제
  • [ Code States ] Mini Node Server 과제
_moda
_moda
프론트엔드 개발 공부를 하고 있읍니다.
_moda
ModaLog
_moda
전체
오늘
어제
  • All Records
    • 취업 준비
    • TIL
    • Front end
      • HTML \ CSS
      • JavaScript
      • TypeScript
      • React
      • GIT
      • Node.js
      • 개발 지식
      • 면접 질문 공부
    • Boot Camp
      • code states
      • Project
    • 자료구조 \ 알고리즘 기법
    • Coplit
    • Programmers
    • 모다딥 공부 정리
    • 정보처리기능사

블로그 메뉴

  • 태그
  • 방명록

공지사항

  • 개발자로 가는 길

인기 글

태그

  • react
  • til
  • typescript
  • 타입스크립트
  • 네트워크 기초
  • CODE STATES
  • javascript
  • Coplit
  • 코드스테이츠
  • 모던 자바스크립트 딥 다이브

최근 댓글

최근 글

hELLO · Designed By 정상우.
_moda
[ Code States ] StatesAirline Server 과제
상단으로

티스토리툴바

개인정보

  • 티스토리 홈
  • 포럼
  • 로그인

단축키

내 블로그

내 블로그 - 관리자 홈 전환
Q
Q
새 글 쓰기
W
W

블로그 게시글

글 수정 (권한 있는 경우)
E
E
댓글 영역으로 이동
C
C

모든 영역

이 페이지의 URL 복사
S
S
맨 위로 이동
T
T
티스토리 홈 이동
H
H
단축키 안내
Shift + /
⇧ + /

* 단축키는 한글/영문 대소문자로 이용 가능하며, 티스토리 기본 도메인에서만 동작합니다.