2022.06.26(Sun)
[TIL] Day43
์ด๋ฒ ์ฃผ๋ง์๋ express๋ก server-API-CRUD๋ฅผ ๊ตฌํํด์ ์ ๋ฒ์ฃผ์ ์งํํ๋ React-CRUD-client์ fetch๋ฅผ ํตํด ์ฐ๊ฒฐํด๋ณด๋ ์์ ์ ์งํํ๋ค.
๋ฏธ๋ฃจ๋ค ๋ฏธ๋ฃจ๋ค ์์ง๋ ์์ ๊ธฐ๋ฅ์ธ UPDATE๋ ๊ตฌํ ๋ชปํจ... ํด์ผํ๋๋ฐ ์ฝ๋๊ฐ ๋๋ฌด ์ค๊ตฌ๋๋ฐฉ์ด๋ผ ํ๋ฒ ์ปดํฌ๋ํธ ๊ตฌ์กฐ ์ข ์น ๊ฐ์์์ ํ์ ์งํํด์ผ ํ ๋ฏ ์ถ๋ค..๐ซ
// 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,
};
// 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 ํ์ด์ง์์ ์๋ก๊ณ ์นจํด๋ ๊ธ์ ์์ฑ, ์ญ์ ํ ๊ฒ์ด ๊ณ ๋๋ก ๋จ์์๋ ๐