Section2 Unit10 [Web Server] ๊ธฐ์ด
- CORS & Http ๋ชจ๋๋ก ์๋ฒ ๋ง๋ค๊ธฐ(Mini Node Server)
๐ Chapter1. CORS
• ๊ต์ฐจ ์ถ์ฒ ๋ฆฌ์์ค ๊ณต์ (Cross-Origin Resource Sharing, CORS)๋ ์ถ๊ฐ HTTP ํค๋๋ฅผ ์ฌ์ฉํ์ฌ, ํ ์ถ์ฒ์์ ์คํ ์ค์ธ ์น ์ ํ๋ฆฌ์ผ์ด์ ์ด ๋ค๋ฅธ ์ถ์ฒ์ ์ ํํ ์์์ ์ ๊ทผํ ์ ์๋ ๊ถํ์ ๋ถ์ฌํ๋๋ก ๋ธ๋ผ์ฐ์ ์ ์๋ ค์ฃผ๋ ์ฒด์ ์ด๋ค.
→ ๋ธ๋ผ์ฐ์ ๋ SOP์ ์ํด ๊ธฐ๋ณธ์ ์ผ๋ก ๋ค๋ฅธ ์ถ์ฒ์ ๋ฆฌ์์ค ๊ณต์ ๋ฅผ ๋ง์ง๋ง, CORS๋ฅผ ์ฌ์ฉํ๋ฉด ์ ๊ทผ ๊ถํ์ ์ป์ ์ ์๊ฒ ๋๋ค.
• SOP(Same-Origin Policy. ๋์ผ ์ถ์ฒ ์ ์ฑ )๋ ๊ฐ์ ์ถ์ฒ์ ๋ฆฌ์์ค๋ง ๊ณต์ ๊ฐ ๊ฐ๋ฅํ ์ ์ฑ ์ด๋ค. ๋์ผ ์ถ์ฒ ์ ์ฑ ์ ์ ์ฌ์ ์ผ๋ก ํด๋ก์ธ ์ ์๋ ๋ฌธ์๋ฅผ ๋ถ๋ฆฌํจ์ผ๋ก์จ ๊ณต๊ฒฉ๋ฐ์ ์ ์๋ ๊ฒฝ๋ก๋ฅผ ์ค์ฌ์ค๋ค. (ํดํน ๋ฑ์ ์ํ์์ ๋ณด๋ค ์์ ํด์ง ์ ์๊ธฐ ๋๋ฌธ์ ๋ชจ๋ ๋ธ๋ผ์ฐ์ ๋ ๋ฆฌ๋ณธ์ ์ผ๋ก SOP๋ฅผ ์ฌ์ฉํ๋ค.)
• ํด๋ผ์ด์ธํธ์ ์๋ฒ๋ฅผ ๋ฐ๋ก ๊ฐ๋ฐํ๋ฉด ๋์ ์ถ์ฒ๋ ๋ฌ๋ผ์ง๋๋ฐ, ํด๋ผ์ด์ธํธ ๊ฐ๋ฐ์ ์๋ฒ์์ ์ ๋ณด๋ฅผ ๋ฐ์์ฌ ๊ฒฝ์ฐ๋ ๋๋ฌด๋๋ ๋ง๋ค.
SOP๋ ๋ค๋ฅธ ์ฌ์ดํธ์์ ๋ฆฌ์์ค ๊ณต์ ๋ฅผ ์ ํํ๊ธฐ ๋๋ฌธ์ CORS๋ฅผ ํตํด ๋ค๋ฅธ ์ถ์ฒ์ ๋ฆฌ์์ค๋ฅผ ๋ฐ์์์ผ ํ๋ค.
โญ๏ธ ๊ณผ์ . Mini Node Server
๐ฅ Node.js์ http ๋ชจ๋๋ก ์น ์๋ฒ ๋ง๋ค๊ธฐ
→ Node.js์์ ํ์ผ์ ์ฝ๊ฑฐ๋ ์ฐ๊ธฐ ์ํด fs ๋ชจ๋์ ์ฌ์ฉํ๋ฏ์ด, HTTP ์์ฒญ๊ณผ ์๋ต์ ๋ค๋ฃจ๊ธฐ ์ํด HTTP ๋ชจ๋์ ์ฌ์ฉํ๋ค.
๋ธ๋ผ์ฐ์ ์๋ ์๋ฒ์ ์์ฒญ์ ๋ณด๋ด๊ธฐ ์ํด fetch
๊ฐ์ HTTP ์์ฒญ์ ๋ณด๋ด๋ ๋๊ตฌ๊ฐ ๊ธฐ๋ณธ์ ์ผ๋ก ๋ด์ฅ๋์ด ์๋ค. ์๋ฒ๋ ํด๋ผ์ด์ธํธ(๋ธ๋ผ์ฐ์ )์ HTTP ์์ฒญ์ ๋ง๊ฒ ์๋ต์ ๋ณด๋ผ ์ ์๋๋ก ์ฝ๋๋ฅผ ์์ฑํด์ผ ํ๋ค. Node.js๋ HTTP ์์ฒญ์ ๋ณด๋ด๊ฑฐ๋, ์๋ต์ ๋ฐ์ ์ ์๋ ๋๊ตฌ๋ค์ ์ ๊ณตํ๋ค. HTTP ์์ฒญ์ ์ฒ๋ฆฌํ๊ณ ์๋ต์ ๋ณด๋ด ์ฃผ๋ ํ๋ก๊ทธ๋จ์ ์น ์๋ฒ(Web Server)๋ผ๊ณ ๋ถ๋ฅธ๋ค.
๐ ๊ณต์ ๊ฐ์ด๋ ๋ฌธ์: HTTP ํธ๋์ญ์ ํด๋ถ(Anatomy of an HTTP Transaction)
โ๏ธ Bare Minimum Requirement
- ์ด๋ฒ ์คํ๋ฆฐํธ์ ์ด๋ฏธ ํด๋ผ์ด์ธํธ, http ์๋ฒ๊ฐ ๋ชจ๋ ์์ฑ๋์ด ์๋ค. HTTP ํธ๋์ญ์ ํด๋ถ๋ฅผ ์ฐธ๊ณ ํ์ฌ Mini-Node-Server๋ฅผ ์์ฑํ๋ฉด ๋๋ค.
• POST์ ๋ฌธ์์ด์ ๋ด์ ์์ฒญ์ ๋ณด๋ผ ๋๋ HTTP ๋ฉ์์ง์ body(payload)๋ฅผ ์ด์ฉํฉ๋๋ค.
• ์๋ฒ๋ ์์ฒญ์ ๋ฐ๋ฅธ ์ ์ ํ ์๋ต์ ํด๋ผ์ด์ธํธ๋ก ๋ณด๋ด์ผ ํฉ๋๋ค.
• CORS ๊ด๋ จ ํค๋๋ฅผ OPTIONS
์๋ต์ ์ ์ฉํด์ผ ํฉ๋๋ค.
• ํด๋ผ์ด์ธํธ์ preflight request
์ ๋ํ ์๋ต์ ๋๋ ค์ค์ผ ํฉ๋๋ค.
• preflight request
์ ๋ํ ์๋ต ํค๋๋ ์ด๋ฏธ ์์ฑ๋์ด ์์ต๋๋ค.
Endpoint(URL) | Method | ๊ธฐ๋ฅ |
/lower | POST | ๋ฌธ์์ด์ ์๋ฌธ์๋ก ๋ง๋ค์ด ์๋ตํด์ผ ํฉ๋๋ค |
/upper | POST | ๋ฌธ์์ด์ ๋๋ฌธ์๋ก ๋ง๋ค์ด ์๋ตํด์ผ ํฉ๋๋ค |
๊ตฌํ๊ณผ์
๐ก TIP. nodemon
์ค์น
์๋ฒ ์ฝ๋๋ฅผ ์์ ํ๋ฉด ์๋ฒ๋ฅผ ๋งค๋ฒ ๋ค์ ์คํํด์ผ ํ๋๋ฐ, nodemon์ ์ฌ์ฉํ๋ฉด ์ด๋ฅผ ์๋์ผ๋ก ํด์ค๋ค.
npm install nodemon
// package.json์ scripts์ ์ถ๊ฐ
"start": "nodemon server/basic-server.js"
→ npm start
๋ก ์๋ฒ ์คํ
1. http ๋ชจ๋ ํ์ต
์น์ 1๊ณผ ์น์ 2์ ์ด๋ฐ๋ถ์ Node.js๋ฅผ ์ค์ณ์ง๋๊ฐ๋ฏ ๋ฐฐ์ ์์ง๋ง ๊ธฐ์ต๋์ง ์๋ ๋ฌด์ง ์ํ…
Node.js๋ก ์ฝ๋๋ฅผ ์์ฑํด ๋ณธ ์ ์ด ์์ด์ http ๋ชจ๋๋ก ์น ์๋ฒ๋ฅผ ์ด๋ป๊ฒ ๋ง๋๋์ง ๋ถํฐ ๊ณต๋ถํด์ผ ํ๋ค. ๊ณต์๋ฌธ์์ HTTP ํธ๋์ญ์ ํด๋ถ๋ฅผ ์ฐฌ์ฐฌํ ์ฝ์ด๋ดค์ง๋ง ๋ชจ๋ฅด๋ ๊ฐ๋ ์ด ๋๋ฌด ๋ง๊ณ , ์ดํด๊ฐ ์ ๋์ง ์์์ ๊ตฌ๊ธ๋ง๊ณผ ์ฑ (๋ง์นจ ์์ ์ Node.js๋ ๊ณต๋ถํ๊ณ ์ถ์๋ ์์ฌ์ ๊ตฌ๋งคํ๋)์ ํตํด ํ์ต์ ํ๋ค. ์ฑ ์ด ์ ๋ฆฌ๊ฐ ์ ๋์ด ์์ด์ ์ดํดํ๊ธฐ ํธํ๋ค.
์๋๋ ์ฑ ๋ณด๋ฉด์ ๊ฐ๋ตํ๊ฒ ํ์ตํ ๋ด์ฉ ์ ๋ฆฌ ๐
๐ฉ๐ป๐ป http ๋ชจ๋๋ก ์๋ฒ ๋ง๋ค๊ธฐ
// http ๋ชจ๋ ์ฌ์ฉ
const http = require("http");
/*
http ๋ชจ๋์ createServer ๋ฉ์๋
๋งค๊ฐ๋ณ์๋ก request(์์ฒญ)์ response(์๋ต)๋ฅผ ๋ฐ์
→ createServer๋ฅผ ์ฌ๋ฌ๋ฒ ํธ์ถํ๋ฉด ํ ๋ฒ์ ์ฌ๋ฌ ์๋ฒ๋ฅผ ์คํํ๋ ๊ฒ๋ ๊ฐ๋ฅ
*/
const server = http.createServer((req, res) => {
res.writeHead(200, { 'Content-type': 'text/html; charset=utf-8' });
res.write('<h1>HELLO :)</h1>');
res.end('<p>Hello Server</p>');
/*
writeHead ์๋ต์ ๋ํ ์ ๋ณด ๊ธฐ๋ก (setHeader๋ ํ๋ํ๋ ์ง์ )
write ํด๋ผ์ด์ธํธ๋ก ๋ณด๋ผ ๋ฐ์ดํฐ
end ์๋ต์ข
๋ฃ ๋ฉ์๋๋ก ์ธ์๊ฐ ์์ผ๋ฉด ๊ทธ ๋ฐ์ดํฐ๋ ํด๋ผ์ด์ธํธ๋ก ๋ณด๋ด๊ณ ์๋ต ์ข
๋ฃ
(end๋ ํจ์๊ฐ ์ข
๋ฃ๋๋ ๊ฒ์ด ์๋๊ธฐ ๋๋ฌธ์ ํจ์๋ฅผ ์ข
๋ฃํ๊ณ ์ถ์ผ๋ฉด return์ ์ฌ์ฉํด์ผ ํจ)
→ ์์ ์์ ๋ <h1>HELLO :)</h1>์ <p>Hello Server</p> ๋ฌธ์์ด์ ํด๋ผ์ด์ธํธ๋ก ๋ณด๋ธ ํ ์๋ต ์ข
๋ฃ
→ ๋ธ๋ผ์ฐ์ ๋ ์๋ต ๋ด์ฉ์ ๋ฐ์์ ๋ ๋๋ง
*/
})
// createServer ๋ฉ์๋ ๋ค์ listen ๋ฉ์๋(ํฌํธ ๋ฒํธ์ ์ฝ๋ฐฑ ํจ์)๋ก ์๋ฒ ์ฐ๊ฒฐ
.listen(8080, () => {
console.log("PORT 8080");
})
/* listen ๋ฉ์๋์ ์ฝ๋ฐฑ ํจ์ ๋ฃ๋ ๋์ listening ์ด๋ฒคํธ ๋ถ์ฌ๋ ๋จ
server.listen(8080); // ์๋ฒ ์ฐ๊ฒฐ
server.on("listening", () => { // on()์ ์ด๋ฒคํธ๋ฅผ ์ฐ๊ฒฐํ๋ ํจ์. on(์ด๋ฒคํธ๋ช
, ์ฝ๋ฐฑ)
console.log("PORT 8080")
});
server.on("error", (error) => {
console.error(error);
})
*/
2. ๊ณผ์ basic-server.js ์์ฑ
const http = require('http');
const PORT = 4999;
const ip = 'localhost';
const server = http.createServer((req, res) => {
// res.end("Hello, Node JS Server");
/* ↑ server ์คํ์ ๋ณด์ฌ์ฃผ๋ ๋ฌธ๊ตฌ (๊ตฌํ ํ ์ญ์ ํด์ผ ์ ์๋์)
์๋ฒ๋ฅผ node server.js ๋ก ๋ธ๋ผ์ฐ์ ์์ ์คํ์ ๋ฌดํ๋ก๋ฉ์ด ๋๋ ์ด์ : ์๋ต์ด ์๊ธฐ ๋๋ฌธ */
// Preflight Request
if (req.method === 'OPTIONS') {
res.writeHead(200, defaultCorsHeader);
res.end();
}
// POST
if (req.method === 'POST') {
if (req.url === '/upper') {
let data = '';
req.on('data', chunk => { // ์์ฒญ์ data๋ฅผ stream ํ์์ผ๋ก ๋ฐ์
data += chunk;
// ํ์ธ์ฉ ์ฝ๋
console.log("-------------------------------")
console.log("UPPERCASE")
console.log(chunk) // EX. Buffer๋ก ์ถ๋ ฅ <Buffer 79 63 65 66 66 6f 72 74>
console.log(chunk + chunk) // chunk๋ฅผ +๋ก ์ฐ๊ฒฐ์ ๋ฌธ์์ด๋ก ์๋ ๋ณํ
/*
on()์ ์ด๋ฒคํธ๋ฅผ ์ฐ๊ฒฐํ๋ ํจ์์ด๊ณ , ์์ 'data'์ ์๋์ 'end'๋ ์ด๋ฒคํธ์ด๋ค.
stream : ๋ฐ์ดํฐ๋ฅผ ์กฐ๊ฐ ์กฐ๊ฐ์ผ๋ก ์ฒ๋ฆฌํ๊ธฐ ์ํ ๋ฐฉ๋ฒ์ผ๋ก ํฐ ๋ฐ์ดํฐ๋ฅผ ํจ์จ์ ์ผ๋ก ์ฒ๋ฆฌํ ์ ์๋๋ก ๋์์ค๋ค.
chunk : stream์์ ์ ์ก๋๋ ๋ฐ์ดํฐ์ ์์ ์กฐ๊ฐ.
buffer : raw ๋ฐ์ด๋๋ฆฌ ๋ฐ์ดํฐ๋ฅผ ์ ์ฅํ ์ ์๋ ํน์ํ ์ ํ์ ๊ฐ์ฒด
→ ์คํธ๋ฆผ์์ ๋ฐ์ดํฐ๋ฅผ ์ฒ๋ฆฌํ๊ฑฐ๋ ์ ์กํ ๋๋ chunk ๋จ์๋ก ๋๋์ด ์ฒ๋ฆฌํ๋ค. (๋ฉ๋ชจ๋ฆฌ ํจ์จ์ฑ๊ณผ ์ฑ๋ฅ ๋ฉด์์ ์ด์ )
*/
console.log("data", data)
console.log("chunk", chunk.toString()) // Buffer๋ toString()์ผ๋ก ๋ฌธ์์ด๋ก ๋ณํ ๊ฐ๋ฅ
console.log("-------------------------------")
});
req.on('end', () => { // ์์ฒญ์ data๋ฅผ ๋ค ๋ฐ์ ํ ์คํ
data = data.toUpperCase();
res.writeHead(201, defaultCorsHeader);
res.end(data);
});
} else if (req.url === '/lower') {
let data = '';
req.on('data', chunk => {
data += chunk;
// ํ์ธ์ฉ ์ฝ๋
console.log("-------------------------------")
console.log("LOWERCASE")
console.log("data", data)
console.log("chunk", chunk.toString()basic-server.js)
console.log("-------------------------------")
});
req.on('end', () => {
data = data.toLowerCase();
res.writeHead(201, defaultCorsHeader);
res.end(data);
});
} else {
res.writeHead(400, defaultCorsHeader);
res.end();
}
}
});
server.listen(PORT, ip, () => {
console.log(`http server listen on ${ip}:${PORT}`);
});
const defaultCorsHeader = {
'Access-Control-Allow-Origin': '*',
'Access-Control-Allow-Methods': 'GET, POST, PUT, DELETE, OPTIONS',
'Access-Control-Allow-Headers': 'Content-Type, Accept',
'Access-Control-Max-Age': 10
};
๋ด์ผ ์ค์ ๋ผ์ด๋ธ์ธ์ ๋ basic-server ๋ฆฌ๋ทฐ๋ฅผ ํ๋์ง ์ ๋ชจ๋ฅด๊ฒ ์ง๋ง, ์๋ง ๋ฆฌ๋ทฐ๋ฅผ ํ๋ฉด ์ด ๊ธ์ ์์ ๋ ์๋..?!
node.js๋ฅผ ์ฌ์ฉํด ๋ณผ ์ ์๋ ์ข์ ๊ธฐํ์๊ณ , ์์ผ๋ก ๋ ๊ณต๋ถํ๊ณ ์ถ๋ค๋ ์๊ฐ์ด ๋๋ ๊ณผ์ ์๋ค :)
๐ ์ค๋์ ํ๊ณ
์ด์ ์ ๋์์ ๋ง๋ณด๊ธฐ๋ ํ ์ ์์ง๋ง, ์ฌ์ฉํ ์ค ์ ํ ๋ชจ๋ฅด๋ node.js๋ก ์น์๋ฒ๋ฅผ ๋ง๋๋ ์ค์ต์ ํ๋ค. ์ ๋ง ์๋ฌด๊ฒ๋ ๋ชจ๋ฅด๋๋ฐ, ํ์ต ์๋ฃ์ ๊ณต์ ๋ฌธ์๋ก๋ ์ถฉ๋ถํ ์ดํด๊ฐ ๋์ง ์์ ์ด๋ ค์ ๋ค. ์ด์ ์ ์๋ฐ์คํฌ๋ฆฝํธ๋ฅผ ๋ฐฐ์ฐ๋ฉฐ node.js๋ ๋ค๋ค๋ณด๊ณ ์ถ์ด์ ๊ด๋ จ ์ฑ ์ ๊ตฌ๋งคํ ์ ์ด ์์๋๋ฐ, ๊ทธ ๋๋ ํผ์ณ๋ณด์ง๋ ๋ชปํ ์ด ์ฑ ์ด ๋์์ด ์ ๋ง ๋ง์ด ๋์๋ค. ๐ ์ด๋ ๊ฒ ์ ๋ ๊ฒ ์ฝ๋๋ฅผ ์์ฑํ๋ฉฐ ์์ฑ์ ํ์ง๋ง, ์์ง๋ ์ต์์น ์์ node.js
์๋ฐ์คํฌ๋ฆฝํธ๋ฅผ ๋ฐฐ์ฐ๋ฉฐ ๋ฐฑ์๋์ ๋ชจ๋ฐ์ผ ๊ฐ๋ฐ๊น์ง ๊ฐ๋ฅํ๋ค๋ ์ด์ ์ด ์ ๋ง ํฌ์ง ์์๊น, ๋ผ๊ณ ์๊ฐํ์๋๋ฐ (๋ฌผ๋ก ๋ค์ดํฐ๋ธ๋งํผ์ ๋ชปํ๊ฒ ์ง๋ง) ๊ณผ์ฐ ์กฐ๊ธ์ฉ์ด๋ผ๋ ์ ๊ฒ๋ค์ ๋ด๊ฐ ๋ค ํด๋ณผ์ ์์๊น…
์ค๋๋ ์ ๋ง ์ด์ฌํ ํด์ผ๊ฒ ๋ค๋ ์๊ฐ์ด ๋๋๋ ๋๋ ํ๋ฃจ์๋ค. ๐ซ
'Frontend Dev > ๐ฅ ์ฝ๋์คํ ์ด์ธ FE ๋ถํธ์บ ํ' ์นดํ ๊ณ ๋ฆฌ์ ๋ค๋ฅธ ๊ธ
Section2 Unit10 [Web Server] ๊ธฐ์ด - StatesAirline Server (0) | 2023.06.05 |
---|---|
Section2 Unit10 [Web Server] ๊ธฐ์ด - Refactor Express (0) | 2023.06.02 |
Section2 Unit9 [React] ํด๋ผ์ด์ธํธ Ajax ์์ฒญ - StateAirline Client ๊ณผ์ ๋ฆฌ๋ทฐ (0) | 2023.05.31 |
Section2 Unit9 [React] ํด๋ผ์ด์ธํธ Ajax ์์ฒญ (0) | 2023.05.30 |
Section2 Unit8 [HTTP/๋คํธ์ํฌ] ์ค์ต - Postman (0) | 2023.05.26 |