본문 바로가기
  • soldonii's devlog
Javascript 공부/Zero To Mastery(-)

(19) Node.js와 Express.js 1

by soldonii 2019. 8. 27.

*Udemy의 "The Complete Web Developer in 2019 : Zero To Mastery" 강의에서 학습한 내용을 정리한 포스팅입니다.

*https://soldonii.github.io에서 2019년 8월 5일(월)에 작성한 글을 티스토리로 옮겨온 포스팅입니다.

*자바스크립트를 배우는 단계라 오류가 있을 수 있습니다. 틀린 내용은 댓글로 말씀해주시면 수정하겠습니다. 감사합니다. :)


1. Node.js 입문

Node 덕분에 자바스크립트 언어를 웹페이지가 아니라 내 컴퓨터, 로봇 등 세상 어디에서나 사용할 수 있게 되었다. 최근에 node는 서버를 만들 때 굉장히 활발하게 사용되고 있다. 속도가 굉장히 빠르기 때문이다.

 

터미널에서 node 라고만 입력하면 바로 node 모드로 들어가서 자바스크립트를 이용할 수 있다. 브라우저에서 자바스크립트를 이용할 때와 약간의 차이점은 있다. 예를 들면 node에는 window 객체가 존재하지 않는다. 왜냐하면 DOM에서 배웠듯, window 객체는 브라우저가 자체적으로 제공하는 객체이기 때문이다.

대신 node에는 대표적으로 global 객체가 존재한다. global 객체를 활용해서 사용하는 메소드 중 대표적인 것이 process() 이다. process는 내가 현재 터미널에서 어떤 것을 구동하고 있는지, 즉 현재 컴퓨터가 어떤 동작을 수행하고 있는지를 보여준다. process.exit() 을 하면 하던 프로세스를 멈추고 터미널로 돌아온다.

 

2. Running script.js in Node

node에서 자바스크립트 파일을 실행시키려면 간단하게 node {파일명} 을 터미널에 입력하면 된다. 이 경우 node는 파일을 다 읽은 후에 마지막 명령을 마치고 자동으로 process.exit() 을 수행하여 다시 터미널로 돌아온다.

 

3. Modules in Node

새로운 ES 문법인 import 를 node에서 구동할 경우 syntax error를 일으킨다. node에는 아직 ES6의 기능이 다 갖춰지지 않았기 때문이다. 따라서 다른 파일의 정보를 불러오려면 common JS 방식으로 명령해야 하며, 따라서 import 의 경우 require 로, export 의 경우 module.exports 로 입력해야 한다.

// script.js 파일
import largeNumber from './script2.js'
const a = largeNumber;
const b = 5;
console.log(a+b);

// script2.js 파일
const largeNumber = 456;
export default largeNumber;

 

클라이언트 단에서는 위처럼 import, export 를 통해 script.js 파일이 script2.js 파일을 불러와서 변수 largeNumber를 활용할 수 있었으나, node에서는 위 코드를 아래와 같은 common JS 방식으로 변환해서 사용해야 한다.

// script.js 파일
const script2 = require('./script.js');
const a = script2.largeNumber;
const b = 5;
console.log(a+b);

// script2.js 파일
const largeNumber = 456;
module.exports = {
  largeNumber: largeNumber
};

 

참고로 script2.js 파일에서 export하는 대상은 객체이기 때문에, script.js 파일에서 변수 largeNumber에 접근하려면 script2.largeNumber와 같이 dot notation을 이용해야 한다.

 

4. Types of Modules

node에는 내장되어 있는 모듈이 있다. 그 중 대표적인 것이 fs 모듈http 모듈이다.

  • fs 모듈 : file system을 읽을 수 있는 모듈이다.
const c = require('fs').readFile;
console.log(c);

 

파일의 내용을 output으로 전달하는 fs 모듈 내 메소드 중 하나인 .readFile() 을 통해 특정 output을 뽑아낸 뒤 작업할 수 있따.

  • http 모듈 : 서버 생성시 사용하는 모듈이다.
  • nodemon

nodemon은 npm 패키지 중 하나로, 파일에 변화가 생길 시 바로바로 변화를 반영해 차이를 즉각 확인할 수 있도록 돕는 패키지이다. 원래 node에서는 node {파일명} 으로 파일을 읽을 때, 파일 읽기가 끝나면 process.exit() 을 자동으로 수행해 다시 터미널로 나온다고 했다. 따라서 파일 변경을 확인하고 싶어도 매번 다시 파일을 재실행했어야 했지만, nodemon을 통해 번거로움을 줄일 수 있다.

 

