๐ ์ฐธ๊ณ ๐ ํธ๋ํฝ vs ์ฒ๋ฆฌ๋
- โ๏ธ ํธ๋ํฝ : ํ๋ฅด๋ ๋ฐ์ดํฐ์ ์
- โ๏ธ ์ฒ๋ฆฌ๋ : ์ฒ๋ฆฌ๋๋ ํธ๋ํฝ์ ์
์ ํธ๋ฅผ ์ ์กํ๊ณ ํด๋น ์ ํธ์ ์์ ํ์ธ์ ๊ฑธ๋ฆฐ ์๊ฐ์ ๋ํ ๊ฐ
์ด๋ค ๋ฉ์์ง๊ฐ ๋ ์ฅ์น ์ฌ์ด๋ฅผ ์๋ณตํ๋๋ฐ ๊ฑธ๋ฆฐ ์๊ฐ
๐๏ธ ์์ : google์ ping ๋ณด๋ด๊ธฐ
๐ ์ฐธ๊ณ ๐ ping (Packet InterNet Groper)
- ์ปดํจํฐ์ ๋คํธ์ํฌ ์ํ๋ฅผ ์ ๊ฒ, ์ง๋จํ๋ ๋ช ๋ น
- ๋์ ์ปดํจํฐ๋ฅผ ํฅํด ์ผ์ ํฌ๊ธฐ์ packet ๋ณด๋ด๊ณ (ICMP echo request), ๋์ ์ปดํจํฐ๊ฐ ์๋ต ๋ฉ์์ง(ICMP echo reply) ๋ณด๋ด๋ฉด ๋ถ์ํ์ฌ ์ฅ๋ ์ฌ๋ถ ๋ฐ ๋คํธ์ํฌ ์ํ ํ์
- TCP/IP ํ๋กํ ์ฝ ์ค
ICMP
ํตํด ๋์ํ๋ฏ๋ก, ํด๋น ํ๋กํ ์ฝ ์ง์ํ์ง ์๋ ๊ธฐ๊ธฐ๋ ping ์ํ ๋ถ๊ฐ
(1) ๋ฒ์ค ํ ํด๋ก์ง
ํน์ง
์ฅ์
๋จ์
(2) ์คํ ํ ํด๋ก์ง
ํน์ง
์ฅ์
๋จ์
(3) ํธ๋ฆฌ ํ ํด๋ก์ง
ํน์ง
์ฅ์
๋จ์
๐ ์ฐธ๊ณ ๐ ๋ฐฑ๋ณธ์ผ์ด๋ธ
- ์ฌ๋ฌ ์ํ ๋คํธ์ํฌ๋ฅผ ๋ฌถ์ด ๋๊ท๋ชจ ํ์ดํ๋ผ์ธ์ ํตํด ๋์ ๋์ญํญ์ผ๋ก ๋ค๋ฅธ ๋คํธ์ํฌ๋ค์ ์งํฉ๊ณผ ์ฐ๊ฒฐ๋๋ ๋คํธ์ํฌ (๋๊ท๋ชจ ํจํท ํต์ ๋ง)
(4) ๋งํ ํ ํด๋ก์ง
ํน์ง
์ฅ์
๋จ์
(5) ๋ฉ์ ํ ํด๋ก์ง
์ข ๋ฅ
ํน์ง
์ฅ์
๋จ์
(1) ์ ๋์บ์คํธ (1:1 ํต์ )
(2) ๋ฉํฐ์บ์คํธ (1:N ํต์ )
(3) ๋ธ๋ก๋์บ์คํธ (1:N ํต์ )
const app = require('express')(); // express ๊ธฐ๋ฐ ์๋ฒ๋ฅผ ๊ตฌ๋์ํค๋๋ฐ ํ์ํ ๋
ธ๋ ๊ตฌ์ฑ
const http = require('http').Server(app); const io = require('socket.io')(http); // web socket ๊ธฐ๋ฐ์ผ๋ก broadcast ํ๋๋ฐ ํ์ํ ๋ชจ๋
const port = process.env.PORT || 3000;
app.get('/', (req, res) => {
res.sendFile(__dirname + '/index.html'); // index.html ์ ๋ฌ
});
io.on('connection', (socket) => { // ์ฐ๊ฒฐ๋ user ๋ค์๊ฒ ๋ฉ์์ง ์ ๋ฌ
socket.on('chat message', msg => {
io.emit('chat message', msg);
});
});
http.listen(port, () => {
console.log(`Socket.IO server running at
http://localhost:${port}/`);
});
node a.js
๋ช
๋ น์ด ์คํ127.0.0.01:3000
์ ์ <!DOCTYPE html>
<html>
<head>
<title>Socket.IO chat</title>
<style>
body { margin: 0; padding-bottom: 3rem; font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif; }
#form { background: rgba(0, 0, 0, 0.15); padding: 0.25rem; position: fixed; bottom: 0; left: 0; right: 0; display: flex; height: 3rem; box-sizing: border-box; backdrop-filter: blur(10px); }
#input { border: none; padding: 0 1rem; flex-grow: 1; border-radius: 2rem; margin: 0.25rem; }
#input:focus { outline: none; }
#form > button { background: #333; border: none; padding: 0 1rem; margin: 0.25rem; border-radius: 3px; outline: none; color: #fff; }
#messages { list-style-type: none; margin: 0; padding: 0; } #messages > li { padding: 0.5rem 1rem; }
#messages > li:nth-child(odd) { background: #efefef; }
</style>
</head>
<body>
<ul id="messages"></ul>
<form id="form" action="">
<input id="input" autocomplete="off" /><button>Send</button>
</form>
<script src="/socket.io/socket.io.js"></script>
<script>
var socket = io();
var messages = document.getElementById('messages'); var form = document.getElementById('form');
var input = document.getElementById('input');
form.addEventListener('submit', function(e) { e.preventDefault();
if (input.value) {
socket.emit('chat message', input.value);
input.value = '';
}
});
socket.on('chat message', function(msg) {
var item = document.createElement('li'); item.textContent = msg; messages.appendChild(item);
window.scrollTo(0, document.body.scrollHeight);
});
</script>
</body>
</html>
๐ ์ฐธ๊ณ ๐ socket
- ๋ ํธ์คํธ๋ฅผ ์ฐ๊ฒฐํ๋ ์ธํฐํ์ด์ค ์ญํ ์ ํ๋ ๋ฐ์ดํฐ ์ฃผ๊ณ ๋ฐ๋ ๊ตฌ์กฐ์ฒด
- ๊ตฌ์ฑ : ํ๋กํ ์ฝ, IP ์ฃผ์, ํฌํธ ๋๋ฒ
(1) LAN (๊ทผ๊ฑฐ๋ฆฌ ํต์ ๋ง, local area network)
(2) MAN (๋๋์ ํต์ ๋ง, metropolitan area network)
(3) WAN (๊ด์ญ ํต์ ๋ง, wide area network)
๐ ์ฐธ๊ณ ๐ TCP / IP ๊ณผ์
- 1) ์น ๋ธ๋ผ์ฐ์ ์
www.google.com
์ ๋ ฅ
- ๊ตฌ๊ธ ์น ์๋ฒ์ 80๋ฒ ํฌํธ๋ก HTTP Request ๋ณด๋ด๋ ๊ฒ๊ณผ ๋์ผ
- 2) HTTP Request ๋ณด๋ด๊ธฐ ์ํด ๊ฐ ๊ณ์ธต์ ํ์ํ ์ ๋ณด๋ฅผ ํจํท์ ๋ด์ ์ ์ก
- 3) Application ๊ณ์ธต : HTTP Request ํค๋ ์ถ๊ฐ
- 4) TCP ๊ณ์ธต : TCP ํค๋
- SP (์ถ๋ฐ์ง ํฌํธ ๋ฒํธ) : ๋ด ์ปดํจํฐ์์ ๋ง๋ ์์ผ์ ํฌํธ ๋ฒํธ
- DP (๋ชฉ์ ์ง ํฌํธ ๋ฒํธ) : 80ํฌํธ๋ก ์์ฒญ
- 5) Internet ๊ณ์ธต : IP ํค๋
- SA (์ถ๋ฐ์ง IP ์ฃผ์) : ๋ด IP ์ฃผ์
- DA (๋ชฉ์ ์ง IP ์ฃผ์) : ๋๋ฉ์ธ ์ ๋ณด๋ก IP์ฃผ์ ์๊ธฐ ์ํด ๋๋ฉ์ธ ์๋ฒ์ DNS ์ฟผ๋ฆฌ ๋ณด๋ด๊ณ , IP ์ฃผ์ ์๋ต ๋ฐ์
- 6) Network Access ๊ณ์ธต : Ethernet ํค๋
- SA (์ถ๋ฐ์ง MAC ์ฃผ์) : ๋ด MAC ์ฃผ์
- DA (๋ชฉ์ ์ง MAC ์ฃผ์) : ๊ตฌ๊ธ MAC ์ฃผ์๊ฐ ์๋, ๋ฌผ๋ฆฌ์ ์ผ๋ก ์ฐ๊ฒฐ๋ ํจํท ์ ๋ฌ๋ ๋ผ์ฐํฐ/๊ฒ์ดํธ์จ์ด์ MAC ์ฃผ์ (ARP ํ๋กํ ์ฝ ์ฌ์ฉ)
- 7) ํจํท ์ ์ก ์ , 3-way handshaking์ผ๋ก ์ฐ๊ฒฐ ์ค์
- ์ปจํธ๋กค ๋นํธ(ACK, SYN ํ๋๊ทธ) ์ฌ์ฉ
- 8) ๋ผ์ฐํ ํตํด ์์ฑ๋ ํจํท์ ๋ชฉ์ ์ง ์๋ฒ์ ์ ์ก
www.google.com
์ ํจํท ์ ์ก ํ HTML ์๋ต ๋ฐ์- ํด๋ผ์ด์ธํธ๋ ์๋ต ๋ฐ์ HTML์ ๋ธ๋ผ์ฐ์ ์ ๋์
- 9) HTTP ์๋ต ๋๋๋ฉด, 4-way handshaking์ผ๋ก ์ฐ๊ฒฐ ์ข ๋ฃ
- ์ปจํธ๋กค ๋นํธ (ACK, FIN ํ๋๊ทธ) ์ฌ์ฉ
๐ ์ฐธ๊ณ ๐ PDU (Protocol Data Unit)
- ์ ํ๋ฆฌ์ผ์ด์ ๊ณ์ธต : ๋ฉ์์ง
- ์ ์ก ๊ณ์ธต : ์ธ๊ทธ๋จผํธ(TCP), ๋ฐ์ดํฐ๊ทธ๋จ(UDP)
- ์ธ๊ทธ๋จผํธ : ์ ์ ํ ํฌ๊ธฐ๋ก ์ชผ๊ฐ ์กฐ๊ฐ (์ธ๊ทธ๋จผํธ = ๋ฐ์ดํฐ๊ทธ๋จ)
- ์ธํฐ๋ท ๊ณ์ธต : ํจํท
- ํจํท : ์ธ๊ทธ๋จผํธ SP์ DP๊ฐ ํฌํจ๋ IP ํค๋๊ฐ ๋ถ์ ํํ์ ์กฐ๊ฐ
- ๋งํฌ ๊ณ์ธต : ํ๋ ์(๋ฐ์ดํฐ ๋งํฌ ๊ณ์ธต), ๋นํธ(๋ฌผ๋ฆฌ ๊ณ์ธต)
- ํ๋ ์ : MAC ์ฃผ์ ํค๋์ CRC/์ฒดํฌ์ฌ ํธ๋ ์ผ๋ฌ๊ฐ ๋ถ์ ์กฐ๊ฐ
๐ ์ฐธ๊ณ ๐ CRC/์ฒดํฌ์ฌ ํธ๋ ์ผ๋ฌ
- ๋ฐ์ดํฐ ์ค๋ฅ ๊ฐ์ง๋ฅผ ์ํ ํจ์๊ฐ ์ ์ฉ๋ ๊ฐ
- ๋งํฌ์ ์ค๋ฅ(๊ณผ๋ํ ํธ๋ํฝ)๋ก ์ธํด ๋ฐ์ดํฐ ์์์ ๊ฐ์งํ๋ ์ญํ
MTU (Maximum Transmission Unit)
ping www.google.com -f -l 1500
ifconfig
en0 (windows)netsh interface ipv4 show interfaces
MSS (Maximum Segment Size)
PMTUD (Path MTU Discovery)
ํจํท์ด ๋ถํ ๋์ง ์๋ ๊ฒฝ์ฐ
1) application layer ๊ฐ๋
2) HTTP (HyperText Transfer Protocol)
3) SSH (Secure SHell)
4) FTP (File Transfer Protocol)
5) SMTP (Simple Mail Transfer Protocol)
Nodemailer
๋ผ์ด๋ธ๋ฌ๋ฆฌ ์ด์ฉํ์ฌ JS ๊ธฐ๋ฐ์ผ๋ก SMTP ํตํด ๋ฉ์ผ // create reusable transporter object using the default SMTP
transport
let transporter = nodemailer.createTransport({
host: "smtp.ethereal.email",
port: 587,
secure: false, // true for 465, false for other ports auth: {
user: testAccount.user, // generated ethereal user
pass: testAccount.pass, // generated ethereal password },
});
1) transport layer ๊ฐ๋
2) TCP (Transmission Control Protocol)
3) UDP (User Datagram Protocol)
๐ ์ฐธ๊ณ ๐ ์ค๋ฅ ๊ฒ์ฌ ๋ฉ์ปค๋์ฆ
- โ๏ธ ์ฌ์ ์ก
- ์๊ฐ ์ด๊ณผ ๊ธฐ๊ฐ ์ง๋๋ฉด ์๋ฒ๋ ์ ๋ฌ๋์ง ์์ ๋ฐ์ดํฐ์ ๋ํด ์ฌ์ ์ก ์๋
- โ๏ธ ์ฒดํฌ์ฌ
- ์ก์ ๋ ๋ฐ์ดํฐ ์ฒดํฌ์ฌ๊ณผ ์์ ๋ ์ฒดํฌ์ฌ ๊ฐ์ ๋น๊ตํด์ ๋์ผํ์ง ํ์ธ (๋ฌด๊ฒฐ์ฑ ํ๊ฐ)
(1) SYN ๋จ๊ณ ๐คตโโ๏ธ โก๏ธ ๐ฅ๏ธ
ISN
์ ๋ด์ SYN
ํจํท ๋ณด๋(2) SYN + ACK ๋จ๊ณ ๐ฅ๏ธ โก๏ธ ๐คตโโ๏ธ
ISN
์ ๋ณด๋ด๋ฉฐ ์น์ธ๋ฒํธ๋ก ISN + 1
๋ณด๋(3) ACK ๋จ๊ณ ๐คตโโ๏ธ โก๏ธ ๐ฅ๏ธ
ISN + 1
ํ ๊ฐ์ธ ์น์ธ๋ฒํธ๋ฅผ ๋ด์ ACK๋ฅผ ์๋ฒ์ ๋ณด๋ํด๋ผ์ด์ธํธ์ ์๋ฒ์ ์ํ
๐ ์ฐธ๊ณ ๐ listen
- ์๋ฒ๊ฐ ํด๋ผ์ด์ธํธ ์ฐ๋ฝ ๋๊ธฐ ์ํ
- ํด๋น ์ํ๊ธฐ๋ฐ์ผ๋ก ์๋ฒ ๋ฉ์๋ ์ด๋ฆ ๊ฒฐ์
const express = require('express') const app = express() const port = 3000 app.get('/', (req, res) => { res.send('Hello World!') }) app.listen(port, () => { console.log(`Example app listening on port ${port}`) })
๐ ์ฐธ๊ณ ๐ ISN
- TCP ๊ธฐ๋ฐ ๋ฐ์ดํฐ ํต์ ์์ ๊ฐ ์ ์ฐ๊ฒฐ์ ํ ๋น๋ ๊ณ ์ ํ 32๋นํธ ์ํ์ค ๋ฒํธ
- TCP ์ฐ๊ฒฐ์ ํตํด ์ ์ก๋๋ ๋ค๋ฅธ ๋ฐ์ดํฐ์ ์ถฉ๋๋์ง ์๋๋ก ์ํ์ค ๋ฒํธ ํ ๋น
- wireshark(ํจํท ๋ถ์ tool)๋ก TCP ์ฐ๊ฒฐ ํ์ธ
๐ ์ฐธ๊ณ ๐ TIME_WAIT
- ์ง์ฐ ํจํท ๋ฑ ๋ฐ์์ ๋ฐ์ดํฐ ๋ฌด๊ฒฐ์ฑ์ ํด๊ฒฐํ๊ธฐ ์ํ ํจํท ๋๊ธฐ ์๊ฐ
- (FIN ํ๋๊ทธ๊ฐ ACK ๋ณด๋ค ๋จผ์ ๋์ฐฉํ ๊ฒฝ์ฐ)์์ง ์๋ฒ๋ก๋ถํฐ ๋ฐ์ง ๋ชปํ ๋ฐ์ดํฐ๊ฐ ์์ ๊ฒ์ ๋๋นํด ํจํท ๊ธฐ๋ค๋ฆฌ๋ ๊ณผ์
- 2 *
MSL
๋์ ๋๊ธฐMSL (Maximum Segment Lifetime)
: ์ต๋ ํจํท ์๋ช (๋ณดํต 2๋ถ)- ์ฐ๊ฒฐ์ด ์ฌ๋ฐ๋ฅด๊ฒ ๋ซํ ์ํ๋ก ๋ง๋ค๊ธฐ ์ํด ์กด์ฌ
- CLOSED๊ฐ ์๋์ด ์์ ๊ฒฝ์ฐ ์ค๋ฅ ๋ฐ์ํ์ฌ, ์ผ์ ์๊ฐ๋ง ๊ธฐ๋ค๋ฆฌ๋๋ก ์ค์
- CentOS/Ubuntu : 60์ด, Window :4๋ถ
- Ubuntu ์ค์ ํ์ผ
include/net/tcp.h #define TCP_TIMEWAIT_LEN (60*HZ) //TIME-WAIT
๐ ์ฐธ๊ณ ๐ routing protocol
EGP (Exterior Gateway Protocol)
: ๋ค๋ฅธ ๊ทธ๋ฃน๊ณผ ๋ผ์ฐํ ์ ๋ณด๋ฅผ ๊ตํํ๋ ํ๋กํ ์ฝ (๋๋ฉ์ธ๊ฐ ๋ผ์ฐํ )
- 1) EGP (๊ฒ์ดํธ์จ์ด ์ญ์ธ ํ๋กํ ์ฝ)
- 2) BGP (๊ฒฝ๊ณ ๊ฒ์ดํธ์จ์ด ํ๋กํ ์ฝ)
IGP (Internal Gateway Protocol)
: ๋์ผ ๊ทธ๋ฃน ๋ด์์ ๋ผ์ฐํ ์ ๋ณด๋ฅผ ๊ตํํ๋ ํ๋กํ ์ฝ (๊ธฐ์ ๋ด๋ถ)
- Distance Vector Protocol
- ๊ฒฝ๋ก ์ค์ ์ ์ํ ์์๋ฅผ ๊ฑฐ๋ฆฌ์ ๋ฐฉํฅ์ ์ค์
- ํ ์๋ฅผ ๊ธฐ์ค์ผ๋ก ๊ฒฝ๋ก ์ฐพ์
- 1) RIP (๋ผ์ฐํ ์ ๋ณด ํ๋กํ ์ฝ)
- 2) IGRP (๋ด๋ถ ๊ฒฝ๊ณ ๋ผ์ฐํ ํ๋กํ ์ฝ)
- Link State Protocol
- ์ ์ฒด ๋คํธ์ํฌ topology, path ๋ฑ ์ ๋ณด๋ฅผ DB๋ก ์ ์ฅ
- DB ๊ทผ๊ฑฐ๋ก SPF ์๊ณ ๋ฆฌ์ฆ(Shortest Path First) ์ฌ์ฉํ์ฌ ๊ฒฝ๋ก ์ฐพ์
- 3) OSPF (์ต๋จ ๊ฒฝ๋ก ์ฐ์ ํ๋กํ ์ฝ)
1) ๊ฐ๋
2) ๊ตฌ์ฑ์์
3) ์ค์ต
netstat -r
1) gateway ๊ฐ๋
2) gateway ๋ฐฉ์
3) ํ
1) IP ์ฃผ์ (Internet Protocol Address)
2) MAC ์ฃผ์ (Media Access Control Address)
ipconfig
en0์ ethernet, (windows)ipconfig/all
๐ ์ฐธ๊ณ ๐ OUI์ UAA
- OUI : IEEE์์ ํ ๋นํ ์ ์กฐ์ฌ ์ฝ๋
- UAA : ์ ์กฐ์ฌ์์ ๊ตฌ๋ณ๋๋ ์ฝ๋
๐ ์ฐธ๊ณ ๐ IEEE (Institute of Electrical and Electronics Engineers)
- ์ ๊ธฐ/์ ์/์ ์ฐ ๋ถ์ผ์ ๊ตญ์ ๊ธฐ๊ตฌ ๋ฐ ํํ
- ๊ด๋ จ ์ ๋ฌธ๊ฐ๋ค์ด ํฉ๋ณํด์ ์ฐฝ์คํ ๊ตญ์ ์กฐ์ง
- ๊ด๋ จ ๊ธฐ์ ๊ณต์ ์ ํ์ค ์ ์๋ฑ ํ๋
1) IPv4 ๊ฐ๋
2) IPv6 ๊ฐ๋
๐ ์ฐธ๊ณ ๐ TTL
- ํจํท์ด ๋คํธ์ํฌ์์ ๋ฌดํ์ํํ์ง ์๋๋ก ํ๋ ๋ณ์
- ํจํท์ด ๋คํธ์ํฌ์์ ๋ผ์ฐํฐ ๊ฑฐ์น ๋๋ง๋ค TTL๊ฐ 1์ฉ ๊ฐ์
- ๊ฐ์ด 0์ด ๋๋ฉด ํจํท ํ๊ธฐ
๐ ์ฐธ๊ณ ๐ CRC
- ์ํ ์ค๋ณต ๊ฒ์ฌ
- ๋คํธ์ํฌ์์์ ๋ฐ์ดํฐ ์ค๋ฅ๊ฐ ์๋์ง ํ์ธํ๊ธฐ ์ํ ์ฒดํฌ๊ฐ ๊ฒฐ์ ๋ฐฉ์
- ๋ฐ์ดํฐ ์ ์กํ๊ธฐ ์ ์ ์ฃผ์ด์ง ๋ฐ์ดํฐ์ ๊ฐ์ ๋ฐ๋ผ CRC๊ฐ ๊ณ์ฐํ์ฌ ๋ฐ์ดํฐ ๋ถ์ฌ ์ ์ก
- ๋ฐ์ดํฐ ์ ์ก์ด ๋๋ ํ ๋ฐ์ ๋ฐ์ดํฐ์ ๊ฐ์ผ๋ก ๋ค์ CRC๊ฐ ๊ณ์ฐ
- ๋ ๊ฐ ๋น๊ตํด์ ๋ค๋ฅผ ๊ฒฝ์ฐ, ๋ฐ์ดํฐ ์ ์ก ๊ณผ์ ์ค ์ค๋ฅ(์ก์ ๋ฑ)๊ฐ ์ถ๊ฐ๋์ด ์ ์ก๋ ๊ฒ
- ์ค์น
npm install crc
- ์ฌ์ฉ
import crc32 from 'crc/crc32': crc32('hello').toString(16): // "3610a686"
classful ๊ฐ๋
IP ์ฃผ์ ๊ตฌ์ฑ: ๋คํธ์ํฌ ์ฃผ์ + ํธ์คํธ ์ฃผ์
1) ํด๋์ค A
2) ํด๋์ค B
3) ํด๋์ค C
๐ ์ฐธ๊ณ ๐ ํด๋์คํ IP ์ฃผ์ ๊ท์น
- ์ฒซ ์ฃผ์ : ๋คํธ์ํฌ ์ฃผ์ (X.0.0.0)
- ๋ง์ง๋ง ์ฃผ์ : ๋ธ๋ก๋์บ์คํ ์ฃผ์ (X.255.255.255)
- ํญ์ 2๊ฐ ์ ์ธํ๊ณ ์ฌ์ฉ
์ฌ์ฉ์๊ฐ HTTP ์์ฒญ์ ํค๋์ ๋ฐ๋ ์ฃผ๊ณ ๋ฐ์
1) HTTP Header ๊ฐ๋
๐ ์ฐธ๊ณ ๐ HTTP ํ์ธ
- 1) www.naver.com โก๏ธ chrome ๊ฐ๋ฐ์ ๋๊ตฌ
- 2) Network โก๏ธ Fetch/XHR
- 3) (API ์์ฒญ์ ๋ฐ๋ ๋ฆฌ์์ค ์ค) count.nhn ํ์ธ
- 4) Preview (Body)
2) ์ผ๋ฐํค๋
3) ์์ฒญํค๋
4) ์๋ตํค๋
์๋ฒ์์ ์ค์ ํ๋ ํค๋
์๋ฒ์ ์ํํธ์จ์ด ์ ๋ณด ํฌํจ (๋ณด์์ ์ํด ๊ฐ๋ตํ๊ฒ ํ์)
NWS (Naver Web Server)
์์ฑ
// node.js
const http = require('http'); // http ๋ชจ๋ ๋ถ๋ฌ์ด
const hostname = '127.0.0.1';
const port = 3000;
const server = http.createServer((req, res) => { // server ๊ฐ์ฒด์ server ์ธ์คํด์ค ๋ด๊ธฐ
res.setHeader('Content-Type', 'text/plain; charset=utf-8'); // key-value ํํ
res.setHeader('kundol', "i love you, but you don't love me"); // ํค๋ ์ปค์คํ
๊ฐ๋ฅ
res.end('ํฐ๋, ๊ทธ๋ ์ ์ธ๊ฐ?!\n');
});
server.listen(port, hostname, () => { // ํด๋น ๋ฉ์๋๋ฅผ ํตํด server ๊ตฌ๋
console.log(`Server running at http://${hostname}:${port}/`);
});
// ์คํ : node [์คํํ์ผ๋ช
]
๐ ์ฐธ๊ณ ๐ RTT (Round Trip Time, ์๋ณต ์ง์ฐ ์๊ฐ)
- ์ ํธ๋ฅผ ์ ์ก + ์ ํธ์ ์์ ํ์ธ์ ๊ฑธ๋ฆฐ ์๊ฐ
- ์ด๋ค ๋ฉ์์ง๊ฐ ๋ ์ฅ์น ์ฌ์ด๋ฅผ ์๋ณตํ๋ ๋ฐ ๊ฑธ๋ฆฐ ์๊ฐ
์ฅ์ 1๏ธโฃ) keep-alive
- default (๊ธฐ๋ณธ ์ต์
) : ๋งค๋ฒ ๋ฐ์ดํฐ ์์ฒญ์๋ง๋ค TCP ์ฐ๊ฒฐ ์๋ก ํ์ง ์๊ณ , 1๋ฒ ์ฐ๊ฒฐ๋ง์ผ๋ก ์ฌ๋ฌ ๊ฐ ํ์ผ ์ก์์ ๊ฐ๋ฅ
- header : timeout(์ฐ๊ฒฐ์ ์ง์๊ฐ) ๋ฐ max(์ต๋ ์์ฒญ ์) ์ง์
const express = require('express') // express ๋ชจ๋ ๊ธฐ๋ฐ์ผ๋ก ์๋ฒ ๊ฐ๋
const app = express()
app.get('/',(req, res) =>{ // path(/)์ ์ ๊ทผํ๊ฒ ๋๋ฉด, ํ๋จ json ๋ฐํํ๋ ์๋ฒ
res.json({"a" : 1})
})
const server = app.listen(12010)
server.keepAliveTimeout = 30 * 1000 // KeepAliveTimeout(TCP ์ฐ๊ฒฐ์ ์ธ์ ๊น์ง ์ ์งํ ์ง ์ค์ ํ๋ ํค๋) 30์ด๋ก ์ค์ (default 5์ด)
์ฅ์ 2๏ธโฃ) ํธ์คํธ ํค๋
์ฅ์ 3๏ธโฃ) ๋์ญํญ ์ต์ ํ
Range:bytes=5000-
ํค๋ ์ถ๊ฐํ์ฌ ๋ค์ด๋ก๋ ์ฌ๊ฐ ์์ฒญ ๊ฐ๋ฅ๋จ์ 1๏ธโฃ) HOL (Head Of Line blocking) ๋ฌธ์
์์ฒญ ์ค์ด๊ธฐ
HTTP/2 ๊ฐ๋
์ฅ์ 1๏ธโฃ) HOL Blocking ํด๊ฒฐ
์ฅ์ 2๏ธโฃ) ๋ฉํฐํ๋ ์ฑ
์ฅ์ 3๏ธโฃ) ์๋ฒํธ์
์ฅ์ 4๏ธโฃ) ํค๋์์ถ
ํํ๋ง ์ธ์ฝ๋ฉ ์์ถ
๋ฐฉ๋ฒ์ ํตํด ์์ถ ํ ์ ์ก ์ฅ์ 5๏ธโฃ) ์คํธ๋ฆผ ์ฐ์ ์์ ์ค์
๐ ์ฐธ๊ณ ๐ ํํ๋ง ์ธ์ฝ๋ฉ
- ๋ฌธ์์ด์ ๋ฌธ์ ๋จ์๋ก ์ชผ๊ฐ ๋น๋์๋ฅผ ์ธ์ด ๋น๋๊ฐ ๋์ ์ ๋ณด๋ ์ ์ ๋นํธ์๋ก ํํ
- ๋น๋์ ๋ฎ์ ์ ๋ณด๋ ๋ง์ ๋นํธ์๋ก ํํํด ํ์ํ ๋นํธ์์ ์ค์ด๋ ์๊ณ ๋ฆฌ์ฆ
HTTP/3 ๊ฐ๋
์ฅ์ 1๏ธโฃ) ๋ฉํฐํ๋ ์ฑ, ์ด๊ธฐ ์ฐ๊ฒฐ ์ค์ ์ ์ง์ฐ์๊ฐ ๊ฐ์
์ฅ์ 2๏ธโฃ) ์ด๊ธฐ ์ฐ๊ฒฐ ์ค์ ์ ์ง์ฐ์๊ฐ ๊ฐ์
์ฅ์ 3๏ธโฃ) FEC (Forward Error Correction, ์๋ฐฉํฅ ์ค๋ฅ ์์ ๋ฉ์ปค๋์ฆ)
๐ ์ฐธ๊ณ ๐ RSA ์ทจ์ฝ์
- RSA์ ๊ฒฝ์ฐ : ํด๋ผ์ด์ธํธ๊ฐ ์์ฑํ ์ธ์ ํค(์์ ์ํธ๊ฐ)์ ์๋ฒ๋ก ์ ์ก
โก๏ธ ์ 3์๊ฐ ์๋ฒ์ ๊ฐ์ธํค ํ์ทจํ ๊ฒฝ์ฐ SSL Handshake ๊ณผ์ ๋ณตํธํ ํ์ฌ ๋ณผ ์ ์์ (PFS ์ง์X)- DH์ ๊ฒฝ์ฐ : ํด๋ผ์ด์ธํธ-์๋ฒ๊ฐ ์๋ก ๊ตํํ DH ๋งค๊ฐ๋ณ์ ์ฌ์ฉํด ๊ฐ์ธํค ๋ง๋ฆ
โก๏ธ DH ํ์ทจ๋นํด๋ ๊ณตํต ์ํธํค ๋ง๋ค์ง ๋ชปํด ์ํ ์ ์
- RSA ํค ๊ตํ ๊ณผ์
- ์๋ฒ์์ ๊ณต๊ฐํค+๊ฐ์ธํค ์์ฑํ๊ณ SSL ์ธ์ฆ์๋ฅผ ํตํด ๊ณต๊ฐํค๋ฅผ ํด๋ผ์ด์ธํธ์๊ฒ ์ ์ก
- ํด๋ผ์ด์ธํธ๋ ๊ณต๊ฐํค๋ก ์ธ์ ํค๋ฅผ ์ํธํ ํ์ฌ ์๋ฒ์ ์ ์ก
- ์๋ฒ๋ ์ธ์ ํค๋ฅผ ๋ณตํธํ ํ์ฌ ํต์ ์ ์ฌ์ฉ
๐ ์ฐธ๊ณ ๐ PFS (Perfect Forward Secrecy)
- ๋น๋ฐํค๊ฐ ๋ ธ์ถ๋์์ ๊ฒฝ์ฐ์๋ ๊ธฐ์กด ์ํธ๋ฌธ์ ๋ ธ์ถ๋ ๋น๋ฐํค๋ก ํด๋ X
- ECDHE ๋ฐฉ์์ด PFS ์ง์
- DH ๋ฐฉ์์ ์ธ์ ํค๋ฅผ ์์ ํ๊ณ ๊ฐ๋จํ๊ฒ ์์ฑ ๊ฐ๋ฅ โก๏ธ ์ฃผ๊ธฐ์ ์ผ๋ก ์ธ์ ํค ๋ณ๊ฒฝํ์ฌ ์ผ์ ์ฃผ๊ธฐ๋ง๋ค ๋ค๋ฅธ ์ธ์ ํค ๊ฐ์ง
- ๊ณต๊ฒฉ์๊ฐ ํน์ ์์ ์ ๋ฐ์ดํฐ๋ฅผ ๋ณตํธํํ๊ณ ์ถ์ ๊ฒฝ์ฐ ํน์ ์์ ์ ์ธ์ ํค ํ์
1) TLS ๊ฐ๋
2) TLS Handshake (TLS 1.3)
3) TLS ํจํท๋ถ์
4) DH ๋งค๊ฐ๋ณ์ (Diffie-Hellman)
๐ ์ฐธ๊ณ ๐ ํ์๊ณก์ ์ํธํ ๋ฐฉ๋ฒ
- ๊ณก์ ์ ์ฌ์ฉํ์ฌ ๊ฐ์ธ ํค ๋ณด์ ์๋ง ์ ์ ์๋ ํ์๊ณก์ ๊ทธ๋ฆผ
- ํ์๊ณก์ ์ ๊ธฐ๋ฐ์ผ๋ก ๊ต์ฐจ์ ์์ฑ
- ๊ต์ฐจ์ ์ ์๋ฅผ ๊ธฐ๋ฐ์ผ๋ก ์ํธ ์ค์ ํ๋ ๋ฐฉ๋ฒ
5) ์ฌ์ดํผ์ํธ
TLS
: ํ๋กํ ์ฝAES_128_GCM
: AEAD ์ฌ์ดํผ ๋ชจ๋SHA256
: ํด์ฑ ์๊ณ ๋ฆฌ์ฆ๐ ์ฐธ๊ณ ๐ AEAD (Authenticated Encryption with Associated Data) ์ฌ์ดํผ ๋ชจ๋
- ๋ฐ์ดํฐ ์ํธํ ์๊ณ ๋ฆฌ์ฆ
- ๐๏ธ ์์ : AES_128_GCM
- 128๋นํธ์ ํค๋ฅผ ์ฌ์ฉํ๋
AES ์๊ณ ๋ฆฌ์ฆ
+ ๋ณ๋ ฌ ๊ณ์ฐ์ ์ฉ์ดํGCM ์ํธํ ์๊ณ ๋ฆฌ์ฆ
์ด ๊ฒฐํฉ๋ ์๊ณ ๋ฆฌ์ฆ
๐ ์ฐธ๊ณ ๐ ์ ์์๋ช
- ์ก์ ์๊ฐ ์์ ์ ์ ์์ ์ฆ๋ช ํ๋ ์ ์ฐจ/์ ๋ณด
- ์ ์์๋ช ์ ํตํด ์ธ์ฆ์์ ์ฃผ์ฒด๊ฐ
์๋น์ค ์ ๊ณต์
์ธ์ง ํ์ธ- ๊ธฐ๋ก๋ ์ ์์๋ช ๊ธฐ๋ฐ์ผ๋ก CA์ ๊ณต๊ฐํค๋ก ๋ณตํธํ ํด์ ์ง๋ฌธ์ ์ป๊ณ , ์ธ์ฆ์์ ๊ธฐ๋ก๋ ์ ๋ณด๋ฅผ ํด์ ํจ์์ ์ ๋ ฅํ์ฌ ๋ ํด์์ ์ผ์น ์ฌ๋ถ ํ์ธ (์ ํจ์ฑ ๊ฒ์ฆ)
- ์ ํจ์ฑ ๊ฒ์ฆ : ์ธ์ฆ์๊ฐ ๋ณ์กฐ๋์ง ์๊ณ , ์ธ์ฆ์๊ฐ "์๋น์ค ์ ๊ณต์"๊ฒ์์ ํ์ธํ๋ ๊ณผ์
๐ ์ฐธ๊ณ ๐ ์ธ์ฆ์
์ฃผ์ฒด
+๊ณต๊ฐํค
ํฌํจํ๋ ๋จ์ ๋ฐ์ดํฐ ํ์ผ
- ์ฃผ์ฒด : ์ธ์ฆ์ ๋ฐ๊ธํ CA, ๋๋ฉ์ธ, ์น์ฌ์ดํธ ์์ ์, ์ธ์ฆ์ ์์ ์
- ๊ณต๊ฐํค : ์ฒซ ์ธ์ฆ์ ์ฌ์ฉ (๊ณต๊ฐํค, ๊ณต๊ฐํค ์ํธํ ๋ฐฉ๋ฒ)
- ํด๋ผ์ด์ธํธ์์ ์๋ํ ์๋ฒ๊ฐ ๋ง๋์ง ํ์ธ์ ์ฌ์ฉ
- ์ธ์ฆ๊ธฐ๊ด(CA)์์ ๋ฐ๊ธํ SSL ์ธ์ฆ์ ๊ธฐ๋ฐ์ผ๋ก ์ธ์ฆ
- ์์ ์ ์น์ฌ์ดํธ ์์์ SSL ์ธ์ฆ์ ๋ง๋ค ์๋ ์์
๐ ์ฐธ๊ณ ๐ CA (Certificate Authority)
- ์ธ์ฆ์๋ฅผ ๋ฐ๊ธํ๋ ๊ธฐ์ ๋ค
- CA๋ก๋ถํฐ ์ธ์ฆ์๋ฅผ ๊ตฌ์ ํ ๋ ์๋น์ค์ ๋๋ฉ์ธ, ๊ณต๊ฐํค ๊ฐ์ ์ ๋ณด๋ฅผ ์ ์ถํด์ผ ํจ
- ์ข ๋ฅ
- ๋จ์ผ ๋๋ฉ์ธ : 1๊ฐ ๋๋ฉ์ธ์ ์ ์ฉ๋๋ ์ธ์ฆ์ (ex. www.naver.com)
- ์์ผ๋์นด๋ : ๋๋ฉ์ธ์ ํ์๋๋ฉ์ธ๋ ํฌํจํ๋ ์ธ์ฆ์ (www.cloudflare.com, blog.cloudflare.com)
- ๋ฉํฐ ๋๋ฉ์ธ : ๊ด๋ จ๋์ง ์์ ๋ค์์ ๋๋ฉ์ธ์ ์ ์ฉ๋๋ ์ธ์ฆ์
๐ ์ฐธ๊ณ ๐ 0 - RTT
- ์ธ์ ํค ์์ฑ ํ ๋ค์ ์ฌ์ดํธ ๋ฐฉ๋ฌธํ๋ฉด, ๋ฏธ๋ฆฌ ๋ง๋ค์ด ๋์ ์ธ์ ํค(PSK)๋ฅผ ๊ธฐ๋ฐ์ผ๋ก ์ฐ๊ฒฐํด์ ์ธ์ฆ์ ๋๋ ๋น์ฉX
- ์ธ์ฆ์ ๊ดํ RTT๊ฐ ๋ฐ์ํ์ง ์์
https://search.shopping.naver.com
(์ค๋ฆฌ์ง) + /catalog
+ (๊ฒฝ๋ก) /33803998618?adId...
(์ฟผ๋ฆฌ)(1) ๋ก๊ทธ์ธ ์ ์ง์ ์ฌ์ฉ
(2) ์บ์ฑ
<!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>
<style>
/* CSS */
.button-62 {
background: linear-gradient(to bottom right, #EF4765,
#FF9A5A);
border: 0;
border-radius: 12px;
color: #FFFFFF;
cursor: pointer;
display: inline-block;
font-family: -apple-system, system-ui, "Segoe UI",
Roboto, Helvetica, Arial, sans-serif;
font-size: 16px;
font-weight: 500;
line-height: 2.5;
outline: transparent;
padding: 0 1rem;
text-align: center;
text-decoration: none;
transition: box-shadow .2s ease-in-out;
user-select: none;
-webkit-user-select: none;
touch-action: manipulation;
white-space: nowrap;
}
.button-62:not([disabled]):focus {
box-shadow: 0 0 .25rem rgba(0, 0, 0, 0.5), -.125rem
-.125rem 1rem rgba(239, 71, 101, 0.5), .125rem .125rem 1rem
rgba(255, 154, 90, 0.5);
}
.button-62:not([disabled]):hover {
box-shadow: 0 0 .25rem rgba(0, 0, 0, 0.5), -.125rem
-.125rem 1rem rgba(239, 71, 101, 0.5), .125rem .125rem 1rem
rgba(255, 154, 90, 0.5);
} #field{
font-size: 27px;
}
body{
display: flex;
justify-content: center;
align-items: center;
margin: 0 auto;
height: 100vh;
}
</style>
</head>
<body> <div>
<input type="text" id="field" />
<input type="button" class="button-62" value="๊ฒ์"id="save" />
<input type="button" class="button-62" value="์กฐํ"
id="read" />
<input type="button" class="button-62" value="์ญ์ "
id="clear" />
</div>
</body>
<script>
window.onload = async () => {
const field = document.getElementById("field"),
save = document.getElementById("save"),
read = document.getElementById("read"),
clear = document.getElementById("clear")
save.addEventListener("click", e => localStorage.setItem("์
๋ ฅ๊ฐ", field.value))
read.addEventListener("click", e => alert(window.localStorage["์
๋ ฅ๊ฐ"]))
clear.addEventListener("click", e => {
window.localStorage.clear()
field.value = ""
})
if (window.localStorage["์
๋ ฅ๊ฐ"]) {
field.value = window.localStorage["์
๋ ฅ๊ฐ"] }
}
</script>
</html>
1) ๊ฐ๋
axios.get(url, {
headers: {
Cookie: "cookie1=value; cookie2=value; cookie3=value;"
}
}).then
2) ์ธ์ ์ฟ ํค
3) ์๊ตฌ ์ฟ ํค
4) ๋ฌธ๋ฒ
Set-Cookie: <cookie-name>=<cookie-value>
Set-Cookie: <cookie-name>=<cookie-value>; Expires=<date>
Set-Cookie: <cookie-name>=<cookie-value>; Max-Age=<non-zero-digit>
Set-Cookie: <cookie-name>=<cookie-value>; Domain=<domain-value>
Set-Cookie: <cookie-name>=<cookie-value>; Path=<path-value>
Set-Cookie: <cookie-name>=<cookie-value>; Secure
Set-Cookie: <cookie-name>=<cookie-value>; HttpOnly
Set-Cookie: <cookie-name>=<cookie-value>; SameSite=Strict
const http = require('http');
const hostname = '127.0.0.1';
const port = 3000;
const server = http.createServer((req, res) => {
res.setHeader('Content-Type', 'text/plain; charset=utf-8');
res.setHeader('Set-Cookie', ['kundol = amumu; httponly',
'loltier = master; Secure']);
res.end('ํฐ๋, ๊ทธ๋ ์ ์ธ๊ฐ?!\n'); });
server.listen(port, hostname, () => {
console.log(`Server running at http://${hostname}:${port}/`);
});
5) ์ฟ ํค์ ์ํ์ด์ฝ๋ฉ
๋ฐฉ๋ฌธ ๊ธฐ๋ก์ ์ถ์ ํ ๋ ์ฟ ํค ์ฌ์ฉ๋จ
๐ ์ฐธ๊ณ ๐ ์ ๋นํธ์ ์ฟ ํค ์ธ์ ํ์์์ (๊ณต๊ฒฉ์ ์ ๊ทผ ์ฐจ๋จ)
- ๋ก๊ทธ์ธ ์ ์งํ๊ธฐ ์ํด์ ์ ๋นํธ ๋ก๊ทธ์ธ ํ๋ฉด์์ '๋ก๊ทธ์ธ ์ํ ์ ์ง' ํ์ฑํ
- PC ์น์์ ์ง์๋๋ ๊ธฐ๋ฅ์ผ๋ก '๋ก๊ทธ์ธ ์ํ ์ ์ง' ํ์ฑํ ์ฌ๋ถ์ ๋ฐ๋ผ ๊ธฐ๋ณธ ๋ก๊ทธ์ธ ์ ์ง ์๊ฐ์ด ์ค์ ๋จ
- ๋ก๊ทธ์ธ ์ํ ์ ์ง ํ์ฑํ : ๋ก๊ทธ์ธ ์ ์ง ์๊ฐ ๊ธฐ๋ณธ 24์๊ฐ
- ๋ก๊ทธ์ธ ์ํ ์ ์ง ๋นํ์ฑํ : ๋ก๊ทธ์ธ ์ ์ง ์๊ฐ ๊ธฐ๋ณธ 3์๊ฐ
๊ณตํต์ 1๏ธโฃ) ํ์ํ ์ด์
๊ณตํต์ 2๏ธโฃ) ์ ์ฅ๋ชฉ๋ก
์ฐจ์ด์ 1๏ธโฃ) ๋ก์ปฌ ์คํ ๋ฆฌ์ง vs ์ธ์
์คํ ๋ฆฌ์ง vs ์ฟ ํค
์ฐจ์ด์ 2๏ธโฃ) ์ธ์
์ฟ ํค vs ์๊ตฌ์ฟ ํค
์ฐจ์ด์ 3๏ธโฃ) ์ธ์
vs ์ธ์
์ฟ ํค vs ์ธ์
์คํ ๋ฆฌ์ง
1) ๊ฐ๋
2) ์ธ์ฆ ํ๋ก์ธ์ค
์ธ์
ID
์์ฑ โก๏ธ ์๋ฒ์์ ์ธ์
ID
๋ฅผ ์ฟ ํค๋ก ์ค์ ํด์ ํด๋ผ์ด์ธํธ์ ์ ๋ฌ์ธ์
ID
๋ฅผ ์ฟ ํค์ ํฌํจ์์ผ ์์ฒญ์ธ์
ID
๋ก ์ ์ ๋ก๊ทธ์ธํ ID์ธ์ง ํ์ธ3) ๋จ์
๐ ์ฐธ๊ณ ๐ ์ง๋ ฌํ ๋ฐ ์ญ์ง๋ ฌํ
- ๋คํธ์ํฌ๊ฐ ๊ฐ์ฒด๋ฅผ ์ก์์ ํ๊ธฐ ์ํด์ ๊ฐ์ฒด๋ฅผ ๋ฐ์ดํฐ์คํธ๋ฆผ์ผ๋ก ๋ณํ ํ์
- โ๏ธ ์ง๋ ฌํ
- ๊ฐ์ฒด์ ์ ์ฅ๋ ๋ฐ์ดํฐ๋ฅผ ์คํธ๋ฆผ์ ๋ด๊ธฐ ์ํด ์ฐ์์ ์ธ(serial) ๋ฐ์ดํฐ๋ก ๋ณํ
- โ๏ธ ์ญ์ง๋ ฌํ
- ์คํธ๋ฆผ ๋ฐ์ดํฐ๋ฅผ ๋ค์ ์ฝ์ด์์ ๊ฐ์ฒด๋ก ๋ง๋ฆ
npm install escape-html express express-session
// ์ฌ์ฉ์๊ฐ ๋ณด๋ธ ๊ฐ์ ๋ณด์์ ์ํด escapeํ๊ธฐ ์ํ ๋ชจ๋์
๋๋ค. // ์๋ฅผ ๋ค์ด foo&bar>>foo&bar ๋ก ๋ฐ๊ฟ๋๋ค.
const escapeHtml = require('escape-html')
const express = require('express')
const session = require('express-session')
const app = express()
// ๋ฐ์ข
์ ๋ฐ๋ณด๋ฉ์ฒญ์ด >> SHA256 >>
// 9e8821c8ef4ab43ba09310af54e98caedc13e314efdea720bf513b9b3675faf4 app.use(session({
name: "session-id",
secret:
"9e8821c8ef4ab43ba09310af54e98caedc13e314efdea720bf513b9b3675faf4"
,
resave: false,
saveUninitialized: false
}))
// ๋ฏธ๋ค์จ์ด : auth
const isAuthenticated = (req,res, next) =>{
// ๋ง์ฝ ์ธ์
์ด ์๋ค๋ฉด ๋ค์ ๋ฏธ๋ค์จ์ด๋ก. ๊ทธ๊ฒ ์๋๋ผ๋ฉด. ๋ค์ route๋ก ์ ์ด๊ถ์ ๋๊น๋๋ค.
if (req.session.user) next()
else next('route') }
// ๋ง์ฝ isAuthenticated ํ๋ค๋ฉด logout์ ๋ณด์ฌ์ค๋ค. app.get('/', isAuthenticated, function (req, res) {
res.send(escapeHtml(req.session.user) + '๋ ํ์ํฉ๋๋ค!') })
// ๋ง์ฝ isAuthenticated ํ์ง ์๋ค๋ฉด login์ ๋ณด์ฌ์ค๋ค. app.get('/', function (req, res) {
res.send('<p>๋ก๊ทธ์ธ</p><form action="/login" method="post">' + 'Username: <input name="user"><br>' +
'Password: <input name="pass" type="password"><br>' + '<input type="submit" text="Login"></form>')
})
// ๋ก๊ทธ์ธ์์ฒญ >> ์ธ์
์์ฑ
app.post('/login', express.urlencoded({ extended: false }), function (req, res) {
if(req.body.user === "kundol" && req.body.pass === "1234"){ req.session.regenerate(function (err) {
if (err) next(err)
// input : user ์ ์๋ ๊ฐ์ req.session.user์ ํ ๋น req.session.user = req.body.user
//์ธ์
์์ฑ>>์ฟ ํค๊ฐ ์ค์ >>์ดํ ๋ค์ ๋ฆฌ๋ค์ด๋ ํ
req.session.save(function (err) {
if (err) return next(err)
res.redirect('/')
})
})
}else res.redirect('/')
})
app.listen(3000, () => console.log("server is started :
http://localhost:3000"))
1) ๊ฐ๋
2) ์ธ์ฆ ํ๋ก์ธ์ค
HTTP Header-Authorization/Cookie์
๋ด์ ์๋ฒ์ ์์ฒญ4) ์ฅ์
5) ๋จ์
๐ ์ฐธ๊ณ ๐ SAML (Security Assertion Markup Language)
- ์ธ์ฆ(Authentication)/์ธ๊ฐ(Authorization)
โก๏ธSAMLAssertion
์์ ์ธ์ฆ/๊ถํ ์ ๋ณด- ์์ด๋ดํฐํฐ ๊ณต๊ธ์ ์ฒด(IdP)์์ ์๋น์ค ๊ณต๊ธ์ ์ฒด(SP)๋ก ๊ถํ ์ธ์ฆ ์๊ฒฉ ์ฆ๋ช ์ ์ ๋ฌํ ๋ ์ฌ์ฉ๋๋ XML๊ธฐ๋ฐ ํ์ค ๋ฐ์ดํฐ ํฌ๋งท
- SSO ๊ธฐ๋ฅ ์ ๊ณตํ๊ธฐ ์ํด ์ํฐํ๋ผ์ด์ฆ ์ ํ๋ฆฌ์ผ์ด์ ์์ ์ผ๋ฐ์ ์ผ๋ก ์ฌ์ฉ
- ์ ํ๋ฆฌ์ผ์ด์ ๊ฐ ์ปค๋ฎค๋์ผ์ด์ ์ด ์์ ํ๊ฒ ์ด๋ฃจ์ด์ ธ 1๋ฒ์ ๋์งํธ ์๋ช ์ผ๋ก ๋ชจ๋ ๋ฆฌ์์ค ์ด์ฉ
- ์ธ์ฆ ํ๋ก์ฐ
User
: ์ธ์ฆ ์ํ๋ ์ฌ์ฉ์Indentity Provider(IDP)
: ์ธ์ฆ ์ ๋ณด ์ ๊ณต์Service Provider(SP)
: ์๋น์ค ์ ๊ณต์
๐ ์ฐธ๊ณ ๐ OAuth (Open Authorization)
์ธ์ฆ(Authentication)/์ธ๊ฐ(Authorization)
โก๏ธAccess Token
์์ ๊ถํ ์ ๋ณด- ์ฌ์ฉ์๊ฐ ๋ก๊ทธ์ธ ์๊ฒฉ ์ฆ๋ช ์ ๊ณต์ ํ์ง ์๊ณ , ํ์ฌ ์ ํ๋ฆฌ์ผ์ด์ ์ด ์ฌ์ฉ์ ๋ฐ์ดํฐ์ ์ก์ธ์คํ ์ ์๋๋ก ํ๋ ๊ฐ๋ฐฉํ ์ธ์ฆ ํ์ค
- ์์ ๋ฏธ๋์ด ํ๋ซํผ์ด๋ API ๊ฐ์ ์ธ๋ถ ์๋น์ค์ ๋ฐ์ดํฐ์ ์ก์ธ์ค ํด์ผํ๋ ์ ํ๋ฆฌ์ผ์ด์ ์์ ์ฌ์ฉ
- ์ธ์ฆ ํ๋ก์ฐ
Resource Owner
: ์์ ์์ ์ (User)Client
: ํด๋ผ์ด์ธํธ (ex. 3rd party app)Service Provider
: ์๋น์ค ์ ๊ณต์
-Resource Server
: ์์ ์๋ฒ
-Authorization Server
: ๊ถํ ์๋ฒ
๐ ์ฐธ๊ณ ๐ OIDC (OpenID Connect)
- ์ธ์ฆ(Authentication)/
์ธ๊ฐ(Authorization)
โก๏ธID Token
์์ ์ธ์ฆ ์ ๋ณด- Access Token : Bearer ํ ํฐ ํ์
- ID Toekn : JSON Web Toekn ํ์
(๋๊ฐ ์ธ์ฆํ๋์ง, ๋ฐํ์(issuer) ๋๊ตฌ์ธ์ง ํ์ธ ๊ฐ๋ฅ)- ์ธ์ฆ ํ๋ก์ฐ
npm install express cookie-parser jsonwebtoken cors
// npm install express cookie-parser jsonwebtoken
// ๋ณดํต ์ด๋ฐ ํ ํฐ์ ๊ดํ ๋ด์ฉ์ ๋ฐ๋ก .env ํ์ผ์ ๋์ต๋๋ค.
// ์์ ์ด๊ธฐ ๋๋ฌธ์ ํํ์ผ์ ๋์ต๋๋ค.
// ํ ํฐ์ ์์ฑํ ๋ ์ฌ์ฉ๋๋ ๋น๋ฐํค
// ๋ฐ์ข
์ ๋ฐ๋ณด๋ฉ์ฒญ์ด >> SHA256 >> 9e8821c8ef4ab43ba09310af54e98caedc13e314efdea720bf513b9b3675faf4 const ACCESS_TOKEN_SECRET= "9e8821c8ef4ab43ba09310af54e98caedc13e314efdea720bf513b9b3675faf4" const REFRESH_TOKEN_SECRET= "9e8821c8ef4ab43ba09310af54e98caedc13e314efdea720bf513b9b3675faf4"
const PORT = 12010
//๋ผ์ฐํ
์ค์ ์ ์ฝ๊ฒ, ๋ฏธ๋ค์จ์ด ์ค์ ์ ์ฝ๊ฒ ๋์์ฃผ๋ express ํ๋ ์์ํฌ
const express = require('express');
// ์ฟ ํค ํธ๋ค๋ง์ ์ฝ๊ฒ ํด์ฃผ๋ ๋ชจ๋
const cookieparser = require('cookie-parser');
//jwt์ ๊ดํ ๋ก์ง์ ์ค์ ํ ์ ์๊ฒ ํ๋ ๋ชจ๋.
const jwt = require('jsonwebtoken')
// browser - postman์์ ์์ฒญ์ ํ๊ฒ ๋๋ฉด CORS๊ฐ ๊ฑธ๋ฆฌ๋๋ฐ ์ด๋ฅผ ๊ฐ๋ฅํ๊ฒ ํด์ฃผ๋ ๋ชจ๋.
// CORS์ ์์ธํ ์ค๋ช
์ ํฐ๋์ ํฐ์ - CORS๋ฅผ ์ฐธ๊ณ .
const cors = require('cors')
const app = express();
// ๋ฏธ๋ค์จ์ด๋ฅผ ์ค์
app.use(cors())
app.use(express.json()); app.use(express.urlencoded({ extended: false })); app.use(cookieparser());
// DB์ ์๋ ์ ์ ์ ๋ณด๋ฅผ ํ๋ด๋ด๋ ๊ฐ์ฒด const userInfo = {
username: 'kundol',
password: '1234',
email: 'kundol@gmail.com'
}
//ํ ํฐ์ ๋ง๋ค ๋ ์ฐ๋ ์ ์ ๊ฐ์ฒด const user = {
username: userInfo.username,
email: userInfo.email
}
// ๋๊ฐ์ ํ ํฐ์ ๋ํ ๋ง๋ฃ๊ธฐํ ์ต์
: accessํ ํฐ์ ์งง๊ฒ. refreshํ ํฐ์ ๊ธธ๊ฒ
const accessOpt = {
expiresIn: '10m'
}
const refreshOpt = { expiresIn: '1d'
}
// ์ฟ ํค ์ต์
const cookieOpt = {
httpOnly: true,
sameSite: 'Strict',
secure: true,
maxAge: 24 * 60 * 60 * 1000
}
const isAuthenticated = (req, res, next) =>{ if(!req.headers.authorization){
return next('route') }
let auth = req.headers.authorization
if (auth.startsWith("Bearer ")){
auth = auth.substring(7, auth.length);
}
const user = jwt.verify(auth, ACCESS_TOKEN_SECRET)
//์ธ์ฆ๋ ์ ์ ๊ฐ ์๋ค๋ฉด ๋ค์ ๋ฏธ๋ค์จ์ด๋ก. ๊ทธ๊ฒ ์๋๋ผ๋ฉด ๋ค์ ๋ผ์ฐํ
์ผ๋ก. ์ ์ด๊ถ์ ๋๊ธด๋ค.
if (user) return next()
else return next('route') }
app.get('/', isAuthenticated, function (req, res) { return res.status(200).send("ํ์ฉ๋ ์์ฒญ์
๋๋ค.")
})
app.get('/', (req, res) =>{
return res.status(401).send("ํ์ฉ๋์ง ์์ ์์ฒญ์
๋๋ค.") })
app.post('/login', (req, res) => {
const { username, password } = req.body; console.log(req.body)
console.log(username, password)
if (username === userInfo.username && password ===
userInfo.password) {
const accessToken = jwt.sign(user, ACCESS_TOKEN_SECRET,
accessOpt);
const refreshToken = jwt.sign(user, REFRESH_TOKEN_SECRET,
refreshOpt);
// cookie์๋ refreshํ ํฐ์ ๋ด์ต๋๋ค.
// ์ดํ ์์ฒญ์์ refreshํ ํฐ์ ๊ธฐ๋ฐ์ผ๋ก accesstoken์ ๊ฐฑ์ ๋ฐ์ต๋๋ค.
console.log("jwtํ ํฐ์ด ์์ฑ๋์์ต๋๋ค.")
console.log(refreshToken)
console.log(accessToken)
res.cookie('jwt', refreshToken, cookieOpt);
return res.json({ accessToken, refreshToken}); }
else {
//๋ง์ฝ ์ธ์ฆ์ ํ์ง ์์ ๊ฒฝ์ฐ
return res.status(401).json({message: "์ธ์ฆ๋์ง ์์
์์ฒญ์
๋๋ค."}); }
})
// accessํ ํฐ ์์ฒญ ์ ์ ๋จผ์ refresh ํ ํฐ ์์ฒญ์ ๋จผ์ ํจ. app.post('/refresh', (req, res) => {
console.log("REFRESH์์ฒญ") console.log(req.cookies) if (req.cookies.jwt) {
const refreshToken = req.cookies.jwt; jwt.verify(refreshToken, REFRESH_TOKEN_SECRET, (err, decoded) => {
if (err) {
return res.status(401).json({ message: '์ธ์ฆ๋์ง
์์ ์์ฒญ์
๋๋ค.' }); }else {
console.log(decoded)
const accessToken = jwt.sign(user, ACCESS_TOKEN_SECRET, accessOpt);
return res.json({ accessToken }); }
}) } else {
return res.status(401).json({ message: "์ธ์ฆ๋์ง ์์ ์์ฒญ์
๋๋ค." });
} })
app.listen(PORT, () => {
console.log(`์๋ฒ์์ : http://localhost:${PORT}`); console.log(`๋ก๊ทธ์ธ์์ฒญ : http://localhost:${PORT}/login`); console.log(`refresh์์ฒญ : http://localhost:${PORT}/refresh`);
})
/*
์๋ฒ์์ : http://localhost:12010
๋ก๊ทธ์ธ์์ฒญ : http://localhost:12010/login refresh์์ฒญ : http://localhost:12010/refresh {
"username": "kundol",
"password": "1234",
"email": "kundol@gmail.com"
}
curl -X POST http://localhost:12010/refresh -H 'Content-Type:
application/json' --cookie
"jwt=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VybmFtZSI6Imt1bmRv
bCIsImVtYWlsIjoia3VuZG9sQGdtYWlsLmNvbSIsImlhdCI6MTY3MjI3MzgxNSwiZX
hwIjoxNjcyMzYwMjE1fQ.rAhD3tF11APHaSoxUp1F5DtNUte-5mt8HjawHoVVbns"
*/
npm install express
const express = require('express') const app = express()
const port = 3000
app.get('/', (req, res) => { res.status(401).send('์ธ์ฆ๋์ง ์์ ์์ฒญ์
๋๋ค.')
})
app.listen(port, () => {
console.log(`Example app listening on port ${port}`)
})
GET : ๋ฐ์ดํฐ ์ฝ๊ธฐ
POST : ๋ฐ์ดํฐ ์์ฑ
// ์๋ฅผ ๋ค์ด email: "kundol@naver.com"์ ์์ ํ๋ค๊ณ ํ์ ๋ const obj = {
"id": 2,
"email": "kundol@naver.com",
"first_name": "Janet",
"last_name": "Weaver",
"avatar": "https://reqres.in/img/faces/2-image.jpg"
}
const obj2 = {
"email": "kundol@naver.com"
}
// PUT
const PutRequest = () => { fetch("https://reqres.in/api/users/2", {
headers: {
"Accept": "application/json",
"Content-Type": "application/json"
},
method: "PUT",
body: JSON.stringify(obj)
}).then(res => res.json())
.then(data => console.log(data))
PutRequest();
// PATCH
const PatchRequest = () => {
fetch("https://reqres.in/api/users/2", {
headers: {
};
"Accept": "application/json",
"Content-Type": "application/json"
},
method: "PATCH",
body: JSON.stringify(obj2)
}).then(res => res.json())
.then(data => console.log(data))
PatchRequest();
/* {
id: 2,
email: 'kundol@naver.com',
first_name: 'Janet',
last_name: 'Weaver',
avatar: 'https://reqres.in/img/faces/2-image.jpg',
updatedAt: '2022-12-19T01:13:39.638Z'
}
{ email: 'kundol@naver.com', updatedAt: '2022-12-19T01:13:39.639Z'
}
*/
1) ๊ฐ๋
2) L7 ์ค์์น
๐ ์ฐธ๊ณ ๐ ํฌ์ค์ฒดํฌ
- ์๋ฒ์ ์ ์/๋น์ ์ ์ฌ๋ถ ํ๋ณ
- ์ ์ก ์ฃผ๊ธฐ์ ์ฌ์ ์ก ํ์ ๋ฑ์ ์ค์ ํ ํ ๋ฐ๋ณต์ ์ผ๋ก ์๋ฒ์ ์์ฒญ์ ๋ณด๋
- L4 ๋๋ L7 ์ค์์น์ ์ฌ์ฉ
๐ ์ฐธ๊ณ ๐ ์๋ฒ ์ด์คํ
- ๋ก๋ ๋ฐธ๋ฐ์์ ๋ํ์ ๊ธฐ๋ฅ
- ์๋น์ค๋ฅผ ์์ ์ ์ผ๋ก ์ด์ฉํ๊ธฐ ์ํด์ 2๋ ์ด์์ ์๋ฒ ํ์์
- ์๋ฌ๊ฐ ๋ฐ์ํ์ฌ ์๋ฒ 1๋ ์ข ๋ฃํด๋ ์์ ์ ์ผ๋ก ์ด์ฉ ๋ชฉ์
1) ๊ฐ๋
2) L4 ์ค์์น
1) ๊ฐ๋
2) ๋ผ์ฐํฐ
3) L3 ์ค์์น
1) ๊ฐ๋
2) NIC (Network Interface Card)
3) ๋ฆฌํผํฐ
4) AP (Access Point)
๐ ์ฐธ๊ณ ๐ OSI 7๊ณ์ธต vs TCP/IP 4๊ณ์ธต
- OSI 7๊ณ์ธต : ๋คํธ์ํฌ ์ ์ก์ ๋ฐ์ดํฐ ํ์ค ์ ๋ฆผ
- TCP/IP 4๊ณ์ธต : ์ค์ ์ธํฐ๋ท ํต์ ์ ๋ฐ์ํ ์ธํ ๋ ํ์ค
๐ ์ฐธ๊ณ ๐ ์ ์ LAN
- ๋์ถ์ผ์ด๋ธ, ๊ด์ผ์ด๋ธ ๊ธฐ๋ฐ์ผ๋ก ๋ง๋ค์ด์ง ์ ์ LAN์ ์ด๋ฃจ๋ ์ด๋๋ท์ IEEE802.3 ํ๋กํ ์ฝ์ ๊ธฐ๋ฐ์ผ๋ก ์ ์ด์คํ ํต์ ์ ์ฌ์ฉ
- ๊ด์ญ ํต์ ๋ง ๊ธฐ์ ์๋ ํ์ฉ๋์ง๋ง ์ผ๋ฐ์ ์ผ๋ก ๊ทผ๊ฑฐ๋ฆฌ ํต์ ๋ง ๊ธฐ์
- โ๏ธ IEEE802.3
- ์ฐ๊ฒฐ๋ ์ด๋๋ท์์ ๋ฌผ๋ฆฌ ๊ณ์ธต, ๋ฐ์ดํฐ๋งํฌ ๊ณ์ธต์ ๋งค์ฒด ์ ๊ทผ ์ ์ด๋ฅผ ์ ์ํ๋ Working Group
- ์ด๋๋ทํ๋ ์์ ์ด๋ค ๊ตฌ์กฐ ๊ธฐ๋ฐ์ธ์ง, ์ผ์ด๋ธ์ ์ต๋ ์ ์ก๋, ์ด๋ค ์ผ์ด๋ธ๋ง ๊ฐ๋ฅํ์ง ๋ฑ ์ ํ ๊ท์น
- โ๏ธ ์ ์ด์คํ ํต์ (Full Duplex)
- ์์ชฝ ์ฅ์น๊ฐ ๋์์ ์ก์์ ํ ์ ์๋ ๋ฐฉ์
- ์ก์ ๋ก, ์์ ๋ก ๋๋ ์ ๋ฐ์ดํฐ ์ฃผ๊ณ ๋ฐ์
- ํ๋ ๊ณ ์ ์ด๋๋ท์ ๊ธฐ๋ฐ
- โ๏ธ CSMA/CD (Carrier Sense Multiple Access with Collision Detection)
- ์ถฉ๋ ๊ฐ์ง ๊ธฐ๋ฅ์ ์ฌ์ฉํด ์ถฉ๋ ์ฌ๋ถ ํ์ธ
- IEEE 802.3 LAN์ ์ด๋๋ท ์ ์ก ํ๋กํ ์ฝ์์ ์ฌ์ฉ
- 1๏ธโฃ ํ์ ๊ฐ์ง : ์ก์ ์ ์ ํ์ ์ด ๋น์ด์๋์ง ํ์ธ (Carrier Sense)
- 2๏ธโฃ ๋ฐ์ดํฐ ์ ์ก : ๋น์ด์์ ๊ฒฝ์ฐ ๋คํธ์ํฌ์ ๋ชจ๋ ์ปดํจํฐ๊ฐ ๋ฐ์ดํฐ ์ ์ก์ํด ๋์์ ์ก์ธ์ค ์๋ (Multiple Access)
- 3๏ธโฃ ์ถฉ๋ ๋ฐ์ : ๋์์ ๋ฐ์ดํฐ ์ ์กํ ๊ฒฝ์ฐ ์ถฉ๋ ๋ฐ์ ํ ๋คํธ์ํฌ ์์ ๋ค๋ฅธ ์ปดํจํฐ์๊ฒ ์ถฉ๋ ์๋ฆผ (Collision Detection)
- 4๏ธโฃ ํ์ ๊ฐ์ง: ์ถฉ๋ ์์ ๊ฒฝ์ฐ ์ผ์ ์๊ฐ ๋๊ธฐ ํ ์ฌ์ ์ก
- CSMA๋ฐฉ์ ๋จ๋ง์ ์ฆ๊ฐ์ ๋ฐ๋ผ ๋์ ์ ์ก(์ถฉ๋)ํ ํ๋ฅ ๋์์ง๋ ๋ฌธ์ ์ ๊ฐ์
๐ ์ฐธ๊ณ ๐ ๋ฌด์ LAN
- IEEE802.11 ํ์ค๊ท๊ฒฉ์ ๋ฐ๋ฅด๋ฉฐ ๋ฐ์ด์คํ ํต์ ์ ์ฌ์ฉ
- ๋ฌด์ ๋, wifi ๋ฑ ๋ฌด์ ๊ทผ๊ฑฐ๋ฆฌ ํต์ ๋ง์ ์ํ ์ปดํจํฐ ๋ฌด์ ๋คํธ์ํฌ์ ์ฌ์ฉ๋๋ ๊ธฐ์
- โ๏ธ ๋ฐ์ด์คํ ํต์ (Half Duplex)
- ์์ชฝ ์ฅ์น๋ ์๋ก ํต์ ํ ์ ์์ง๋ง, ๋์์๋ ํต์ X
- ํ ๋ฒ์ ํ ๋ฐฉํฅ๋ง ํต์ ํ๋ ๋ฐฉ์
- ์ฅ์น๊ฐ ์ ํธ๋ฅผ ์์ ํ๊ธฐ ์์ํ๋ฉด, ๋ฐ๋ก ์๋ตํ ์ ์๊ณ ์์ ์ด ์๋ฃ๋ ๋๊น์ง ๋๊ธฐ
- โ๏ธ CSMA/CA (Carrier Sense Multiple Access with Collision Avoidance)
- ์ถฉ๋ ํํผ ๊ธฐ๋ฅ ์ฌ์ฉ
- ์ฅ์น์์ ๋ฐ์ดํฐ ๋ณด๋ด๊ธฐ ์ Carrier ๊ฐ์ง ๋ฑ์ผ๋ก ์ฌ์ ์ ๊ฐ๋ฅํ ์ถฉ๋ ๋ฐฉ์ง
- IEEE 802.11 ๋ฌด์ ๋ ์ ์ก ํ๋กํ ์ฝ์์ ์ฌ์ฉ
- 1๏ธโฃ ํ์ ๊ฐ์ง : ์ก์ ์ ์ ํ์ ์ด ๋น์ด์๋์ง ํ์ธ (Carrier Sense)
- 2๏ธโฃ IFS ๋๊ธฐ : ์ฑ๋์ด idle ํด๋ IFS ๋์ ๋๊ธฐํ์ฌ ์ ์ก ๋ฆ์ถฐ ์ถฉ๋ ํผํจ
- IFS(InterFrame Space) ํ๋ ์๊ฐ ๊ณต๊ฐ
- IFS ์์ผ๋ฉด ํ๋ ์ ์ฐ์ ์์ ๋์
- 3๏ธโฃ Cotention Window ๋๊ธฐ
- Contention Window๋ time-slot์ผ๋ก ๋๋ ์ผ์ ์๊ฐ
- ์ ์กํ ์ค๋น๊ฐ ๋ ๋ ธ๋๋ random ์(0~(2^k-1))๋งํผ ๋๊ธฐ ํ ํ๋ ์ ์ ์ก
- ๋ ธ๋๋ ๋งค time-slot ๋ค์ ์ฑ๋ ๊ฐ์ง
- ํด๋น ์๊ฐ๋์ busy ์ํ๋ฉด ํ์ด๋จธ ์ค์ง ํ idle ์ํ๊ฐ ๋๋ฉด ๋ค์ ํ์ด๋จธ ์์
- ์ถฉ๋ ๊ฐ๋ฅ์ฑ ์์ ๊ฒฝ์ฐ ํผํจ (Collision Avoidcnace)
- 4๏ธโฃ ๋ฐ์ดํฐ ์ ์ก
- ํ๋ ์ ์ ๋๋ก ๋ฐ๊ณ + ACK ์ธ๊ทธ๋จผํธ ๋ฐ์ ๊ฒฝ์ฐ โก๏ธ ์ข ๋ฃ
- ํ๋ ์ ๋ฐ์ง ๋ชปํ ๊ฒฝ์ฐ โก๏ธ k = k + 1 ์ ๊ณผ์ ๋ฐ๋ณต (k๊ฐ ์ ํด์ง Kmax๋ณด๋ค ์ปค์ง๋ฉด ํด๋น ํ๋ ์ ์ ์ก ๋ฒ๋ฆผ)
1) ์์ธ
2) ๋ชจ๋ํฐ๋ง
3) AWS ์คํ ์ค์ผ์ผ๋ง
4) netdata๋ฅผ ์ด์ฉํ ๋ชจ๋ํฐ๋ง
1) ๊ฐ๋
2) ์ํท ๋ธ๋ ์ด์ปค ๋์๊ณผ์
์ํท ๋ธ๋ ์ด์ปค๋ฅผ ์๋น์ค๊ฐ ์ฌ์ด์ ๋ฃ๊ณ ๊ด๋ จ ํจ์๋ค ๋ํ
๋คํธ์ํฌ ์ฅ์ ๋ฅผ ๋ชจ๋ํฐ๋งํ์ฌ ํน์ ์๋น์ค๊ฐ timeou์ผ๋ก ์ค์ ๋ ์๊ฐ ์ด๊ณผํ ๊ฒฝ์ฐ
์ํท ๋ธ๋ ์ด์ปค๊ฐ trip ๋๋ฉฐ ๊ทธ ์ดํ ์ถ๊ฐ์ ์ธ ํธ์ถ์ ๋ฐ์X (fail fast)
3) ์ํท ๋ธ๋ ์ด์ปค ์ํ
4) ๊ตฌํ
1) ๋ถํ์ํ ์ปจํ ์ธ ์ ๊ฑฐ
select *
๋ก ์กฐํํ๋ ์ฟผ๋ฆฌ์์ ์ค์ ๊ธฐ๋ฅ์ด ์ฌ์ฉ๋์ง ์๋ ์นผ๋ผ ๋ชจ๋ ์ ๊ฑฐ2) CDN์ ํตํ ์ปจํ ์ธ ์ ๊ณต
3) ์ปจํ ์ธ ์บ์ฑ
4) ์ปจํ ์ธ ์์ถ
5) ์ปจํ ์ธ ๋ฏธ๋ฆฌ ์ค๋น๋ ์๋ต
1) Uniform-Interface
const express = require('express')
const app = express()
app.get('/good',(req, res) =>{
res.status(200).json({"a" : 1})
})
app.get('/bad',(req, res) =>{
res.setHeader('content-type', 'application/json'); // json()๋ฉ์๋ ์ฐ๊ฒ ๋๋ฉด, application/json ํ์
res.send("ํฐ๋์ด")
})
const server = app.listen(12010, () =>{
console.log("์ค๋๋ ์ฌ๋ฐ๋ CS๊ณต๋ถ์๋ฒ ~ : http://127.0.0.1:12010/good") })
const express = require('express'); const app = express();
const books = [
{ id: 1, title: '์๋ฐ์คํฌ๋ฆฝํธ ํ์คํ MEVN', author: 'ํฐ๋1'}, { id: 2, title: 'CS์ง์๋
ธํธ', author: 'ํฐ๋2'},
{ id: 3, title: '์๋ฐ์คํฌ๋ฆฝํธ ์ด๋๋๋ ๋ฒจ', author: 'ํฐ๋3'},
];
app.get('/books', (req, res) => {
const bookCollection = books.map((book) => ({
...book,
links: [{ rel: 'self', href: `/books/${book.id}` }]
}));
res.status(200).json(bookCollection);
});
app.get('/books/:id', (req, res) => {
const bookId = parseInt(req.params.id);
const book = books.find((book) => book.id === bookId);
if (book) {
book.links = [{ rel: 'self', href: `/books/${book.id}` }]; res.status(200).json(book);
} else {
res.status(404).json({ error: 'Book not found' });
} });
app.listen(12010, () => { console.log('ํฐ๋์ด์ ์ฑ
์๋ฒ ์์ :
http://127.0.0.1:12010/books');
});
{"link":http://kundol.net/todos/{id}, "data":[{...}]}
[ {
"url":
"https://api.github.com/repos/octocat/Hello-World/milestones/1",
"html_url":
"https://github.com/octocat/Hello-World/milestones/v1.0",
"labels_url":
"https://api.github.com/repos/octocat/Hello-World/milestones/1/lab
els",
"id": 1002604,
"node_id": "MDk6TWlsZXN0b25lMTAwMjYwNA==",
"number": 1,
"state": "open",
"title": "v1.0",
"description": "Tracking milestone for version 1.0",
"creator": {
"login": "octocat",
"id": 1,
"node_id": "MDQ6VXNlcjE=",
"avatar_url":
"https://github.com/images/error/octocat_happy.gif",
"gravatar_id": "",
"url": "https://api.github.com/users/octocat",
"html_url": "https://github.com/octocat",
"followers_url":
"https://api.github.com/users/octocat/followers",
"following_url":
"https://api.github.com/users/octocat/following{/other_user}",
"gists_url":
"https://api.github.com/users/octocat/gists{/gist_id}",
"starred_url":
"https://api.github.com/users/octocat/starred{/owner}{/repo}",
"subscriptions_url":
"https://api.github.com/users/octocat/subscriptions",
"organizations_url":
"https://api.github.com/users/octocat/orgs",
"repos_url": "https://api.github.com/users/octocat/repos",
"events_url":
"https://api.github.com/users/octocat/events{/privacy}",
"received_events_url":
"https://api.github.com/users/octocat/received_events",
"type": "User",
"site_admin": false
},
"open_issues": 4,
"closed_issues": 8,
"created_at": "2011-04-10T20:09:31Z",
"updated_at": "2014-03-03T18:58:10Z",
"closed_at": "2013-02-12T13:22:01Z",
"due_on": "2012-10-09T23:39:01Z"
} ]
2) Stateless
3) Cacheable
4) Client-Server ๊ตฌ์กฐ
5) Layered System
app.get('/books')
// ๋ชจ๋ ์ฑ
์ ์กฐํํฉ๋๋ค. app.post('/books/:booksid')
// ์ฑ
์ ์์ฑํฉ๋๋ค. app.put('/books/:booksid')
// ์ฑ
์ ์์ ํฉ๋๋ค. app.get('/books/:booksid')
// ํน์ ์ฑ
์ ์กฐํํฉ๋๋ค. app.put('/users/:userid/books/:booksid') // ์ด๋ค ์ ์ ๊ฐ ํน์ ์ฑ
์ ๋น๋ฆฝ๋๋ค. app.patch('/users/:userid/books/:booksid') // ์ด๋ค ์ ์ ๊ฐ ํน์ ์ฑ
์ ๋น๋ฆฝ๋๋ค.
1) ๋ธ๋ผ์ฐ์ ๊ตฌ์ฑ
2) ๊ณผ์
1) ๊ณผ์
2) DOM ํธ๋ฆฌ ๊ตฌ์ถ
3) CSSOM ํธ๋ฆฌ ๊ตฌ์ถ
DOM ํธ๋ฆฌ์ CSSOM ํธ๋ฆฌ๋ฅผ ์์์ ๋ง๊ฒ ๊ฒฐํฉํ์ฌ ๋ ๋๊ฐ์ฒด (Render Object) ์์ฑ
๋ ๋ ํธ๋ฆฌ๋ ๋ ์ด์์์์ ๊ณต๊ฐ์ ์ฐจ์งํ์ง ์๋ ์์๋ ํฌํจX
๐ ์ฐธ๊ณ ๐
display:none
์visibility:hidden
์ฐจ์ด
display:none
: ๋ ๋ํธ๋ฆฌ์์ ์ญ์ ๋จvisibility:hidden
: ์์๋ ๋ณด์ด์ง ์์ง๋ง, ์ญ์ ๋์ง ์๊ณ ๋ ์ด์์์ ๊ณต๊ฐ ์ฐจ์งํจ
๐ ์ฐธ๊ณ ๐ Renderํธ๋ฆฌ์ DOMํธ๋ฆฌ๋ 1:1 ๋์์ผ๊น
- NO
- DOMํธ๋ฆฌ > ๋ ๋๊ฐ์ฒด > ๋ ๋ํธ๋ฆฌ ๋๋ ๊ณผ์ ์์
display:none
์ผ๋ก ์ฌ๋ผ์ง๋ ๋ ๋ ๊ฐ์ฒด(๋ ธ๋)๋ค์ด ์์ด์ 1:1 ๋์ ์๋จ
๋ฆฌ๋ค์ด๋ ํธ
, ์บ์ฑ
, DNS
, IP ๋ผ์ฐํ
, ARP
, TCP ์ฐ๊ฒฐ ๊ตฌ์ถ
์ ๊ฑฐ์ณ ์ปจํ
์ธ ์์ฒญ, ์๋ตํ๋ TTFB(Time to First Byte)๋ธ๋ผ์ฐ์ ๋ ๋๋ง
๊ณผ์ ์ ๊ฑฐ์ณ ๋ค์ด๋ฒ ํ๋ฉด ๋ํ๋จ๐ ์ฐธ๊ณ ๐ FQDN (Fully Qualified Domain Name)
- ํธ์คํธ์ ๋๋ฉ์ธ์ด ํฉ์ณ์ง ์์ ํ ๋๋ฉ์ธ ์ด๋ฆ
- ํธ์คํธ : www ๋ฑ
- ๋๋ฉ์ธ : naver.com
chrome://net-internals#dns
ipconfig/displaydns
๋ฐ์ ๋ฐ์ดํฐ๋ฅผ ๋ฐํ์ผ๋ก ๋ธ๋ผ์ฐ์ ์์ง์ด ๋ธ๋ผ์ฐ์ ๋ ๋๋ง ๊ณผ์ ์ ๊ฑฐ์ณ ํ๋ฉด์ ๋ง๋ฆ
๐๏ธ ์์ :
๐ ์ฐธ๊ณ ๐
- โ๏ธ