Web Dev/ELICE

26 :: Node.js, 서버 만들기, express.js, 왜 Docker 쓰나

HJPlumtree 2021. 11. 30. 17:48

엘리스 SW 엔지니어 트랙 26일차

박성국님 실시간 강의

 

 

6주차 시작

Node.js로 들어왔다!

 

6주만에 Node.js로 들어왔다

이건 좋을 수도 있지만

앞에 내용의 복습이 없으면

다 까먹는다는 이야기

예방해야된다

 

 

웹에 대한 소개로 시작했다

 

SSR vs CSR

CSR

장점

첫 로딩 정적파일 다 받는다

동적으로 빠르게 렌더링, UX 뛰어남

서버에 요청 횟수 적다

단점

모든 정적 파일 로드 될때까지 시간 걸림

SEO 문제 발생

 

SSR

장점

초기 로딩 속도 빠름

SEO 가능

단점

매번 새로 고침

서버에 매번 새로 요청 => 서버 부하 가중 (캐싱 같은게 어느정도 커버)

 

선호하는 것을 이용하면 된다고 한다

 

 

Node.js

서버에서 동작하는 자바스크립트 엔진

 

IO needs to be done differently
- Ryan Dahl -

 

이벤트 기반(event-driven)

이벤트가 콜백큐에 들어오고 => 콜백 스택에 쌓이고, 처리하고 다음 콜백 큘로 넘어가는 방식

이벤트 루프가 다음 콜백을 처리하려면 지금 처리하고 있는 콜백 실행이 완료 되야한다

 

싱글 스레드지만 멀티 스레드처럼 행동하도록 도와주는

docker 등

 

Glitch 통해 인터넷에서 Node.js 사용할 수 있다

Glitch 링크 => https://glitch.com/

 

 

ES6에 관한 이야기

Lexical, Spread operator, Closure 등

 

Spread Operator를 제대로 안쓰고 있는 것 같다

object에도 되는구나

const a = {
    nick: 'jj',
    email: 'email'
}

const b = {
    age: 22
}

const user = {
    ...a,
    ...b
}

console.log(user) // {nick: 'jj', email: 'email', age: 22}

 

const user = {
    nickName: 'HJ',
    age: 22,
    email: "asdf"
}

const { nickName, ...personalData } = user

console.log(personalData) // {age: 22, emil:"asdf"}

 

 

Node.js 모듈

모듈 불러올 때

require

console.log(require('./animals'))

ECMA 단체가 정한 표준은 import, export

외부 모듈을 불러올 때 npm으로 설치하는 것

 

npm

외부 모듈 불러올 때 설치 도와주는 녀석

 

경로

const animals = require('.animals.js')
const http = require('http')

 

 

Node.js 내장 모듈

데이터 구조 

  • Buffer
  • Stream

 

Buffer

자바스크립트에서 값은 대부분 Buffer

이미지 객체, 파일 객체 등

 

데이터 표현하는 구조

아무런 인코딩 하지 않으면 byte값으로 표현

consol 찍으면 16진수

 

Stream

데이터를 작은 Chunk로 쪼개서 처리

큰 데이터 처리하거나

비동기적으로 얻을 수 있는 데이터 처리할 때 유용하다

 

대형 데이터를 다루는 일/회사에서 필요

 

dirname, filename

console.log('dirname', __dirname)
console.log('filename', __filename)

http

신기하네 서버 만들기

const http = require('http')
const server = http.createServer()

server.listen(3000, function() {
    console.log('서버 실행');
})

dns

IP주소 볼 수 있네

const dns = require('dns')

dns.lookup('google.com', (err, address, family) => {
    console.log(address, family);
})

// family는 버전

path

많이 사용된다

경로 가지고 노는건가보다

const path = require('path')
const fs = require('fs')

const filePath = path.resolve(__dirname, './test.txt')
const fileContent = fs.readFileSync(filePath, 'utf-8')

console.log(fileContent);

 

그외 내장 모듈 

  • process
  • setInterval
  • setTimeout
  • clearInterval
  • clearTimeout
  • util
  • fs
  • os
  • 등 등 등 

 

비동기를 부를 때 콜백으로 에러 처리를 받는구나

동기를 부를 때 에러 처리는 try, catch

 

 

오후 타임 시간

김병철님 실시간 강의

 

 

Node.js란?

어려운말: Chrome V8 JavaScript 엔진으로 빌드된 JavaScript 런타임이다

 

  1. 파이어폭스가 스파이몽키 만들고,
  2. 구글이 Chrome V8 엔진을 만들었는데
  3. 자바스크립트가 쓸만해 보였다
  4. 그래서 한 남자가 로컬에서도 쓸 수 있게 만들어 놓은거

런타임 환경: 프로그램이 동작할 수 있는 환경

=> 런타임 에러 프로그램 동작중 에러

 

