728x90

nodejs 는 

chrome v8 javascrpit엔진으로 빌드된 javascript런타임이다.

 

( "자바스크립트 런타임"이란 "자바스크립트 코드를 실행하는 환경"을 말한다. 

자바스크립트는 일반적으로 브라우저에서 실행된다. 

다른 환경에서도 실행될 수 있지만 이를 위해서는 자바스크립트 엔진을 다른 프로그램에 내장하여 자바스크립트 코드를 실행할 수 있는 환경을 만들어야한다. 자바스크립트 엔진과 함께 필요한 라이브러리, 모듈, api 등을 포함하는 것이 자바스크립트 런타임이다. 

)

 

브라우저에서 실행되는 자바스크립트와 달리 nodejs 는 파일 시스템,네트워크 등과 같은

서버 사이드 기능을 제공하여, 서버 사이드 웹 개발을 위한 환경을 제공한다. 

이를 통해 *비동기식 I/O, 이벤트 기반 처리 모델 등을 활용해 높은 성능의 웹 애플리케이션을 만들 수 있다.

 

또한 노드js는 npm이라는 패키지 매니저를 제공한다. node package manager

이를 통해 라이브러리, 모듀르 프레임워크 등의 다양한 패키지를 쉽게 설치하고 관리할 수 있다.

 

 

(I/O(Input/Output)는 컴퓨터에서 데이터를 읽고 쓰는 작업을 말합니다. 이때, 데이터를 읽고 쓰는 과정에서 CPU는 다른 작업을 수행할 수 없는 차단(blocking) 상태에 빠지게 됩니다. 이러한 문제를 해결하기 위해 비동기식 I/O(Asynchronous I/O)가 등장했습니다.)

 

+

express는 

노드Js를 위한 웹 프레임워크이다. 간결하고 유연한 구조를 가지고 있는 것이 특징

노드js의 http 모듈을 기반으로하며, 

http 요청

라우팅 및 미들웨어 처리를 쉽게 할 수 있도록 한다.

 

다음과 같은 기능을 제공한다. 

  1. 라우팅: HTTP 요청의 URL을 해당하는 처리기(콜백 함수)에 매핑합니다. 이를 통해 사용자는 특정 URL에 대한 요청에 대한 적절한 응답을 반환할 수 있습니다.
  2. 미들웨어: 요청을 처리하기 전에 실행되는 작업을 구성할 수 있습니다. 예를 들어 요청 헤더의 유효성을 검사하거나 로깅을 수행하는 등의 작업을 수행할 수 있습니다. 또한 미들웨어를 사용하여 사용자 정의 라우팅 및 오류 처리 논리를 구현할 수도 있습니다.
  3. HTTP 요청 및 응답: Express는 HTTP 요청 및 응답을 쉽게 처리할 수 있는 기능을 제공합니다. 예를 들어 요청 본문을 구문 분석하거나 특정 상태 코드로 응답을 반환할 수 있습니다.
  4. 뷰 엔진: Express는 다양한 뷰 엔진을 지원합니다. 이를 통해 사용자는 HTML 및 CSS와 같은 마크업 언어로 페이지를 렌더링할 수 있습니다. 대표적인 뷰 엔진으로는 Pug, EJS, Handlebars 등이 있습니다.

 

728x90
728x90

만들기에 앞서서 

이거 먼저 만들어놔야

어떤 모듈 들어가있는지 확인할 수 있어

 

만드는 법  npm init

 

수업 듣다가 놓쳐서 에러뜨길래 물어보니까

 

 

 

스크립트에 

"start" : "nodemon app"

으로 바꿔줘야 했고

 

scripts 부분에 start 속성 잊지 말고 넣어야~!!

nodemon app을 하면 app.js를 nodemon으로 실행한다는 뜻이야  

 

코드 수정하면 노드몬이 서버 자동으로 재시작함 콘솔에서 rs 입력해서 수동으로 재시작할 수 있어

(개발용으로만 하는거 권장)

 

 

 

