Tech stack:
Other tools used:
과제 주제로 Node.js와 express를 활용하여 쇼핑몰의 백엔드 서버를 만들게 되었음. 아래의 필수요구사항을 모두 구현하였음:
대부분은 강의를 응용하면 API를 구현하는 방법 자체는 이해하기 어렵지 않았음. 다만 언제나 그렇듯 개발 과정에서 크고 작은 문제는 상당히 많았음 (순서 뒤죽박죽 주의)
status: {
type: String, // status 필드 추가
default: "FOR_SALE", // 기본 값은 "FOR_SALE"
},
const createdSpartSchema = joi.object({
name: joi.string().min(3).max(50).required(),
thumbnailUrl: joi.string(),
price: joi.number().min(100).max(10000000).required(),
description: joi.string().min(10).required(),
seller: joi.string().min(3).max(30).required(),
password: joi.string().min(4).required(),
});
const updatedSpartSchema = joi.object({
name: joi.string().min(3).max(50),
description: joi.string().min(10),
status: joi.string(),
price: joi.number().min(100).max(10000000),
});
// 1. 상품 작성 API
router.post("/goods", async (req, res, next) => {
try {
const validation = await createdSpartSchema.validateAsync(req.body);
const { name, thumbnailUrl, price, description, seller, password } =
validation; // 전역변수로 빼보자
// 기본 상태는 판매 중
const status = "FOR_SALE";
const product = new Spart({
name,
thumbnailUrl,
price,
description,
seller,
password,
status,
});
const savedProduct = await product.save();
return res
.status(201)
.json({ message: "상품 등록됐음~~", product: savedProduct });
} catch (error) {
next(error);
}
});
// 4. 상품 정보 수정 API
router.put("/goods/:productId", async (req, res, next) => {
try {
const { productId } = req.params;
const { password, ...updateFields } = req.body;
const validation = await updatedSpartSchema.validateAsync(updateFields);
const product = await Spart.findById(productId).exec();
if (!product) {
return res.status(404).json({ message: "상품 없음...!!!" });
}
if (password !== product.password) {
return res.status(401).json({ message: "비번 그게 아님" });
}
// 업데이트 필드 적용
Object.assign(product, validation);
const updatedProduct = await product.save();
return res
.status(200)
.json({ message: "수정됐음~~", product: updatedProduct });
} catch (error) {
next(error);
}
});
import express from "express";
import connect from "./schemas/index.js";
import spartRouter from "./routes/spart.router.js";
import errorHandler from "./middlewares/error-handler.js";
import Spart from "./schemas/spart.schemas.js";
const app = express();
const PORT = 3000;
connect();
// ejs endeavor
app.set("view engine", "ejs");
app.set("views", "./views");
app.use(express.json());
app.use(express.urlencoded({ extended: true }));
// ejs endeavor
app.use(express.static("./style"));
app.use((req, res, next) => {
console.log("Request URL:", req.originalUrl, "-", new Date());
next();
});
const router = express.Router();
// ejs endeavor
app.get("/", async (req, res) => {
const products = await Spart.find()
.select("name thumbnailUrl price seller status createdAt")
.sort("-createdAt")
.exec();
res.render("index", { post: products });
});
app.use("/api", [router, spartRouter]);
app.use(errorHandler);
app.listen(PORT, () => {
console.log(PORT, "포트로 서버가 열렸어요!");
});
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Spart Store</title>
<link rel="stylesheet" href="styles.css" />
</head>
<body>
<h1>Spart Store</h1>
<div class="product-grid">
<% post.forEach(product => { %>
<div class="product">
<img src="<%= product.thumbnailUrl %>" alt="<%= product.name %>">
<h3><%= product.name %></h3>
<p><%= product.price %> 원</p>
<p><%= product.seller %></p>
<p><%= product.status %></p>
</div>
<% }); %>
</div>
</body>
</html>
느낀점/배운점은 과제 제출하며 작성한 답변으로 퉁치겠음:
Q2. 대표적인 HTTP Method의 4가지 (GET, POST, PUT, DELETE)는 각각 어떤 상황에서 사용하였나요?
- 상품등록: POST / 상품목록조회 및 상세조회: GET / 상품정보수정: PUT / 상품삭제: DELETE
Q3. API 설계 시 RESTful한 원칙을 따랐나요? 어떤 부분이 RESTful한 설계를 반영하였고, 어떤 부분이 그렇지 않았나요?
- REST의미에 따라 직관적으로 리소스를 정의하여 이해하기 쉽도록 RESTful한 설계를 반영하였습니다. URL 경로별 앞서 언급한 HTTP method에 따라 해당 자원에 대한 기능/행위를 표현할 수 있도록 구현했습니다.
Q4. 폴더 구조(Directory Structure)를 역할 별로 분리하였다면, 어떤 이점을 가져다 주었을까요?
- 우선 기능과 역할별로 폴더 구조를 분리하며 느낀점은 가독성이 높아 코드를 쉽게 찾고 이해하는데 용이하다는 것입니다. 이는 향후 유지보수에 있어서도 도움이 될 것이라 생각되며, 특정 기능이나 모듈을 담당하는 파일들이 한 폴더에 모여있으면 해당 기능에 대한 테스트나 디버깅에도 수월할 것 같습니다.
Q5. mongoose에서 상품 상태는 어떠한 방식으로 관리하였나요? 이 외에도 어떤 방법들이 있었을까요?
- 상품 상태의 경우 저는 String타입으로 관리하였으나 옵션이 두 가지(FOR SALE / SOLD OUT) 뿐이라 boolean타입으로도 관리할 수 있을 것 같다 생각했습니다. 제 todo 리스트에 있었으나 시간관계상 시도해보지 못했습니다.
[Node.js] sparamin 1 - 공사중 (2) | 2024.01.31 |
---|---|
[Node.js] Spart Store 2 (4) | 2024.01.23 |
[Node.js] NBC Movie Review 2 (4) | 2024.01.16 |
[Node.js] - NBC Movie Review 1 (1) | 2024.01.11 |
2024.01.08 - 개인프로젝트 1차 제출完 (2) | 2024.01.08 |