목표
1. Node.js만 사용하기 - Express 사용 X
2. httpie를 사용해서 서버와 통신하기
3. CRUD 기능 구현하기
필요 데이터
User | Posting | ||
id | PK | postingId | PK |
name | userId | FK | |
title | |||
password | content | ||
date |
API 명세서
매서드 | url | 매서드 | url | ||
유저 정보 전체 보기 | GET | /user | 포스팅 전체 보기 | GET | /post |
유저 정보 추가 | POST | /user/register | 포스팅 작성 | POST | /post/write |
유저 정보 수정 | PATCH | /user/update/{id} | 포스팅 수정 | PATCH | /user/update/{id} |
유저 정보 삭제 | DELETE | /user/delete/{id} | 포스팅 삭제 | DELETE | /user/delete/{id} |
특정 유저의 정보와 포스팅 보기 |
GET | /user/postingList/{Id} |
요청 라우터
const server = http.createServer((req, res) => {
console.log("-----START------");
const { url, method } = req;
res.setHeader("content-type", "application/json");
if (method === "GET") {
if (url === "/user") {
getUserList(req, res);
return;
}
if (url === "/post") {
getPostList(req, res);
return;
}
if (url.startsWith("/user/postingList/{Id}")) {
let params = url.split("/")[3];
getUnifiedData(req, res);
return;
}
}
if (method === "PATCH") {
let params = url.split("/")[3];
if (url.startsWith("/user/update/")) {
patchUpdateUserInfo(req, res, params);
return;
}
if (url.startsWith("/post/update/")) {
patchUpdatePosting(req, res, params);
return;
}
}
if (method === "POST") {
if (url === "/user/register") {
postSignUp(req, res);
return;
}
if (url === "/post/write") {
postWritePost(req, res);
return;
}
}
if (method === "DELETE") {
let params = url.split("/")[3];
if (url === "/user/delete") {
deleteUserInfo(req, res, params);
return;
}
if (url === "/post/delete") {
deletePosting(req, res, params);
return;
}
} else {
resError(req, res);
}
});
처음에 수정할 정보를 모두 body에 담아 보내는 코드로 작성했다가 나중에 url에서 params로 target userId나 postingId를 식별하고, 변경할 내용은 body에 담아 보내는 코드로 수정을 했다.
각 method와 url에 따라 동작할 함수는
const getUserList = (req, res) => {
res.end(JSON.stringify(users));
console.log("유저들 정보 전송!!");
};
const getPostList = (req, res) => {
res.end(JSON.stringify(posts));
console.log("포스트 정보 전송!!");
};
이런 식으로 따로 만들어두었다. 코드를 전체 공개하기엔 너무 길어서 CRUD 기능을 구현하며 정리하고 싶었던 개념만 다루겠당
HTTP 요청에서 데이터를 보내는 방법
1. 매개변수(params)로 보내기
Node.js에서 url에 담긴 params를 확인하려면 url.split("/")으로 url을 분할해야 한다. 그러면 url의 각 데이터들이 배열에 ["", "user", "update", "123"] 담긴다. 이 중 원하는 데이터가 있는 인덱스를 찾아서 parmas 변수에 담은 뒤 활용하면 된다. HTTpie로 요청을 보낼 땐 url 부분에 수정할 유저의 id를 넣고, body에 변경할 이메일 주소를 적었다.
const patchUpdateUserInfo = (req, res, params) => {
let body = "";
req.on("data", (data) => (body += data));
req.on("end", () => {
const userInfo = JSON.parse(body);
const userId = params;
if (!userId) {
res.statusCode = 400;
res.end(
JSON.stringify({ message: "변경할 유저ID를 알려주세요." })
);
return;
}
const updated = updateUser(userId, userInfo);
if (updated) {
res.end(
JSON.stringify({ message: `${userId}의 정보가 성공적으로 업데이트되었습니다.` })
);
console.log(`${userId}의 정보가 성공적으로 업데이트되었습니다.`);
} else {
res.statusCode = 404;
res.end(JSON.stringify({ message: "유저가 없습니다." }));
}
});
};
// 요청
http PATCH http://127.0.0.1:3000/user/update/유저id email="email@naver.com"
// 응답
{
"message": "유저id의 정보가 성공적으로 변경되었습니다."
}
2. 요청 body에 보내기
수정할 대상의 정보와 수정할 내용 모두 body에 담아 보내도 된다. 수정하기 전 코드를 가져왔당
const patchUpdatePosting = (req, res) => {
let body = "";
req.on("data", (data) => (body += data));
req.on("end", () => {
const postingInfo = JSON.parse(body);
const postingId = postingInfo.id;
// params에 정보를 보냈을 땐 url에서 postingId를 찾는다.
// 이번엔 body에 담긴 id로 변경할 postingId를 찾으면 된다.
if (!postingId) {
res.statusCode = 400;
res.end(JSON.stringify({ message: "존재하지 않는 포스팅입니다." }));
return;
}
const updated = updatePosting(postingId, postingInfo);
const idx = posts.findIndex(
(post) => post.postingId === parseInt(postingId)
);
if (updated) {
res.end(JSON.stringify({ data: { ...posts[idx] } }));
console.log(`${postingId}번 게시글이 성공적으로 수정되었습니다.`);
} else {
res.statusCode = 404;
res.end(JSON.stringify({ message: "게시글 수정에 실패했습니다." }));
}
});
};
// 요청
http PATCH http://127.0.0.1:3000/posting/update/ postingId=2 content="내용을 수정했어요!!"
// 응답
{
"data": {
"content": "내용을 수정했어요!!",
"date": "2023-07-28T00:00:00.000Z",
"postingId": 2,
"title": "제목제목",
"userId": "User3"
}
}
다른 점은 body에서 postingId를 가져온다는 점이당.
HTTP 응답헤더 설정 : setHeader와 writeHead
writerHead는 setHeader + res.statusCode 두 가지의 기능을 가지고 있다.
HTTP 응답 헤더는 클라이언트와 서버가 요청 또는 응답으로 부가적인 정보를 전송할 수 있도록 해준다. 대표적으로 사용하는 헤더에는 Content-Type이 있다.
// statusCode
response.statusCode = 404;
// setHeader
response.setHeader('Content-Type', 'application/json'); // 대소문자 구분 안함
// writeHead
response.writeHead(200, {
'Content-Type': 'application/json',
'X-Powered-By': 'bacon'
});
HTTP 응답 헤더를 설정하기 위해 setHeader(name, value)와 writeHead(statusCode, headers)를 사용할 수 있다. setHeader는 한 번에 하나의 HTTP 응답 헤더를 설정할 수 있다. setHeader와 더불어 상태코드를 설정할 때 response.statusCode = 404;를 사용한다.
res.setHeader('Content-Type', 'application/json');
res.setHeader('Cache-Control', 'no-cache');
이렇게 여러 번 호출해도 된다.
writeHead는 setHeader와 statusCode의 기능을 갖고 있다. 한 번에 응답에 대한 상태코드와 헤더를 설정할 수 있다. 다만 HTTP 서버 응답 시 한 번만 사용 가능하다. 여러 번 호출할 경우 첫 번째 호출만 유의미하고, 나머지 호출은 무시한다. 그래서 부가적으로 HTTP 헤더 설정이 필요한 경우 setHeader를 사용해야 한다.
request.on()
request.on을 이용해서 HTTP 요청과 관련된 이벤트가 발생했을 때 이벤트를 어떻게 처리할 것인지 정할 수 있다.
request.on은 두 개의 인자를 받는다. 하나는 이벤트 이름, 하나는 지정된 이벤트가 발생했을 때 실행할 콜백함수이다.
request.on의 이벤트
1. data : 데이터를 수신할 때 실행할 이벤트
2. end : 클라이언트로부터 모든 데이터를 수신 완료했을 때 실행할 이벤트
3. error : 요청 처리 중 에러가 발생했을 때의 이벤트
request.on 예시
const postWritePost = (req, res) => {
let body = "";
req.on("data", (data) => (body += data));
// data(chunk data)가 들어올 때마다 body에 chunk data를 넣는다.
req.on("end", () => {
// 클라이언트로부터 모든 data를 수신하면 실행한다.
const post = JSON.parse(body);
// body를 파싱해서 자바스크립트 객체로 만든다.
posts.push({
id: post.id,
title: post.title,
content: post.content,
date: new Date(),
name: post.name,
});
// posts에 새로운 게시글 정보를 추가한다.
res.end(JSON.stringify("게시물이 정상적으로 등록되었습니다."));
console.log("게시물 추가 완료!!!");
});
};
response.end()
response.end()는 HTTP 응답의 종료와 클라이언트에게 데이터를 동시에 보낼 때 사용한다. 한 번에 데이터를 보내고 통신을 종료하기 때문에 한 번만 호출할 수 있다.
// 간단한 문장으로 응답을 보낼 수 있다.
res.end('Hello, World!');
// 혹은 JSON 형태로 응답을 보낼 수 있다.
res.end(
JSON.stringify({ message: "User ID is missing in the request." })
);
response.end()와 비슷한 개념으로 response.end()가 있다.
response.write()는 청크 단위로 클라이언트에 데이터를 보낼 때 사용한다. 여러 번 반복해서 보낼 수 있으며, 통신의 연결에는 아무런 영향을 주지 않기 때문에 response.write()로 데이터를 보낸 뒤 response.end()로 통신이 끝났다는 신호를 보내야 한다.
확실히 직접 기능을 구현하면서 코드를 작성해보고, 궁금했던 개념들을 정리하니 학습이 잘된당!! 다음엔 Express도 연습해봐야지. 화이팅이당~!!
댓글