1. 오늘의 학습 목표
학습 목표: 대부분의 웹 애플리케이션의 기본이 되는 데이터 처리 기능인 CRUD(Create, Read, Update, Delete)를 이해합니다. 각 기능에 매칭되는 HTTP 메서드(POST, GET, PUT, DELETE)를 올바르게 사용하여 RESTful한 API를 직접 구현하는 방법을 배웁니다.
핵심 요약: CRUD는 데이터를 다루는 4가지 기본 연산입니다. 이 연산들을 적절한 HTTP 메서드와 연결하여 API를 설계하는 것은 백엔드 개발의 가장 핵심적인 기술 중 하나입니다.
2. 핵심 개념 파헤치기
2.1. CRUD란 무엇인가?
CRUD는 영속성을 갖는 데이터 저장소에서 데이터를 다루는 네 가지 기본 기능을 의미하는 약어입니다.
- Create (생성): 새로운 데이터를 만듭니다 (회원 가입, 새 글 작성)
- Read (읽기/조회): 기존 데이터를 읽어옵니다 (게시판 목록 보기, 내 정보 보기)
- Update (수정): 기존 데이터를 변경합니다. (프로필 수정, 글 내용 바꾸기)
- Delete (삭제): 기존 데이터를 삭제합니다. (회원 탈퇴, 글 삭제)
2.2. CRUD와 REST API HTTP 메서드 매핑
REST API에서는 CRUD 연산을 각각의 목적에 맞는 HTTP 메서드에 매핑하여 사용합니다.
Create → POST: 새로운 리소스를 생성합니다. 요청 본문(request body)에 생성할 데이터를 담아 보냅니다.
Read → GET: 리소스를 조회합니다. 데이터를 가져오기만 하므로 요청 본문은 사용하지 않습니다.
Update → PUT 또는 PATCH: 리소스를 수정합니다.
- PUT: 리소스 전체를 교체하는 의미입니다.
- PATCH: 리소스의 일부만 수정하는 의미입니다. (일반적으로 더 많이 사용됩니다.)
Delete → DELETE: 리소스를 삭제합니다.
3. 코드로 배우기
3.1. 구현 목표
실제 데이터베이스 대신, 메모리 상의 배열을 데이터 저장소로 사용하여 사용자 데이터를 관리하는 완전한 CRUD API를 구현합니다. (Day 26의 라우터-컨트롤러 구조를 유지합니다.)
3.2. [1단계: 데이터 준비 및 express.json() 미들웨어]
server.js에 POST와 PUT 요청의 본문(req.body)을 파싱하기 위한 필수 미들웨어인 express.json()을 추가합니다. 컨트롤러에서는 임시 데이터베이스 역할을 할 배열을 만듭니다.
//server.js
//...
//JSON 요청 본문을 파싱하기 위한 미들웨어
app.use(express.json());
//...
//controllers/userController.js
//임시 데이터베이스 (메모리 배열)
let users = [
{ id: 1, name: 'Alice' },
{ id: 2, name: 'Bob' },
];
//... 컨트롤러 함수들 ...
3.3. [2단계: 컨트롤러에 CRUD 로직 구현]
userController.js에 실제 CRUD 로직을 작성합니다.
//controllers/userController.js
//... (임시 데이터베이스) ...
// READ (모든 사용자 조회)
exports.getAllUsers = (req, res) => {
res.status(200).json({ users });
};
//CREATE (새 사용자 생성)
exports.createUser = (req, res) => {
const newUser = {
id: users.length > 0 ? users[users.length - 1].id + 1 : 1,
name: req.body.name,
};
users.push(newUser);
res.status(201).json(newUser);
};
//UPDATE (사용자 정보 수정)
exports.updateUser = (req, res) => {
const { id } = req.params;
const userIndex = users.findIndex(u => u.id === parseInt(id));
if (userIndex > -1) {
users[userIndex].name = req.body.name;
res.status(200).json(users[userIndex]);
} else {
res.status(404).send('User not found');
}
};
// DELETE (사용자 삭제)
exports.deleteUser = (req, res) => {
const { id } = req.params;
const initialLength = users.length;
users = users.filter(u => u.id !== parseInt(id));
if (users.length < initialLength) {
res.status(204).send(); // 204 No Content
} else {
res.status(404).send('User not found');
}
};
3.4. [3단계: 라우터에 CRUD 경로 연결]
userRoutes.js에 PUT과 DELETE 메서드에 대한 라우트 추가합니다
//routes/userRoutes.js
//...
router
.route('/:id')
.get(userController.getUserById) //(READ One - 이전 시간에 구현)
.put(userController.updateUser) //UPDATE
.delete(userController.deleteUser); //DELETE
//...
4. 전체 코드
controllers/userController.js
//임시 DB
let users = [
{ id: 1, name: 'Alice' },
{ id: 2, name: 'Bob' },
{ id: 3, name: 'Charlie' },
];
let nextId = 4;
exports.getAllUsers = (req, res) => res.status(200).json({ users });
exports.getUserById = (req, res) => {
const user = users.find(u => u.id === parseInt(req.params.id));
user ? res.status(200).json(user) : res.status(404).send('User not found');
};
exports.createUser = (req, res) => {
if (!req.body.name) return res.status(400).send('Name is required');
const newUser = { id: nextId++, name: req.body.name };
users.push(newUser);
res.status(201).json(newUser);
};
exports.updateUser = (req, res) => {
const user = users.find(u => u.id === parseInt(req.params.id));
if (user) {
user.name = req.body.name || user.name;
res.status(200).json(user);
} else {
res.status(404).send('User not found');
}
};
exports.deleteUser = (req, res) => {
const index = users.findIndex(u => u.id === parseInt(req.params.id));
if (index > -1) {
users.splice(index, 1);
res.status(204).send();
} else {
res.status(404).send('User not found');
}
};
routes/userRoutes.js
const express = require('express');
const router = express.Router();
const userController = require('../controllers/userController');
router
.route('/')
.get(userController.getAllUsers)
.post(userController.createUser);
router
.route('/:id')
.get(userController.getUserById)
.put(userController.updateUser)
.delete(userController.deleteUser);
module.exports = router;
server.js
const express = require('express');
const app = express();
const port = 3000;
const userRouter = require('./routes/userRoutes');
//JSON body parser 미들웨어
app.use(express.json());
app.get('/', (req, res) => res.send('CRUD API is running...'));
app.use('/api/users', userRouter);
app.listen(port, () => {
console.log(`Server listening at http://localhost:${port}`);
});'개발 > 웹 개발' 카테고리의 다른 글
| Day 29-30: SQL 기초와 심화 (CRUD와 JOIN) (1) | 2024.09.06 |
|---|---|
| Day 28: 데이터베이스 (SQL vs NoSQL) (1) | 2024.09.03 |
| Day 26: REST API 서버 (라우팅과 컨트롤러 분리) (0) | 2024.09.02 |
| Day 25: Node.js와 Express 서버 만들기 (0) | 2024.08.30 |
| Day 24: 백엔드의 역할과 책임 (1) | 2024.08.28 |