라벨이 node js인 게시물 표시

NestJS Redis Pub/Sub과 Cluster로 SocketIO 채팅 앱 만들기 -2

 이제 본격적으로 Cluster를 이용한 채팅앱 서버를 만들도록 하겠습니다. 처음 이글을 보시는 분들은 이전글을 참고해 주시기 바랍니다. 링크 : NestJS Redis Pub/Sub과 Cluster로 SocketIO 채팅 앱 만들기 -1 제 컴퓨터는 12개의 코어를 갖고 있기 때문에 12개의 Workers를 만듭니다. 먼저 src경로에 'app-cluster.service.ts'를 만들어 줍니다. // src/app-cluster.service.ts import { Injectable } from '@nestjs/common' ; import * as os from 'os' ; const cluster = require ( 'cluster' ); // nodejs의 cluster를 사용 const numCPUs = os . cpus (). length ; // 현재 os의 cpu갯수 확인 @ Injectable () export class AppClusterService { static clusterize ( callback : Function ): void { console . log ( '총 cpu갯수 : ' , numCPUs ); if ( cluster . isMaster ) { console . log ( `Master server started on ${ process . pid } ` ); for ( let i = 0 ; i < numCPUs ; i ++) { cluster . fork (); } cluster . on ( 'exit' , ( worker , code , signal ) => { // 워커가 죽을시 console . log ( `Worker ${ worker . process . pi...

NestJS Redis Pub/Sub과 Cluster로 SocketIO 채팅 앱 만들기 -1

이미지
 채팅앱을 만드는 법은 이전글에도 설명을 했지만 멀티 Cluster를 사용하여 채팅앱의 효율을 극대화 하기 위해서 글을 작성합니다. 위 블로그는 이전에 작성한 채팅앱을 기준으로 프로그래밍을 합니다. 해당 자료는 아래 링크를 참고해 주시기 바랍니다. 링크0 : NestJS Redis Pub/Sub과 socketIO로 채팅 앱 만들기 -0 링크1 : NestJS Redis Pub/Sub과 socketIO로 채팅 앱 만들기 -1 링크2 : NestJS Cluster를 이용하여 CPU최대로 활용하기 사진1) 개선된 채팅앱 백엔드 구조도  사진1을 확인할때 이전 채팅앱과 다른점은 서버가 1개 이상이라는 것입니다. 서버안에 Worker가 있는데 이것은 PID가 다른 NestJS프로그램입니다. 해당 서버의 CPU코어수에 따라 Worker를 생성할수 있으며 각각의 워커는 채팅앱 백엔드를 구성합니다.  만약 PubSub기능을 사용하지 않고 그대로 한다면 문제점이 생깁니다.  사진2) PubSub을 사용하지 않을시 문제점 사진2에서 SocketIO 1을 통해서 데이터가 Worker 1으로 전송이 되면 서버를 통해서 Redis에 저장도비니다. 그러면 Server1의 Worker1만 제외하고 나머지 Worker는 Redis의 데이터를 읽기전까지 데이터가 변경 된것을 모르게 됩니다. 사진3) PubSub을 적용후 데이터 흐름 사진2와 달리 사진3은 PubSub기능을 적용한 데이터 흐름도 입니다. SocketIO 1이 Worker1을 통해 Redis에 Publish합니다. 그러면 Redis는 이 데이터를 해당 채널에 SubScribe하는 Worker에 전달합니다. 필요시 Publish한 서버에도 전송합니다. 사진3에서 SubScribe 서버는 Server1과 Server2입니다. 즉 Server에 연결된 모든 Worker가 SocketIO1(Server1)의 Publish 한 데이터를 알수있습니다. 이전...

NestJS Redis Pub/Sub과 socketIO로 채팅 앱 만들기 -1

