9월 8일(수) Web Server 기초 (HTTP 트랜잭션 해부)

남이섬·2021년 9월 8일
0

요청

HTTP Methods / CRUD

GET / READ
POST / CREATE
DELETE / DELETE
PUT / UPDATE
OPTIONS / -
PATCH / UPDATE

OPTIONS

  • preflight reqest
  • CORS를 처리하기위한 아이

응답

HTTP Status Code

200 / 성공
300 / 리디렉션(다른 경로 이동)
400 / 클라이언트 잘못
500 / 서버 잘못

REST api
http 메소드를 목적에 맞게 적절한 naming convention을 따라서
HTTP API를 만드는 방법론

HTTP message

GET은 query parameter를 사용
POST, PUT, PATH는 body에 내용을 쓴다

content-Type 주고 받는 body의 형태

HTTP 트랜잭션 해부

transaction - 처리(과정) / 주고받는 (요청/응답)메세지

모든 node 웹 서버 애플리케이션은 웹 서버 객체를 만들어야 합니다. 이 때 createServer를 이용합니다.

const http = require('http');
const server = http.createServer((request, response) => {
  // 여기서 작업이 진행됩니다!
});

위와 같이 코드 작성시 서버를 만들 수 있다

요청을 실제로 처리하려면 listen 메서드가 server 객체에서 호출되어야 합니다. 대부분은 서버가 사용하고자 하는 포트 번호를 listen에 전달하기만 하면 됩니다. 몇 가지 다른 옵션도 있으므로 API 문서를 참고하세요.

const http = require('http');
const server = http.createServer((request, response) => {
  // 여기서 작업이 진행됩니다!
});
sever.listen(5000)

즉, 요청을 처리하기 위해선 listen 메서드를 사용해야한다

postman을 사용하여 (http://localhost:5000)을 GET으로 호출하면 읽어 올 수 있다

메서드, url, 헤더

GET/southbig/messeages
Content-Type: application/json

메서드 = GET
url = southbig/messeages
header = Content-Type: application/json

요청을 처리할 때, 우선은 메서드와 URL을 확인한 후 이와 관련된 적절한 작업을 실행하려고 할 것입니다. Node가 request 객체에 유용한 프로퍼티를 넣어두었으므로 이 작업은 비교적 쉽게 할 수 있습니다.

const { method, url } = request;

즉, request 객체를 통하여 method와 url을 받아올 수 있다

주의: request 객체는 IncomingMessage의 인스턴스입니다.

여기서 method는 항상 일반적인 HTTP 메서드/동사가 될 것입니다. url은 전체 URL에서 서버, 프로토콜, 포트를 제외한 것으로, 세 번째 슬래시 이후의 나머지 전부라고 볼 수 있습니다.

header

const { headers } = request;
const userAgent = headers['content-type'];

postman에서 메서드 POST로 json현태로 요청을 보내면 확인 할 수 있다
(header의 content-type 부분의 application/json이 호출 된다)

ex)