익스프레스 쓸거니까 밑에 애들깔아줘야 저렇게 들어가는 거임

 

npm i express

npm i -D nodemon

npm i morgan cookie-parser express-session dotenv body-parser

 

한번에 여러 개 깔 수 있음 (밑줄친건 안깔았나? 보면 없어서 안깔은거같기도 하고..)

 

원래 로그인페이지만 따라 만들고

과제로 다른 페이지로 넘어가는 거 함. 

 

일단 결과물

 

 

 

 

로그인 페이지 login.html

<!DOCTYPE html>
<html lang="ko">
  <head>
    <meta charset="UTF-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Document</title>
  </head>
  <body>
    <h1>Login Page</h1>
    <hr />
    <form method="post">
      <table>
        <tr>
          <td><label>UserName</label></td>
          <td><input type="text" name="login" /></td>
        </tr>
        <tr>
          <td><label>Password</label></td>
          <td><input type="password" name="password" /></td>
        </tr>
      </table>
      <input type="submit" name="" />
    </form>
  </body>
</html>

 

 

메인 페이지 main.html

<!DOCTYPE html>
<html lang="ko">
  <head>
    <meta charset="UTF-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>메인페이지</title>
  </head>
  <body>
    <form method="POST">
      <h1>메인페이지</h1>
      <button name="loginpage" value="login-page">로그인페이지</button>
      <button name="naver" value="naver-page">검색페이지</button>
    </form>
  </body>
</html>

 

 

app.js

const express = require("express");
const cookieParser = require("cookie-parser");
const bodyParser = require("body-parser");
const morgan = require("morgan");
const fs = require("fs");
const app = express();
const port = 3001;

//미들 웨어 설정
app.use(morgan("dev"));
app.use(cookieParser());
app.use(bodyParser.urlencoded({ extended: false }));

//라우터 설정
// app.get("/", (req, res) => res.send("Hello World"));
//들어가서 뜨는 로그인페이지 만약 쿠키들어있으면 성공 뜸
// app.get("/", (req, res) => {
//   if (req.cookies.auth) {
//     res.send("<h1>Login Success</h1>");
//   } else {
//     res.redirect("/login");
//   }
// });
// //메인페이지 추가해봄
app.get("/", (req, res) => {
  if (req.cookies.auth) {
    res.send("<h1>Login Success</h1>");
  }

  // fs.readFile("main.html", (error, data) => {
  //   res.send(data.toString());
  // });
  else {
    // res.redirect("/login");

    //send는 한번만 쓸수 있어서..end처럼끝내버리는거였음 그래서 밑에또부를때충돌남!!
    //여러개쓰고 싶으면 write
    //그거뿐만 아니라 불러올때 충돌나는것도 있음..
    fs.readFile("main.html", (error, data) => {
      res.send(data.toString());
    });
  }
});

app.post("/", (req, res) => {
  if (req.body.loginpage) {
    console.log(req.body);
    res.redirect("/login");
  } else req.body.naver;
  {
    res.redirect("https://www.naver.com/");
  }
});

//html페이지로
app.get("/login", (req, res) => {
  fs.readFile("login.html", (error, data) => {
    res.send(data.toString());
  });
});
//단순페이지요청(클라이언트가ㅏ요청한걸로 쿠키생성)
app.post("/login", (req, res) => {
  //쿠키생성
  let login = req.body.login;
  let password = req.body.password;
  console.log(login, password);
  console.log(req.body);
  if (login == "rint" && password == "1234") {
    res.cookie("auth", true);
    res.redirect("/");
  } else {
    res.redirect("/login");
  }
});

app.listen(port, () => console.log("example app listening on port"));

 

 

 

콘솔에서

cd 폴더주소

npm start

 

하면 

콘솔 넣은거 example app listening on port 잘 뜸

 

port 값 3001로 할당해놔서 들어가면

뜬다! 

 

버튼 두개 만들어놓은 이유가 button 눌렀을 때 name 값 잘 보내와지는지 볼라고

메인페이지 일때 

 

만약

localhost:3001/ 일때