이미지
 안녕하세요. 이번에는 NestJS와 Redis의 Pub/Sub기능을 이용하여 채팅 채널을 만들도록 하겠습니다. 채팅 채널을 테스트히기 위한 툴로는 Postman을 사용할 것이며 자세한 내용은 아래 링크를 참고해 주시기 바랍니다. 링크 : Postman 소켓IO 테스트하기 그리고 이전글을 참고하실려면 아래 링크를 확인해 주시기 바랍니다. 링크 : NestJS Redis Pub/Sub과 socketIO로 채팅 앱 백엔드 만들기 -0 일단 현재 블로그에서 작성하는 Node버전은 16.17.0이며 NestJS버전은 9.1.2입니다. 프로젝트를 생성(위 블로그에서는 nestjs-microservice-example)하고 필요한 npm모듈을 설치합니다. socketIO모듈을 설치할때는 아래 링크를 참고해 주시기 바랍니다. 링크 : NestJS SocketIO - 방을 선택해서 들어가는 채팅방 만들기 위 사항이 마무리 되면 microservice 모듈을 설치합니다. - @nestjs/microservices npm 설치 $ npm i --save @nestjs/microservices copy - redis바탕으로 microservices를 구상할때 설치 $ npm i --save ioredis copy 먼저 최상단 루트에 .development.env파일을 만들어주고 아래와 같이 작성합니다. NESTJS_PORT=4500 REDIS_PORT=6379 REDIS_HOST="localhost" NestJS_PORT가 4500이지만 추가로 실행할 서버는 포트번호를 다르가 하면서 추가하시면 됩니다. 사진1) 백엔드 구성 사진1은 개발할려는 기본적인 백엔드 구조 입니다. 모듈안에는 컨트롤러와 웹소켓 서버(socketio.gateway)가 있는데 기본적으로 웹소켓이 채팅앱입니다.  다만 Redis에서 데이터를 Subscribe는 socket_publish에서 받고나서 socketio.ga...

NestJS Redis Pub/Sub과 socketIO로 채팅 앱 백엔드 만들기 -0

이미지
 안녕하세요 알렉스 입니다. 이번에는 채팅앱 백엔드를 만들면서 백엔드를 구현하도록 하겠습니다. 백엔드를 NodeJS로 구현을 할때 문제점은 NodeJS가 싱글스레드라는 것입니다. 이는 아래 링크를 참고해 주시기바랍니다. 링크 : Node JS의 싱글스레드 -1 쉽게 말해서 CPU가 한번에 한가지 일만 한다는 것입니다. 물론 NodeJS가 빠르기는 하지만 한번에 많은 부하가 가해지면 서버가 다운될 위험이 있습니다.  사진1) 서버 한개로 채팅앱 구현  만약 서버 하나로만 채팅앱을 구현할때 단일 서버 또는 SocketIO로 많은 부하가 가해질수 있고 이로 인해서 서버가 다운 될수가 있습니다. 사진2) 채팅앱 백엔드 구조 이를 위해 Redis의 Pub/Sub기능을 이용하여 채팅앱을 분산(or MicroService)하여 개발할 것입니다. 사진2의 NestJS-1, NestJS-2, NestJS-3은 코드는 같지만 각각 다른 서버 또는 포트에서 동작하고 있는 프로그램 입니다. 각각의 서버는 SocketIO서버를 통해서 유저들과 통신을 하게 됩니다. 이때 user1이 작성한 내용은 Redis에 Publish되고 NestJS2, 3에 Subscribe되서 해당되는 유저들도 데이터를 전달 받습니다. 즉 각 서버는 분리되어있지만 Redis의 Pub/Sub기능으로 인해 데이터를 즉각적으로 공유할수 있습니다. 물론 NodeJS은 싱글 스레드이지만 여러개의 스레드를 동시에 사용할수 있습니다. 그러면 1개의 서버를 사용해도 부담이 적죠. 하지만 그것에 대한 내용은 나중에 작성하도록 하겠습니다. 이번 시리즈는 싱글스레드 NestJS을 이용해서 분산 채팅앱을 만드는것에 집중하도록 하겠습니다. 다음글 : NestJS Redis Pub/Sub과 socketIO로 채팅 앱 만들기 -1 

Session authentication(세션 인증) JavaScript 코드

이미지
 안녕하세요. 저번 글에 이어서 실제로 세션을 이용하여 코드를 작성하도록 하겠습니다.  세션에 대한 개념적 설명을 링크 를 참고해 주시기 바랍니다. 먼저 npm init을 진행합니다. npm 초기화 방법은 링크 를 참고해 주시기 바랍니다. 4개의 npm 모듈을 설치합니다. express, express-session, cookie-parser, nodemon 이중 nodemon은 해당 링크 에서 설치 및 사용법이 나와 있습니다. 설치가 완료가 된 다음 위와 같이 index.js파일을 만들어줍니다. const express = require ( "express" ); const session = require ( "express-session" ); const cookieParser = require ( "cookie-parser" ); const app = express (); const PORT = 5000 ; // 서버 동작을 확인하기 위한 파트 app . get ( '/' , ( req , res ) => { res . status ( 200 ); res . send ( "<h1>Working Well</h1>" ) }) app . listen ( PORT , () => console . log ( `Server at ${ PORT } ` )); 위 코드와 같이 작성하고 테스트를 합니다.  위 2개 사진과 같이 서버도 정상 동작 되고 root url의 get 요청도 정상적으로 되었습니다. const express = require ( "express" ); const session = require ( "express-session" ); const cookieParser = require ( "cookie-pars...