const http = require('http');
const server = http.createServer((request, response) => {
consol.log(method, url, header[content-type'])
});
sever.listen(5000)

consol.log 값 = POST /hello/world application/json

HTTP 라우팅(routing) - 메소드와 url을 기준으로 기능을 나눠서 구현하는 것

요청바디

POSTPUT 요청을 받을 때 애플리케이션에 요청 바디는 중요할 것입니다. 요청 헤더에 접근하는 것보다 바디 데이터를 받는 것은 좀 더 어렵습니다. 핸들러에 전달된 request 객체ReadableStream 인터페이스를 구현하고 있습니다. 이 스트림에 이벤트 리스너를 등록하거나 다른 스트림에 파이프로 연결할 수 있습니다. 스트림'data''end' 이벤트에 이벤트 리스너를 등록해서 데이터를 받을 수 있습니다.

각 'data' 이벤트에서 발생시킨 청크는 Buffer입니다. 이 청크가 문자열 데이터라는 것을 알고 있다면 이 데이터를 배열에 수집한 다음 'end' 이벤트에서 이어 붙인 다음 문자열로 만드는 것이 가장 좋습니다.

on('data', ...)

  • 요청에서 데이터가 도착했을때
  • 두번째 인자인 콜백함수 첫번째 인자로 chunk가 들어 온다
  • 모든 데이터가 한번에 오지 않기 때문에 (buffer가 여러번 생길 수 있기 때문에)on(data)부분은 여러번 불릴 수 있다

네트워크메세지는 buffer의 형태로 온다

위 형식으로 데이터가 싸이게 되며

on('end', ...)

  • 요청에서 데이터가 다 전달 됐을때
  • 최종 단계에서 딱 한번만 불린다

스트림

  • 물줄기
  • 즉, 데이터가 지나가는 곳

buffer

  • 스트림을 지나가는 데이터

chunk

  • 덩어리, 조각
  • 스트림을 지나는 어떤 데이터가 Buffer로 전달이 되는데 그것을 청크라고 이름으로 붙인 아이
  • consol.leg(chunk)를 하게 되면 값은 Buffer가 나온다, Buffer16진수 조합으로 되어있다, 16진수의 조합으로 된 buffer들을 한 곳에 모아 두고 on('end', ...)를 이용하여 변환 시켜 준다
let body = [];
request.on('data', (chunk) => {
  body.push(chunk);
}).on('end', () => {
  body = Buffer.concat(body).toString();
  // 여기서 `body`에 전체 요청 바디가 문자열로 담겨있습니다.
});

Buffer

let body = [];
request.on('data', (chunk) => {
console.log(chunk) => chunk <Buffer 41 41 41>
  body.push(chunk);
console.log(body) => body [ <Buffer 41 41 41> ]
}).on('end', () => {
  body1 = Buffer.concat(body)
console.log(body1) => body1 <Buffer 41 41 41>
  // 여기서 `body`에 전체 요청 바디가 문자열로 담겨있습니다.
});

즉, chunk = <Buffer 41 41 41>
body에 chunk를 담고
Buffer와 body 배열을 합치면 <Buffer 41 41 41> 원래 청크 그대로가 나온다
거기서 toString()을 해주면 문자열이되는데

처음 chunk(<Buffer 41 41 41>) 여기에 toString을 해줘도 문자열이 된다

console.log(Buffer)

Buffer [Function: Buffer] {
  poolSize: 8192,
  from: [Function: from],
  of: [Function: of],
  alloc: [Function: alloc],
  allocUnsafe: [Function: allocUnsafe],
  allocUnsafeSlow: [Function: allocUnsafeSlow],
  isBuffer: [Function: isBuffer],
  compare: [Function: compare],
  isEncoding: [Function: isEncoding],
  concat: [Function: concat],
  byteLength: [Function: byteLength],
  [Symbol(kIsEncodingSymbol)]: [Function: isEncoding]

추후 Buffer에 대하여 추가적으로 알게 되면 정리해 보겠다

HTTP 상태 코드

따로 설정하지 않으면 응답의 HTTP 상태 코드는 항상 200입니다. 물론 모든 HTTP 응답이 이를 보장하는 것은 아니고 어떤 경우에는 다른 상태 코드를 보내기를 원할 것입니다. 상태 코드를 변경하려면 statusCode 프로퍼티를 설정해야 합니다.

response.statusCode = 404; // 클라이언트에게 리소스를 찾을 수 없다고 알려줍니다.

응답 헤더 설정

편리한 setHeader 메서드로 헤더를 설정

response.setHeader('Content-Type', 'application/json');
response.setHeader('X-Powered-By', 'bacon');

응답에 헤더를 설정할 때 헤더 이름의 대소문자는 중요하지 않습니다. 헤더를 여러 번 설정한다면 마지막에 설정한 값을 보낼 것입니다.

명시적인 헤더 데이터 전송

지금까지 설명한 헤더와 상태 코드를 설정하는 메서드는 "암묵적인 헤더"를 사용하고 있다고 가정합니다. 이는 바디 데이터를 보내기 전 적절한 순간에 헤더를 보내는 일을 노드에 의존하고 있다는 의미입니다.

원한다면 명시적으로 응답 스트림에 헤더를 작성할 수 있습니다. 헤더를 작성하는 writeHead 메서드가 있습니다. 이 메서드는 스트림에 상태 코드와 헤더를 작성합니다.

writeHead 메소드를 사용하여 뒤의 코드를 같이 쓸 수 있다

response.writeHead(200, {
  'Content-Type': 'application/json',
  'X-Powered-By': 'bacon'
});
<명시적 작성>

response할때 writeHead 메소드를 사용하여 명시적으로 코드 작성을 할 수있지만, 생략가능하며 생략시 암묵적으로 설정 가능하다

ex)
response.writeHead(200) 작성시
postman에서 200번에서 응답을 오는것을 확인 할 수 있다

github HTTP 트랜잭션 해부

profile
즐겁게 살자

0개의 댓글