[TIL] Day43 #React-CRUD-server

Beanxxยท2022๋…„ 6์›” 26์ผ
0

TIL

๋ชฉ๋ก ๋ณด๊ธฐ
43/120
post-thumbnail

2022.06.26(Sun)
[TIL] Day43

์ด๋ฒˆ ์ฃผ๋ง์—๋Š” express๋กœ server-API-CRUD๋ฅผ ๊ตฌํ˜„ํ•ด์„œ ์ €๋ฒˆ์ฃผ์— ์ง„ํ–‰ํ–ˆ๋˜ React-CRUD-client์— fetch๋ฅผ ํ†ตํ•ด ์—ฐ๊ฒฐํ•ด๋ณด๋Š” ์ž‘์—…์„ ์ง„ํ–‰ํ–ˆ๋‹ค.
๋ฏธ๋ฃจ๋‹ค ๋ฏธ๋ฃจ๋‹ค ์•„์ง๋„ ์ˆ˜์ • ๊ธฐ๋Šฅ์ธ UPDATE๋Š” ๊ตฌํ˜„ ๋ชปํ•จ... ํ•ด์•ผํ•˜๋Š”๋ฐ ์ฝ”๋“œ๊ฐ€ ๋„ˆ๋ฌด ์ค‘๊ตฌ๋‚œ๋ฐฉ์ด๋ผ ํ•œ๋ฒˆ ์ปดํฌ๋„ŒํŠธ ๊ตฌ์กฐ ์ข€ ์‹น ๊ฐˆ์•„์—Ž์€ ํ›„์— ์ง„ํ–‰ํ•ด์•ผ ํ• ๋“ฏ ์‹ถ๋‹ค..๐Ÿซ 

๐Ÿ“ ํด๋” ๊ตฌ์กฐ

  • CRUD-PROJECT
    • crud-client
      • components
        • ContentItem.js
        • ContentList.js
        • Editor.js
      • App.js
    • crud-server
      • repository/diaryData.js
      • router/diaryRouter.js
      • controller/index.js
      • app.js

๐Ÿ“Ž crud-server

// app.js
const express = require("express");
const app = express();
const cors = require("cors");
const morgan = require("morgan");
const port = 3001;

app.use(cors()); // cors middleware ์ ์šฉ
app.use(express.json()); // Express ๋‚ด์žฅ ๋ฏธ๋“ค์›จ์–ด ์ ์šฉ
app.use(morgan("tiny")); // HTTP ์š”์ฒญ logger์ธ morgan ์ ์šฉ

// Routing
const diaryRouter = require("./router/diaryRouter");
app.use("/diary", diaryRouter);

// Response
app.get("/", (req, res) => {
  res.status(200).send("My Diary!~!");
});

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

const server = app.listen(port, () => {
  console.log(`[RUN] My CRUD diary Server... | http://localhost:${port}`);
});

module.exports.app = app;
module.exports.server = server;
// router/diaryRouter.js
// TODO: discussions ๋ผ์šฐํ„ฐ๋ฅผ ์™„์„ฑํ•ฉ๋‹ˆ๋‹ค.\
const { diaryController } = require("../controller");
const { findAll, findById, createOne, updateById, deleteById } =
  diaryController;
const express = require("express");
const router = express.Router();

// http://localhost:3001/diary/

router.get("/", findAll); // ๋ชจ๋“  ๋ชฉ๋ก ์กฐํšŒ Router
router.get("/:id", findById); // ๊ธ€ ํ•˜๋‚˜ ์กฐํšŒ Router
router.post("/", createOne); // ๊ธ€ ํ•˜๋‚˜ ์ƒ์„ฑ Router
router.put("/:id", updateById); // ๊ธ€ ํ•˜๋‚˜ ์ˆ˜์ • Router
router.delete("/:id", deleteById); // ๊ธ€ ํ•˜๋‚˜ ์‚ญ์ œ Router

module.exports = router;
// controller/index.js
const { diaryDummyData } = require("../repository/diaryData"); 
const diaryData = diaryDummyData;
const diaryController = {
  // router.get("/", findAll);
  findAll: (req, res) => {
    return res.status(200).json(diaryData);
  },

  // router.get("/:id", findById);
  findById: (req, res) => {
    // path-parameter๊ฐ€ ์žˆ๋‹ค๋ฉด
    if (req.params) {
      // filter ๋Œ€์‹  find ๋ฉ”์†Œ๋“œ ์‚ฌ์šฉ
      const idx = diaryData.find((item) => item.id === Number(req.params.id));
      // ์กฐํšŒํ•˜๋ ค๋Š” id๊ฐ€ ์žˆ๋‹ค๋ฉด ์‘๋‹ต
      if (idx !== undefined) {
        res.status(200).json(idx);
      }
    }
    res.status(404).send("Not found!!");
  },
  
  // router.post("/", createOne); 
  createOne: (req, res) => {
    const newItem = req.body;
    // unshift()๋กœ ์ƒ์„ฑ๋œ data๋ฅผ diaryData ์•ž์— ์ถ”๊ฐ€
    diaryData.unshift(newItem);
    return res.status(200).send("Create Diary!!");
  },

  // router.put("/:id", updateById);
  updateById: (req, res) => {
    const updated = diaryData.filter((item) => item.id === Number(req.body.id));
    // //updated๋Š” ๋ฐฐ์—ด ์•ˆ์— ๊ฐ์ฒด๊ฐ€ ์žˆ๋Š” ํ˜•ํƒœ์ด๋ฏ€๋กœ index:[0]์„ ๊ฐ€์ ธ์˜ด
    // ์ˆ˜์ •ํ•œ ๋‚ด์šฉ์„ body์— ๋ถ™์—ฌ์„œ ์ˆ˜์ •
    const change = { ...updated[0], ...req.body }; // updateํ•  data
    // findIndex() ๋ฉ”์†Œ๋“œ๋กœ id๊ฐ€ ์ผ์น˜ํ•˜๋Š” data์˜ index๋ฅผ ๊ตฌํ•จ
    const idx = diaryData.findIndex(
      (item) => item.id === Number(req.params.id)
    );

    // splice(): ์ƒˆ ์š”์†Œ๋ฅผ ์ถ”๊ฐ€ํ•˜์—ฌ ๋ฐฐ์—ด ๋‚ด์šฉ ๋ณ€๊ฒฝ
    // splice(start index, deleteCount, item)
    diaryData.splice(idx, 1, change);
    return res.status(200).json(change);
  },

  // router.delete("/:id", deleteById);
  deleteById: (req, res) => {
    const deleted = diaryData.findIndex(
      (item) => item.id === Number(req.params.id)
    );
    // splice(): ๋ฐฐ์—ด์˜ ๊ธฐ์กด ์š”์†Œ ์‚ญ์ œ 
    diaryData.splice(deleted, 1);
    return res.status(200).json();
  },
};