Node JS의 Non Blocking(논 블로킹)

이미지
 안녕하세요. 이번 포스트는 저번의 싱글스레드의 연장선이라고 보시면 됩니다. 참고 하실분은 이전 글 링크를 참고 해 주시기 바랍니다. Node JS의 싱글스레드 - 1 Node JS의 싱글스레드 - 2 이번 글의 주제는 Non Blocking에 대한 것입니다. 그런데 Non Blocking이전에 일단 Blocking에 대해서 알아야 합니다. 위 그림은 블로킹 상태를 말하는 것입니다. 하나의 스레드에 하나의 작업만 가능하기 때문에 다음 작업을 진행하기 위해서는 현재의 작업이 마무리 되야 되는 것입니다.  하지만 논 블로킹 방식은 요청을 받으면 바로 진행을 하고 끝나는 순서로 Client에 응답을 합니다.  저번 싱글스레드 주제로 이야기 할때 이상한 점이 있었습니다. 점원은 한명인데 어떻게 동시에 여러잔의 커피를 만드는 것에 대한 이야기 입니다. 직원으로 이야기 하면 어렵지만 Node JS에서 이야기가 달라집니다.  서버에서 CPU가 맡은 작업과 IO가 맡은 작업이 있습니다. 이때 Client에서 요청이 들어오면 CPU에서 연산을 하고 완료가 되면 이를 IO쪽으로 넘김니다. 이후 IO에서도 작업이 완료되면 다시 CPU로 보내서 마무리 하고 응답을 하게 됩니다.   NodeJS은 싱글 스레드이기 때문에 하나의 스레드로 모든 요청 작업을 감당해야 합니다. 즉 위의 그림처럼 3개의 Client의 요청이 왔을때 요청 순서 및 작업이 끝나는 순서대로 응답을 보내게 됩니다.  즉 이처럼 논 블로킹을 이용하여 Node JS서버는 상당한 효율을 발휘합니다. 하지만 고사양의 연산이 필요한 어플리케이션 인 경우 CPU에서 다른 연산을 막을수 있기 때문에 효율이 좋지 않다. 즉 상황에 맞게 사용해야 하는 것이다. 

Node JS의 싱글스레드 - 2

이미지
 안녕하세요. 이번에는 싱글 스레드로 동작되는 Node JS에 오래 걸리는 작업의 요청이 들어올때 어떻게 대응하는지를 알아보겠습니다.  이번에도 모든 요청을 받습니다. 그런데 Client2 손님의 요청사항은 다른 손님의 요청에 비해 상당히 깁니다.  일단 요청 사항에 대해서 진행을 하고 가장 짧은 아이스 아메리카노를 Client1 손님한테 드립니다.   그런데 Client2 손님한테 음료를 주는것이 아닌 Client3 손님의 음료를 먼저 줍니다. 이유는 악마의 음료의 시간이 아이스 카페라테에 비해 훨씬 길기 때문에 먼저 완료된 요청사항 순서로 진행이 되기 때문입니다. Client3손님은 Client2손님의 음료가 나올때까지 기다릴 필요없이 완료되자마자 음료를 받을수 있습니다.  이제 마지막 Client2의 손님이 원하는 음료를 받게 됩니다. 이처럼 Node JS는 모든 요청을 다 받지만 그렇다고 요청의 순서대로 응답을 하지 않습니다. 먼저 끝나는 작업 순으로 Node가 응답을 보내는 것입니다.   위 과정을 커피점으로 묘사해서 설명을 했지만 실제로는 생략된 내용이 있습니다. 자세한 내용은 다음 Node JS에 대해서 글을 작성할때 설명 드리겠습니다. 다음글 : Node JS의 Non Blocking(논 블로킹)

Node JS의 싱글스레드 - 1