요청.바디에 name=loginpage 이면

응답. 다시지시. localhost:3001/login

 

그것도 아니면 

요청.바디에.naver이면

응답. 다시지시.링크

 

 

로그인 페이지 넘어오면 

 

내가 get post 차이가 뭘까 에러날때마다 

다같이 얘기했음 이것도 찾아서 정리해봐야겠다

 

암튼 내가 이해한거는  

/login 일때

fs.readFile 이거는 파일 읽어서 불러오고 띄우고 

응답으로 res.send (express에서는 이거 사용)

 

 

요청.바디에.login을 login에 할당

할당하고

만약 input의 name=login이랑 정한 값이랑 같으면

응답.특정 쿠키를 만들어서

응답. "/"로 다시 불러와

 

그거 아니면

응답."/login" 불러와

 

 

 

설정한 값 잘 넣어서

쿠키값이 가지고 응답되었어!

그래서 "/" 다시 메인페이지로 돌아왔는데

왜 글자가 뜨냐면

 

 

 

 

 

 

 

만약에 

요청.쿠키들이.auth 면

응답.글자로~

 

이거 넣어서 임.

 

사실 처음에 잘되다가 

[nodemon] app crashed - waiting for file changes before starting...

 

다시 메인페이지, 버튼 두개 있는 창 띄우고 싶어서쿠키값을 오른쪽에서 삭제했는데에러가 막뜨는거야 

 

 

컨트롤 C해서

npm start

 

다시 구동했는데 됐다가 안됐다가...에러 자꾸 뜸

 

 

 

redirect를 많이해서 그런가 했는데 

위에 코드에도 적었지만

 

 

res.send 때문이었음

이게 응답과 동시에 끝내줘서 다음 동작에 안넘어가는 거야

 

