Unit10 - [Web Server] ๊ธฐ์ดˆ - 3

๊ฐ•์„ฑ์ผยท2023๋…„ 6์›” 5์ผ
0
post-thumbnail

โœ… TIL


์˜ค๋Š˜์€ StatesAirline ์„œ๋ฒ„๋ฅผ Express ํ”„๋ ˆ์ž„์›Œํฌ๋ฅผ ์ด์šฉํ•ด ๋งŒ๋“ค๊ณ , ๋กœ์ปฌ ํ˜ธ์ŠคํŠธ์™€ ์—ฐ๊ฒฐํ•ด์„œ ๊ตฌํ˜„ํ•œ๋‹ค.

์„œ๋ฒ„๋Š” ํด๋ผ์ด์–ธํŠธ์˜ ์š”์ฒญ์— ๋”ฐ๋ผ ํ•ญ๊ณตํŽธ๊ณผ ์˜ˆ์•ฝ ๋ฐ์ดํ„ฐ๋ฅผ ์กฐํšŒ, ์ƒ์„ฑ, ์ˆ˜์ •, ๊ทธ๋ฆฌ๊ณ  ์‚ญ์ œํ•˜๋Š” ๊ธฐ๋Šฅ์„ ์ˆ˜ํ–‰ํ•ด์•ผ ํ•œ๋‹ค.

๐Ÿ’ก ์˜ค๋Š˜์˜ KeyPoint

  • ๊ฐ ์—”๋“œํฌ์ธํŠธ๋งˆ๋‹ค ๋ผ์šฐํ„ฐ๊ฐ€ ์กด์žฌํ•œ๋‹ค.
  • ํ•ด๋‹น ๋ผ์šฐํ„ฐ์— ๋งž๋Š” ์š”๊ตฌ์กฐ๊ฑด ๊ธฐ๋Šฅ์„ ๊ตฌํ˜„ํ•œ๋‹ค.
  • 5๊ฐ€์ง€ HTTP method๋ฅผ ๊ตฌํ˜„ํ•œ๋‹ค.

StatesAirline 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 ์š”์ฒญ์— ๋”ฐ๋ผ ํ•ญ๊ณตํŽธ์„ ์ˆ˜์ •ํ•˜๋Š” ๊ธฐ๋Šฅ์„ ๊ตฌํ˜„ํ•ฉ๋‹ˆ๋‹ค.

  • ๋ชฉํ‘œ

    • Flight API -> ํ•ญ๊ณตํŽธ ์ˆ˜์ •์—์„œ ์ •์˜ํ•œ API ์š”์ฒญ์„ ์ˆ˜ํ–‰ํ•˜๋Š” ์ฝ”๋“œ๋ฅผ ์ž‘์„ฑํ•˜์„ธ์š”.
    • Advanced Challenges์— ์žˆ๋Š” ๋ชจ๋“  ํ…Œ์ŠคํŠธ๋ฅผ ํ†ต๊ณผํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.
  • ์ฐธ๊ณ  ๋‚ด์šฉ

    • flight.uuid๋Š” ๋ณ€๊ฒฝ๋˜๋ฉด ์•ˆ ๋ฉ๋‹ˆ๋‹ค.
    • flight JSON์˜ ์ผ๋ถ€๋งŒ ์ˆ˜์ •ํ•  ์ˆ˜ ์žˆ์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

StatesAirline Server API document



โš™๏ธ Code

// ๐Ÿ’ฌ ์ฃผ์–ด์ง„ ์ฝ”๋“œ (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:
  },
};

// โœ… ๊ตฌํ˜„ํ•œ ์ฝ”๋“œ (flightController)

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

module.exports = {
  
  findAll: (req, res) => {
    const { departure_times, arrival_times, destination, departure } =
      req.query;
    
    // router.get("/", findAll); // Get localhost:3001/flight?departure=ICN&destination=CJU
    // ๋„์ฐฉ์‹œ๊ฐ„, ์ถœ๋ฐœ์‹œ๊ฐ„์— ๋Œ€ํ•œ ํ•„ํ„ฐ๋ง
    if (departure_times && arrival_times) {
      const filteredData = flights.filter(
        (flight) =>
          flight.departure_times === departure_times &&
          flight.arrival_times === arrival_times
      );
      return res.status(200).json(filteredData);
    }
    
    // ์ถœ๋ฐœ์ง€, ๋„์ฐฉ์ง€์— ๋Œ€ํ•œ ํ•„ํ„ฐ๋ง
    else if (departure && destination) {
      const filteredData = flights.filter(
        (flight) =>
          flight.departure === departure && flight.destination === destination
      );

      return res.status(200).json(filteredData);
    }

    // router.get("/", findAll); // GET localhost:3001/flight/
    // ๊ทธ ์™ธ๋Š” ์ „์ฒด ํ•ญ๊ณตํŽธ ๋ฐ์ดํ„ฐ๋ฅผ ์‘๋‹ต์œผ๋กœ ์ „์†ก
    return res.status(200).json(flights);
  },

  // router.get("/:uuid", update); // GET localhost:3001/flight/af6fa55c-da65-47dd-af23-578fdba40bed
  findById: (req, res) => {
    const { uuid } = req.params;

    const filteredData = flights.filter((flight) => flight.uuid === uuid);
    res.status(200).json(filteredData);
  },
  
  // router.put("/:uuid", update); // PUT localhost:3001/flight/af6fa55c-da65-47dd-af23-578fdba40bed
  update: (req, res) => {
    const { uuid } = req.params;
    const bodyData = req.body;

    const flightIndex = flights.findIndex((flight) => flight.uuid === uuid);

    if (flightIndex === -1) {
      return res.status(404).json({ error: "Flight not found" });
    }

    // ๊ธฐ์กด ํ•ญ๊ณตํŽธ ๋ฐ์ดํ„ฐ๋ฅผ ์ƒˆ๋กœ์šด ๋ฐ์ดํ„ฐ๋กœ ์—…๋ฐ์ดํŠธํ•ฉ๋‹ˆ๋‹ค.
    flights[flightIndex] = { ...flights[flightIndex], ...bodyData };

    return res.status(200).json(flights[flightIndex]);
  },
};
// โœ… ๊ตฌํ˜„ํ•œ ์ฝ”๋“œ (bookController)

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

