티스토리 뷰
저번 Node.js - 1에서는 app.all() 메서드로 라우팅 처리를 한 뒤, response.send() 메서드를 이용하여 요청에 맞는 데이터를 보내는 방법까지 알아보았습니다. 이러한 방식으로 서버는 클라이언트에게 데이터를 제공합니다. 그렇다면 클라이언트는 서버로 어떻게 정보를 제공할까요?
클라이언트가 서버에 데이터를 제공하는 경우는 다음과 같습니다.
- 포털 사이트에서 검색하는 경우 (무엇을 검색하는지 서버에 알려주어야 함)
- 로그인을 하는 경우 (아이디와 패스워드를 서버에 알려주어야 함)
클라이언트에서 서버로 정보를 전달하는 가장 기본적인 방법은 요청 매개변수를 이용하는 것입니다. 경로 뒤에 ? 기호를 붙이고 키=값 형태를 & 기호로 이어 입력하는 것이죠. Node.js에서 요청 매개변수로 전달된 데이터는 request.param() 메서드로 추출할 수 있습니다.
POST 요청으로 전달된 데이터를 추출하기 위해서는 body-parser 미들웨어를 이용하면 됩니다. body-parser 미들웨어를 이용하면 request 객체에 body 속성이 추가됩니다. POST 요청으로 전달된 데이터를 request.body.${데이터이름} 형식으로 추출하면 됩니다.
예제를 진행하기 위한 폴더 구성은 다음과 같습니다.
public --------- index.html, index.js
server.js
간단한 예시 코드를 작성하여 이해를 돕도록 하겠습니다. 먼저 html 폼을 작성해줍니다. 이 html 문서에 연결된 index.js 파일에서는 각 input 태그에 입력된 값을 추출하고 XMLHttpRequest 객체를 이용해 값을 서버로 전송합니다. POST 요청이므로 setRequestHeader 메서드를 통해 Content-type 속성을 설정하고 send() 메서드를 통해 추출된 데이터를 전달하였습니다.
<body>
<form id="myForm">
<label for="name">상품명</label>
<input id="name" name="name" type="text" /><br />
<label for="price">가격</label>
<input id="price" name="price" type="number" /><br />
<input type="submit" value="제출" />
</form>
<textarea id="txtarea" cols="100" rows="25" disabled>
</textarea>
</body>
// index.js
"use strict";
const myForm = document.querySelector("#myForm");
const name = document.querySelector("#name");
const price = document.querySelector("#price");
const txtarea = document.querySelector("#txtarea");
myForm.addEventListener("submit", (e) => {
txtarea.value = "";
e.preventDefault();
const request = new XMLHttpRequest();
const url = "/data.json";
request.open("POST", url, true);
request.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
request.send(`name=${name.value}&price=${price.value}`);
request.addEventListener("readystatechange", () => {
if (request.readyState == 4 && request.status == 200) {
const data = JSON.parse(request.responseText);
data.forEach(item => {
txtarea.value += `${item.name}: ${item.price}\n`;
})
}
})
})
서버에서는 XMLHttpRequest 객체를 통해 POST 요청으로 전달된 데이터를 추출하기 위해 body-parser 미들웨어를 사용하였습니다. 추출된 값을 배열에 저장한 뒤 response.send()를 통해 다시 값을 클라이언트에 전달하였습니다. 서버로부터 값을 전달받은 클라이언트는 그 값을 textarea에 보여줍니다.
const express = require("express");
const app = express();
const bodyParser = require("body-parser");
const PORT = 52273;
let ITEMS = [
{ name: "우유", price: "2000" },
{ name: "아메리카노", price: "3900" },
{ name: "카페라떼", price: "4300" },
{ name: "카페모카", price: "4800" },
]
app.use(express.static("public"));
app.use(bodyParser.urlencoded({ extended: false }));
app.all("/data.json", (request, response) => {
const name = request.body.name;
const price = request.body.price;
console.log(`POST 요청! name=${name} price=${price}`);
ITEMS.push({ name, price });
console.log("데이터를 성공적으로 추가하였습니다.");
const { name: itemName, price: itemPrice } = ITEMS[ITEMS.length - 1];
console.log(`추가된 데이터: name=${itemName} price=${itemPrice}`);
response.send(ITEMS);
})
app.listen(PORT, () => {
console.log(`server running at port ${PORT}`);
})
위 예제를 실행한 결과는 다음과 같습니다.
당연한 이야기지만 Node.js로 구현된 서버 측에서 저장하고 있는 ITEMS 배열은 휘발성 데이터입니다. 서버를 종료하면 그동안 저장해놓았던 데이터는 원본을 제외하고 사라지게 됩니다. 따라서 추가된 데이터를 영구적으로 보관하고 싶다면 Node.js 측에서 mySQL과 같은 데이터베이스와 연동시켜 데이터를 보관하면 됩니다.
동적 라우트 요청 매개변수
위키피디아 사이트에서 검색을 해보면 다음과 같은 형태로 라우트됩니다. 키=값 형태의 요청 매개변수를 사용하는 것이 아니라 경로에 직접 입력합니다.
- HTML 검색 : http://en.wikipedia/wiki/HTML
- Cloud 검색 : http://en.wikipedia/wiki/Cloud
지금까지의 방식대로라면 이런 웹 사이트를 만들기 위해 모든 경로를 라우트해야 할 것입니다. 하지만 동적 라우트를 이용하면 한방에 처리할 수 있습니다. 동적 라우트를 구현하는 방법은 다음과 같이 변할 수 있는 부분을 콜론을 통해 지정합니다. 또한 동적 라우트에 사용한 식별자를 request.params 객체에서 추출할 수 있습니다.
app.all("/products/:id", (request, response) => {
const id = Number(request.params.id);
if (isNaN(id)) {
response.send({ error: "숫자를 입력하세요" });
} else if (items[id]) {
response.send(`<h1>${items[id]}</h1>`)
} else {
response.send({ error: "존재하지 않는 데이터입니다." })
}
})
데이터 수정과 삭제
PUT 요청과 DELETE 요청에 대해 알아보겠습니다. 먼저 PUT 요청에서는 다음과 같이 요청 매개변수를 추출하고 데이터를 수정합니다. body-parser 미들웨어를 이용해 name과 price 값을 추출하고 동적 라우트 요청 매개변수를 사용해 id를 추출한 부분을 주의깊게 살펴보시길 바랍니다.
app.put("/products/:id", (request, response) => {
const id = Number(request.params.id);
const name = request.body.name;
const price = request.body.price;
if (items[id]) {
// 데이터 수정
if (name) {items[id].name = name;}
if (price) {items[id].price = price;}
// 응답
response.send({
message: "데이터 수정 완료",
data: items[id]
})
} else {
// 오류: 요소가 없는 경우
response.send({
error: "존재하지 않는 데이터입니다."
})
}
})
DELETE 요청은 id를 추출하고 이를 기반으로 데이터를 제거합니다. 이를 위햐 items.splice(id, 1)과 같이 배열 API를 사용합니다.
app.del("/products/:id", (request, response) => {
const id = Number(request.params.id);
if (isNaN(id)) {
// 오류: 잘못된 경로
response.send({
error: "숫자를 입력하세요"
})
} else if (items[id]) {
// 정상: 데이터 삭제
items.splice(id, 1);
response.send({
message: "데이터를 삭제하였습니다"
})
} else {
// 오류: 요소가 없을 경우
response.send({
error: "존재하지 않는 데이터입니다."
})
}
})
'Node.js' 카테고리의 다른 글
#1. Node.js - 1 (0) | 2021.12.22 |
---|---|
Node.js와 연동하기 (0) | 2021.12.21 |
MySQL (0) | 2021.12.21 |