쉬운말: 로컬에서 JS가 돌아갈 수 있는 환경 제공

JS 써놓고 브라우저 안띄어서 확인 가능하다!

 

Node.js 이용 VSCode에서 디버깅 하는법도 배웠다

 

 

이벤트 루프

모든 함수는 stack에 담긴다

비동기 함수(setTimeout)은 Task Queue에 담긴다

 

  1. stack이 비면(함수 실행이 다 끝나면)
  2. 이벤트 루프라는 녀석이
  3. Task Queue를 보고 있으면 stack에 담는다

즉, 비동기 함수는 stack 빌때만,

다시 즉, 모든 함수가 끝나야지만 비동기가 실행된다

그걸 도와주는게 이벤트 루프

 

이걸 설명하기 위해 이벤트 루프

fun1이 stack에 들어간다

그 다음 func2 들어간다

setTimeout은 Task Queue로 들어간다

function delay() {
    for (let i = 0; i < 1000000000; i++);
}

function func1() {
    delay();
    func2();
    console.log("Func1 끝!");
}

function func2() {
    delay();
    console.log("Func2 끝!");
}

function timeout_func() {
    console.log("Func3 끝!");
}

setTimeout(timeout_func, 5);
func1();

 

 

싱글 스레드 + 비동기

쓰레드(thread)는 작업단위

 

Node.js => 싱글 쓰레드

혼자 일을 해야되는 단점이 있다

 

 

npm(Node Pakage Manager)

설치하는데 도와주는 애

 

ES Lint

문법적 오류나 안티 패턴 찾아주고

일관된 코드 스타일 유지

개발자가 쉽게 읽을 수 있도록 도와준다

 

ES Lint 사용환경 만들기

npm init

npm i eslint --save--dev

vscode 확장 설치

node_modules에서 .bin으로 가서 eslint --init

 

Prettier 도 설치

npm i prettier --save--dev

 

참고 Prettier로 코딩 스타일 통일하기

링크 => https://www.daleseo.com/js-prettier/

 

서버 만들기

F5 => Node.js로 실행

const http = require("http");
const port = 9999;

http
  .createServer((req, res) => {
    res.end("Hello, World!");
  })
  .listen(port, () => {
    console.log("서버가 켜졌어요!!!");
  });

 

하나씩 뜯어보자

 

CommonJS 방식은 Node.js에서 사용하는 방식

ES2015 모듈 개넘 나오기 전부터 사용됨

 

ES2015

import http from 'http'

CommonJS

const http = require('http')

 

package.json을 서로 수정하면 사용할 수 있다

 

 

http.createServer

HTTP 통신 받는 서버를 만든다

 

req(request): 요청정보

res(response): 응답정보

 

res.end()

담길 데이터 다 담겼다 => 요청 클라이언트에 보낸다

 

listen

여러가지(디스코드, 브라우저, 카톡 등) 띄었는데

어디로(port) 가야할지 알려주는 것

 

HTTP port 기본값 80

그래서 검색하는 사이트 url에 port가 안적혀있다

 

 

경로 가지고 놀기

const http = require("http");
const port = 9999;

http
  .createServer((req, res) => {
    if (req.url === "/hello") {
      res.end("H!");
    } else if (req.url === "/bye") {
      res.end("Bye...");
    } else res.end("Hello Word");
  })
  .listen(port, () => {
    console.log("서버가 켜졌어요!!!");
  });

 

 

서버 만드는데 더 편할려구 프레임워크 사용한다

Spring, django, Flask, Express, Nest 등

 

전자정보프레임워크를 한국에서 시켰는데 Spring으로 되어있다...

그래서 Java를 많이 쓰는구나.................

 

백엔드

사용자와 직접 상호작용 X

프론트엔드에서 요청하면 간접적으로 상호작용한다

 

지금까지 HTTP 모듈 사용했다

 

이후로는 Express.js 라는 프레임워크 설치해서 사용할거다

JS => Express.js + Mongoose

TS => Nest.js + TypeORM

 

 

Express

Express의 장점

npm 등 확장 마켓 플레이스

성능 측면도 좋다

 

Express.js

npm으로 설치

npm i express

const express = require("express");
const port = 9999;

// 이게 http에서 createServer
const app = express();

app.get("/", (req, res) => {
  res.send("Hello, World!");
});

app.get("/hello", (req, res) => {
  res.send("Hello");
});

app.listen(port, () => {
  console.log(`서버가 ${port}번 포트에서 동작하고 있어요`);
});

 

 

막간 토크

Docker 왜 쓰나?

설치의 문제때문에 나왔다

 

서버 설치하면 오류 계속 뜬다

서버 많으면 서버 구동을 위해 뭔가 많이 깔아야된다

그럼 오류 덩어리

 

Docker는

서버 설치가 완료된 컨테이너 갖고 있다

이걸 받아서 사용하기만 하면된다