http 모듈로 서버 만들기
4.1 요청과 응답 이해하기
1
2
3
4
5
6
7
8
9
10
11
12
13
- req : 요청에 관한 정보
- res : 응답에 관한 정보.
- .writeHead : 헤더. 응답에 대한 정보를 기록하는 메서드.
- 첫번째 인수 : 코드
- 두번째 인수 : 응답에 대한 정보를 알림.
- .write : 본문(Body)
- 첫번째 인수 - 클라이언트로 보낼 데이터. 여러번 호출해서 데이터를 여러개 보내도 됨.
- .end : 응답을 종료함. 여기에도 데이터를 넣어서 보낼 수 있음.
- 서버가 실행되면, 해당 포트번호에서 요청이 오기를 기다림
- listen 메소드 : 포트번호와 콜백함수를 넣음.
- 이벤트 리스너 : 서버에 이벤트리스너를 등록할 수 있음. ex) server.on('listening', () => {}) 으로 함.
- 'listening' : 연결됐을때 발생함. listen 메소드의 콜백함수 대신에 사용해도 됨.
- 'error' : 서버에 에러가 발생했을 때 발생.
4.1 기타
1
2
3
4
5
6
7
8
- 코드
- 2xx : 성공
- 3xx : 리다이렉션
- 4xx : 요청 오류
- 5xx : 서버오류
- 포트번호 : 80번을 사용하면 주소에서 포트를 생략할 수 있음. https 일경우 443번
- 실제로 배포할 땐 80번 혹흥 443번 포트를 사용
- 응답은 무조건 보내야한다. 아니면 클라이언트는 하염없이 기다리게 됨.
4.2 REST 와 라우팅 사용하기
1
2
3
4
5
6
7
8
9
10
11
12
13
14
- REST : REpresentational State Transfer. 서버의 자원을 정의하고 자원에 대한 주소를 지정하는 방법. 일종의 약속
- 주소뿐만 아니라 GET, POST, PUT, PATCH, DELETE, OPTIONS 등의 메서드와 함께 사용됨.
- GET : 자원을 가져올 때. 요청의 본문에 데이터를 넣지 않음. 쿼리 데이터로 보냄.
- 브라우저에서 캐싱할 수 있으므로 같은 주소로 보낼때 성능이 좋아짐.
- post : 자원을 등록할 때. 요청의 본문에 새로 등록할 데이터를 넣어보냄
- PUT : 서버의 자원을 요청에 들어있는 자원으로 치환할때 사용. 본문에 데이터를 넣음
- PATCH : 서버의 자원의 일부만 수정하고자할 때 사용. 본문에 데이터를 넣음
- DELETE : 서버의 자원을 삭제하고자 할 때 사용. 데이터를 넣지 않음
- OPTIONS : 요청을 하기 전에 통신 옵션을 설명하기 위해 사용.
- 만약 로그인 같은 애매한 동작이 있다면 그냥 POST 하면 된다.
- 이렇게 REST 방식으로 하게 되면, 클라이언트에 구애받지 않고 사용할 수 있어서 좋다.
- RESTful 서버구조
HTTP 메서드 | 주소 | 역할 |
---|---|---|
GET | / | restFront.html 파일 제공 |
GET | /about | about.html 파일 제공 |
GET | /users | 사용자 목록 제공 |
GET | 기타 | 기타정적파일제공 |
POST | /user | 사용자 등록 |
PUT | /user/사용자id | 해당 id의 사용자 수정 |
DELETE | /user/사용자id | 해당 id의 사용자 제거\ |
1
2
3
4
5
6
7
8
9
- 라우팅
- req.method 로 GET, POST 등 HTTP 요청 메소드를 구분할 수 있음
- req.url 로 요청한 url을 구분할 수 있음.
- req.on('data', callback)
- 요청의 본문에 들어있는 데이터를 꺼내는 작업.
- req, res 는 내부적으로 스트림으로 되어있기에 요청/응답의 데이터가 스트림 형식으로 전달.
- 또 .on 에서 알수 있듯이 이벤트도 달려있음.
- 이때 받은 데이터는 문자열이므로 JSON 형식으로 만드는 JSON.parse 과정이 필요하다.
4.2 기타
1
- res.end 를 한다고 함수가 끝나지 않는다. 따라서 중간에 끝내야할땐 return res.end() 를 한다.
4.3 쿠키와 세션 이해하기
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
- 클라이언트가 누구인지 구분하기위해, 서버는 응답을 할 때 쿠키를 생성하여 같이 보냄.
- 쿠키는 유효기간이 있으며, 단순한 키-값 쌍임.
- 서버로부터 쿠키가 오면 브라우저는 저장해뒀다가 다음에 요청을 보낼때 쿠키도 함께 보냄.
- 서버는 동봉된 쿠키를 보고 누구인지 파악함.
- req.headers.cookie 에 쿠키가 들어있음.
- res.writeHead(200, {'Set-Cookie':'mycookie=test'; Expires= ${expires.toGMTString()}; HttpOnly; Path=/`,});
- 쿠키 작성해서 보내는 법은 이렇게. 옵션사이는 ; 로 구분
- Expires 옵션으로 언제 삭제할지 설정가능. 기본은 클라이언트가 종료될때까지.
- HttpOnly 옵션 : 자바스크립트에서 접근할 수 없도록 함.
- Path=URL : 쿠키가 전송될 URL을 특정. 기본은 /. 모든 URL에서 전송가능.
- Max-age=초 : 날짜대신 초를 입력할 수 있음.
- Secure : HTTPS 일 경우에만 쿠키를 전송함.
- Domain=도메인명 : 쿠키가 전송될 도메인을 특정
- 세션 : 서버에 사용자 정보를 저장하고, 클라이언트와는 세션 아이디로만 소통함.
- 쿠키에 세션 아이디를 저장하고, 그 세션 아이디로 서버에 있는 정보를 접근하는 것.
- 꼭 쿠키를 쓰지 않아도 되는데, 대부분은 쿠키가 간단해서 쿠키를 쓴다. 이를 세션 쿠키라고 함.
4.3 기타
1
2
3
4
- url 모듈
- url.parse(req.url) : 요청 url을 파스함
- qs.parse(query) : 쿼리를 파스하여 JSON 형태로 바꿔줌.
- encodeURIComponent() : 헤더에는 한글을 설정할 수 없으므로, 인코딩하는 메소드
4.4 https와 http2
1
2
3
4
- https : 웹 서버에 SSL 암호화를 추가합니다.
- GET이나 POST 요청을 할 때 오가는 데이터를 암호화해서 중간에 다른 사람이 요청을 가로채더라도 내용을 확인할 수 없게함.
- 인증서를 인증기관에서 구입해야 사용가능.(Let's Encrypt 같은 기관에서 무료로 발급)
- 인증서가 있다면 다음과 같이
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
const https = require("https");
const fs = require("fs");
https
.createServer(
{
cert: fs.readFileSync("도메인 인증서 경로"),
key: fs.readFileSync("도메인 비밀키 경로"),
ca: [
fs.readFileSync("상위 인증서 경로"),
fs.readFileSync("상위 인증서 경로"),
],
},
(req, res) => {
res.writeHead(200, { "Content-Type": "text/html; charset=utf-8" });
res.write("<h1>Hello Node!</h1>");
res.end("<p>Hello Server!</p>");
}
)
.listen(443, () => {
console.log("443번 포트에서 서버 대기 중입니다!");
});
1
2
- http2 : SSL 암호화와 더불어 최신 HTTP 프로토콜인 http/2 를 사용할 수 있게함.
- 기존 1.1 보다 요청 및 응답 방식이 개선되고, 속도고 많이 개선 됨.
4.5 cluster
1
2
3
4
5
6
7
8
9
- cluster 모듈 : 기본적으로 싱글 프로세스로 동작하는 노드가 CPU 코어를 모두 사용할 수 잇도록 하는 모듈. 포트를 공유하는 노드 프로세스를 여러 개 둘 수 있어서, 요청이 많이 들어왔을 때 병렬로 실행된 서버의 개수만큼 요청이 분산되게 함.
-> 스레드가 아니라 프로세스임.
- 단점 : 메모리를 공유하지 못함. / 세션을 메모리에 저장하는 경우 문제가 됨. -> 레디스로 해결
- 마스터 프로세스 : 요청이 들어오면, 만들어진 워커 프로세스에 요청을 분배함.
- 워커 프로세스 : 실질적인 일을 하는 프로세스
- 실무에서는 pm2 등의 모듈로 cluster를 처리함.