Express로 CRUD api 만들기 (01)
해당 시리즈는 한양대학교 정보시스템학과 2021학년도 2학기 데이터베이스시스템 수업 및 시험 대체 과제로 기획되었습니다.
일단은 데이터베이스는 생각하지 말고, 빠르게 express로 CRUD부터 만들어보자.
CRUD는 Create, Read, Update, Delete의 약자로, 대부분의 자료를 다루는 메소드 들이 이 범주내에 들어온다.
일반적으로 Create는 html의 POST로, Read는 html의 GET으로, Update는 PATCH로, Delete는 DELETE로 구현한다.
데이터 정의
유저 한 명에 대한 데이터는 다음과 같이 표현된다.
필드 | 설명 | 예시 |
---|---|---|
id |
User 식별용 id. unique key. alphanumeric으로 이루어진다. | "J9f3l0s7" |
name |
User에게 표시되는 이름. unique key. UTF-8. | "nick" |
email |
User의 email 주소. | "user@example.com" |
tier |
User의 구독 정보. | "default" |
typescript의 interface로 나타내면 다음과 같다.
interface User {
id: string;
name: string;
email: string;
tier: string;
}
임시로 데이터베이스를 대신할 json파일을 생성하자. nick
, lauren
, david
3명의 유저를 만들어두겠다.
// user.sample.json
{
"user": [
{
"id": "S8fs9jQ3",
"name": "nick",
"email": "nick@example.com",
"tier": "admin"
},
{
"id": "Q3J9d2j1",
"name": "lauren",
"email": "david@example.com",
"tier": "default"
},
{
"id": "Z3JnLm0s",
"name": "david",
"email": "david@example.com",
"tier": "alpha"
}
]
}
먼저 모든 유저 정보를 한 번에 확인할 수 있도록 route를 설정해주자.
// Route: /users (GET) - Return all users
app.get('/admin/users', (req: Request, res: Response) => {
res.send(jsonFile)
})
http://localhost:{설정한 포트}/admin/users
로 요청을 보내면, 위에서 생성한 json파일을 반환한다.
request
GET localhost:3624/admin/users
response
[
{
"id": "S8fs9jQ3",
"name": "nick",
"email": "nick@example.com",
"tier": "admin"
},
{
"id": "Q3J9d2j1",
"name": "lauren",
"email": "david@example.com",
"tier": "default"
},
{
"id": "Z3JnLm0s",
"name": "hello",
"email": "david@example.com",
"tier": "alpha"
}
]
CRUD 구성
생성(Create)는 보통 POST 메소드로 통신한다. POST는 값을 추가할 때 사용된다. 성공적으로 POST 통신이 이루어지면 응답으로 201 CREATED
를 보낸다.
/users
로 POST 메소드를 보내면 새로운 User를 생성하도록 한다.
// create method
// Route: /user (POST) - Create new user
app.post('/user', (req: Request, res: Response) => {
const user = req.body
user.id = nanoid(8)
users.push(user)
res.send(user)
})
request
POST localhost:3624/users
request body
{
"name": "test",
"email": "test@example.com",
"tier": "test"
}
읽기(Read)는 보통 GET 메소드로 통신한다. GET은 값을 읽어올 때 사용된다. 성공적으로 GET 통신이 이루어지면 응답으로 200 OK
를 보낸다. GET 통신 이후에는 원본이 변경되지 않아야한다.
// read method
// Route: /user/:id (GET) - Return user with id
app.get('/user/:id', (req: Request, res: Response) => {
const id = req.params.id
const userFounded = users.find((user: User) => user.id === id)
if (userFounded) {
res.send(userFounded)
} else {
res.status(404).send({ message: `User with id ${id} not found` })
}
})
request
GET localhost:3624/users/S8fs9jQ3
response
{
"id": "S8fs9jQ3",
"name": "nick",
"email": "nick@example.com",
"tier": "admin"
}
수정(Update)는 보통 PATCH 메소드로 통신한다. PATCH는 값을 수정할 때 사용된다. 성공적으로 PATCH 통신이 이루어지면 응답으로 200 OK
를 보낸다.
// update method
// Route: /user/:id (PUT) - Update user with id
app.put('/user/:id', (req: Request, res: Response) => {
const id = req.params.id
const userIndex = users.findIndex((user: User) => user.id === id)
if (users[userIndex]) {
const user = {
...users[userIndex],
...req.body
}
console.log(user)
users[userIndex] = user
res.send(user)
} else {
res.status(404).send({ message: `User with id ${id} not found` })
}
})
request
PUT localhost:3624/user/Q3J9d2j1
request body
{
"tier": "alpha"
}
response
{
"id": "Q3J9d2j1",
"name": "lauren",
"email": "david@example.com",
"tier": "alpha"
}
삭제(Delete)는 보통 DELETE 메소드로 통신한다. DELETE는 값을 삭제할 때 사용된다. 성공적으로 DELETE 통신이 이루어지면 응답으로 204 NO CONTENT
를 보낸다. DELETE 통신 이후에는 다시 그 데이터에 접근할 수 없어야한다.
// delete method
// Route: /user/:id (DELETE) - Delete user with id
app.delete('/user/:id', (req: Request, res: Response) => {
const id = req.params.id
const userFounded = users.find((user: User) => user.id === id)
if (userFounded) {
const userIndex = users.findIndex((user: User) => user.id === id)
users.splice(userIndex, 1)
res.send({ message: `User with id ${id} deleted` })
} else {
res.status(404).send({ message: `User with id ${id} not found` })
}
})
request
localhost:3624/user/Q3J9d2j1
response
{
"message": "User with id Q3J9d2j1 deleted"
}