5. 서버 만들기

node를 통해 아주 간단한 서버를 만들어보자.

const http = require('http');

const server = http.createServer(() => {
  console.log('I hear you!');
}); 
server.listen(3000);

 

node에 내장되어 있는 http 모듈을 불러온 후, http 모듈에 내장된 createServer() 메소드를 이용해서 서버를 만들고, localhost:3000을 통해 방금 만든 서버에 접근하겠다는 의미이다.(숫자는 반드시 3000이 아니어도 된다.) 이 상황에서 웹 브라우저에서 localhost:3000에 접근하면, 어떤 일도 발생하지 않고 계속 loading되고 있다. 터미널로 가보면 "I hear you!"가 출력되어 있다. 왜냐면 이 서버는 node에서 작동되고 있기 때문이다. 다만 3000이라는 서버를 통해 클라이언트와 연결만 되어 있는 상태이다.

브라우저에서 계속 loading만 이뤄지는 이유는 서버가 어떠한 response도 클라이언트에게 전달해주지 않았기 때문이다. response를 넘겨줘 보자.

const http = require('http');

const server = http.createServer((request, response) => {
  response.setHeader('Content-Type', 'text/html');
  response.end('<h1>Helloooooo!</h1>');
});
server.listen(3000);

 

서버가 클라이언트에 보낼 response를 생성했으며, 크롬 개발자도구의 네트워크탭을 보면 아래와 같은 정보가 전달되었음을 확인할 수 있다.

localhost:3000
request headers
request response

마찬가지로 클라이언트의 요청 또한 node를 통해서 받을 수 있다.

const http = require('http');

const server = http.createServer((request, response) => {
	console.log('headers', request.headers);
  console.log('method', request.method);
  console.log('url', request.url);
  response.setHeader('Content-Type', 'text/html');
  response.end('<h1>Helloooooo!</h1>');
});
server.listen(3000);

 

위 코드는 header, method, url에 해당되는 request를 서버에 전달한 것이며, 아래와 같은 결과가 node에 출력된다.

node request

서버가 클라이언트에 보낼 response는 반드시 text/html일 필요는 없다. setHeader() 메소드에서 response 종류를 'application/json'으로 설정함으로서 JSON 정보를 전달하는 것도 가능하다.

const http = require('http');

const server = http.createServer((request, response) => {
	console.log('headers', request.headers);
  console.log('method', request.method);
  console.log('url', request.url);
	
  const user = {
    user: 'John',
    hobby: 'Skating'
  }
  response.setHeader('Content-Type', 'application/json');
  response.end(JSON.stringify(user));
});
server.listen(3000);

 

위 코드의 경우 아래와 같은 결과물이 클라이언트에게 전달된다. response를 보면 서버가 보낸 JSON 메소드를 웹 브라우저가 알아서 parse하여 자바스크립트 객체로 받아들인 것을 볼 수 있다.

json to frontend1

하지만 node에 내장된 http 모듈보다 서버 생성에 더 좋은 방식이 있는데 express.js가 바로 그것이다.

 

6. Introduction to Express.js

프론트엔드 파트에서 더 쉽고 빠르게 일하기 위해 React.js 라이브러리가 탄생했다면, 백엔드 파트에서는 Express.js 라이브러리가 있다. npm install express 로 설치하고, express를 사용하려면 아래와 같이 세팅하면 된다.

const express = require('express');
const app = express();
app.listen(3000);

 

클라이언트에 response를 전달하려면, http 모듈에서는 setHeader()end() 메소드를 사용한 것과 달리, get() 메소드속 send() 메소드를 이용하면 된다.

const express = require('express');
const app = express();

app.get('/', (req, res) => {
  const user = {
    name: 'Sally',
    hobby: 'Soccer'
  }
  res.send(user); // 객체가 출력된다.
  res.send("<h1>hellooo!!</h1>"); // 화면에서 Hellloooo!가 출력된다.
})
app.listen(3000);

 

send() 와 http 모듈에서의 setHeader() 메소드는 근본적으로 같은 역할이지만, setHeader() 에서는 content type을 지정해줬던 것과 달리, Express.js에서의 send() 메소드는 response로 text를 보내면 알아서 text로, JSON 객체를 보내면 알아서 JSON으로 content type이 설정된다.

또한 http 모듈을 이용하면 자바스크립트 객체를 보낼 때 JSON.stringify()가 필요했지만, Express의 경우 JSON으로 변환하지 않아도 알아서 값을 변환해서 보내준다.

댓글