이미지
 안녕하세요. 알렉스 입니다. 이번에는 Node.JS가 왜 싱글스레드를 채용하고 개념에 대해서 알아보도록 하겠습니다.  일단 스레드를 일종의 직원이라고 보면 됩니다. 스레드가 많을수록 일하는 직원이 많아지는 것인데 Node JS는 단일 스레드를 채택했습니다. 위 그림에서 Client1이 아이스 아메리카를 주문하고 있습니다. 이때 Node직원이 응답을 하고 아이스 아메리카노를 만듭니다. 첫 그림의 메뉴에서 아이스 아메리카노는 약 10초간의 시간이 소요됩니다.  10초가 지난후 Node직원은 아이스 아메리카노를 Client1에 제공을하고 이후 업무를 종류하게 됩니다. 하지만 지금은 단일 client1의 요청이고 복수의 요청이 들어오면 어떻게 될까요? 위 그림처럼 여러 client가 줄지어 요청을 할때 Node가 첫번째 client의 요청을 듣고 작업을 수행한후 완료할때까지 10초가 걸립니다. 그리고 다음 손님또한 요청을 받고 그만큼 시간이 걸립니다. 이때 마지막 손님은 앞의 모든 손님들의 주문이 완료될때까지 기다려야하는데 그렇게 되면 인내심이 바닥나서 가게를 나갈수가 있습니다.  일단 주문을 한꺼번에 받습니다. 그리고 바로 받은 요청에 대해서 작업을 실행합니다.   첫 줄의 손님은 아이스 아메리카노를 요청했기 때문에 10초만에 음료가 준비 됩니다. 두번째, 세번째 손님도 주문한 순서대로 음료를 받게 됩니다. 하지만 중간에 상당히 오래 걸리는 주문을 하게 되면 어떻게 될까요. 순차적으로 주문을 받는데 중간에 악마의 음료를 주문해서 그 뒤로 주문한 사람이 오랫동안 기다려야 할까요? 이 내용은 다음 블로그 글에서 알려드리도록 하겠습니다. 다음글 : Node JS의 싱글스레드 -2

Ubuntu에서 동작되는 PORT를 터미널로 종료(kill)

이미지
  위 터미널을 이용하여 6000포트를 이용하여 http서버를 임시적으로 만든다. 다른 터미널을 열서 똑같은 6000포트의 http서버를 만든다. 하지만 이미 이전 터미널에서 6000포트를 이미 잡기 때문에 해당 포트를 강제로 종료하는 명령어를 사용해야 한다. 실제 포트 6000에 어떻게 잡고있는지 확인해야한다. 터미널에 입력할 키워드는 아래와 같다 $ lsof -i TCP:[Port Number : 위 사진에서는 6000] | grep LISTEN 이제 다음에 나온 터미널 결과는 아래와 같다 node    21478 alex   21u  IPv6 189694      0t0  TCP *:x11 (LISTEN) 여기서 2번째 column에 주목해야 한다. 21478은 PID이다. 이 PID number를 이용하여 해당 포트를 kill할수 있다. 아래 터미널 키워드를 입력하여 해당 포트(여기서는 6000)를 종료할수 있다. $ kill -9 [PID number : 여기서는 21478] 또는 궂이 확인을 안하고 바로 종료하는 방법이 있다. 아래 터미널 키워드를 입력하여 해당 포트(여기서는 6000)를 종료할수 있다. $ kill -9 $(lsof -i TCP:[Port Number : 위 사진에서는 6000] | grep LISTEN | awk '{print $2}')

node js를 localhost가 아닌 웹상에 직접 올리는 방법(PC이용)

이미지
 node js로 작업을 하다보면 항상 localhost:[포트번호] 로 진행하는 경우가 대다수이다. 물론 혼자서 작업을 한다면 상관이 없지만 협업을 하는 상황이면 Front-End와 Back-End 사이의 테스트를 진행해야 한다. AWS를 이용한 테스트는 복잡하고 시간이 걸리기 때문에 최종작업에서 시행하는게 낳다고 생각한다.  따라서 이번 글은 본인의 PC를 서버로 만들어 테스트 할수 있는 환경을 작성하도록 하겠다. const express = require ( 'express' ); // middleware const app = express (); const PORT = 5000 ; // 서버 체크 app . get ( '/' , ( req , res ) => { console . log ( "GET Request from Client" ); res . send ( '<h1>Server is Working</h1>' ) }) app . listen ( PORT , () => { console . log ( `Server is starting ${ PORT } ` ); }); 위는 매우 간단한 node js를 이용한 localhost서버를 만든 것이다.  포트는 5000번이며 GET요청을 할시 Client쪽에서는 'Server is Working'의 글자가 보이게 된다. 이제 현재 localhost:5000의 IP를 전세계 어디서나 접속할수 있는 웹으로 만들자. 먼저 Global로 localtunnel을 설치한다. - terminal: npm i -g localtunel localhost에서만 구동되는 5000포트를 전세계 web상으로 올린다.  'your url is : ' 이후에 나오는 웹 주소는 실제 전세계 어디서나 접속할수 있는 주소 이다. - terminal: lt --port 5000 처음 ...