그리고 원래 

 

  fs.readFile("main.html", (errordata=> {

      res.send(data.toString());

    });

 

이게 else안에 있는게 아니라 "/" 일때 맨 위에 있었고 그다음에 if였음

 

메인페이지 띄우라는 거랑

쿠키값 있을때 h1 글자창 띄우라는 거랑 충돌 났나봐

 

그래서 else 안에 넣어준거임

res.send도 하나만 쓸 수 있어서 if else 안에 넣어주고...

 

 

 

app.get

app.post 차이

 

 

res.send res.write 차이 궁금~

728x90
728x90

클라이언트가 보내는 요청의 단점, 누가 보낸 건지 몰라. 

대신 로그인 구현하면 되는데 로그인 한후에 새로고침해도 로그아웃 안되도록 

클라이언트가 서버에 누구인지 지속적으로 알려줘야함

쿠키

클라이언트 로컬에 저장되는

유효기간 있고 name=zerocho 처럼 단순한 Key-Value쌍의 작은 데이터 파일

 

쿠키의 구성요소

1. 이름 : 각각의 쿠키를 구별하는데 사용함

2. 유효시간: 쿠키의 유지시간

3. 도메인: 쿠키를 전송할 도메인

4. 경로: 쿠키를 전송할 요청 경로

5. 값: 쿠키와 이름과 관련된 값

 

 

 

동작방식

1. 클라이언트 -> 페이지 request 요청

2. 서버에서 쿠키를 생성

3. http헤더에 쿠키를 포함해서 respond 응답

4. 브라우저가 종료되어도 쿠키의 기한이 정해져 있지 않고 명시적으로 지우지 않는다면 반 영구적으로 쿠키가 남아있게됨

클라이언트 요청(쿠키가지지 않은 상태)
------------->
쿠키와 함께 응답
<-------------
쿠키와 함께 요청
--------------->
응답(쿠키 가진 상태)
<---------------
서버

 

 

 

세션 

브라우저가 종료되기 전까지 클라이언트의 요청을 유지하게 해주는 기술

 

세션은 어쨌든 쿠키를 기반으로 하고 있음

서버측에서 관리하긴함

 

 

 

사용자 많아질수록 서버 메모리 많이 먹어

클라이언트한테 아이디부여하는데 그게 세션아이디임

 

동작방식

  1. 클라이언트가 서버에 로그인 요청
  2. 서버는 클라이언트의 로그인 요청의 유효성을 확인하고(아이디와 비밀번호 검사) unique한 id를 sessionid라는 이름으로 저장
  3. 서버가 응답할 때 응답헤더에 set-cookie: sessionid:a1x2fjz를 추가하여 응답

   4 . 클라이언트는 이후 서버에 요청할 때 전달받은 sessionid:a1x2fjz쿠키를 자동으로 요청헤더에 추가하여 요청

   5. 서버에서는 요청헤더의 sessionid 값을 저장된 세션저장소에서 찾아보고 유효한지 확인후 요청을 처리하고 응답

 

세션의 내용은 서버에 저장되기 때문에 계속하여 늘어날 경우 서버에 부하가 발생

 

 

쿠키와 세션의 차이점

가장 큰 차이점 정보가 저장되는 위치

 

저장위치

쿠키는 서버에 저장되지 않고 클라이언트 로컬에 저장됨

세션은 서버의 자원을 써서 로컬과 서버에 저장됨

 

장단점

보안면에서는 세션이 좋고

속도면에서는 쿠키가 빠름

 

세션은 쿠키를 이용해 id만 저장하고 서버에 저장해

세션도 만료시간 정할 수 있지만 브라우저가 종료되면 만료시간 상관없이 날라감

쿠키는 브라우저 종료해도 파일로 남아있음

 

 

 

얘를 보완해서 JWT가 나옴 책에도 나와~

 

 

 

 

 

책보면서 직접 코드 따라해보기

 

cookie.js  

const http = require("http");
http
  .createServer((req, res) => {
    console.log(req.url, req.headers.cookie);
    res.writeHead(200, { "Set-Cookie": "mycookie=test" });
    res.end("Hello Cookie");
  })
  .listen(8083, () => {
    console.log("8083번 포트에서 서버 대기 중입니다");
  });

 

터미널

 경로 입력하고 서버대기 중 확인

 

 

createServer 메서드의 콜백에서는 req 객체에 담겨있는 쿠키 가져옴

쿠키는

req.headers.cookie 에 들어있음

req.headers는 요청의 헤더 의미 (쿠키는 요청과 응답의 헤더를 통해 오감)

응답의 헤더에 쿠키를 기록해야 돼서

res.writeHead 메서드를 사용함 

"Set-Cookie": "mycookie=test" 는 "다음에 오는 쿠키를 저장해라 : 다음"

 

 

 

 

로컬주소에 접속

req.url과 req.headers.cookies에 대한 정보를 로깅하도록 함

req.url은 주소의 path와 search부분을 알림 (사실 이부분 이해안돼서 찾아봤는데 이해안됨 그래도 읽어보자)

아 이건인가봐 (뒤늦게 발견)

 

 

 

 

위 코드까지는 쿠키 심기만 한거고

그 쿠키가 나인지를 식별 못하고 있음

이제는 사용자를 식별하는 방법을 알아보자

 

cookie2.html

<!DOCTYPE html>
<html lang="ko">
  <head>
    <meta charset="UTF-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>쿠키&세션 이해하기</title>
  </head>
  <body>
    <form action="/login">
      <input id="name" name="name" placeholder="이름을 입력하세요" />
      <button id="login">로그인</button>
    </form>
  </body>
</html>

cookie2.js

const http = require("http");
const fs = require("fs").promises;
const url = require("url");
const qs = require("querystring");
//쿠키는 문자열임 이를 쉽게 사용하기 위해 js객체 형식으로 바꾸는  parseCookies함수
const parseCookies = (cookie = "") =>
  cookie
    .split(";")
    .map((v) => v.split("="))
    .reduce((acc, [k, v]) => {
      acc[k.trim()] = decodeURIComponent(v);
      return acc;
    }, {});
http
  .createServer(async (req, res) => {
    const cookies = parseCookies(req.headers.cookie);

    //주소가 /login으로 시작하는 경우,url과 querystring모듈로 각각 주소와 주소에 딸려오는 query분석한다
    if (req.url.startsWith("/login")) {
      const { query } = url.parse(req.url);
      const { name } = qs.parse(query);
      const expires = new Date();
      //쿠키 유효시간을 현재시간 +5분으로 설정
      expires.setMinutes(expires.getMinutes() + 5);
      //헤더에 302응답코드,리다이렉트 주소와 함께 쿠키를 넣어
      //브라우저는 이 응답코드를 보고 페이지를 해당주소로 리다이렉트함
      //헤더는 한글을 설정할 수 없어서 name변수를encodeURIComponent메서드로 인코딩함
      res.writeHead(302, {
        Location: "/",
        "Set-Cookie": `name=${encodeURIComponent(
          name
        )}; Expires=${expires.toGMTString()};HttpOnly;path=/`,
      });
      res.end();

      //그 외의 경우(/로 접속했을때 등),먼저 쿠키있나없나확인. 없으면 로그인할 수 있는페이지보냄
      //처음 방문한경우 쿠키없으므로 cookie2.html 전송됨 쿠키있다면 로그인한상태로 간주해인사말보냄
      //name이라는 쿠키가 있는 경우
    } else if (cookies.name) {
      res.writeHead(200, { "Content-Type": "text/plain;charset=utf-8" });
      res.end(`${cookies.name}님 안녕하세요`);
    } else {
      try {
        const data = await fs.readFile("./cookie2.html");
        res.writeHead(200, { "Content-Type": "text/html;charset=utf-8" });
        res.end(data);
      } catch (err) {
        res.writeHead(500, { "Content-Type": "text/plain;charset=utf-8" });
        res.end(err.message);
      }
    }
  })
  .listen(8084, () => {
    console.log("8084번 포트에서 서버 대기중입니다!");
  });

set-Cookie로 쿠키 설정할 때 

만료시간 expires 과 HttpOnly, Path같은 옵션 부여함

쿠키 설정할 때 각종 옵션 넣을 수 있고 옵션 사이 세미콜론(;) 써서 구분

쿠키에는 한글 쓰기, 줄바꿈 하면 안됨

  • 쿠키명=쿠키값  기본적 쿠키값 예) mycookie=test
  • Expires=날짜: 만료기한. 기본값은 클라이언트가 종료될 때까지
  • Domain= 도메인명:  쿠키가 전송될 도메인 특정할 수 있음. 기본값은 현재 도메인
  • Path=url : 쿠키가 전송될 url을 특정할 수 있음 기본값은'/'이고 이경우 모든 url에서 쿠키 전송할 수 있음
  • secure: HTTPS 일 경우에만 쿠키가 전송됨
  • HttpOnly: 설정 시 자바스크립트에서 쿠키에 접근할 수 없음 쿠키 조작을 방지하기 위해 설정하는 것이 좋음

 

 

 

 

 

