본문 바로가기
Learn to Code

[TIL] node.js 미니 서버 만들기

by CEOSEO 2021. 4. 30.
728x90
반응형

https://nodejs.org/en/

 

 

2009년에 캘리포니아 출신 개발자 Ryan Dahl에 의해 개발된 node.js는 V8 엔진으로 빌드된 자바스크립트 런타임이다. node.js로 인해 자바스크립트는 웹 브라우저를 벗어난 환경에서도 사용이 가능하게 되었다. 이벤트 기반의 node.js는 non-blocking 특성으로 인해 속도가 빠르다는 장점이 있고, I/O 모델이라는 특성이 있다.

 

node.js를 다운로드하면 기본적으로 함께 받아지는 모듈들이 있는데, 이중 http 모듈을 사용하여 간단한 미니 서버를 만들 수 있다. 이번에 새로운 과제로 만들어본 것은 웹앱에서 POST 요청을 받은 뒤 응답을 리턴해주는 간단한 미니 서버였다. 지금 원하는 것은 프론트엔드 개발자가 되는 것이지만, 서버 사이드도 굉장히 흥미롭다는 것을 처음 알게 되었다.

 

 

 

 

 

nodemon 설치

https://nodemon.io/

 

 

우선 본격적으로 서버를 만들기에 앞서, nodemon을 설치한 뒤 script의 start를 수정해주었다. nodemon은 파일에 업데이트가 생겼을 시 별도의 시도 없이 자동으로 서버를 재시작해주는 편리함을 제공한다. 미니 서버를 배우면서 만드는 입장이기 때문에 실로 엄청난 수정이 있을 예정이기 때문에 nodemon을 써주는 것은 아주 편한 선택이다.

 

 

 

node.js 미니 서버 만들기

 

const http = require('http')

const server = http.createServer((request, response) => {
  // 작업 코드
})

 

우선 시작은 http 모듈을 가져오는 것에서 시작한다. http 모듈은 node.js를 설치할 때 기본으로 함께 번들링되어 있기 때문에 별도로 인스톨 해줄 필요가 없다. 그 다음으론 서버 객체를 생성해야 한다. 새로운 서버를 만들기 위해선 http.createServer()를 사용한다. createServer의 인자로 requestListener가 들어가는데, 이 함수는 해당 서버로 요청이 올 때마다 한번씩 호출된다. 즉, 요청을 받고 응답을 보내고 하는 모든 내용을 이 안에 작성하면 된다.

 

 

const http = require('http')

const server = http.createServer((request, response) => {
  const { method, url } = request
  
})

 

 

그리고 난 뒤, 들어온 요청(request)의 method와 url을 정리해준다. 이번 과제의 목표는 클라이언트로부터 POST 요청으로 들어오는 영문자를 대문자 또는 소문자로 바꾸어서 보내주는 일을 하는 간단한 미니 서버를 만드는 것이었다. 또한, 클라이언트로부터 OPTIONS도 함께 오며, CORS 관련 헤더를 응답을 해야했다. 대문자/소문자로의 전환 여부는 url에서 정해지게 되어 있었고, 그렇기 때문에 라우팅을 아래와 같이 구성하였다.

 

 

const http = require('http')

const server = http.createServer((request, response) => {
  const { method, url } = request
  
  if ( method === "OPTIONS" ) {
    // OPTIONS 요청인 경우 CORS 설정 돌려주기
  }
  
  if ( method === 'POST') {
    if (url === '/upper') {
      // POST 요청이면서 /upper인 경우
      
    } else if (url === '/lower') {
      // POST 요청이면서 /lower인 경우
      
    } else {
      // 기타 모든 경우는 404 리턴
    }
  } 
})

 

이번 과제를 하면서 가장 복잡하다 느꼈던 부분이 요청 body를 받는 것이었다. 앞서 destructuring으로 method와 url을 쉽게 정의한 것과는 다르게 body는 상대적으로 아주 긴 작업을 거쳐야 했다. 우선 요지는, request 'data'와 'end' 이벤트에 이벤트 리스너를 붙여서 데이터를 전달받는 다는 것이다. 'data' 이벤트에서 나오는 chunck는 Buffer 객체이고, Buffer 객체는 문자열 데이터로 이루어져있다. 이를 body라는 배열에 담아준 다음, end로 맺는다. 최종 리턴되는 데이터는 대문자로 바뀌어야 하기 때문에 toUpperCase()를 살포시 넣어주었다.

 

 

const http = require('http')

const server = http.createServer((request, response) => {
  const { method, url } = request
  
  if ( method === "OPTIONS" ) {
    // OPTIONS 요청인 경우 CORS 설정 돌려주기
  }
  
  if ( method === 'POST') {
    if (url === '/upper') {
      let body = []
      request.on('error', (err) => {
        console.error(err)
      }).on('data', (chunk) => {
        body.push(chunk)
      }).on('end', () => {
        body = Buffer.concat(body).toString().toUpperCase()
      })

      response.writeHead(201, defaultCorsHeader)
      response.write(JSON.stringify(body))
      response.end()
    })
    } else if (url === '/lower') {
      // POST 요청이면서 /lower인 경우
      
    } else {
      // 기타 모든 경우는 404 리턴
      
      response.writeHead(404, defaultCorsHeader)
      .end()
    }
  } 
  
  console.log("Listening on http://" + ip + ":" + port);
  server.listen(port, ip);
})

 

defaultCorsHeader는 정해진 규칙이 이미 있어서 해당 객체를 사용했고, response.write()을 사용해 JSON 문자열 데이터로 변경하여 최종 전달한다. url이 /lower인 경우는 /upper인 경우와 완전 동일하며, toUpperCase()인지 toLowerCase()인지의 차이만 있다.

 

 

 

 

728x90
반응형

댓글