TIL Node.js

백광호·2021년 2월 5일

TIL

목록 보기
53/55

새로 배운 것들

Node.js

서버를 만들기 위해서는 HTTP 요청에 따른
응답을 처리할 수 있도록 코드를 작성해야한다.

Node.js는 비동기적으로 움직이는 Javascript환경으로
이벤트 기반 Non-Blocking I/O 모델이다.

여기서 Non-Blocking이란 함수의 실행이
현재 함수의 종료를 기다리지 않는 것이며(비동기)
I/O 모델은 input을 주면 output을 반환하는 모델을 뜻한다.

정리하자면 유저의 클릭이나 네트워크 리소스를 요청하는 이벤트가
논블로킹으로 이루어지는 Input Output 모델이다.

Node.js의 코어 모듈

Node.js를 설치하면 함께 사용할 수 있는 모듈이 있다.
아래 네가지 코어 모듈은 require('')방식으로 사용할 수 있다.

const fa = require('fs')
const http = require('http')

fs.readFile('./something.json', (err, data) => {
  console.log(data)
});

http.get('http://localhost:5000/api', (res) => {
  console.log(res)
})

npm

Node Package Manager의 약자로
오픈소스 라이브러리 생태계 중 하나이다.

npm은 Node.js를 설치하면 함께 설치되는 패키지 매니저이며
npm을 통해 다양한 라이브러리를 다운로드 받을 수 있다.
ex) ESLint, moment 등등...

npm을 이용해 프로젝트 파일을 생성하는 방법은
지난번 ESLint 포스팅에서 다룬적이 있다.

package.json의 역활을 다시 한번 되짚어보면
프로젝트의 상세한 내용이 들어가 있고
어떤 라이브러리가 사용되었는지 알 수 있고, 관리할수 있다.

package.json 문서를 좀 더 살펴보자

여기서 라이브러리를 설치할 때 보통
npm install {라이브러리 이름}
이런식으로 많이 설치하는데 설치할 때에는 꼭 뒤에 --save를 넣어주자
만약 넣지 않게 되면 dependencies에 추가되지 않기 때문에
코드에서는 해당 라이브러리를 사용하지만 npm install을 이용해도
설치되지 않고, 협업 시 충돌이 일어날 확률이 크다.

개발 환경에서만 필요할 때에는 꼭 --save-dev를 붙여주자

npm scripts는 CLI에서 입력했을때 해당 부분에
입력해놓은 코드가 실행되도록 명령어를 만드는 것이다.

npm run {scripts}

위의 예제에 있는 test를 입력할 경우
해당 라이브러리를 실행하는 것이다.
즉, scripts 부분은 사용 가능한 명령어 목록이다.

Node.js에서 서버 구동하기

Javascript로 서버 파일을 만들어 보자

우선은 파일의 최상단에 Node의 코어 모듈을
필요로 하는 변수를 먼저 선언한다

const http = require('http')

그런 다음 파일을 불러올 때 서버를 실행하는 코드를 작성해주면 되는데

우선 통신을 하기 위한 포트와 ip를 선언한다

const PORT = 5000;
const ip = 'localhost';

그다음 Node의 http API 문서에보면 아래와 같은 항목이 있다.

server.listen()

공식 문서에서는 net.Server과 동일하다고 나와있는데
net.Server에서의 server.listen() 작성법을 보면 된다.

TCP 서버의 경우 인자로 포트, 호스트, 콜백함수를 넣을 수 있다.
아까 선언해두었던 포트와 ip를 넣어주자

server.listen(PORT, ip () => {
  console.log(`http server listen on ${ip}:${PORT}`)
  // 통신이 잘 되었다면 해당 로그를 반환할 것이다.
})

이렇게 하면 이제 서버와 통신할 수 있게 된다.

이제 본격적으로 서버를 만들게 되는데 공식문서의 아래 부분을 보면
http.createServer([option][,requestListener])

http.Server의 새 인스턴스를 반환한다고 한다.
이를 활용해 서버를 만들면 된다.

모든 Node웹 서버는 웹 서버 객체를 만들어야 한다.
위에서 설명한 코드를 이용해 아래와 같이 만들면 된다.