이제 이름 노출안되는 버전

세션 방식.

const http = require("http");
const fs = require("fs").promises;
const url = require("url");
const qs = require("querystring");

const parseCookies = (cookie = "") =>
  cookie
    .split(";")
    .map((v) => v.split("="))
    .reduce((acc, [k, v]) => {
      acc[k.trim()] = decodeURIComponent(v);
      return acc;
    }, {});

const session = {};
http
  .createServer(async (req, res) => {
    const cookies = parseCookies(req.headers.cookie);
    if (req.url.startsWith("/login")) {
      const { query } = url.parse(req.url);
      const { name } = qs.parse(query);
      const expires = new Date();
      expires.setMinutes(expires.getMinutes() + 5);
      const uniqueInt = Date.now();
      session[uniqueInt] = {
        name,
        expires,
      };
      res.writeHead(302, {
        Location: "/",
        "Set-Cookie": `session=${uniqueInt}; Expires=${expires.toGMTString()};HttpOnly;Path=/`,
      });
      res.end();
      //세션 쿠키가 존재하고 만료기간이 지나지 않았다면
    } else if (
      cookies.session &&
      session[cookies.session].expires > new Date()
    ) {
      res.writeHead(200, { "Content-Type": "text/plain; charset=utf-8" });
      res.end(`${session[cookies.session].name}님 안녕하세요`);
    } else {
      try {
        const data = await fs.readFile("./cookie2.html");
        res.writeHead(200, { "Content-Type": "text/html;charset=utf-8" });
        res.end(data);
      } catch (err) {
        res.writeHead(500, { "Content-Type": "text/plain;charset=utf-8" });
        res.end(err.message);
      }
    }
  })
  .listen(8085, () => {
    console.log("8085번 포트에서 서버 대기 중입니다");
  });

 

