5장에서 다룰 내용
- 요청 데이터의 수집과 처리
- curl 명령을 통한 POST 요청 제출
- 기본 라우트를 가지는 애플리케이션 제작
5.1. 서버 코드의 수정
다음은 4장 코드를 수정 작업한 것이다.
const port = 3000,
http = require("http"),
httpStatus = require("http-status-codes"),
app = http.createServer();
app.on("request", (req,res) => {
res.writeHead(httpStatus.OK, {
"Content-Type" : "text/html"
});
let responseMessage = "<h1>This will slow on the screen.</h1>";
res.end(responseMessage);
});
app.listen(port);
console.log(`The server has started and is listening on port number: ${port}`);
- 다음 코드는 콜백 함수가 있는 server 객체를 가지고 있으며, 콜백 함수는 요청이 서버로 들어올 때마다 실행된다.
즉, 요청을 받을 때 서버는 요청 및 응답 객체를 실행할 함수가 들어 있는 코드에 전달한다.
- 우리는 수신하는 요청의 종류에 따라 콘텐츠를 변경시키는 것을 원할 것이다. 이를 위해 첫 번째 단계는 요청 헤더에서 어떤 HTTP 메소드와 어떤 URL을 사용할지 정하는 것이다.
5.2. 요청 데이터의 분석
- 각 요청 객체는 rul 속성을 가지고 있으며, req.url 속성을 통해 클라이언트가 어떤 URL 요청을 하고 있는지 파악할 수 있다. 다음을 app.on("request") 을 실행해보자.
console.log(req.method);
console.log(req.url);
console.log(req.headers);
요청의 일부 개체는 다른 중첩 개체를 포함할 수 있기 때문에, JSON.stringify를 사용해 읽기 쉬운 문자열로 변환할 수 있다. (이 함수는 자바스크립트 객체를 인수로 사용해, 문자열을 반환한다.) 다음과 같이 코드를 변경하면 request 메소드를 출려력할 수 있다.
// getJSONsrting 함수
const getJSONString = (obj) => {
return JSON.stringify(obj, null, 2);
};
// 출력
console.log(`Method: ${getJSONString(req.method)}`);
console.log(`URL: ${getJSONString(req.url)}`);
console.log(`Headers: ${getJSONString(req.headers)}`);
우리가 다룰 대부분의 요청은 GET 요청이다.
POST 요청을 한다면, 서버는 송신된 데이터를 처리하고 사용자에게 응답하여 데이터가 수신됐음을 알려야 한다.
- 누군가가 서버에 POST 요청을 하는 경우, POST의 내용(=서버에 전송되는 데이터)의 양을 알지 못하기 때문에, 데이터 청크를 통해서 http 서버로 들어오게 된다.
! 데이터 청크를 통해 스트리밍이 가능하다. 서버에 대량의 정보가 모두 도착하기를 바라는 대신, ReadableStream 라이브러리를 사용해 정보가 도착했을 때 해당 정보의 일부를 가지고 작업할 수 있다.
- req.on("data"): 특정 요청에 대한 데이터를 수신할 때 발생한다.
이 이벤트 핸들러 외부에서 새로운 배열 body를 정의하고, 서버에 도착할 때 순차적으로 데이터 청크를 추가해야 한다.
- 데이터 포스팅
- 클라이언트에서 서버로 포스팅한다.
- 데이터는 여러 가지 관리 가능한 청크 형태로 전송된다.
- 버퍼 객체로 서버는 각 데이터 청크를 수신한다. 수신된 데이터 청크는 서로 붙여 모아야 한다.
- 서버는 모은 데이터들을 원래의 형태로 만들고 클라이언트에 응답한다.
- 클라이언트는 데이터를 포스팅한 요청에 대한 결과를 돌려받는다.
app.on("request", (req,res) => {
// 배열 생성
var body = [];
// 데이터 송신
req.on("data", (bodyDate) => {
body.push(bodyDate);
});
// 데이터 변환 및 출력
req.on("end", () => {
body = Buffer.concat(body).toString();
console.log(`Request Body Contents: ${body}`);
});
console.log(`Method: ${getJSONString(req.method)}`);
console.log(`URL: ${getJSONString(req.url)}`);
console.log(`Headers: ${getJSONString(req.headers)}`);
res.writeHead(httpStatus.OK, {
"Content-Type" : "text/html"
});
let responseMessage = "<h1>This will slow on the screen.</h1>";
res.end(responseMessage);
});
app.listen(port);
console.log(`The server has started and is listening on port number: ${port}`);
- app.on("request") 에 위의 새로운 요청 이벤트 핸들러를 추가해, 들어오는 데이터를 읽는다.
- 배열은 body로 만들어지고 참조된다. 수신된 데이터는 body 배열에 추가된다. 데이터 전송이 완료되면, 세 번째 콜백 함수가 실행된다.
- 마지막으로 body 배열을 텍스트 문자열로 변경하고 요청 내용을 콘솔에 출력한다.
! 데이터 제출을 위한 폼을 만들지 않았기 때문에, curl 명령을 사용해 확인한다.
- curl: 서버에 브라우저를 대신해서 요청을 보낼 수 있는 간단한 방법. 다양한 플래그 옵션을 사용할 수 있다.
- -d(--date): POST 방식으로 요청을 서버로 보내는 플래그.
curl -d "username=Jon&password=secret" http://localhost:3000
5.3. 웹 애플리케이션에 라우트 붙이기
- 라우트: 특정 URL을 위한 요청에 어떻게 애플리케이션에 응답해야 하는지 정의하는 방식.
라우트는 애플리케이션 로직에서 타깃이 될 수 있으며, 클라이언트로 보내는 정보를 특정 지을 수 있게 된다. 라우트를 만나는 것은 통합 애플리케이션 환경 구축에 꼭 필요하다.
const routeResponseMap = {
"/info" : "<h1>Info Page</h1>",
"/contact" : "<h1>Contact Us</h1>",
"/about" : "<h1>Learn More about Us.</h1>",
"/hello" : "<h1>Say hello by emailing us here</h1>",
"/error" : "<h1>Sorry the page you are looking for is not here</h1>"
};
const port = 3000,
http = require("http"),
httpStatus = require("http-status-codes"),
app = http.createServer((request, response) => {
response.writeHead(httpStatus.OK, {
"Content-Type" : "text/html"
});
if (routeResponseMap[request.url]) {
response.end(routeResponseMap[request.url]);
} else {
setTimeout(() => {
response.end("<h1>Welcome!</h1>");
}, 2000);
}
});
app.listen(port);
console.log(`The server has started and is listening on port number: ${port}`);
- routeResposeMap 이라고 하는 응답을 위한 라우트를 생성한다.
- 요청 URL이 위에 있는 내용들과 일치하는지 체크하고, 그에 해당하는 헤더를 응답으로 보낸다.
이 추가 코드로 각기 다른 URL에 따라 다른 콘텐츠로 응답을 줄 수 있다.
다음은 타이머를 건 라우트이다.
setTimeout(() => response.end(routeResponseMap[request.url]), 2000);
다음을 실행해보면 페이지 로딩에 걸리는 시간이 2초 정도 늘어났음을 알 수 있다.
명심할 점은 애플리케이션이 커질수록 웹 페이지의 응답 시간은 자연적으로 느려진다는 것이다.
5.4. 요약
1) 요청 콘텐츠에 따라 포스팅된 데이터를 처리할 수 있다.
2) 타킷 URL을 베이스로 요청 콘텐츠를 분리할 수 있다.
라우트를 작성하면 애플리케이션의 처리 로직이 구성된다. 애플리케이션이 확장됨에 따라 라우트 또한 확장되며, 전달할 수 있는 유형의 콘텐츠도 확장된다.
'교재 정리 > Node.js' 카테고리의 다른 글
Lesson 6. 라우트와 외부 파일 (0) | 2024.05.22 |
---|---|
Lesson 4. Node.js에서 웹 서버 만들기 (0) | 2024.05.17 |
Lesson 03. Node.js 모듈 생성 (0) | 2024.05.16 |
Lesson 02. Node.js 애플리케이션 실행 (0) | 2024.05.16 |
Lesson 0. Node.js 설정과 Javascript 엔진 설치 (0) | 2024.05.14 |