const server = http.createServer((request, response) => {
  // TODO
})

이제 이 안에서 바디를 요청해야된다.
POSTPUT등의 메소드를 요청 받을 경우 바디가 중요해 진다.
요청으로 오는 객체는 스트림 인터페이스를 구현하고 있다.
이 스트림의 dataend 이벤트에 이벤트 리스너를 등록해
데이터를 받을 수 있다.

let body = [];
request.on('data', (chunk) => {
  body.push(chunk);
}).on('end', () => {
  body = Buffer.concat(body).toString();
  // TODO
})

이 과정에서 생기는 오류를 처리할 수 있어야 한다.
만약 처리하지 않으면 Node.js프로그램을
강제로 종료 시킬 수 있는 오류를 던질 것이다.

request.on('error', (err) => {
  console.error(err.stack);
})

지금까지의 내용을 살펴보면 아래와 같다.

const http = require('http')
const PORT = 5000;
const ip = 'localhost';

const server = http.createServer((request, response) => {
  let body = [];
  request.on('error', (err) => {
  console.error(err.stack);
  }).on('data', (chunk) => {
    body.push(chunk);
  }).on('end', () => {
    body = Buffer.concat(body).toString();
    // TODO
  })
})

server.listen(PORT, ip () => {
  console.log(`http server listen on ${ip}:${PORT}`)
  // 통신이 잘 되었다면 해당 로그를 반환할 것이다.
})

여기까지 했다면 이제 요청을 받을 수는 있지만 요청에 응답할수는 없다.
요청에 응답하기 위해선 response를 이용해 요청에 응답해야한다.

응답에는 response.writeHead()라는 함수가 있다.
이 함수를 이용하면 요청에 대한 응답 헤더를 보낼 수 있다.
첫번째 인자로는 상태 코드(HTTP State Code), 두번째 인자로는
헤더를 보낼 수 있다.

위 코드는 사실 response.statusCoderesponse.setHeader()
하나로 합쳐놓은 코드이다. 훨씬 쓰기 편한듯 하다.

여기서는 미리 헤더를 선언해 놓고 위 코드를 이용해
응답 헤더를 보내 보자

const defaultCorsHeader = {
  'Access-Control-Allow-Origin': '*',
  'Access-Control-Allow-Methods': 'GET, POST, PUT, DELETE, OPTIONS',
  'Access-Control-Allow-Headers': 'Content-Type, Accept',
  'Access-Control-Max-Age': 10
}

작성한 헤더 메시지는 프리플라이트 요청에 따른 응답 헤더이다.
이제 헤더를 보냈으니 마지막으로 response.end()를 이용해
바디를 내보내면 된다.

response.end()는 요청에 따른 데이터를 응답하는 함수이다.

여기까지 한 것들을 모두 포함해 예제를 작성해 보면 아래와 같다.

const http = require('http')
const PORT = 5000;
const ip = 'localhost';
const defaultCorsHeader = {
  'Access-Control-Allow-Origin': '*',
  'Access-Control-Allow-Methods': 'GET, POST, PUT, DELETE, OPTIONS',
  'Access-Control-Allow-Headers': 'Content-Type, Accept',
  'Access-Control-Max-Age': 10
}

const server = http.createServer((request, response) => {
  let body = [];
  request.on('error', (err) => {
  console.error(err.stack);
  }).on('data', (chunk) => {
    body.push(chunk);
  }).on('end', () => {
    body = Buffer.concat(body).toString();
    response.writeHead(200, defaultCorsHeader)
    response.end(body)
  })
})

server.listen(PORT, ip () => {
  console.log(`http server listen on ${ip}:${PORT}`)
  // 통신이 잘 되었다면 해당 로그를 반환할 것이다.
})

여기까지 했다면 요청에대한 응답을 내놓는것 까지 하게된다.

아직은 서버에 대해 이제 막 배우기 시작한거라
위의 내용도 모두 맞다고 자부할수는 없다...
하지만 Node.js에서의 서버는 이런식으로 돌아간다는것을 알게 된 것 같다.

profile
안녕하세요

0개의 댓글