코드 따라썼는데 자꾸 안된다고 에러뜸 

바로 이 에러~!!

NodeJS address already in use 

찾아서 따라해서 이전 포트? 종료하고 다시 함

로컬주소 들어가서 정보 입력하니까!

 

 아까 넣었던 쿠키 위에 쌓였다.

이 방식이 세션임

 

 

아까랑 다른 건 쿠키에 이름을 담아서 보내는 대신, uniqueInt라는 숫자값을 보냄. 사용자의 이름과 만료시간은 uniqueInt 속성명 아래에 있는 session이라는 객체에 대신 저장함

이제 cookie.session이 있고 만료기한 넘기지 않았으면 session 변수에서 사용자 정보를 가져와 사용한다.

 

 

안전하게 사용하기 위해서는 다른 사람들이 만든 검증된 코드를 사용하는게 좋대

그건 책 5장에서~~~

 

 

 

 

 

 

 

 

그.런.데.

내가 코드를 다 이해했다? 전혀 아니지요.

 

map 메서드

배열.map((요소, 인덱스, 배열) => { return 요소 });

const oneTwoThree = [1, 2, 3];
let result = oneTwoThree.map((v) => {
  console.log(v);
  return v;
});
// 콘솔에는 1, 2, 3이 찍힘
oneTwoThree; // [1, 2, 3]
result; // [1, 2, 3]
oneTwoThree === result; // false

reduce 메서드

배열.reduce((누적값, 현잿값, 인덱스, 요소) => { return 결과 }, 초깃값);

result = oneTwoThree.reduce((acc, cur, i) => {
  console.log(acc, cur, i);
  return acc + cur;
}, 0);
// 0 1 0
// 1 2 1
// 3 3 2
result; // 6

acc(누적값)이 초깃값인 0부터 시작해서 return하는대로 누적되는 것을 볼 수 있습니다. 초깃값을 적어주지 않으면 자동으로 초깃값이 0번째 인덱스의 값이 됩니다.

 

그렇다고 함 이것이 바로 설명 링크.. 읽어도 잘모르겠지만 암튼 보자 

 

 

 

 

 

 

 

NodeJS address already in use 문제 해결 - JooTC

NodeJS address already in use 문제 해결 방법 Error: listen EADDRINUSE: address already in use :::5000 현재 다른 프로세스에서 사용 중이라 해당 서비스를 시작할 수 없다는 에러입니다.

jootc.com

 

 

 

 

 

출처

728x90
728x90

개념 정리 <Node.js교과서>- 조현영 지음 책 요약

 

Node.js®는 Chrome V8 JavaScript 엔진으로 빌드된 JavaScript 런타임입니다.

 

 

기본개념

 

1.서버

네트워크를 통해 클라이언트레 정보나 서비스를 제공하는 컴퓨터 또는 프로그램

 

노드는 서버 애플리케이션 실행하는데 제일 많이 사용됨.

서버는 클라이언트의 요청에 대해 응답해야 함. 

 

 

2. 자바스크립트 런타임

노드는 자바스크립트 런타임. 런타임은 특정 언어로 만든 프로그램들을 실행할 수 있는 환경을 뜻함

 

 

<노드의 내부 구조>

Node.js Core Library
Node.js Bindings
V8 (  -> 오픈소스 자바스크립트 엔진) libuv (  -> 비동기 I/O)

 

