node.js를 이용한 http 서버 구축/응답

node.js

  • JavaScript를 기계어로 compile 해주는 엔진(chrome: v8)으로 빌드되어 JavaScript가 구동되는 환경
  • 이벤트 기반의 non-blocking I/O model이다.
    • 이벤트: 유저의 버튼 클릭, 네트워크에 리소스 요청 등
    • non-blocking: 다음 함수의 실행이 현재 함수의 종료를 기다리지 않고 실행됨
    • I/O model: input을 주면 ouput을 반환하는 모델


node core modules

  • node.js는 3가지 타입의 module을 쓸 수 있다.
    • core modules, local modules, third party modules
  • node.js가 시작되면 자동으로 로드되기 때문에 별도의 설치 없이 사용 가능한 모듈이다.
  • 응용 프로그램에서 사용하기 위해서는 require() 메소드로 모듈을 가져와야 한다.
  • core module의 종류: http, url, querystring, path, fs, util
  const module = require('module_name');


npm

  • node package manager: 응용 프로그램에 node.js 패키지를 설치하는 command line tool
  • 오픈 소스 node.js packages의 온라인 레파지토리
  • 유용한 모듈을 만들어 레포지토리에 게시할 수 있고 npm에 올라와있는 패키지는 터미널에서 npm을 통해 설치하여 사용할 수 있다.
  • node.js 설치 시 함께 포함되어 있으며, npm -v 명령어로 npm 버전을 확인할 수 있다.
  • 최신 버전 업데이트 시 npm install npm -g
  • 패키지 설치 시 npm install 패키지이름
  • package.json: 프로젝트 정보, 프로젝트 셋업에 대한 정보 등을 모아 관리하는 파일
  • package.json 파일의 dependency 항목에서 프로젝트에서 사용 중인 패키지 정보를 관리한다. 여러 명의 개발자가 하나의 프로젝트를 진행할 경우 패키지를 프로젝트에 포함시키는 대신 package.json을 통해 필요한 패키지를 설치할 수 있다.
    • 패키지를 package.json 파일의 dependency 항목에 추가하기 위해서는 설치 시 –save 옵션을 줘야 한다.
  • dev-dependency 항목에서는 프로젝트와 직접적인 관계는 없고 개발만을 위해 필요한 dependenciy를 관리한다.
    • 설치 시 –dev 옵션을 준다.
  • npm init : ‘npm을 사용하는 프로젝트로 정의’한다는 뜻으로, 폴더에 package.json 파일이 생성된다.

    $ npm install --save nodemon
    $ npm install @babel/core --save-dev
    
    // package.json
    {
      // project에 관한 정보
      "name": "",
      "version": "",
      "description": "",
          
      // 설정된 script 코드
      "scripts": {
        "start": "nodemon script.js",
            
      // 프로젝트에서 사용 중인 패키지 정보
      "dependencies": {
        "nodemon": "^2.0.6"
      }
      // 개발에 필요한 패키지 정보
      "devDependencies": {
        "@babel/core": ""
      }
    }
    


HTTP 서버 요청/응답 과정

  • 웹에서 이루어지는 클라이언트와 서버 간의 데이터 교환 프로토콜
  • 요청(requests): 클라이언트(보통의 경우 브라우저)에 의해 전송되는 메시지
  • 응답(responses): 서버에서 응답으로 전송되는 메시지
  • 주소창에 url을 입력하는 get 요청 시 서버의 응답 과정을 알아보자.
  • http://www.google.com/int1/ko_kr/about/
    • http:// 사용하는 프로토콜을 정의
    • www.google.com 도메인 네임
    • /init1/ko_kr/about/ 서버 내에서 routing(분기)되는 주소 1. 주소창을 통해 하는 요청은 모두 GET Request로, 서버에 url로 된 http request를 보내면, 2. DNS(Domain Name Server)가 요청 받은 url의 ip로 응답해준다.
    • 요청과 응답 메세지 등 클라이언트와 서버 사이에 전송되는 모든 메세지는 TCP/IP 연결을 통해 전송된다.
    • 서버가 요청을 승인하면 status code가 담긴 메세지를 클라이언트에 전송한다. “200 OK”는 요청 성공 메세지
    • 웹 서버의 routing(주소 탐색 규칙)에 따라 요청을 처리한다.
    • 서버가 웹사이트의 파일들을 데이터 패킷의 형태로 전송 프로토콜에 따라 브라우저에 전송한다.
    • 서버가 보내주는 자원(html, js file..)을 브라우저에서 처리한다. 즉 브라우저는 전송받은 데이터 패킷들을 조립하여 웹 사이트를 렌더링한다.


TCP vs. UDP

  • 전송 프로토콜
  • 응답으로 전송되는 데이터는 IP 주소를 통해 디바이스에 도착한 후 헤더에 있는 프로토콜 정보로 UDP 혹은 TCP 연결인지 확인한 후 각 헤더의 port number를 통해 목표 프로세스로 들어간다.
    • 기본적으로 80 포트를 사용한다.(주소 뒤 콜론과 함께 있는 숫자로, 없을 경우 80이 생략된 것)
  • 만약 웹 사이트가 데이터 전체로서 한 번에 전송된다면 한 번에 하나의 사용자만 다운로드 가능 할 것이다. 여러 웹 사용자가 동시에 웹 사이트를 이용 가능하게 하기 위해 데이터를 수천개의 작은 조각들로 전송한다.
  • 이 데이터 조각들을 패킷이라 하며 패킷을 전송하는 방식에 따라 TCP 혹은 UDP로 분류된다. 일반적으로 신뢰성이 높은 TCP 연결을 사용한다.
  • TCP(Transmission Control Protocol): IP와 함께 사용하는 프로토콜
    • 연결형 프로토콜로서 데이터의 흐름 제어가 가능하다. 패킷(데이터 조각)의 경로가 존재하며 속도가 느리고 신뢰성이 보장된다.
    • 파일 전송과 같은 속도보다 신뢰성 있는 전송이 중요할 경우 사용
  • UDP(User Datagrm Protocol): 데이터를 데이터그램 단위로 처리하는 프로토콜
    • 비연결형 프로토콜로서 각 패킷은 독립적이며 서로 다른 경로로 전송된다. 속도가 빠르지만 신뢰성이 낮다.
    • 음악이나 동영상 스트리밍 같은 데이터가 일부 누락되어도 상관 없는 경우 사용


cache

  • 웹 캐시 또는 HTTP 캐시
  • HTTP responses를 일시적으로 저장하는 곳
  • 다음 HTTP request 조건이 만족될 때 까지 캐시에 저장한 리소스를 사용할 수 있다.


HTTP status code

  • “200 OK”: 요청 성공
  • “201 Created”: 요청이 성공하여 새로운 리소스가 생성됨(일반적으로 POsT, PUT 요청)
  • “304 Not Modified”: 캐시 목적. 요청에 대한 응답이 수정되지 않음. 클라이언트는 응답의 캐시된 버전을 사용할 수 있음
  • 400 번대 code: 클라이언트 에러
    • “400 Bad Request”: 잘못된 문법으로 인해 서버가 요청을 이해할 수 없음
    • “403 Forbidden”: 클라이언트가 콘텐츠에 접근할 권한이 없음 => 거절
    • “404 Not Found”: 요청받은 리소스를 찾을 수 없음
  • 500 번대 code: 서버 에러
    • “500 Internal Server Error”: 서버가 처리할 수 없는 요청


HTTP 메시지의 구성

HTTP Request

request


HTTP Response

request


HTTP transaction

http 모듈 불러오기

 const http = require('http');


서버 생성

  • createServer 메소드로 웹 서버 객체를 만든다.
  • parameter로 요청에 대한 콜백 함수를 전달
  • 생성된 서버는 몇 가지 이벤트를 가지는데, 대표적으로 3가지 이벤트는:
    • connection: 클라이언트와 서버 간의 연결 이벤트
    • request: 클라이언트로부터 서버로 http 요청 발생
    • close: 서버 종료 이벤트
  • request 이벤트가 발생하면 콜백 함수를 호출하며 request 객체와 response 객체가 파라미터로서 전달된다.
    • request 객체는 클라이언트의 요청에 관한 정보를 담고 있다.
    • response 객체는 서버의 응답에 대한 정보를 담고 있다.
 const server = http.createServer((request, response) => {
  // 응답 내용
 })


request body

  • request 객체는 바이트 데이터를 읽을 수 있는 ReadableStream 인터페이스를 구현하고 있으며, 이 스트림에 이벤트 리스너를 등록할 수 있다.
  • 스트림이 chunk(데이터 덩어리)를 클라이언트에게 전달/양도할 때 data 이벤트가 발생한다
    • 스트림에 data 이벤트 리스너를 연결하면 스트림이 flowing mode로 전환되며 데이터가 사용 가능한 즉시 전달된다.
  • data 이벤트의 chunk는 Buffer 객체이며 문자열 데이터이므로 데이터를 배열에 모은 후 end 이벤트에서 문자열로 만들어야 한다.
    • Buffer 객체는 바이트로 구성된 고정된 길이의 배열
let body = [];
request.on('data', (chunk) => {
  body.push(chunk);
}).on('end', () => {
  body = Buffer.concat(body).toString();
});


Errors

  • request 스트림의 에러 시 스트림에서 ‘error’ 이벤트가 발생하며 오류를 전달한다.
  • 이벤트에 오류에 대한 리스너가 등록되어 있지 않으면 에러가 발생하면서 node.js가 종료될 수 있다.
  • 요청 스트림에 ‘error’ 리스너를 추가해 오류를 처리해줘야 한다.
request.on('error', (err) => {
  console.error(err.stack);
});


HTTP status code

  • response의 HTTP status code는 기본적으로 200
  • 상태 코드를 변경하려면 statusCode 프로퍼티를 설정한다.
 response.statusCode = 404;


Response Headers

  • setHeader() 메소드로 헤더 설정
 response.setHeader('Content-Type', 'application/json');
 response.setHeader('X-Powered-By', 'bacon');


header data 전송

  • 바디 데이터를 전송할 때 헤더는 기본적인 셋팅으로 전송된다.
  • 헤더를 사용자 설정으로 작성할 때 writeHead 메소드를 사용한다.
 response.writeHead(200, {
  'Content-Type': 'application/json',
  'X-Powered-By': 'bacon'
 });

Response Body 전송

  • response 객체는 WritableStream
  • 응답 바디는 일반적인 스트림 메소드를 사용해 작성
  • write 메소드는 여러번 호출 가능한 데이터 전송 메소드
  • end 메소드는 스트림에 보내는 데이터 문자열의 끝을 의미, 응답을 종료
 response.write('<html>');
 response.write('<body>');
 response.write('<h1>Hello, World!</h1>');
 response.write('</body>');
 response.write('</html>');
 response.end();
 
 // end 한번으로 간단하게 작성 가능
 response.end('<html><body><h1>Hello, World!</h1></body></html>');

Categories:

Server

Load Comments