Node로 서버 구동해보기 (http vs express 비교)

제이밍·2021년 8월 25일
6

node.js

노드는 서버일까 ?

보통 node 하면 서버를 떠올리기 쉬운데 사실 node 는 서버가 아닌 자바스크립트코드를 읽어서 처리해 주는 런타임이다.

런타임을 쉽게 말하면 실행기라고 할 수 있다.
기존 HTML에 종속되어 HTML없이 읽히지 못했던 javascript가 강해질 수 있던 계기도 javascript를 실행해주는 Node가 생긴 이후이다.

Node내부를 간단하게 살펴보면 크롬 브라우저 엔진인 v8이 해석한다고 할 수 있다.

그렇다면 왜 Node를 서버라고 혼동할까?

javascript로 서버실행코드를 작성한다고 생각해 보자. 이 코드는 결국 Node가 실행시키기 때문에
Node가 서버라고 생각 될 수 있기때문에 node를 서버라고 착각 할 수 있다.

app.js 라는 파일을 만들어 동작하면 app.js안에있는 자바스크립트 파일을 읽어 http가 서버를 생성하게해 서버가 열리는 것일뿐 node가 서버역할을 하지는 않는다.

비슷한 예로 typescript를 해석하는 deno가 있을 수 있다.

node의 특징

1. 이벤트 기반
이벤트가 발생할 때 미리 지정해둔 작업을 수행하는 방식이다.
ex) 클릭, 스크롤, 네트워크 요청, 타이머 등..

2. 논 블로킹 I/O
비동기이면서 논 블로킹
동기이면서 블로킹

3. 프로세스 vs 스레드
노드는 원래 멀티스레드 이다?!

프로그램을 하나 띄우면 프로세스가 하나 띄워진다.
노드를 실행하게 되면 멀티 프로세스와 스레드가 돌아간다. 하지만 우리가 컨트롤 할 수 있는 부분은 단 하나의 스레드 때문에 우리는 노드를 싱글스레드 라고 표현한다.

Node14 버전부터 멀티스레드 사용 가능!
-> 동시에 여러가지 일을 할 수 있게 된다.

서버로서의 노드

우리 컴퓨터는 노드 덕분에 서버가 될 수 있다!

node.js 실행하기

1.package.json 파일을 생성

npm init <initializer>

npm init <initializer> can be used to set up a new or existing npm package.

npm init은 npm 패키지를 설정하는 데 사용 되며, <initializer> 없이 npm init을 하게되면 콘솔창에서 여러가지 질문을 받아 적절한 package.json을 생성한다.

http 서버 구동 해보기 (http는 node 에서 제공하는 모듈)

http 서버가 하는 역할

  1. 프론트에서 요청을 보내면 응답을 보낸다.
  2. 요청과 응답은 언제나 1:1로 일어난다. (한가지 요청에 대한 응답이 여러개인 경우 한번에 합쳐서 보낸다)
  3. 만일 서버에서 응답을 보내지 않을 경우 특정 시간(30초 정도)후에 브라우저가 자동으로 응답실패로 처리한다.


http서버로 Localhost 창 띄우기

/GET/favicon 은 브라우저 에서 요청 하는 부분이므로 우리가 직접 조작하기는 불가능 하다.

실행하기

node app.js

localhost를 통해 서버가 잘 동작하고 있는 걸 확인 할 수 있다.

res.write

res.write를 사용해 html 요소를 write 해 줄 수 있으며 마지막 요소는 매소드 .end를 사용해 종료시켜야 한다.

api 생성

기본적인 CRUD api를 만들때 주소들이 다양하기 때문에 if 문으로 method를 구분해 줘야 하고 if문이 많아지면 코드를 깔끔하게 작성하기 어렵기 떄문에 express 라는 프레임워크를 함께 사용하는 경우가 많다.

EXPRESS

app.set();

app.use 👉🏻 모든 코드에서 실행된다.

// http를 사용하고 있는 express
const express = require("express");
const path = require("path");
const app = express();
// 전역변수 port 를 설정하는 느낌
app.set("port", process.env.PORT || 3000);

next();

next() 를 써 줘야 다음코드로 넘어가 실행된다.

app.use((req, res, next) => {
 console.log("모든 요청에 실행하고싶어요");
 next();
});

라우터

app.get("/" 과 같이 메서드 + 주소 👉🏻 라우터 라고 부른다.

app.get("/", (req, res) => {
 // 가져올때 html 파일이 변경되었는지 확인한다.
 res.sendFile(path.join(__dirname, "./index.html"));
});
app.post("/", (req, res) => {
 res.send("hello express");
});
app.get("/about", (req, res) => {
 res.send("hello express");
});
app.listen(app.get("port"), () => {
 console.log("익스프레스 서버 실행");
});

와일드카드 와 *

와일드카드 👉 항상 다른 라우터 아래에 위치해야한다.
* 👉 모든 get 요청에 대해 다 처리하겠다.

app.get("/:name", (req, res) => {
 // 가져올때 html 파일이 변경되었는지 확인한다.
 res.send(`hello ${req.params.name}`);
});
app.get("*", (req, res) => {
 res.send(`hello All`);
});

미들웨어(Middleware)

미들웨어는 연속으로 사용 할 수 있다.

app.use(
 (req, res, next) => {
  console.log("1 모든 요청에 실행하고싶어요");
  // next() 를 써 줘야 다음코드로 넘어가 실행된다.
  next();
 },
 (req, res, next) => {
  console.log("2 모든 요청에 실행하고싶어요");
  next();
 },
 (req, res, next) => {
  console.log("3 모든 요청에 실행하고싶어요");
  next();
 },
);

status(200)은 생략가능

app.post("/", (req, res) => {
 res.status(200).send("hello express");
});

custom 에러 미들웨어

반드시 4가지 매개변수를 다 써야한다. (err, req, res, next)

app.use((err, req, res, next) => {
 console.error(err);
 res.send("에러났지만 안알려줌");
});
app.listen(app.get("port"), () => {
 console.log("익스프레스 서버 실행");
});

http VS express 사용 비교!

http

if (req.method === "GET") {
 if (req.url === "/about") {
  res.writeHead(200, { "Content-Type": "text/html; charset=utf-8" });
  return res.end("hello express");
 }
}

express

app.get("/about", (req, res) => {
 res.setHeader("Content-Type", "text/html");
 res.send("hello express");
});

http

if (req.method === "GET") {
 if (req.url === "/about") {
  res.writeHead(200, { "Content-Type": "application/json" });
  return res.end(JSON.stringify({ hello: "hello express" }));
 }
}

express

app.get("/about", (req, res) => {
 res.json({ hello: "hello express" });
});

가볍게 알아두면 좋은 지식

스케일링(scaling)

스케일링이라는 단어를 이해하기 전에 백엔드와 프론트를 나누는 이유에 대해 생각해 볼 필요가 있다.
만약 프론트와 백엔드가 하나의 컴퓨터 안에 있게 된다면, 기존 서버 PC와 똑같은 서버 PC가 복제가 된다. 하지만 실제로 트래픽이 발생하는 서버는 프론트엔드 서버이기 때문에 백엔드 서버의 복제는 불필요하다.

이러한 이유로 프론트엔드와 백엔드 서버를 각 각의 서버 PC로 분리해서 관리하는 것이 자원을 아끼며 효율적으로 관리할 수 있는 것이다.

Referance

https://leehyungi0622.github.io/2021/06/03/202106/210603-server_scaling/

profile
모르는것은 그때그때 기록하기

0개의 댓글