1) Node.js
1-1) 비동기 통신의 기본 로직(AJAX 기본 포맷)
1-2) server 분리(front, back) 후 AJAX 구현
1) Node.js
1-1) 비동기 통신의 기본 로직(AJAX 기본 포맷)
GET / index.html
GET /ajax GET
POST /ajax POST
$ npm init -y
$ npm install express
※ 브라우저가 "Content-Type"에 따라 읽는 모드가 달라진다! --> 이로 인해 "Content-Type"이 달라지면 요청을 새로 다시 보낸다!!
※ url을 안바꾸고 요청을 만들어서 보내는 것이 "AJAX"의 기본원리이다!!
server.js
const express = require("express");
const nunjucks = require("nunjucks");
const app = express();
app.use(express.static("public")); // server.js 파일을 기준으로 "public" 디렉토리 안의 모든 디렉토리와 파일들을 router로 만들겠다는 의미이다!!
app.use(express.urlencoded({ extended: false })); // query string(Content-type) 데이터를 읽을 수 있는 body parser 역할을 하는 코드
app.use(express.json()); // JSON(Content-type) 타입을 읽을 수 있는 body parser 역할을 하는 코드
app.set("view engine", "html");
nunjucks.configure("views", {
express: app,
});
app.get("/", (req, res) => {
res.render("index.html");
});
app.get("/ajax", (req, res) => {
console.log("GET /ajax 요청 옴!!");
const userid = req.query.userid;
let flag = true;
if (userid === undefined) {
flag = false;
}
console.log(req.query.userid, flag);
// res.status(404).send("test~~~!!"); // 이를 통해 상태코드를 200(default 값)에서 404로 바꿔줄 수 있음!!
// res.status(200).send("true");
res.status(200).send(`${flag}`);
});
app.post("/ajax", (req, res) => {
console.log("POST /ajax 실행됨!!");
const userid = req.body.userid;
let flag = true;
if (userid === undefined) {
flag = false;
}
res.send(`${flag}`);
});
app.listen(3000, () => {
console.log("server start");
});
views/index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Document</title>
</head>
<body>
test입니다~~
<!-- GET /ajax -->
<button id="ajax_get">ajax_get</button>
<button id="ajax_post">ajax_post</button>
<p id="msg"></p>
<script type="text/javascript" src="/js/index.js"></script>
</body>
</html>
public/js/index.js
// XMLHttpRequest 메서드를 사용하여 요청을 보냄!!
// new 키워드를 통해 XMLHttpRequest 메서드가 class 혹은 생성자 함수 형태임을 확인할 수 있음!!
const xhr = new XMLHttpRequest(); // {open:()=>{}, setRequestHeader:()=>{}, send:()=>{}, onload:()=>{}}
// open
const ajax_get = document.querySelector("#ajax_get");
const ajax_post = document.querySelector("#ajax_post");
const msg = document.querySelector("#msg");
ajax_get.addEventListener("click", () => {
// console.log(xhr);
xhr.open("get", "http://localhost:3000/ajax?userid=web7722");
xhr.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
// 여기까지는 request message를 만드는 과정이고, 아래 send 메서드를 사용하여 실제 request message를 날린다!!
xhr.send(); // 여기서 진짜 요청이 날아간다!(위의 코드들은 사전 작업에 해당함!)
xhr.onload = () => {
// console.log(xhr.readyState, xhr.status, xhr.response); // 4(응답이 왔다는 의미이다!!) 200(response message의 상태코드에 해당함!!) 'get'(request method가 아니라 response body 영역에 있는 내용임!!)
// xhr.readyState --> 4
if (xhr.readyState === 4 && xhr.status === 200) {
// console.log(xhr.response);
const response = xhr.response;
if (response === "true") {
msg.innerHTML = "아이디가 중복되었습니다.";
msg.style.color = "red";
} else {
msg.innerHTML = "사용 가능한 아이디입니다.";
msg.style.color = "green";
}
}
};
});
// userid에 "web7722" 값 넣기
ajax_post.addEventListener("click", () => {
xhr.open("post", "http://localhost:3000/ajax");
// xhr.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
// xhr.send("userid=web7722");
xhr.setRequestHeader("Content-type", "application/json");
const data = { userid: "web7722" };
xhr.send(JSON.stringify(data));
// application/json --> "JSON 객체(ex. userid: "web7722")"를 보내야 함!!
// application/x-www-form-urlencoded --> "query string(ex. userid=web7722)"을 보내야 함!!
});
// ajax, fetch, axios --> 사용 방법만 다를 뿐 근본적인 목표와 내용은 동일함!!
1-2) server 분리(front, back) 후 AJAX 구현
CORS(host를 기준으로 다른 컴퓨터들끼리 통신하는 것을 막는 역할을 함!!) : HTTP Protocol에서 header에 있음!!
- CORS는 port, 즉 end-point(도착지점)까지 확실히 체크함!!
- CORS 처리는 허용한 사람에게만 주겠다는 의미이다!!(브라우저 기준)
※ host : 인터넷이 되는 컴퓨터
비동기 통신
현재 AJAX를 통해 비동기 통신 흐름을 익히는 것을 목표로 함!
비동기 통신을 배운 목적 : front, back server를 나누기 위함!!
- 이유 : 비동기 통신을 해야지만 Origin(CORS가 허용한 URI)에 다른 요청을 보낼 수 있기 때문이다.
- front, back 서버를 나눈 후 ajax 통신을 하다보니 "CORS" 에러(보내는 사람과 받는 사람의 path가 다른 경우에 기능을 막는 것을 의미함)가 발생함!!
- 이러한 CORS 에러를 막기 위해서는 back server의 response message 상 Origin을 허용한다고 설정해두면 된다!!
front
server.js
const express = require("express");
const nunjucks = require("nunjucks");
const app = express();
app.use(express.static("public"));
app.set("view engine", "html");
nunjucks.configure("views", {
express: app,
});
app.get("/", (req, res) => {
res.render("index.html");
});
app.get("/ajax", (req, res) => {
res.send("get");
});
app.post("/ajax", (req, res) => {
res.send("post");
});
app.listen(3005, () => {
console.log("server start");
});
views/index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Document</title>
</head>
<body>
<h1>AJAX</h1>
<button id="ajax_get">ajax_get</button>
<button id="ajax_post">ajax_post</button>
<div id="msg"></div>
<div id="userlist">
<!-- <ul>
<li>1</li>
<li>web7722</li>
<li>1234</li>
<li>sangbeom</li>
<li>남자</li>
</ul> -->
</div>
<input type="text" name="userid" id="userid" />
<button id="btn">유저 추가</button>
<script src="/js/index.js" type="text/javascript"></script>
</body>
</html>
public/js/index.js
const xhr = new XMLHttpRequest();
const ajax_get = document.querySelector("#ajax_get");
const ajax_post = document.querySelector("#ajax_post");
const msg = document.querySelector("#msg");
// request({ method: "get", path: "/users/5", body: "" }, callback);
const request = ({ method, path, body }, callback) => {
const host = "http://localhost:3000";
const xhr = new XMLHttpRequest();
xhr.open(method, `${host}${path}`);
xhr.setRequestHeader("Content-type", "application/json");
xhr.send(JSON.stringify(body));
xhr.onload = () => {
if (xhr.status === 200) {
callback(xhr.response);
}
};
};
/*
ajax_get.addEventListener("click", () => {
const view = (xhr) => {
if (xhr.readyState === 4 && xhr.status === 200) {
console.log(xhr.response);
}
};
request({ method: "get", path: "/users/1" }, view);
});
*/
ajax_get.addEventListener("click", () => {
request({ method: "get", path: "/users/1" }, (response) => {
console.log(response);
});
});
ajax_post.addEventListener("click", () => {
request({ method: "post", path: "/users" }, (response) => {
console.log(response);
});
});
// 브라우저에 render해주는 코드
const userList = document.querySelector("#userlist");
const btn = document.querySelector("#btn");
const card = ({ idx, userid, userpw, username, gender }) => {
const ulElement = document.createElement("ul");
const idxElement = document.createElement("li");
const idElement = document.createElement("li");
const pwElement = document.createElement("li");
const nameElement = document.createElement("li");
const genderElement = document.createElement("li");
idxElement.innerHTML = idx;
idElement.innerHTML = userid;
pwElement.innerHTML = userpw;
nameElement.innerHTML = username;
genderElement.innerHTML = gender;
ulElement.append(idxElement);
ulElement.append(idElement);
ulElement.append(pwElement);
ulElement.append(nameElement);
ulElement.append(genderElement);
userList.append(ulElement);
};
request({ method: "get", path: "/users" }, (response) => {
const arr = JSON.parse(response);
console.log(arr);
arr.forEach((v) => {
card(v);
});
});
// 요청 코드
btn.addEventListener("click", () => {
request(
{
method: "post",
path: "/users",
body: {
userid: document.querySelector("#userid").value,
userpw: "1234",
username: "sangbeom",
gender: "남자",
},
},
(response) => {
// console.log(response);
card(JSON.parse(response));
}
);
// card({
// idx: 2,
// userid: "web7722",
// userpw: "4567",
// username: "sangbeom",
// gender: "male",
// });
});
/*
ajax_get.addEventListener("click", () => {
xhr.open("get", "http://localhost:3000/users/5");
xhr.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
xhr.send();
xhr.onload = () => {
if (xhr.readyState === 4 && xhr.status === 200) {
console.log(xhr.response);
}
};
});
ajax_post.addEventListener("click", () => {
xhr.open("post", "http://localhost:3000/users");
xhr.setRequestHeader("Content-type", "application/json");
const data = {
userid: "web7722",
userpw: "1234",
username: "sangbeom",
gender: "남자",
};
xhr.send(JSON.stringify(data));
xhr.onload = () => {
if (xhr.readyState === 4 && xhr.status === 200) {
console.log(xhr.response);
}
};
});
*/
back
server.js
const express = require("express");
const cors = require("cors");
const app = express();
app.use(express.urlencoded({ extended: false }));
app.use(express.json());
// npm install cors
app.use(cors());
// 아래 코드는 "app.use(cors());"로 대체 가능함!!
// app.use((req, res, next) => {
// res.setHeader("Access-Control-Allow-Origin", "*");
// res.setHeader("Access-Control-Allow-Methods", "POST, GET, OPTIONS, DELETE");
// res.setHeader("Access-Control-Allow-Headers", "Content-type");
// next();
// });
const user = [
{
idx: 1,
userid: "web7722",
userpw: "1234",
username: "sangbeom",
gender: "남자",
},
];
// GET /board/list
// POST /board/write
// GET /board/view
// POST /board/modify
// POST /board/delete
// RESTful API는 기본적으로 단어의 복수형을 사용하도록 하기에 "boards"로 씀!
// path 부분에 동사가 들어가면 안 된다!!
// list --> GET /boards
// view --> GET /boards/1(여기서 1은 고유한 식별자 값에 해당함!!)
// write --> POST /boards
// modify --> PUT /boards
// delete --> DELETE /boards
// list page
app.get("/users", (req, res) => {
res.json(user); // "res.json"은 "res.send"와 동일하다고 보면 됨!
// res.send("GET /users");
});
// write page
app.post("/users", (req, res) => {
const { userid, userpw, username, gender } = req.body;
const response = {
idx: user[user.length - 1].idx + 1,
userid,
userpw,
username,
gender,
};
user.push(response);
// res.send("POST /users");
res.json(response);
});
// view page
// 해당 코드는 항상 맨 아래에 있어야 잘 동작하기 때문에 맨 아래에 작성할 것을 권한다!!
app.get("/users/:id", (req, res) => {
// console.log(req.params);
// res.json(user);
const { idx } = req.params;
const [response] = user.filter((v) => v.idx === parseInt(idx));
res.json(response);
});
app.listen(3000, () => {
console.log("server start");
});
'Node.js' 카테고리의 다른 글
Node.js(13) - XMLHttpRequest/fetch/axios, 비동기 통신 댓글 CRUD(axios 활용) (0) | 2023.01.05 |
---|---|
Node.js(12) - 비동기 통신 댓글 CRUD, Postman 및 Database 활용 (0) | 2023.01.04 |
Node.js(10) - express를 활용한 게시판 구현(CRUD) 및 Router 나누기 (0) | 2022.12.20 |
Node.js(9) - express를 활용한 게시판 구현 (0) | 2022.12.19 |
Node.js(8) - express (0) | 2022.12.14 |