728x90
HTTP 프로토콜
- 우리가 브라우저에서 url을 입력하고 엔터를 누르면 HTT 요청을 보내게 되는데 TCP 3-way handshake과정을 거친다.
- 플래그 정보
- SYN(Synchronize Sequence Number) / 000010
- 연결 설정. Sequence Number를 랜덤으로 설정하여 세션을 연결하는 데 사용하며, 초기에 Sequence Number를 전송한다.
- ACK(Acknowledgement) / 010000
- 응답 확인. 패킷을 받았다는 것을 의미한다.
- Acknowledgement Number 필드가 유효한지를 나타낸다.
- 양단 프로세스가 쉬지 않고 데이터를 전송한다고 가정하면 최초 연결 설정 과정에서 전송되는 첫 번째 세그먼트를 제외한 모든 세그먼트의 ACK 비트는 1로 지정된다고 생각할 수 있다.
- FIN(Finish) / 000001
- 연결 해제. 세션 연결을 종료시킬 때 사용되며, 더 이상 전송할 데이터가 없음을 의미한다.
- SYN(Synchronize Sequence Number) / 000010
TCP 3-way handshake
- TCP 통신을 이용하여 데이터를 전송하기 위해 네트워크 연결을 설정(Connection Establish) 하는 과정
- 양쪽 모두 데이터를 전송할 준비가 되었다는 것을 보장하고, 실제로 데이터 전달이 시작하기 전에 한 쪽이 다른 쪽이 준비되었다는 것을 알 수 있도록 한다.
- 즉, TCP/IP 프로토콜을 이용해서 통신을 하는 응용 프로그램이 데이터를 전송하기 전에 먼저 정확한 전송을 보장하기 위해 상대방 컴퓨터와 사전에 세션을 수립하는 과정을 의미한다.
작동방식
- client는 server와 연결하기 위해 TCP 3-way handshake를 통해 연결을 요청한다.
- client와 server는 모두 서로 연결요청을 할 수 있다. 연결요청을 먼저 시도한 요청자를 client, 연결 요청을 받은 수신자를 server로 보면 된다.
- client는 server와 연결하기 위해 SYN을 보낸다.
- server는 SYN을 받고 client로 받았다는 신호인 ACK와 SYN을 보낸다.
- 접속요청을 받은 server가 요청을 수락했으며, client도 포트를 열어달라는 메시지를 전송한다.
- client는 server로부터 받은 ACK와 SYN을 받고 ACK를 보낸다.
- 마지막으로 client가 수락확인을 보내 연결을 맺는다.
- 이때, 전송할 데이터가 있으면 이 단계에서 데이터를 전송할 수 있다.
TCP 4-way handshake
- 4-Way Handshake은 연결을 해제 (Connecntion Termination)하는 과정이다. 여기서는 FIN 플래그를 이용한다.
작동방식
- client와 server는 모두 서로 연결요청을 할 수 있다. 연결요청을 먼저 시도한 요청자를 client, 연결 요청을 받은 수신자를 server로 보면 된다.
- server와 client가 연결된 상태에서 클라이언트가 연결을 종료한다는 FIN을 보내며 접속을 끊는다.
- server는 FIN을 받고 데이터가 없다는 것을 의미하는 ACK를 보낸다.
- server는 client에게 응답을 보내고 남은 데이터가 있다면 마저 전송을 마친다.
- client는 server에서 ACK를 받은 후에 server가 남은 데이터 처리를 끝내고 FIN 패킷을 보낼때까지 기다린다.
- server는 데이터를 모두 보낸 후, 연결 종료에 합의한다는 의미로 FIN을 client에게 보낸다.
- client는 FIN을 받고 확인했다는 ACK를 server에 보낸다.
HTTP 프로토콜을 이용한 웹서버 개발
1. HTTP 모듈을 선언
- 내장 모듈인 http 모듈을 사용한다.
- 요청과 응답을 처리하는 기능을 제공하는 모듈이다.
const exem = require("http");
2. 서버 객체 생성
- createServer메소드: 서버 객체를 만들어준다. 매개변수로 전달되는 콜백함수에는 매개변수로 req, res를 전달해준다.
- req: http 요청의 정보. url, 메소드(GET, POST 등) 요청 헤더 정보, 바디의 내용이 있다.
- res: http 응답의 정보. 상태코드는 statusCode, 응답헤더, 바디의 내용이 있다.
- res.setHeader: 응답 헤더의 내용을 설정할 수 있다.
- Content-Type: 응답의 내용
- application/json: 응답의 내용을 JSON 형식의 데이터로 전송
- charset=utf-8: 응답의 문자를 인코딩. utf-8로 설정
- res.end: 내용을 응답하고 종료하는 메소드
- 응답하는 내용은 매개변수로 전달하면 된다.
- 매개변수의 내용을 브라우저 내용으로 확인할 수 있다.
- 파비콘 요청을 무시하기
- 브라우저에 요청을 보내면 웹사이트의 아이콘인 파비콘의 url이 자동으로 요청된다. 해당 부분을 무시하는 방법이 있다.
// 파비콘 무시 처리를 헤주자.
if(URL === "/favicon.ico"){
res.end();
return;
}
const server = exem.createServer((req, res)=>{
// statusCode 200 == 성공
res.statusCode = 200;
res.setHeader("Content-Type", "application/json", "charset=utf-8");
// 요청한 URL은 뭐지?
const URL = req.url;
console.log(URL) //브라우저에서 요청한 url의 값이 콘솔로 뜬다.
// /: main 페이지의 경로
// /list: 글의 목록 페이지 혹은 게시판
// /add: 글을 추가하는 페이지
// 파비콘 무시 처리
if(URL === "/favicon.ico"){
res.end();
return;
}
console.log(URL);
switch (URL) {
case "/":
res.end("main page")
break;
case "/list":
res.end("list page")
break;
case "/add":
res.end("add page")
break;
}
})
3. 서버 대기 상태
- listen메서드로 첫 번째 매개변수 exem서버를 대기 상태로 만들어 놓자
server.listen(4000, ()=>{
console.log("서버 잘 열렸음")
})
fs 모듈
- 파일 입출력 처리를 할 때 사용하는 모듈
- 파일을 생성, 삭제, 읽기 쓰기 등의 작업을 할 수 있다.
fs모듈 불러오기
- 내장 모듈이므로, 별도의 라이브러리 없이 바로 불러서 사용 가능하다.
const fs = require("fs");
existsSync_폴더 존재 유무 확인
- 파일이 주어진 경로에 이미 존재하는지 여부를 동기적으로 확인하는데 사용하는 메소드
- ' Sync ' 구문이 있는 메소드는 동기적으로 작동한다.
- 반환값은 true,false를 가진다.
let folder = fs.existsSync("./Test");
console.log(folder);
/*결과
폴더가 있을 경우: true
폴더가 없을 경우: false */
mkdir 또는 mkdirSync_폴더 생성
- mkdir: 폴더를 비동기적으로 생성하는 메소드이다.
- 첫 번째 매개변수: 생성할 폴더의 경로를 입력
- 두 번째 매개변수: 폴더 생성 시 호출할 콜백함수
- 콜백함수의 첫 번째 매개변수: 에러의 내용
- mkdirSync: 폴더를 동기적으로 생성하는 메소드이다.
if (!folder) {
// mkdir: 비동기적으로 실행
fs.mkdir("./Test", (err) => {
if (err) {
console.log(err)
console.log("에러남");
}
else {
console.log("Test 폴더 잘 만들어짐")
}
})
// mkdirSync: 동기적으로 실행
fs.mkdirSync("./Test");
console.log("폴더 잘 만들었음")
}
writeFile 또는 writeFileSync_파일 추가
- writeFile: 파일을 비동기적으로 쓸 수 있는 메소드. 파일에 데이터를 작성할 수 있다.
- 첫 번째 매개변수: 파일의 이름 경로
- 두 번째 메개변수: 파일에 작성할 내용
- 세 번째 매개변수: 콜백함수
- 콜백함수의 매개변수는 에러 내용의 객체를 전달 받는다.
- writeFileSync: 파일을 동기적으로 쓸 수 있는 메소드
// 비동기적으로 들어간다.
fs.writeFile("./Test/temp.txt", "Hello nodejs", (err)=>{
if(err){
console.log(err)
}
else{
console.log("파일이 잘 만들어졌다.")
}
})
// 동기적으로 실행되는 메소드
fs.writeFileSync("./Test/temp.txt", "Hello nodejs")
readFile 또는 readFileSync_파일 내용 읽기
- readFile: 파일을 비동기적으로 읽어주는 메소드.
- 첫 번째 매개변수: 파일의 경로
- 두 번째 매개뱐수: 인코딩의 내용
- 인코딩 내용을 작성하지 않으면 자동으로 null이 출력된다.
- null은 buffer객체로 읽어온다.
- 세 번째 매개변수: 콜백함수
- 콜백함수의 첫 번째 매개변수: 에러의 내용을 객체
- 콜백함수의 두 번째 매개변수: 읽어온 파일의 내용
- readFileSync: 동기적으로 파일을 읽어오는 메소드
- 동기적으로 실행하기 때문에 콜백이 필요없다.
- 메소드의 반환값으로 파일을 읽러온 data가 나온다.
// 비동기적으로 파일을 읽어오는 메소드
fs.readFile("./Test/temp.txt", "utf-8",(err,data)=>{
if(err){
console.log(err);
}
else{
console.log(data);
}
})
// 동기적으로 파일을 읽어오는 메소드
let data = fs.readFileSync("./Test/temp.txt","utf-8");
rm_파일을 제거하는 메소드
- rm: 폴더를 삭제한다.
- 첫 번째 매개변수: 삭제할 폴더의 경로
- 두 번째 매개변수: 옵션 객체를 전달하는데 {recursive : true}
- recursive 키의 값에 따라 true나 false를 전달해주는데 폴더 안의 내용까지 제거할 것인지 결정한다.
- 세 번째 매개변수: 콜백함수
- 콜백함수는 매개변수로 에러 내용의 객체를 전달받는다.
fs.rm("./Test",{recursive : true},(err)=>{
if(err){
console.log("err")
console.log("에러났음")
}
else{
console.log("폴더 잘 삭제함")
}
})
내장 모듈 http & fs를 이용하여 웹 서버 생성
- views 폴더에 'main.html', 'list.html', 'add.html'을 생성하고 코드를 실행한다.
main.html 또는 list.html 또는 add.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">
<!-- main page의 경우 -->
<title>main page</title>
<!-- list page의 경우 -->
<title>list page</title>
<!-- add page의 경우 -->
<title>add page</title>
</head>
<body>
<!-- main page의 경우 -->
<h1>메인 페이지</h1>
<!-- list page의 경우 -->
<h1>리스트 페이지</h1>
<!-- add page의 경우 -->
<h1>추가 페이지</h1>
</body>
</html>
index.js
// 내장모듈 http, fs
const http = require("http");
const fs = require("fs");
const server = http.createServer((req,res)=>{
// createServer 메서드 서버 객체 만들고
// 콜백 함수의 매개변수로 req 요청 내용을 가지고 있는 객체
// res 응답 내용을 가지고 있는 객체를 전달 받는다.
// setHeader: 응답 헤더내용 설정
res.setHeader("Content-Type", "application/json", "charset=utf-8");
// 요청한 url이 뭘까?
const URL = req.url;
// 요청한 url이 파비콘이면 그냥 무시
if(URL === "/favicon/ico"){
res.end();
// end(): 내용을 응답하고 종료하는 메소드
// 응답을 안해주면 클라이언트는 요청을 하고 계속 기다림.
return;}
// 요청한 URL의 내용에 따라서 응답
switch (URL) {
case "/":
fs.readFile("./views/main.html",(err,data)=>{
if(err){
// 에러가 나면 파일을 못 불러왔네?
// 404: 파일을 불러오지 못했어
res.statusCode = 404;
res.end("파일 없어....")}
else{
// 파일 잘 가져왔으면
res.statusCode = 200;
// 전달하는 컨텐츠의 내용은 html 파일의 내용이다.
res.setHeader("Content-Type", "text/html");
res.end(data);}})
break;
case "/list":
fs.readFile("./views/list.html",(err,data)=>{
if(err){
res.statusCode = 404;
res.end("파일 없어!")}
else{
res.statusCode = 200;
res.setHeader("Content-Type", "text/html");
res.end(data)}})
break;
case "/add":
fs.readFile("./views/add.html",(err,data)=>{
if(err){
res.statusCode = 404;
res.end("파일 없어!")}
else{
res.statusCode = 200;
res.setHeader("Content-Type", "text/html");
res.end(data)}})
break;}
});
server.listen(4000, ()=>{
console.log("나 잘 열렸음. 확인하려고 콜백 함수 작성하는 것. 콜백 없어도 돼!")})
npm init
- npm init은 package.json 파일을 만들어준다.
- package.json을 만들 때 속성을 입력하라고 한다.
- package.json
- npm을 통해 설치된 패키지 목록들을 관리하고 프로젝트의 정보 및 기타 실행 스크립트를 작성하는 파일이다.
- 메타데이터 설명을 가지고 있는 json 파일. 초기화 명령어
- 메타데이터: 데이터들을 설명해주는 데이터(속성)
- 예) 책이 한 권 있다고 가정, 제목, 저자, 출판사 등의 책의 정보가 메타데이터.
- 메타데이터: 데이터들을 설명해주는 데이터(속성)
npm init
- 현재 디렉터리에 NPM 기반으로 프로젝트를 생성할 수 있다.
- 패키지 이름, 버전, 설명 등의 정보들을 직접 입력해야 한다.
PS D:\Test> npm init
This utility will walk you through creating a package.json file.
It only covers the most common items, and tries to guess sensible defaults.
See `npm help init` for definitive documentation on these fields
and exactly what they do.
Use `npm install <pkg>` afterwards to install a package and
save it as a dependency in the package.json file.
Press ^C at any time to quit.
package name: (230501) test
version: (1.0.0) 1.0.0
description: test
git repository: test
author: test
license: (ISC) isc
...
npm init -y
- 모든 설정을 기본 값으로 설정하는 명령어이다.
PS D:\Test> npm init -y
Wrote to D:\Test\package.json:
{
"name": "230501",
"version": "1.0.0",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"keywords": [],
"author": "",
"license": "ISC",
"dependencies": {
"mysql2": "^3.2.4"
},
"devDependencies": {},
"description": ""
}
- name: 프로젝트의 이름이다.
- version: 프로젝트의 버전을 정의한다.
- description: 프로젝트의 설명. 문자열로 작성하면 된다.
- keywords: 프로젝트를 검색할 때 참조하는 키워드들을 배열로 전달해주면 된다.
- author: 패키지를 만든사람. 작업자 정보
- license: 패키지 라이선스
- main: 이 값을 작성해주면 패키지를 require 함수로 불러올 때 이 파일을 불러올 수 있다.
- scripts: 우리가 자주 실행할 것 같은 명령어를 작성해두고 npm 명령어로 실행할 수 있다.
- 예) npm run test
"scripts" : {start : "node index4.js"} === npm start == node index4.js
- 예) npm run test
외부 모듈 설치_Mysql2
Mysql2를 사용하는 이유
- mysql 모듈도 있는데 왜 mysql2를 사용하는 것일까?
- mysql 모듈은 콜백 기반이기 때문에 promise 기반으로 사용하기 힘들다.
- mysql2는 promise 기반을 지원하기 때문에 사용하기 편하다.
- 공식문서에서도 mysql2를 사용하라고 권장한다.
외부 모듈 설치받는 방법
- npm 사이트에 접속하여 설치를 원하는 모듈을 검색한다.
- 원하는 모듈을 선택해서 우측의 Install 코드를 복사한다.
- 비주얼 스튜디오 코드로 돌아가 터미널에서 복사한 Install 코드를 붙여넣어 설치를 진행한다.
외부 모듈 설치 명령어
- 모듈을 지정해서 설치하는 방법
// 둘 중 하나를 사용하면 된다.
npm install (외부 모듈의 이름)
npm i (외부 모듈의 이름)
- package.json에 있는 dependencies 내용의 모듈을 다 설치받는 방법
- 모듈을 사용한 작업물을 공유 시, 모듈도 같이 깃 등에 공유할 때는 포함시키지 않는다.
- 모듈을 공유하는건 크기가 크고 시간이 오래걸리기 때문이다.
- 때문에 다른 작업자들이 어떤 모듈을 설치했는지 알기도, 하나하나 찾아서 받기에도 쉽지 않으므로 한꺼번에 내려받는 방법이 편할 것이다.
- 모듈을 사용한 작업물을 공유 시, 모듈도 같이 깃 등에 공유할 때는 포함시키지 않는다.
// 둘 중 하나를 사용하면 된다.
npm install
npm i
package.json에서 dependencies
//package.json
{
"name": "230501",
"version": "1.0.0",
...
"dependencies": {
"mysql2": "^3.2.4"
}
}
- dependencies에서 ' ^3.2.4 '는 mysql2의 버전을 나타낸다. 그런데 버전 앞에 있는 ' ^ '는 무엇을 의미할까?
- ^ : 해당 버전이 없으면 다른 버전을 찾아서 설치 받는다는 내용이다.
- 실제 설치된 버전은 ' package-lock.json '에 있다.
Mysql 연결
Mysql Workbench_커넥션, 스키마 생성
- 워크벤치에서 ' MySQL Connections ' 옆에 있는 ' + ' 버튼을 클릭하여 새로운 커넥션을 만든다.
- 생성 시, 커넥션 이름/유저 이름/ 비밀번호 등의 설정을 확인하여 생성한다.
- 해당 커넥션에 들어가 좌측 카테고리에서 ' Schemas ' 를 눌러 스키마 탭을 연다.
- 스키마 생성: 스키마 탭에서 마우스 오른버튼을 클릭하여 'Create Schemas... '을 클릭한다.
- Name : 원하는 이름을 작성한다.
- Charset/Collation: 원하는 문자인코딩 방식과 정렬방식을 선택한다.
- 현재는 Charset - utf8을, Collation -utf8_bin을 선택한다.
Javascript_모듈 연결, Mysql 연결, 테이블 생성
- 좌측 카테고리에서 스키마에 생성된 테이블을 찾는다.
- 테이블 이름 옆에 뜬 세 번째 아이콘을 선택한다.
- Result Grid에서 null 값에 데이터를 입력한다.
- 현재의 경우, id값은 고유한 값을 가지고 있고, 자동으로 값이 증가함으로 별도의 값을 입력하지 않아도 된다.
PS D:\Test> node index5.js
[
{ id: 1, name: '이름', number: '010-0000-0000', series: '123' },
{ id: 2, name: '내이름', number: '010-1111-1111', series: '456' },
{ id: 3, name: '네이름', number: '010-2222-2222', series: '789' }
]
테이블이 있어
더보기
- TCP 3-way handshake & TCP 4-way handshake
- fs 모듈
728x90
'블록체인_9기 > 💚 Node.js' 카테고리의 다른 글
29강(과제X)_230508_Node.js(MVC 패턴으로 게시판 페이지 제작) (1) | 2023.05.09 |
---|---|
28강_Node.js (express, ejs, mysql2, path로 게시판 만들기) (0) | 2023.05.08 |
27강(과제X)_230502_Nodejs(express, get / post, path, ejs) (0) | 2023.05.03 |
25강(과제X)_230428_Node.js(OSI 전송계층, TCP, UDP, TCP Server, client, Mysql) (0) | 2023.05.01 |
24강(과제X)_230427_nodejs(Nodejs란?, REPL, 런타임 환경, 파일 실행 모드, 모듈, 내장모듈, 내장객체, 웹서버) (0) | 2023.04.28 |