2024.05.01 프로그래머스-CRUD 맛보기2
핸들러
- Request 가 발생 했을 때, http method와 url 에 따라 호출 되는 함수(기능)
- 핸들러 안에서 예외처리까지 수행해야 한다.
express 로 god 멤버 요청해보기
- 그룹 god 의 멤버를 조회 할 객체를 만들어 놓고, 해당 객체에 접근하는 api 코드들을 작성한다.
- 전체 멤버조회
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
const express = require("express"); const app = express(); const PORT = 3000; const members = [ { id: 1, name: "박준형", position: "래퍼" }, { id: 2, name: "데니안", position: "래퍼" }, { id: 3, name: "윤계상", position: "래퍼" }, { id: 4, name: "손호영", position: "리드보컬" }, { id: 5, name: "김태우", position: "메인보컬" }, ]; app.listen(PORT, () => { console.log(`Server listen : ${PORT}`); }); // member 전체 조회 app.get("/members", (req, res) => { res.json(members); });
- 만약 전체 멤버 변수에 멤버가 없다면? 에 대한 예외 처리도 추가해주어야 한다.
1 2 3 4 5 6 7 8 9 10
// member 전체 조회 app.get("/members", (req, res) => { if (members.length === 0) { res.status(200); // member의 내부 정보가 없는 것이므로 응답코드는 200 res.send("member 정보가 없습니다."); } else { res.json(members); } });
express로 각 멤버 세부정보 조회
‘/members/:id’ 로 GET 요청이 올때, id 에 해당하는 멤버의 정보만 조회하는 API 코드를 작성한다.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
// member 개별적으로 조회 app.get("/members/:id", (req, res) => { // 개별적으로 조회하기 위해선 json Array로 선언된 members의 각 요소에 올바르게 접근해야한다. const { id } = req.params; /** * 내가 생각한 json array 에서 요소 찾는 법 * 배열에서 findeIndex를 통해 해당 요소의 Index 반환 (false 일때 -1 이 반환됨) */ const memberIndex = members.findIndex((member) => member.id === +id); //id는 string으로 넘어오므로 숫자 형변환 console.log(`찾는멤버 ID : ${id}, 멤버 인덱스 : ${memberIndex}`); if (memberIndex > -1) { //찾는 member 가 존재하는 상태 const member = members[memberIndex]; // 찾는 멤버 할당 res.json(member); } else { // 찾는 member가 없을 때 // Not Found Status 인 404 할당 res.status(404).send("찾는 멤버가 없습니다."); //res 체이닝 } });
- findIndex method를 통해, 해당멤버가 존재하는지 부터 검사한다.
- 이때 동등비교를
===
를 사용했는데, 이 엄격한 동등비교는 타입변환을 강제하지 않기때문에,+id
로 값을 비교하였다.
- 이때 동등비교를
- findIndex를 사용한 이유는, false 일 때 -1이 반환되는데, -1이 아닐때에만 새로운 변수를 사용 (메모리사용) 을 위해 findIndex를 사용했다.
- findIndex method를 통해, 해당멤버가 존재하는지 부터 검사한다.
express 로 새로운 멤버 등록 api 코드 작성하기
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
app.post("/members/:id", (req, res) => {
// id, name, position 을 member에 push 해야 한다.
// body와 id 할당
const { id } = req.params;
const { name, position } = req.body;
console.log(name, position);
if (!name || !position) {
res.status(400).send("올바른 정보를 입력해주세요, name & position");
return;
}
/**
* 처리할 예외 사항
* 이미 있는 id를 '등록' 하는 것은 PUT으로 해야한다.
* 때문에 Post로 오는 중복 id 에 대한 요청은 400(Bad Request) 로 처리
*/
if (members.findIndex((member) => member.id === +id) > -1) {
res.status(400).send("이미 등록되어있는 멤버입니다.");
return;
} else {
const newMember = {
id,
name,
position,
};
members.push(newMember);
res.status(200).json(newMember);
return;
}
});
- 이미 있는 멤버에 대해서는 put 요청으로 수정을 해주는 것이 올바르다고 생각하여, 중복 Id 의 POST 요청에서는 예외로 지정하였다.
- 또한 넘어오는 body 인 name, position 이 없으면, undefined로 할당 되기 때문에, 예외로 처리 하였다.
새로운 프로젝트 만들기
- 팬카페 컨셉의 사이트
- 회원은 여러명의 아티스트의 팬이 될 수 있다.
- https://github.com/ykdman/fantom
기능
회원
- 로그인
- 회원 정보 조회
- 회원 가입
- 회원 탈퇴
팬 되기
- 회원이 팬을 맺은 아티스트를 위한 팬 개인의 기록소 만들기
- 기록소 수정
- 기록소 삭제
API 설계
회원
로그인 POST
‘/login’ - req : body (id, pw)
- res : ‘로그인 성공’
- redirect : main page
회원 가입 POST
‘/signup’ - req : body (id, pwd, name)
- res : 회원가입을 환영합니다.
- redirect : ?
회원 정보 조회 GET
‘/users/:id’ - req : params (id)
- res : json (id, pwd?, name)
- redirect :
회원 탈퇴 DELETE
‘/users/:id’ - req : params (id)
- res : message 탈퇴가 완료되었습니다.
ArichiTecture
- 소스 구성
- src
- model : 데이터 저장소
- controllers : 핸들러 함수 저장소
- index.js : 서버 코드
회원가입 api 작성
- method :
POST
- user.controller.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
/** user.controller.js*/
const db = require("../model/data.js");
/**
* user 회원 가입 API : POST
* @param {Request} req
* @param {Response} res
* @returns {Response}
*/
const signupUser = (req, res) => {
const { id, pwd, name } = req.body;
const validReq = validRequest([id, pwd, name]);
if (!validReq) {
res.status(400).send("올바른 가입정보를 입력하세요");
return;
}
const existId = db.get(id);
if (existId) {
res.status(400).send(`이미 존재하는 아이디 입니다. : ${id}`);
return;
} else {
const newUser = {
pwd,
name,
};
db.set(id, newUser);
res.status(200).json({ id, ...newUser, message: "회원가입 완료" });
}
};
module.exports = {
loginUser,
signupUser,
};
- index.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
const express = require("express");
const app = express();
const PORT = 3000;
// controllers
const userControllers = require("./controllers/user.contorller.js");
app.listen(PORT, () => {
console.log(`server listen : ${PORT}`);
});
// body Parser
app.use(express.json());
// middlw Ware (logger)
app.use((req, res, next) => {
const start = Date.now();
console.log(`start: ${req.method} ${req.url}`);
next(); // router 실행
const diffTime = Date.now() - start;
console.log(`end: ${req.method} ${req.baseUrl}${req.url} ${diffTime}ms`);
});
app.post("/signup", userControllers.signupUser);
- 추가적으로 body 유효성 검증을 위한 util 함수를 하나 user.controller.js에 작성하였다.
1
2
3
4
5
6
7
8
9
function validRequest() {
for (const item of [...arguments]) {
if (typeof item === "undefined") {
return false;
}
}
return true;
}
로그인 API 작성
- method :
POST
- user.controller.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
/** user.controller.js*/
/**
* user 로그인 API : POST
* @param {Request} req
* @param {Response} res
* @returns {Response}
*/
const loginUser = (req, res) => {
const { id, pwd } = req.body;
console.log(typeof pwd);
const validReq = validRequest([id, pwd]);
const idExist = db.get(id);
// 계정정보를 올바르게 입력 안했을때
if (!validReq) {
res.status(400).send("올바른 로그인 정보를 입력해주세요");
return;
}
// db가 비어있거나, 일치하는 id 가 없을 때
if (db.size === 0 || !idExist) {
res.status(404).send("해당 ID가 존재하지 않습니다.");
return;
}
// ID 존재 상황
if (idExist) {
const dbUser = db.get(id);
console.log(dbUser);
if (dbUser && dbUser.pwd === pwd) {
res.status(200).send(`${id} : ${dbUser.name} 님 로그인을 환영합니다.`);
} else {
res.status(400).send("비밀번호가 일치하지 않습니다.");
}
}
};
- index.js 작성
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
const express = require("express");
const app = express();
const PORT = 3000;
// controllers
const userControllers = require("./controllers/user.contorller.js");
app.listen(PORT, () => {
console.log(`server listen : ${PORT}`);
});
// body Parser
app.use(express.json());
// middlw Ware (logger)
app.use((req, res, next) => {
const start = Date.now();
console.log(`start: ${req.method} ${req.url}`);
next(); // router 실행
const diffTime = Date.now() - start;
console.log(`end: ${req.method} ${req.baseUrl}${req.url} ${diffTime}ms`);
});
app.post("/signup", userControllers.signupUser);
// login
app.post("/login", userControllers.loginUser);
회원 개별 조회 API 작성
- method :
GET
- user.controller.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
/**
* 회원 개별 조회 API : GET
* @param {Request} req
* @param {Response} res
*/
const getUser = (req, res) => {
const { id } = req.params;
const dbUser = db.get(id);
//db에 회원 id가 없는 경우
if (!dbUser) {
res.status(404).send(`${id} 회원이 존재하지 않습니다.`);
}
const user = {
id,
pwd: dbUser.pwd,
name: dbUser.name,
};
res.status(200).json(user);
};
module.exports = {
loginUser,
signupUser,
getUser,
};
- index.js
1
app.get("/users/:id", userControllers.getUser);
개별 회원 삭제 API
- method :
POST
- user.controller.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
/**
* 개별 회원 탈퇴 API : DELETE
* @param {Request} req
* @param {Response} res
*/
const deleteUser = (req, res) => {
const { id } = req.params;
const validReq = validRequest([id]);
if (!validReq) {
res.status(400).send("올바른 id를 입력해주세요");
}
const dbUser = db.get(id);
// 올바른 user 존재 시 삭제
if (dbUser) {
const userDeleteState = db.delete(id);
if (userDeleteState) {
res.status(200).send(`${id} 회원이 정상적으로 탈퇴 되었습니다.`);
} else {
res.status(505).send(`${id}의 탈퇴가 이루어지지 않았습니다.`);
}
}
};
- index.js 라우터 코드 추가
1
app.delete("/users/:id", userControllers.deleteUser);
이 기사는 저작권자의 CC BY 4.0 라이센스를 따릅니다.