3. 이벤트 기반 event-driven

이벤트(클릭, 네트워크 요청 등과 같은)가 발생할 때 미리 지정해둔 작업을 수행하는 방식 의미한다.

특정 이벤트가 발생할 때 무엇을 할지 미리 등록해놔야하는데 이걸 이벤트 리스너에 콜백함수를 등록한다고 표현한다.

발생한 이벤트가 없거나 발생했던 이벤트를 다 처리하면 노드는 다음 이벤트가 발생할 때까지 대기.

 

<이벤트 기반>

시스템 2. 이벤트 발생
--------------------->

<---------------------
3. 등록된 콜백함수 호출
이벤트 리스너

1. 이벤트 리스너에 콜백함수 등록

이벤트 기반 모델에서는 이벤트 루프라는 개념 등장. 여러 이벤트 동시발생시 어떤 순서로 콜백함수를 호출할지를 이벤트 루프가 판단함.  노드와 자바스크립트에서 이벤트 루프는 정말 중요 개념~!

 

이벤트 루프:
이벤트 발생시 호출할 콜백 함수들을 관리하고, 호출된 콜백 함수의 실행순서결정하는 역할 담당. 노드가 종료될 때까지 이벤트 처리위한 작업을 반복해서 루프라고 부름.
백그라운드:
setTimeout 같은 타이머나 이벤트 리스너들이 대기하는 곳. 자바스크립트가 아닌 다른 언어로 작성된 프로그램이라고 봐도 된다. 여러 작업이 동시에 실행될 수 있음
테스크 큐:
이벤트 발생 후, 백그라운드에서는 테스크 큐로 타이머나 이벤트 리스너의 콜백 함수를 보낸다. 정해진 순서대로 콜백들이 줄 서 있어서 콜백 큐라고 부른다. 보통은 완료된 순서대로 서있지만 특정한 경우 순서 바뀌기도함.

 

4. 논 블로킹 I/O 

 

작업은

동시에 실행될 수 있는 작업과

동시에 실행될 수 없는 작업있음 

 

자바스크립트 코드는 동시에 실행될 수 없음

하지만 js상에서 돌아가는게 아닌 입력Input 출력Output 작업같은 건 동시처리 가능

 

(파일 시스템 접근이나 네트워크를 통한 요청 같은 작업이 I/O의 일종)

 

이런 작업시 노드는 

논블로킹 방식으로 처리하는 방법을 제공한다. 

 

<백그라운드 작업완료 확인 여부>
논블로킹:
이전 작업이 완료될 때까지 대기하지 않고 다음작업 수행
블로킹:
이전 작업 끝나야만 다음작업 수행

 

 

노드는 I/O 작업을 백그라운드로 넘겨 동시에 처리하곤 함.

작업 순서에 따라 작업 시간 단축되어 성능 크게 달라짐! 동시에 처리될 수 있는 I/O 작업이라도 논블로킹 방식으로 코딩하지 않으면 의미 퇴색되므로 논 블로킹 방식으로 코딩하는 습관 들이기!!

 

하지만 아무리 논블로킹 방식으로 코드 작성해도 우리가 전부 작성한 코드는 서로 동시에 실행되지 않기에 소요시간이 짧아지진 않는다. 실행 순서만 바뀔뿐. 그래도 논블로킹을 통해 실행 순서를 바꿔줌으로써 그 작업 때무에 간단한 작업들이 대기하는 상황을 막을 수 있다는 점에서 의의가 있다. 

논블로킹과 동시가 같은 의미가 아니라는 것도 알아두기 . 동시성은 동시 처리가 가능한 작업을 논 블로킹 처리해야 얻을 수 있음.

노드에서는 동기와 블로킹이 유사하고 비동기와 논블로킹이 유사함.