module.exports = {
  diaryController,
};

๐Ÿ“Ž crud-client

// fetch์ชฝ ์ฝ”๋“œ๋งŒ ์‚ดํŽด๋ณด๊ธฐ ูฉ( แ› )ูˆ

function App() {
  const url = "http://localhost:3001/diary";
  const [data, setData] = useState([]);

  // ์ฒ˜์Œ ๋ Œ๋”๋ง๋  ๋•Œ๋งŒ fetch ์ ์šฉ
  useEffect(() => {
    getDiary();
  }, []);

  // fetch๋กœ server์—์„œ data ๊ฐ€์ ธ์˜ค๋Š” function'
  const getDiary = () => {
    fetch(url)
      .then((res) => res.json()) // json ํ˜•์‹์œผ๋กœ data ๊ฐ€์ ธ์˜ค๊ธฐ
      .then((data) => setData(data)); // data ์ƒํƒœ ๋ณ€๊ฒฝ ํ•จ์ˆ˜ ์‹คํ–‰
  };


  // Create-๊ธ€ ์ถ”๊ฐ€
  const onCreate = (title, content) => {
    const createdAt = new Date().toLocaleDateString();
    const newItem = {
      id: dataId.current,
      username: "SooBin",
      title,
      content,
      createdAt,
    };
    dataId.current += 1;
    setData([newItem, ...data]);

    fetch(url, {
      method: "POST",  // ์ƒ์„ฑ ๋ฉ”์†Œ๋“œ ์ ์šฉ
      headers: {
        // client->server๋กœ ์š”์ฒญ์‹œ json ๋ฐ์ดํ„ฐ ํ˜•์‹ ๊ถŒ์žฅ ์˜๋ฏธ
        "Accept": "application/json",
        // ํ˜„์žฌ ์ „์†กํ•˜๋Š” ๋ฐ์ดํ„ฐ๊ฐ€ json์ž„์„ ์˜๋ฏธ
        "Content-Type": "application/json", 
      },
      // json ํ˜•์‹์œผ๋กœ ๋ณ€ํ™˜
      body: JSON.stringify(newItem),
    }).then((res) => {
      if (res.status === 201) {
        getDiary();
      }
    });
  };


  // Delete-๊ธ€ ์‚ญ์ œ
  const onDelete = () => {
    const deletedDiary = data.filter((item) => item.id !== Number(id));
    setData(deletedDiary);
    setIsTitleClick(false);
    fetch(url + `/${id}`, {
      method: "DELETE", // ์‚ญ์ œ ๋ฉ”์†Œ๋“œ ์ ์šฉ
    }).then((res) => {
      // 202 status: ์š”์ฒญ ์„ฑ๊ณต์ ์œผ๋กœ ์ ‘์ˆ˜ & ์•„์ง ํ•ด๋‹น ์š”์ฒญ์— ๋Œ€ํ•ด ์ฒ˜๋ฆฌ ์ค‘์ด๊ฑฐ๋‚˜ ์ฒ˜๋ฆฌ ์‹œ์ž‘ ์ „
      // 204 status: ์š”์ฒญ์ด ์„ฑ๊ณต & client๊ฐ€ ํ˜„์žฌ ํŽ˜์ด์ง€์—์„œ ๋ฒ—์–ด๋‚˜์ง€ ์•Š์•„๋„ ๋จ์„ ์˜๋ฏธ
      if (res.status === 202 || 204) {
        getDiary();
      }
    });
  };

  ...
}

export default App;

์š”๋กœ์ฝค ์ ์šฉํ•˜๋ฉด React client ํŽ˜์ด์ง€์—์„œ ์ƒˆ๋กœ๊ณ ์นจํ•ด๋„ ๊ธ€์„ ์ƒ์„ฑ, ์‚ญ์ œํ•œ ๊ฒƒ์ด ๊ณ ๋Œ€๋กœ ๋‚จ์•„์žˆ๋Œœ ๐Ÿ™Œ

profile
FE developer

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