댓글 검색 목록

[Nodejs] Node.js 및 웹 소켓을 사용하여 전문적인 채팅 API를 작성하는 방법

페이지 정보

작성자 운영자 작성일 20-06-21 13:17 조회 768 댓글 0

NodeJS에서 소켓을 사용하여 전문 채팅 API 솔루션을 만드는 방법 [초보자 수준] 


https://www.freecodecamp.org/news/create-a-professional-node-express/ 


채팅 응용 프로그램이 무대 뒤에서 어떻게 작동하는지 궁금한 적이 있습니까? 오늘은 MongoDB를 사용하여 NodeJS / ExpressJS 위에 빌드 된 REST + 소켓 기반 애플리케이션을 작성하는 방법에 대해 설명하겠습니다.


나는 지금이 기사의 내용을 일주일 이상 연구 해 왔으며, 그것이 누군가를 도울 수 있기를 바랍니다.


전제 조건 


  • 컴퓨터에 Mongodb 설정 [설치 안내서 작성]
  • Windows 사용자의 경우 설치 안내서를 찾을 수 있습니다. [여기]
  • macOS 사용자의 경우 설치 안내서를 찾을 수 있습니다. [여기] [필요한 시점까지]
  • Linux 사용자의 경우 설치 안내서를 찾을 수 있습니다. [여기]
  • 컴퓨터에 노드 / NPM 설치 [설치 링크는 여기에 있습니다 (노드 버전 v12.18.0을 사용하고 있습니다)

우리가 다룰 주제 


일반 


  • express 서버 만들기
  • API 유효성 검사를 수행하는 방법
  • 전체 애플리케이션을위한 기본 스켈레톤 생성
  • MongoDB 설정 (설치, express설정)
  • 사용자 API + 데이터베이스 작성 (사용자 작성, id로 사용자 가져 오기, 모든 사용자 가져 오기, id로 사용자 삭제)
  • 미들웨어가 무엇인지 이해
  • JWT (JSON 웹 토큰) 인증 (디코딩 / 인코딩)-로그인 미들웨어
  • 사용자가 연결을 끊고, ID를 추가하고, 대화방에 참여하고, 대화방을 음소거 하려고 할 때 이벤트를 처리하는 웹 소켓 클래스
  • 대화방 및 대화 메시지 데이터베이스 모델 논의

API 


  • 사용자 간 대화 시작
  • 대화방에서 메시지 작성
  • ID별로 대화방 대화보기
  • 전체 대화를 읽은 것으로 표시합니다 (Whatsapp와 유사)
  • 모든 대화에서 최근 대화 받기 (Facebook 메신저와 유사)

Bonus  - API  


  • 모든 관련 메시지와 함께 ID별로 대화방 삭제
  • 아이디로 메시지 삭제

시작하기 전에 다음 비디오에서 몇 가지 기본 사항을 다루고 싶었습니다.


ExpressJS의 기본 이해 


경로는 무엇입니까? 컨트롤러? CORS (Cross Origin Resource Sharing)를 어떻게 허용합니까? 최종 사용자가 API 요청에서 JSON 형식으로 데이터를 보내도록 하려면 어떻게 해야 합니까?


이 비디오에서 이 모든 것 (REST 규칙 포함)에 대해 이야기합니다.



또한, 이 비디오의 전체 소스 코드에 대한 GitHub 링크가 있습니다 [0 장]


"Chapter 0"소스 코드에 대한 README.md를 살펴보십시오. 비디오에서 언급 한 모든 관련 학습 링크와 우편 배달부에 대한 놀라운 30 분 자습서가 있습니다.


API 엔드 포인트에 API 유효성 검사 추가 


아래 비디오에서 "make-validation"이라는 라이브러리를 사용하여 사용자 정의 유효성 검사를 작성하는 방법을 배웁니다.



다음은 이 비디오의 전체 소스 코드에 대한 GitHub 링크입니다 [0 장].


다음은 make-validation 라이브러리 링크 [GitHub] [npm] [example]입니다.


이 튜토리얼의 전체 소스 코드는 여기에서 찾을 수 있습니다. 의견이 있으시면 http://twitter.com/adeelibr에서 저에게 연락하십시오. 이 튜토리얼을 좋아한다면 github 저장소에 별표를 남겨주세요.


ExpressJS의 기본 사항과 사용자 응답의 유효성을 검사하는 방법에 대해 알아 보겠습니다.



시작하기 


chat-app라는 폴더를 만듭니다.


mkdir chat-app;
cd chat-app;

다음을 입력하여 프로젝트 루트 폴더에서 새 npm 프로젝트를 초기화하십시오.

npm init -y

다음 패키지를 설치하십시오.

npm i cors @withvoid/make-validation express jsonwebtoken mongoose morgan socket.io uuid --save;
npm i nodemon --save-dev;

그리고 package.json scripts 섹션에서 다음 두 스크립트를 추가하십시오.


"scripts": {
	"start": "nodemon server/index.js",
	"start:server": "node server/index.js"
},

package.json은 이제 다음과 같이 보일 것입니다 :


{
  "name": "chapter-1-chat",
  "version": "0.0.0",
  "private": true,
  "type": "module",
  "scripts": {
    "start": "nodemon server/index.js",
    "start:server": "node server/index.js"
  },
  "dependencies": {
    "@withvoid/make-validation": "1.0.5",
    "cors": "2.8.5",
    "express": "4.16.1",
    "jsonwebtoken": "8.5.1",
    "mongoose": "5.9.18",
    "morgan": "1.9.1",
    "socket.io": "2.3.0",
    "uuid": "8.1.0"
  },
  "devDependencies": {
    "nodemon": "2.0.4"
  }
}

이제 프로젝트의 루트 폴더에 server라는 새 폴더를 만듭니다.

cd chat-app;
mkdir server;
cd server;

서버 폴더 안에 index.js라는 파일을 만들고 다음 내용을 추가하십시오.

import http from "http";
import express from "express";
import logger from "morgan";
import cors from "cors";
// routes
import indexRouter from "./routes/index.js";
import userRouter from "./routes/user.js";
import chatRoomRouter from "./routes/chatRoom.js";
import deleteRouter from "./routes/delete.js";
// middlewares
import { decode } from './middlewares/jwt.js'

const app = express();

/** Get port from environment and store in Express. */
const port = process.env.PORT || "3000";
app.set("port", port);

app.use(logger("dev"));
app.use(express.json());
app.use(express.urlencoded({ extended: false }));

app.use("/", indexRouter);
app.use("/users", userRouter);
app.use("/room", decode, chatRoomRouter);
app.use("/delete", deleteRouter);

/** catch 404 and forward to error handler */
app.use('*', (req, res) => {
  return res.status(404).json({
    success: false,
    message: 'API endpoint doesnt exist'
  })
});

/** Create HTTP server. */
const server = http.createServer(app);
/** Listen on provided port, on all network interfaces. */
server.listen(port);
/** Event listener for HTTP server "listening" event. */
server.on("listening", () => {
  console.log(`Listening on port:: http://localhost:${port}/`)
});

indexRouter userRouter chatRoomRouter & deleteRouter의 경로를 추가해 봅시다.


프로젝트의 루트 폴더에 경로라는 폴더를 만듭니다. 경로 폴더 안에 다음 파일을 추가하십시오.


  • index.js
  • user.js
  • chatRoom.js
  • delete.js


routes / index.js의 내용을 먼저 추가해 봅시다 :


import express from 'express';
// controllers
import users from '../controllers/user.js';
// middlewares
import { encode } from '../middlewares/jwt.js';

const router = express.Router();

router
  .post('/login/:userId', encode, (req, res, next) => { });

export default router;

다음으로 routes / user.js에 컨텐츠를 추가해 봅시다 :

import express from 'express';
// controllers
import user from '../controllers/user.js';

const router = express.Router();

router
  .get('/', user.onGetAllUsers)
  .post('/', user.onCreateUser)
  .get('/:id', user.onGetUserById)
  .delete('/:id', user.onDeleteUserById)

export default router;

이제 route / chatRoom.js에 콘텐츠를 추가해 보겠습니다 :


import express from 'express';
// controllers
import chatRoom from '../controllers/chatRoom.js';

const router = express.Router();

router
  .get('/', chatRoom.getRecentConversation)
  .get('/:roomId', chatRoom.getConversationByRoomId)
  .post('/initiate', chatRoom.initiate)
  .post('/:roomId/message', chatRoom.postMessage)
  .put('/:roomId/mark-read', chatRoom.markConversationReadByRoomId)

export default router;

마지막으로 routes / delete.js에 내용을 추가해 봅시다 :


import express from 'express';
// controllers
import deleteController from '../controllers/delete.js';

const router = express.Router();

router
  .delete('/room/:roomId', deleteController.deleteRoomById)
  .delete('/message/:messageId', deleteController.deleteMessageById)

export default router;

이제 경로가 만들어 졌으므로 각 경로에 대한 컨트롤러를 추가하겠습니다.


controllers라는 새 폴더를 만듭니다. 해당 폴더 안에 다음 파일을 작성하십시오.


  • user.js
  • chatRoom.js
  • delete.js

controllers / user.js로 시작해 봅시다 :


export default {
  onGetAllUsers: async (req, res) => { },
  onGetUserById: async (req, res) => { },
  onCreateUser: async (req, res) => { },
  onDeleteUserById: async (req, res) => { },
}

다음으로 controllers / chatRoom.js에 컨텐츠를 추가하겠습니다 :


export default {
  initiate: async (req, res) => { },
  postMessage: async (req, res) => { },
  getRecentConversation: async (req, res) => { },
  getConversationByRoomId: async (req, res) => { },
  markConversationReadByRoomId: async (req, res) => { },
}

마지막으로 controllers / delete.js에 컨텐츠를 추가해 봅시다 :


export default {
  deleteRoomById: async (req, res) => {},
  deleteMessageById: async (req, res) => {},
}

지금까지 각 경로에 빈 컨트롤러를 추가 했으므로 아직 많은 작업을 수행하지 않습니다. 약간의 기능을 추가하겠습니다.


한가지 더 – 미들웨어라는 새 폴더를 추가하고 그 폴더 안에 jwt.js라는 파일을 만듭니다. 그런 다음 다음 내용을 추가하십시오.



import jwt from 'jsonwebtoken';

export const decode = (req, res, next) => {}

export const encode = async (req, res, next) => {}

이 파일의 기능에 대해 조금 이야기하겠습니다. 지금은 무시하겠습니다.


우리는 다음과 같이 끝냈습니다.

  • 포트 3000에서 수신 대기하는 Express 서버 작성
  • server.js에 CORS (cross-origin-resource)를 추가했습니다.
  • server.js에 로거를 추가했습니다.
  • 또한 빈 컨트롤러가 있는 경로 처리기를 추가했습니다.

위의 비디오에서 다루지 않은 지금까지 멋진 것은 없습니다.


응용 프로그램에서 MongoDB를 설정합시다 


코드베이스에 MongoDB를 추가하기 전에 다음 중 하나를 실행하여 시스템에 설치되어 있는지 확인하십시오.


MongoDB 설치에 문제가 있는 경우 https://twitter.com/adeelibr으로 알려주십시오. 사용자 정의 안내서를 작성하거나 설치 비디오 안내서를 작성하겠습니다. :)


Robo3T를 MongoDB GUI로 사용하고 있습니다.


이제 MongoDB 인스턴스가 실행되고 Robo3T가 설치되어 있어야 합니다. (여러분이 좋아하는 GUI 클라이언트를 사용할 수 있습니다. Robo3T가 너무 좋아서 사용하고 있습니다. 또한 오픈 소스입니다.)


다음은 YouTube에서 내가 Robo3T를 6 분 소개하는 작은 비디오입니다.




MongoDB 인스턴스가 시작되면 코드에 MongoDB 통합을 시작하십시오.


루트 폴더에 config라는 새 폴더를 만듭니다. 해당 폴더 안에 index.js라는 파일을 만들고 다음 내용을 추가하십시오.


const config = {
  db: {
    url: 'localhost:27017',
    name: 'chatdb'
  }
}

export default config

일반적으로 MongoDB 인스턴스가 실행될 기본 포트는 27017입니다.


여기서는 데이터베이스 URL (db에 있음)과 chatdb 인 데이터베이스 이름에 대한 정보를 설정합니다 (원하는 대로 호출 할 수 있음).


그런 다음 config / mongo.js라는 새 파일을 만들고 다음 내용을 추가하십시오.


import mongoose from 'mongoose'
import config from './index.js'

const CONNECTION_URL = `mongodb://${config.db.url}/${config.db.name}`

mongoose.connect(CONNECTION_URL, {
  useNewUrlParser: true,
  useUnifiedTopology: true
})

mongoose.connection.on('connected', () => {
  console.log('Mongo has connected succesfully')
})
mongoose.connection.on('reconnected', () => {
  console.log('Mongo has reconnected')
})
mongoose.connection.on('error', error => {
  console.log('Mongo connection has an error', error)
  mongoose.disconnect()
})
mongoose.connection.on('disconnected', () => {
  console.log('Mongo connection is disconnected')
})

다음과 같이 server / index.js 파일에서 config / mongo.js를 가져옵니다.


.
.
// mongo connection
import "./config/mongo.js";
// routes
import indexRouter from "./routes/index.js";

언제든지 길을 잃은 경우 이 자습서의 전체 소스 코드가 여기에 있습니다.


우리가 여기서 하고 있는 일을 단계별로 논의 해 보자.


먼저 config.js 파일을 config / mongo.js로 가져옵니다. 다음으로 다음과 같이 CONNECTION_URL에 값을 전달합니다.


const CONNECTION_URL = `mongodb://${config.db.url}/${config.db.name}`

그런 다음 CONNECTION_URL을 사용하여 다음을 수행하여 Mongo 연결을 형성합니다.


mongoose.connect(CONNECTION_URL, {
  useNewUrlParser: true,
  useUnifiedTopology: true
})

이것은 몽구스에게 Node / Express 애플리케이션으로 데이터베이스와 연결하도록 지시합니다.


몽고에 제공하는 옵션은 다음과 같습니다.


  • useNewUrlParser : MongoDB 드라이버가 현재 연결 문자열 구문 분석기를 더 이상 사용하지 않습니다. useNewUrlParser : true는 몽고에게 몽고의 새로운 파서를 사용하도록 지시합니다. (true로 설정되면 CONNECTION_URL에 데이터베이스 포트를 제공해야 합니다.)
  • useUnifiedTopology : 기본적으로 False입니다. MongoDB 드라이버의 새로운 연결 관리 엔진 사용을 선택하려면 true로 설정하십시오. 안정적인 연결을 유지하지 못하는 경우를 제외하고 이 옵션을 true로 설정해야 합니다.


다음으로 몽구스 이벤트 핸들러를 다음과 같이 추가합니다.


mongoose.connection.on('connected', () => {
  console.log('Mongo has connected succesfully')
})
mongoose.connection.on('reconnected', () => {
  console.log('Mongo has reconnected')
})
mongoose.connection.on('error', error => {
  console.log('Mongo connection has an error', error)
  mongoose.disconnect()
})
mongoose.connection.on('disconnected', () => {
  console.log('Mongo connection is disconnected')
})
  • connected 데이터베이스 연결이 설정되면 호출됩니다
  • disconnected 몽고 연결이 비활성화되면 호출됩니다
  • error Mongo 데이터베이스에 연결하는 동안 오류가 발생하면 호출됩니다
  • reconnected 이벤트는 데이터베이스 연결이 끊어진 후 호출 된 후 다시 연결을 시도합니다.

이 작업을 완료하면 server / index.js 파일로 이동하여 config / mongo.js를 가져 오십시오. 그게 다야. 이제 다음을 입력하여 서버를 시작할 때


npm start;

다음과 같이 보일 것입니다 :


Screenshot-2020-06-15-at-19.42.53.png 

서버를 시작할 때 기록


이 메시지가 표시되면 Mongo를 애플리케이션에 성공적으로 추가 한 것입니다.


사용자를 위한 첫 번째 API 섹션을 설정하겠습니다 


사용자를 위한 API 설정에는 이 튜토리얼에 대한 인증 토큰이 없습니다. 주요 초점은 여기서 채팅 애플리케이션에 대해 알려주는 것입니다.


User Modal Scheme 


사용자 컬렉션을 위한 첫 번째 모델 (데이터베이스 체계)을 만들어 봅시다.


models이라는 새 폴더를 만듭니다. 해당 폴더 안에 User.js라는 파일을 만들고 다음 내용을 추가하십시오.


import mongoose from "mongoose";
import { v4 as uuidv4 } from "uuid";

export const USER_TYPES = {
  CONSUMER: "consumer",
  SUPPORT: "support",
};

const userSchema = new mongoose.Schema(
  {
    _id: {
      type: String,
      default: () => uuidv4().replace(/\-/g, ""),
    },
    firstName: String,
    lastName: String,
    type: String,
  },
  {
    timestamps: true,
    collection: "users",
  }
);

export default mongoose.model("User", userSchema);

이것을 조각으로 나누자.


export const USER_TYPES = {
  CONSUMER: "consumer",
  SUPPORT: "support",
};

기본적으로 소비자와 지원의 두 가지 유형의 사용자가 있습니다. 프로그래밍 방식으로 API 및 DB 유효성 검사를 보장하기 위해 이 방법으로 작성했습니다. 나중에 설명하겠습니다.


다음으로 단일 문서 (객체 / 항목 / 항목 / 행)가 사용자 컬렉션 내부에서 어떻게 보이는지에 대한 스키마를 만듭니다 (컬렉션은 MySQL 테이블과 동일 함). 우리는 이것을 다음과 같이 정의합니다 :


const userSchema = new mongoose.Schema(
  {
    _id: {
      type: String,
      default: () => uuidv4().replace(/\-/g, ""),
    },
    firstName: String,
    lastName: String,
    type: String,
  },
  {
    timestamps: true,
    collection: "users",
  }
);

여기서 우리는 mongoose에게 사용자 컬렉션의 단일 문서에 대해 구조가 다음과 같이 되기를 원한다고 말합니다.


{
	id: String // will get random string by default thanks to uuidv4
    	firstName: String,
    	lastName: String,
    	type: String // this can be of 2 types consumer/support
}

스키마의 두 번째 부분에는 다음과 같은 것이 있습니다.


{
    timestamps: true,
    collection: "users",
}

타임 스탬프를 true로 설정하면 스키마에 createdAt 및 updatedAt 날짜 값이라는 두 가지가 추가됩니다. 새 항목을 만들 때마다 createdAt가 자동으로 업데이트 되고 mongoose를 사용하여 데이터베이스에서 항목을 업데이트하면 updatedAt가 업데이트 됩니다. 이 두 가지는 몽구스에 의해 자동으로 수행됩니다.


두 번째 부분은 수집입니다. 이것은 내 컬렉션 이름이 데이터베이스 내에 어떤 것을 보여줄 지를 보여줍니다. 사용자 이름을 지정하고 있습니다.


마지막으로 다음과 같이 객체를 내 보냅니다.

export default mongoose.model("User", userSchema);

따라서 mongoose.model은 2 개의 매개 변수를 사용합니다.


  • 모델 이름 (사용자는 여기)
  • 해당 모델과 연관된 스키마 (이 경우 userSchema)


참고 :이 경우 사용자 인 모델 이름을 기반으로 스키마 섹션에 컬렉션 키를 추가하지 않습니다. 이 사용자 이름을 가져 와서 s를 추가하고 이름으로 모음을 작성합니다.


좋습니다. 이제 첫 번째 모델이 있습니다


어디에서나 붙어 있다면 소스 코드를 살펴보십시오.

















































































































































































댓글목록 0

등록된 댓글이 없습니다.

웹학교 로고

온라인 코딩학교

코리아뉴스 2001 - , All right reserved.