1. 요청과 응답 이해하기
•
클라이언트와 서버는 요청(Req:Request)와 응답(Res:Response)로 구성 되어있으며, 클라이언트로 요청을 보내고 서버에서는 요청의 내용을 읽고 처리한 뒤 클라이언트에 응답을 보낸다.
•
즉 서버에는 요청을 받는 부분과 응답을 보내는 부분이 있어야 한다.
•
요청과 응답은 이벤트 방식이라고 생각
•
클라이언트로부터 요청이 왔을 때 어떤 작업을 수행할지 이벤트 리스너를 미리 등록해야 함.
/server0.js
const http = require('http'); //http 서버가 있어야 웹 브라우저의 요청을 처리할 수 있으므로 http 모듈을 사용
http.createServer((req, res) => {
// 여기에 어떻게 res 할지를 작성을 한다.
});
JavaScript
복사
•
http 서버가 있어야 웹 브라우저의 요청을 처리할 수 있으므로 http 모듈을 사용
•
http 모듈에는 createServer 메서드가 있다.
•
인수로 요청에 대한 콜백 함수를 넣을 수 있으며, 요청이 들어올 때마다 매번 콜백 함수가 실행된다. 따라서 이 콜백 함수에 응답을 적으면 된다.
•
createServer의 콜백 부분을 보면 req와 res 매개변수가 있다.
•
보통 request를 줄여 req라고 표현하고, response를 줄여 res라고 표현합니다.
•
req 객체는 요청에 관한 정보들을, res 객체는 응답에 관한 정보들을 담고 있다.
•
아직은 코드를 실행해도 아무 일도 일어나지 않는다.
•
상단에 주석 넣는 란에 요청에 대한 응답도 넣어주지 않았고 서버와 연결하지도 않았기 때문
•
다음 예제에서 응답을 보내는 부분과 서버에 연결하는 부분을 추가해보겠습니다.
/server1.js
const http = require('http');
http.createServer((req, res) => {
res.writeHead(200, { 'Content-Type': 'text/html; charset=utf-8' });
/*
res.writeHead는 응답에 대한 정보를 기록하는 메서드 :
첫 번째 인수로 성공적인 요청임을 의미하는 200을,
두 번째 인수로 응답에 대한 정보를 보내는데
콘텐츠의 형식이 HTML임을 알리고 있다.
또한 한글 표시를 위해 charset을 utf-8로 지정했다.
이 정보가 기록되는 부분을 헤더(Header)라고 부른다.
*/
res.write('<h1>Hello Node!</h1>');
/*
res.write 메서드의 첫 번째 인수는 클라이언트로 보낼 데이터.
지금은 HTML 모양의 문자열을 보냈지만 버퍼를 보낼 수도 있다.
또한, 여러 번 호출해서 데이터를 여러 개 보내도 된다.
데이터가 기록되는 부분을 본문(Body)이라고 부른다.
*/
res.end('<p>Hello Server!</p>');
/*
- res.end는 응답을 종료하는 메서드
만약 인수가 있다면 그 데이터도 클라이언트로 보내고 응답을 종료
*/
})
.listen(8080, () => { // 서버 연결
/*
createServer 매서드 뒤에 listen메서드를 붙이고
클라이언트에 공개할 포트 번호와 포트 연결 완료 후 실행될 콜백 함수를 넣는다.
이제 이 파일을 실행하면 서버는 8080 포트에서 요청이 오기를 기다린다.
*/
console.log('8080번 포트에서 서버 대기 중입니다!');
});
JavaScript
복사
•
상단의 코드를 넣고 node server1를 입력하여 파일을 실행한다.
•
실행화면
•
•
재 실습시 포트 충돌날 수 있으니 한번 수정할 것
•
res 객체에는 res.writeHead와 res.write, res.end
•
위의 예제는 res.write에서 <h1>Hello Node!</h1> 문자열을, res.end에서 <p>Hello Server!</p> 문자열을 클라이언트로 보낸 후 응답이 종료함.
•
브라우저는 응답 내용을 받아서 렌더링한다.
HTTP 상태 코드
•
200이나 500과 같은 숫자는 HTTP 상태 코드
•
res.writeHead에 첫 번째 인수로 상태 코드를 넣었는데, 브라우저는 서버에서 보내주는 상태 코드를 보고 요청이 성공했는지 실패했는지를 판단한다.
•
2XX: 성공을 알리는 상태 코드입니다. 대표적으로 200(성공), 201(작성됨)이 많이 사용됩니다.
•
3XX: 리다이렉션(다른 페이지로 이동)을 알리는 상태 코드입니다. 어떤 주소를 입력했는데 다른 주소의 페이지로 넘어갈 때 이 코드가 사용됩니다. 대표적으로 301(영구 이동), 302(임시 이동)가 있습니다. 304(수정되지 않음)는 요청의 응답으로 캐시를 사용했다는 뜻입니다.
•
4XX: 요청 오류를 나타냅니다. 요청 자체에 오류가 있을 때 표시됩니다. 대표적으로 400(잘못된 요청), 401(권한 없음), 403(금지됨), 404(찾을 수 없음)가 있습니다.
•
5XX: 서버 오류를 나타냅니다. 요청은 제대로 왔지만 서버에 오류가 생겼을 때 발생합니다. 이 오류가 뜨지 않게 주의해서 프로그래밍해야 합니다. 이 오류를 res.riteHead로 클라이언트에 직접 보내는 경우는 거의 없고, 예기치 못한 에러 발생 시 서버가 알아서 5XX대 코드를 보냅니다. 500(내부 서버 오류), 502(불량 게이트웨이), 503(서비스를 사용할 수 없음)이 자주 사용됩니다.
Https
•
https 모듈은 웹 서버에 SSL 암호화를 추가한다.
•
GET이나 POST 요청을 할 때 오가는 데이터를 암호화해서 중간에 다른 사람이 요청을 가로채더라도 내용을 확인할 수 없게 한다.
•
요즘은 로그인이나 결제가 필요한 창에서 https 적용이 필수가 되는 추세
•
상단의 서버에 암호화를 적용하려면 https 모듈을 사용해야 한다.
•
하지만 https는 아무나 사용할 수 있는 것이 아니다.
•
암호화를 적용하는 만큼, 그것을 인증해줄 수 있는 기관도 필요하다.
•
인증서는 인증 기관에서 구입해야 하며, Let’s Encrypt 같은 기관에서 무료로 발급해주기도 한다.
/server2.js
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번 포트에서 서버 대기 중입니다!');
});
JavaScript
복사
•
다른 것은 거의 비슷하지만 createServer 메서드가 인수를 두 개 받는다.
•
두 번째 인수는 http 모듈과 같이 서버 로직이고, 첫 번째 인수는 인증서에 관련된 옵션 객체이다.
•
인증서를 구입하면 pem이나 crt, 또는 key 확장자를 가진 파일들을 제공한다.
•
파일들을 fs.readFileSync 메서드로 읽어서 cert, key, ca 옵션에 알맞게 넣으면 된다.
•
실제 서버에서는 80 포트 대신 443 포트를 사용하면 된다.
Http2
•
노드의 http2 모듈은 SSL 암호화와 더불어 최신 HTTP 프로토콜인 http/2를 사용할 수 있게 한다.
•
http/2는 요청 및 응답 방식이 기존 http/1.1보다 개선되어 훨씬 효율적으로 요청을 보냅니다. http/2를 사용하면 웹의 속도도 많이 개선된다.
•
그림을 보면 http/1.1과 http/2의 차이를 확연하게 느낄 수 있다.
•
실제로는 http/1.1도 파이프라인이라는 기술을 적용하므로 이렇게 큰 차이는 나지 않는다.
•
하지만 http/2가 훨씬 효율적인 것만은 분명합니다.
/server3.js
const http2 = require('http2');
const fs = require('fs');
http2.createSecureServer({
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번 포트에서 서버 대기 중입니다!');
});
JavaScript
복사
•
https 모듈과 거의 유사하다.
•
https 모듈을 http2로, createServer 메서드를 createSecureServer 메서드로 바꾸면 된다.