1. Node.JS로 TODO 를 express를 통해 작업해보자.
Express는 Node.js의 서버 프레임워크이다.
아래와 같이 터미널에서 실행하여 Express 모듈을 설치해야 한다.
npm init -y
npm install express
한편 앞서 헤더를 통해 해결했던 CORS 이슈를 cors 모듈을 이용한 미들웨어로 해결할 수 있다.
npm install cors
app.js 파일을 만들어 아래와 같이 작성한다.
const express = require("express");
const cors = require("cors");
const app = express();
app.use(cors()); // app.use(경로, 미들웨어 함수) 혹은 app.use(미들웨어 함수)는 요청에 대해 핸들링한다.
// 미들웨어 함수는 req, res, next를 응답으로 받아, next()를 호출하는 함수이다.
app.get("/", (req, res) => {
res.json({ url: "암것두 없다" }); //res.json은 객체를 파라미터로 받는다. 받은 객체를 JSON 형식으로 변환하고, 헤더에 application/json을 자동으로 추가해준다.
});
app.listen(8080, () => {
console.log("8080번 포트에서 익스프레스 실행");
});
app.use를 통해 요청을 미들웨어 함수로 핸들링할 수 있다. req를 받아, res를 수정한 후, next()를 통해 다음 구문을 실행하는 방식이다. app.use(cors())는 자동으로 헤더에 cros를 핸들링하는 값을 추가해준다.
app.get(라우트, 리퀘스트 핸들러)와 같은 방식으로 요청을 간단하게 처리할 수 있다.
여기에 노드JS에서 chunk를 파싱하기 위해 했던
req
.on("data", (chunk) => {
requestBody += chunk;
})
.on("end", () => {
const user = JSON.parse(requestBody);
}
위의 작업을 미들웨어를 통해 아래와 같이 단순화할 수 있다.
app.use(express.json());
앞선 node js 예제에서는 자바스크립트 배열을 사용했지만, 이번엔 JSON 파일을 사용해보자.
touch data.json
로 JSON 파일을 만들고,
아래와 같이 get, post 요청을 만들었다.
이때 파일의 주소를 가져오는 데에는 3가지가 사용될 수 있다.
process.cwd()
: app.js가 실행되고 있는 경로를 반환한다.
__dirname
: 현재 파일이 실행되고 있는 경로를 반환한다.
__filename
: 현재 실행중인 파일의 경로를 반환한다.
가령 아래와 같다.
process.cwd() : c:\Users\jonghyun\Desktop\node-js-todo\express-server
__dirname : c:\Users\jonghyun\Desktop\node-js-todo\express-server\routes\user
__filename : c:\Users\jonghyun\Desktop\node-js-todo\express-server\routes\user\[id].js
이렇게 받은 path는 윈도우에서는 역슬래시, 리눅스, 맥, 자바스크립트에서는 슬래시를 사용한다. 경로를 파싱하기 위해서는 path라이브러리를 사용할 수 있다.
const fs = require("fs");
const path = require("path");
app
.route("/user")
.get((req, res) => {
fs.readFile(path.join(__dirname, "data.json"), "utf8", (err, data) => {
const jsonData = JSON.parse(data);
res.json(jsonData);
});
})
.post((req, res) => {
// 기존 데이터 읽기
fs.readFile(path.join(__dirname, "data.json"), "utf-8", (err, data) => {
const jsonData = JSON.parse(data);
jsonData.push({ id: jsonData.at(-1).id + 1, ...req.body });
// 업데이트된 데이터 파일에 쓰기
fs.writeFile(
path.join(__dirname, "data.json"),
JSON.stringify(jsonData, null, 2),
"utf-8",
(err) => {
res.json(jsonData);
}
);
});
});
위와 같은 app.route와 달리, express.Router()를 이용하여 라우터 모듈을 만들 수 있다.
routes\user[id].js 파일을 만든 후,
아래와 같이 user/:id를 받는 로직을 만들었다.
이때 :id로 받은 params는, req.params.id로 접근할 수 있다.
const express = require("express");
const fs = require("fs");
const path = require("path");
const router = express.Router();
router.get("/:id", (req, res) => {
const userId = Number(req.params.id);
fs.readFile(path.join(__dirname, "../../data.json"), (err, data) => {
console.log(userId);
console.log(process.cwd());
console.log(__dirname);
console.log(__filename);
const jsonData = JSON.parse(data);
const user = jsonData.find((user) => user.id === userId);
res.json(user);
});
});
router.patch("/:id", (req, res) => {
const userId = Number(req.params.id);
fs.readFile(path.join(__dirname, "../../data.json"), (err, data) => {
const jsonData = JSON.parse(data);
const user = jsonData.find((user) => user.id === userId);
Object.entries(req.body).forEach((entry) => {
const [key, value] = entry;
user[key] = value;
});
fs.writeFile(
path.join(__dirname, "../../data.json"),
JSON.stringify(jsonData, null, 2),
"utf-8",
(err) => {
res.json(user);
}
);
});
});
module.exports = router;
이렇게 export한 router는 app.use에서 추가할 수 있다.
// app.js
const userRouter = require("./routes/user/[id]");
app.use("/user", userRouter);
전체 코드
app.js
const express = require("express");
const fs = require("fs");
const userRouter = require("./routes/user/[id]");
const path = require("path");
const cors = require("cors");
const app = express();
app.use(cors()); // app.use(경로, 미들웨어 함수) 혹은 app.use(미들웨어 함수)는 요청에 대해 핸들링한다.
// 미들웨어 함수는 req, res, next를 응답으로 받아, next()를 호출하는 함수이다.
app.use((req, res, next) => {
console.log(req.url);
next();
});
app.use(express.json());
app.use("/user", userRouter);
app.get("/", (req, res) => {
res.json({ url: "암것두 없다" }); //res.json은 객체를 파라미터로 받는다. 받은 객체를 JSON 형식으로 변환하고, 헤더에 application/json을 자동으로 추가해준다.
});
app
.route("/user")
.get((req, res) => {
fs.readFile(path.join(__dirname, "data.json"), "utf8", (err, data) => {
const jsonData = JSON.parse(data);
res.json(jsonData);
});
})
.post((req, res) => {
// 기존 데이터 읽기
fs.readFile(path.join(__dirname, "data.json"), "utf-8", (err, data) => {
const jsonData = JSON.parse(data);
jsonData.push({ id: jsonData.at(-1).id + 1, ...req.body });
// 업데이트된 데이터 파일에 쓰기
fs.writeFile(
path.join(__dirname, "data.json"),
JSON.stringify(jsonData, null, 2),
"utf-8",
(err) => {
res.json(jsonData);
}
);
});
});
app.listen(8084, () => {
console.log("8084번 포트에서 익스프레스 실행");
});
routes\user[id].js
const express = require("express");
const fs = require("fs");
const path = require("path");
const router = express.Router();
router.get("/:id", (req, res) => {
const userId = Number(req.params.id);
fs.readFile(path.join(__dirname, "../../data.json"), (err, data) => {
console.log(userId);
console.log(process.cwd());
console.log(__dirname);
console.log(__filename);
const jsonData = JSON.parse(data);
const user = jsonData.find((user) => user.id === userId);
res.json(user);
});
});
router.patch("/:id", (req, res) => {
const userId = Number(req.params.id);
fs.readFile(path.join(__dirname, "../../data.json"), (err, data) => {
const jsonData = JSON.parse(data);
const user = jsonData.find((user) => user.id === userId);
Object.entries(req.body).forEach((entry) => {
const [key, value] = entry;
user[key] = value;
});
fs.writeFile(
path.join(__dirname, "../../data.json"),
JSON.stringify(jsonData, null, 2),
"utf-8",
(err) => {
res.json(user);
}
);
});
});
module.exports = router;