module.exports = {
  // router.get("/", findAll); // GET localhost:3001/book/
  findAll: (req, res) => {
    return res.status(200).json(booking);
  },
  
  // router.get("/:phone", findByPhone); // GET localhost:3001/book/:phone
  findByPhone: (req, res) => {
    const { phone } = req.params;
    const filteredData = booking.filter((booking) => booking.phone === phone);
    return res.status(200).json(filteredData);
  },
  
  // router.get("/:phone/:flight_uuid", findByPhoneAndFlightId); // GET localhost:3001/book/:phone/:flight_uuid
  findByPhoneAndFlightId: (req, res) => {
    const { phone, flight_uuid } = req.params;

    const filteredData = booking.filter(
      (booking) =>
        booking.phone === phone && booking.flight_uuid === flight_uuid
    );
    return res.status(200).json(filteredData);
  },
  
  // router.post("/", create); // POST localhost:3001/book/
  create: (req, res) => {
    const booking_uuid = uuid();

    const { phone, flight_uuid, name } = req.body; // ์š”์ฒญ ๋ฐ์ดํ„ฐ์—์„œ ํ•„์š”ํ•œ ๊ฐ’์„ ์ถ”์ถœํ•œ๋‹ค.

    const newBooking = {
      booking_uuid, 
      phone,
      flight_uuid,
      name,
    };

    booking.push(newBooking); // booking ๋ฐฐ์—ด์— ์ƒˆ๋กœ์šด ์˜ˆ์•ฝ ๋ฐ์ดํ„ฐ๋ฅผ ์ถ”๊ฐ€ํ•œ๋‹ค.

    return res.status(201).json(newBooking);
  },

  // router.delete("/:booking_uuid", deleteByBookingId); // GET localhost:3001/book/{:booking_uuid}
  deleteByBookingId: (req, res) => {
    const { booking_uuid } = req.params;

    const initialLength = booking.length;

    booking = booking.filter(
      (booking) => booking.booking_uuid !== booking_uuid
    );

    if (booking.length === initialLength) {
      return res.status(404).json({ error: "Booking not found" });
    }

    return res.sendStatus(204);
  },
};


๊ตฌํ˜„ํ•œ ์„œ๋ฒ„



๐Ÿ’ก Error Note.

๐Ÿ’ก ์„œ๋ฒ„์— ๋Œ€ํ•ด ์ƒ๊ฐํ•ด๋ณผ ๊ฒƒ

  • ์ฝ”๋“œ ๊ตฌํ˜„์ด ์™„๋ฃŒ๋˜์—ˆ๋Š”๋ฐ, ๊ณ„์† /flight ์š”์ฒญ์—์„œ ์—๋Ÿฌ๊ฐ€ ์ƒ๊ฒผ๋‹ค.
  • ์ฝ”๋“œ๋ฅผ ์•„๋ฌด๋ฆฌ ๋ฆฌํŒฉํ† ๋งํ•ด๋ด๋„ ๊ณ„์† ์—๋Ÿฌ๋Š” ์—ฌ์ „ํ–ˆ๊ณ , ๊ฒฐ๊ตญ ์‹œ์„ ์„ ๋‹ค๋ฅด๊ฒŒ ๋ณด๊ฒŒ ๋˜์—ˆ๋‹ค.
  • ๋ฌธ์ œ๋Š” test ์„œ๋ฒ„์™€ ํด๋ผ์ด์–ธํŠธ์ธ ๋‚ด๊ฐ€ ์š”์ฒญํ•˜๋Š” npm ์„œ๋ฒ„๊ฐ€ crush ํ•˜๋Š” ๊ฒƒ์ด์—ˆ๋‹ค.
  • ๊ฒฐ๊ตญ, ์„œ๋ฒ„๋ฅผ ๋‹ซ๊ณ  vscode ์žฌ์ ‘์† ํ›„, ๋ฐ”๋กœ test๋ฅผ ์ง„ํ–‰ํ•ด์„œ ํ•ด๊ฒฐํ–ˆ๋‹ค.
profile
์•„์ด๋””์–ด๊ฐ€ ๋„˜์น˜๋Š” ํ”„๋ก ํŠธ์—”๋“œ๋ฅผ ๊ฟˆ๊ฟ‰๋‹ˆ๋‹ค ๐Ÿ”ฅ

0๊ฐœ์˜ ๋Œ“๊ธ€