<함수가 바로 return되는지 여부>
동기(synchronous : 동시에 일어나는):
블로킹 방식에서는 백그라운드 작업 완료 여부를 계속 확인하며, 호출한 함수가 바로 return되지 않고 백그라운드 작업이 끝나야 return된다. 
비동기(Asynchronous : 동시에 일어나지 않는):
논블로킹 방식에서는 호출한 함수가 바로 return되어 다음 작읍으로 넘어가며, 백그라운드 작업 완료 여부는 신경쓰지 않고 나중에 백그라운드가 알림을 줄 때 비로소 처리함.

 

동기:  요청과 결과가 한 자리에서 동시에 일어남.설계가 매우 간단하고 직관적이지만 과가 주어질 때까지 아무것도 못하고 대기해야 하는 단점이 있고, 

비동기:  요청한 그 자리에서 결과가 주어지지 않음 동기보다 복잡하지만 결과가 주어지는데 시간이 걸리더라도 그 시간 동안 다른 작업을 할 수 있으므로 자원을 효율적으로 사용할 수 있는 장점이 있습니다.
출처: https://private.tistory.com/24 [공부해서 남 주자]

 

 

 

5. 싱글스레드

 

스레드가 하나뿐이라는 것.

 

프로세스:  운영체제에서 할당하는 작업의 단위.

노드나 웹브라우저 같은 프로그램은 개별적인 프로세스임. 프로세스 간에는 메모리등의 자원 공유안해

스레드: 프로세스 내에서 실행되는 흐름의 단위.

프로세스는 스레드를 여러 개 생성해 여러 작업을 동시에 처리할 수 있음. 스레드들은 부모 프로세스의 자원공유해. 같은 주소의 메모리에 접근 가능해 데이터를 공유할 수 있어

 

 

 

노드는 싱글 스레드?

엄밀히 말하면 싱글 스레드로 동작하지 않음

노드를 실행하면 먼저 프로세스 하나 생성됨 그 프로세스 안에서 스레드 여러개 생성함 . 우리가 직접 제어할 수 있는 스레드는 하나뿐! 그래서 흔히 노드가 싱글 스레드라고 여겨짐.

스레드는 작업을 처리하는 일손. 하나의 스레드만 직접 조작할 수 있으니까 일손이 하나인 것임.

블로킹이 발생할 것 같은 경우에는 논블로킹 방법으로 대기시간을 최대한 줄인다. 

 

 

<노드가 싱글 스레드로 동작하지 않는 두 가지 경우>

스레드풀(Thread Pool)

노드가 특정 동작을 수행할 때 스스로 멀티 스레드를 사용한다. 대표적인 예로 암호화(3.5.5절), 파일입출력(3.6절),압축(3.6.2절) 등이 있다

워커 스레드(Worker Thread)

이제 노드에서도 멀티 스레드를 사용할 수 있게한 기능. 우리가 직접 다수의 스레드를 다룰 수 있음. CPU 작업(연산이 많은 작업)이 많은 경우 워커 스레드를 사용하면 된다.

 

 

 

서버로서의 노드

 

노드는 기본적으로 싱글 스레드, 논블로킹 모델을 사용함. 

따라서 노드 서버의 장단점은 싱글 스레드, 논블로킹 모델의 장단점과 비슷함.

 

노드는 CPU부하가 큰 작업에는 적합하지 않음 연산을 많이 요구하면 스레드 하나가 혼자 감당하기 어려워!

노드는 개수는 많지만 크기는 작은 데이터를 실시간으로 주고받는데 적합함.

네트워크나 데이터베이스, 디스크 작업 같은 I/O에 특화되어있음

 

<노드의 장단점>

장점 단점
멀티 스레드 방식에 비해 적은 컴퓨터 자원 사용 기본적으로 싱글 스레드라서 CPU코어를 하나만 사용
I/O 작업이 많은 서버로 적합 CPU작업이 많은 서버로는 부적합
멀티 스레드 방식보다 쉬움 하나뿐인 스레드가 멈추지 않도록 관리가 필요함
웹 서버가 내장되어있음 서버 규모가 커졌을 때 서버를 관리하기 어려움
자바스크립트를 사용함 어중간한 성능
JSON형식과 쉽게 호환됨  

 

 

 

 

 

 

 

728x90

+ Recent posts