- Published on
express middleware 에 대해서
- Authors
- Name
- 길재훈
nodejs 의 모듈과 객체
여기서 nodejs
는 module system
을 가지는데, 이러한 특징에 대해서 알면 추후 사용에 좋다.
모듈을 마치 하나의 부품처럼 생각하면된다. 이러한 부품들을 모아 하나의 완성품을 만들듯이, nodejs
는 module
의 집합을 통해 하나의 application
을 만든다
module
은 객체지향에서 말하는 encapsulation
과 같다. 변수와 함수의 name space
를 정하여 해당 내부에서만 사용할 수 있도록 만들어준다.
과거의
javascript
는 이러한module
을 지원해주지 않아서,module
사용할 수 있는 여러library(commonjs 등등)
들이 있었다고 한다.실제, 이러한
library
역시 존재하지 않았을 시절에는 하나의javascript
파일안에 엉청난 줄의 코드를 넣었었다고 하는 전설같은 이야기가 전해진다...
es6
에서 부터 javascript
자체에서도 module
을 지원하지만, nodejs
는 es6
이전부터 존재해왔다.
그러므로 nodejs
는 es6
에서 제공해주는 module
이 아닌, commonjs
를 따르는 module
을 default
로 사용한다
현재로는 .mjs
의 확장자를 사용하면 es6
의 module
사용이 가능하다.
commonjs
는 다음의 모듈을 내보내는 방식으로 사용가능하다
- exports.property // exports 객체에 property 를 저장하는 방법
- module.exports = property // module.exports 에 직접 해당 property 를 적용하는 방법
// 이때 property 는 Object, function 같은 객체 및 단일한 원시타입 값을 할당할 수 있다
https module
nodejs
는 native module
로 http
모듈을 제공한다 http
모듈을 사용하면 간단하게 server
구현이 가능하다
const http = require('http')
const server = http.createServer((req, res) => {
res.writeHead(200, { 'Content-Type': 'text/html; charset=utf-8' })
res.end('hi')
})
server.listen(8080, () => console.log('8080port 에서 서버작동중...'))
localhost:8080
으로 접속한다면 hi
라는 문구를 볼 수 있다. 이를 통해 매우 간단한 server
를 만들어 볼 수 있다.
보통은 http
모듈을 사용하여 처리하지 않고 express
를 사용하여 응답 및 요청을 처리한다.
다음은 express
에서 사용되는 req
, res
를 정리한 것이다
req, res
req
는 request
의 약자로, client
로 부터 요청받은 정보를 받아 처리하는 인자이다.
req
는 다음과 같은 기능을 가진다
백문의불여일타 nodejs 에 나온 책에서 잘 정리해놓은 table 이 있어서 참고했다.
method | description |
---|---|
req.body | POST 로 들어오는 req 정보 |
req.query | GET 으로 들어오는 query string |
req.params | 개발시 작성한 router parameter 정보 /:id/:name |
req.headers | HTTP header 정보 |
req.route | 현재 route 정보 |
req.cookies | client 의 cookie 정보 |
req.accepts | Accept HTTP 헤더 필드를 기반으로 지정된 콘텐츠 유형이 허용가능하지 확인 |
req.ip | client 의 ip 주소 값 |
req.path | client 의 요청 경로 |
req.host | 요청한 host 이름 |
req.xhr Ajex | 요청시 true 반환 |
req.protocol | 요청의 protocol(http, https) |
req.secure | secure 요청이면 ture 반환 |
req.url | url 경로 및 query string |
res
는 reqsponse
의 약자로, client
에 응답에 대한 정보를 처리해준다.
method | description |
---|---|
res.send | 응답을 보낸다 |
res.sendFile | file 형태의 응답 |
res.json | json 형태의 응답 |
res.render | SSR 형태의 응답 |
res.locals | view rendering 시 default context 로 포함 |
res.end | 인자로 넣은 data 와 함께 res 종료 |
res.status | 응답코드 설정 |
res.set | 응답 헤더 설정 |
res.cookie | client 에 저장할 cookie 지정 |
res.redirect | 인자로 넣은 URL 로 redirect 기본 응답값 304 |
res.type | Header 의 Content-Type 설정 |
Express
exporess
는http
와fs
모듈을 사용해서 일일히 구현할 필요 없이, 더 쉽게server
를 만들 수 있도록 해주는framework
이다.
REST API
REST API
는 REpresentational State Transfer
의 약자이다. 상태 전이를 표현한 API 라고 생각하면 된다.
REST API
는 주소를 통해서 내용을 표시하는데, 이러한 주소를 (Endpoint
) 라고한다.
Endpoint
에 원하는 자원을 요청하면, 이 요청된 Endpoint
를 확인하여 clinet
가 원하는 resouce
를 제공해주는 방식이다.
이렇게, 요청했을때 응답할 수 있도록 해주는 분기처리를 routing
이라고 하며, routing
을 통해 구조화해서 만든 웹 서버를 RESTful
하다 라고 한다.
이는 다음과 같다
const express = require('express')
const app = express()
app.get('/', (res, req) => {
res.send('Hello world!')
})
app.listen(8080, () => console.log('8080 에서 실행중!!'))
위는 express
를 사용하여 만들었으며, Endpoint
인 /
를, get
요청하면, Hello wolrd!
를 응답으로 보내준다.
미들웨어
Middleware
는 중간의 다리 역할을 하다고 생각하면 쉽다. 중간에서 어떠한 처리를 대신 해주고 그 중간처리의 값을 반환하여, 번거로운 설정및 처리없이 값을 바로 사용할 수 있도록 만든다.
이러한 방식은 매우 중요한데, 예를 들어 cookie
값을 받아서 해당 cookie
를 매번 object
화 시킬 필요없이, 중간에 Middleware
를 통해서 자동적으로 cookie
값을 object
처리 가능하도록 만들 수 있다.
즉, 반복되는 어떠한 기본 처리를 중간에서 알아서 해결해준다.
express
는 이러한 기능들을 middlewares
를 통해 추가하여, 인증 수행 및 예외처리, 세션처리, 라우터 등등.. 을 중간에서 처리할 수 있도록 설정 가능하다.
middleware
는 express
의 핵심 기능이라 할 수 있을정도로 매우 유용한 기능이다.
middleware
를 사용하는데, 2가지 방식을 사용한middleware
를 사용하는데, 2가지 방식을 사용한다다
app.use() // middleware를 전역적으로 사용
app.set() // middleware를 지역적으로 사용
이는 다음처럼 사용가능하다
const express = require('express')
const app = express()
const test = () => {
console.log('test')
}
app.get('/', (req, res, next) => {
res.send('middleware test')
next() // 다음 middleware 를 실행시키기 위해서는 next 인자를 호출해야 한다.
// middleware 는 위에서 아래로 실행되기에 순서가 중요하며, 이 경우
// res.send 를 만났을때 응답이 종료된다.
// 그러므로 next 인자를 호출하여 다음 middleware 로 넘어갈 수 있도록
// 해야한다.
})
app.use(test) // next 인자를 호출해야만 이 `middleware` 가 작동한다.
app.listen(8080, () => console.log('8080 에서 서버실행중!!'))
next
는 다음 middleware
로 넘어가는 역할을 하기에, 흐름을 잘 제어해주어야 한다. next
함수는 인자로도 받을 수 있다고 한다.
next() // 다음 미들웨어로 간다
next(error) // 오류 처리 미들웨어로 간다
에러 처리를 위한 함수는 다음처럼 작성가능하다.
app.use((err, req, res, next) => {
console.log(err.stack)
res.status(500).send('server error')
})
다른 함수와는 다르게 err
인자를 첫번재로 받는다. 이렇게 하면 err
처리시, 이 미들웨어로 가게 된다.
보통 err
처리 미들웨어는 listen
이전의 마지막에 두고 처리하게끔 만든다.
express.static
express
에서 이미지 같은 정적파일을 모아놓은 폴더를 지정할 수 있다. 이는 다음처럼 사용한다.
const path = require('path')
const express = require('express')
const app = express()
app.set('port', process.env.PORT || 8080)
app.use(express.static(path.resolve('.', '/public')))
app.get('/', (req, res, next) => {
res.sendFile(path.resolve('.', 'index.html'))
})
app.use(test) // next 인자를 호출해야만 이 `middleware` 가 작동한다.
app.listen(app.get('port'), () => console.log(`${app.get('port')} 에서 서버실행중!!`))
<html>
<body>
<div>
<h1>test</h1>
<img src="./image.jpg" alt="image" /> // image.jpg 는 public 에서 찾는다.
</div>
</body>
</html>
위는 public
폴더를 static file
을 가진 폴더로 지정한 것이다. 그러므로 해당 html
을 client
로 보낸다고 한다면, html
의 img
는 public
폴더의 경로안에서 찾는다.
http 요청 메서드
http
에 요청 메서드가 존재한다.
이러한 요청 메서드는 client
가 serve
에게 어떠한 요청을 요구하는지 알리는 방법 이라고 생각하면 된다.
예를 들어, 단순히 Endpoint
의 응답값을 얻고 싶다고 해보자. 그럼 GET
메서드를 사용해서 처리 해당 응답 값을 가질 수 있다.
하지만, 꼭 client
는 무엇인가 받기만 하지는 않는다 어떠한 값을 server
에 보낼수도 있다. 이럴때는 POST
를 사용하여 요청할 수 있다.
이러한 요구하는방법을 규격화된 방식을 사용하여 서버와 소통할 수 있도록 만든 것이 요청 메서드
이다.
요청 메서드는 다음과 같다
method | descrioption |
---|---|
GET | resource 를 얻는다 |
POST | resource 를 전송한다 |
PUT | resource 전체를 변경, 덮어씌운다 |
PATCH | resource 의 일부내용을 update 한다 |
DELETE | 삭제한다 |
HEAD | 문서의 정보를 얻는다 |
router
router
를 사용하여 위의 http
요청 메서드에 따른 응답을 처리할 수 있다. router
도 일종의 middleware
이다.
router
는 다음처럼 사용할 수 있다.
app.use('/path', middelware)
app.get('/path', middelware)
app.post('/path', middelware)
app.put('/path', middelware)
app.delete('/path', 'iddelware)
보면 알겠지만, 처음의 인자를 경로로 지정하고, 두번째 인자로 middleware
를 할당하면 해당 endpoint
에 따라 응답값을 보내줄 수 있도록 되어 있다.
dynamic route
express
의 router
는 dynamic route
기능을 제공한다. 다음처럼 사용하면 된다.
app.get('/users/:userId', function (req, res) {
const userId = req.params.userId
// userId를 사용하여 사용자 정보를 가져온다.
res.send('사용자 정보: ' + userId)
})
userId
를 req.params.userId
를 통해 값을 가져와서 해당 사용자 정보를 응답값으로 보내는 로직이다.
이를 통해 각 user
마다 다른 사용자 정보를 따로 처리가능하도록 만들 수 있다. 마치 nextjs
에서 사용하는 동적 라우팅과 매우 유사하다
Morgan
morgan
은 logger API
이다. 이는 console
상에서 log
를 보여주어, 현재 어떠한 상태인지 보여주는 역할을 한다 또한, json
형태로 dump
파일에 기록하게 해주는 windston
이라는 모듈역시 존재한다.
const path = require('path')
const express = require('express')
const logger = require('morgan')
const app = express()
app.static(path.resolve('./static'))
// logger 에 인자를 주어 원하는 모드를 실행할 수 있다
app.use(logger('dev'))
app.use(logger('combined'))
app.use(logger('common'))
app.use(logger('short'))
app.use(logger('tiny'))
//
logger
관련해서는 docs
를 살펴보아야 겠다. 보통은 develop
에서는 dev
를, 배포시에는 combinded
를 사용한다고 한다. combinded
시 더 세부적인 정보를 확인할 수 있다고 한다
exrpess.json, express.urlencoded
post
및 put
요청시에 req.body
에 접근하여 해당 값을 가져온다. 이때, 요청한 값을 parsing
하여 req.body
에 넣어주는데 사용되는 middelware
들이다.
원래는 body-parser
라는 middleware
를 사용했으나, express
로 내장되었다. 그러므로, 위의 express.json
및 express.urlencoded
를 사용할 수 있다.
express.json
은 req.body
가 json
일때 사용되며, express.urlencoded
는 form
에 의한 요청일때 사용한다.
express.urlencoded
는 application/x-www-form-urlencoded
포멧의 form
을 받을때, 이를 객체로 변환하여 바로 사용할 수 있도록 해준다.
이때, extended
옵션이 존재하는데, 이 옵션은 qs
모듈을 사용할지, nodejs
의 queryString
모듈을 사용할지 결정하는 옵션이다.
ture
이면 qs
모듈을 사용한다.
또한 만약, image
혹은 동영상 같은 경우 multipart
형식의 데이터 라면, multer
라는 미들웨어를 추가해야 함은 참고하도록 하자.
cookie-parser 와 express-session
cookie-parser
는 cookie
와 session
을 처리해준다. 보통 cookie
및 session
은 로그인한 사용자를 식별하는데 사용된다. (물론, 용도에 따라 다른방식으로도 사용된다)
만약, user
가 로그인하게 되면, server
에서는 cookie
를 client
에 보내게 되고, 이후부터 client
는 매 요청마다 cookie
를 갖이 보낸다.
server
는 client
가 보낸 cookie
를 확인하여, 해당 user
를 식별한다.
res.writeHead({ 'Set-Cookie': 'user=id' })
client
가 cookie
를 보내게 되면, req.headers.cookie
를 통해 쿠키 값에 접근할 수 있다.
이때, cookie
가 다음처럼 생겨있다
// 위의 cookie 는 다음의 형태를 띈다
user = id
// 만약 cookie 값이 여러개라고 하면 다음처럼 생겨있다
user = id
lang = ko
이러한 문자열을 객체로 변경하려면, 약간의 수고가 필요하다. "user=id;lang=ko"
를 object
로 변환할때 아래처럼 해야하지 않을까 싶다.
const cookies2Object = (cookies) =>
cookies
.split(';')
.map((cookie) => cookie.split('='))
.reduce((acc, cookie) => {
acc[cookie[0]] = cookie[1]
return acc
}, {})
이렇게 따로 가공하는것 것 보다는 미리 잘 만들어둔 middleware
를 사용하는것이 좋다. 그러한 middleware
가 바로 cookie-parser
이다
이때, cookie
값을 받기 위해서 res.cookies.cookieName
으로 해당 쿠키값을 가져올 수 있다.
하지만, cookie
를 그대로 사용하는것은 매우 위험한 일이다. 해당 cookie
의 값을 암호화 시키고, 그 암호화된 값을 키로 사용하여 server
에 저장된 실제 값에 접근하는 방식을 사용한다.
이렇게 cookie
값을 직접 사용안하고 암호화된 값을 키로 사용해 접근하는 방식을 session
이라고 한다
이에 대한 예시는 다음과 비슷하다
const http = require('http')
const sessionKey = +new Data()
const session = {}
session[sessionKey] = { user: 'id' }
const server = http.createServer((req, res) => {
res.writeHead(200, { 'Set-cookie': `session=${sessionKey}` })
res.end('session')
})
server.listen(8080, () => console.log(`8080 서버 사용중!!`))
이 code
를 보면 cookie
는 sessionKey
를 가진 session
이다. 그리고 session
객체에는 sessionKey
를사용하여 실제 값에 접근하는것을 볼 수 있다.
대략, 이러한 방식으로 client
에서 직접 cookie
값을 사용하는것이 아닌, server
에 저장되어 있는 정보를 sessionKey
를 사용하여 안전하게 참조하는것이다.
express-session
을 사용하면, 임의의 키 값을 생성하고, cookie
의 value
값으로 할당한다.
그리고 그 값을 통해 cookie
를 가져온다고 볼 수 있을 것 같다
이는 다음처럼 사용된다
const path = require('path')
const express = require('express')
const logger = require('morgan')
const session = require('express-cookie')
const app = express()
app.set('port', process.env.PORT || 8080)
app.use(express.static(path.resolve('.', './pulbic')))
app.use(logger('dev'))
app.use(sesson({
secret: 'cuteCat', // 암호화
resave: false, // 새로운 요청시 세션에 변동사항이 없어도 다시 저장할지 설정
saveUninitialized: true, // 세션에 저장할 내용이 없어도 저장할지 설정
cookie: {
httpOnly: true, // javascript 접근 안되게 설정
},
}))
app.use(express.json())
app.use(express.urlencoded({ extended: false }))
app.get('/', (req, res) => {
req.session.name ?
res.send(`${req.session.name} 님 환영합니다!`) :
res.send('로그인 해주세요')
})
app.get('/signIn', (req, res) => {
req.session.name = 'testUser'
res.send('login 되었습니다.')
})
app.get('/logout', (req, res) => {
res.clearCookie('connect.sid') // 저장되는 cookie 이름이 defualt 로 connect.sid 이다
res.send('logout 되었습니다.')
})
app.listen(app.get('port'), () => console.log(`${app.get('port')} 서버 작동중!!`)
이를 통해 express
의 middelware
에 대해서 알아보았다.
REST API 구현
REST API
및 RESTful API
는 API
를 REST
형식으로 만들어, 요청 및 응답을 주고 받는 방법이다.
REST API
가 아닌 Query language
로 서술된 GraphQL
역시 존재하지만, GraphQL
역시 알고보면 REST API
를 기반으로 만든 Query language
이다.
실상 GraphQL
은 최근에 나온 방법으로, 실상 현재까지 가장 많이 사용되고 있는 방식은 REST API
를 많이 사용한다.
REST API
는 요청된 주소를 보고 어떠한 요청을 원하는지 알수 있도록 해주는 API
방식이다.
이때, 이 주소
가 중요한데, domain URI
를 통해 Server
에서 처리해준다. URI
에 대해서는 조금더 공부해보도록 한다
const express = require('express')
const app = express()
app.get('/:name', (req, res) => {
const { name } = req.params
res.send(`hello ${name}`)
})
app.listen(8080, () => console.log(`8080 서버 사용중!!`))
dynamic route
를 통해 받은 name parameter
를 사용하여, url
의 name
값을 받아 응답값을 주는 로직이다.
dynamic route
를 사용하면 req
의 paramse
를 통해 :name
값을 받아서 처리할 수 있다.
위의 예시에서 주소로 /Tommy
로 요청을 보내면, hello Tommy
라는 값을 받는다.
이러한 방식을 사용하여 todo list
를 만들어본다 단, DB
를 사용하는것이 아닌 server
상의 변수를 통해 값을 저장해본다. 이는, express
를 통해 어떻게 API
를 주고 받는지를 확인하고자 만든 server
이다.
DB
관련해서 연동하는것은 추후 더 살펴볼 예정이다.
const path = require('path')
const express = require('express')
const logger = require('morgan')
const app = express()
let itemList = [] // todoList 에서 사용될 list
let itemId = 0 // todoList 에서 사용될 idx
const getItemList = (itemList, id, newItem) => {
const item = itemList.find((item) => item.id === id)
const idx = itemList.indexOf(item)
if (newItem) {
itemList.splice(idx, 1, newItem)
} else {
itemList.splice(idx, 1)
}
}
app.set('port', process.env.PORT || 8080)
app.use(express.json())
app.use(express.urlencoded({ extended: ture }))
app.get('/', (req, res) => {
res.send(itemList)
})
app.post('/', (req, res) => {
const item = {
itemId,
date: new Date(),
content: res.body.contents,
}
itemList.push(item)
res.redirect('/')
})
app.put('/:id', (req, res) => {
const { id } = req.params.id
const newItem = {
id: itemId++,
data: new Date(),
content: res.body.content,
}
let itemList = getItemList(itemList, id, newItem)
res.redirect('/')
})
app.delete('/:id', (req, res) => {
const { id } = req.params.id
const newItem = {
id: itemId++,
data: new Date(),
content: res.body.content,
}
let itemList = getItemList(itemList, id)
res.redirect('/')
})
app.listen(app.get('port'), () => console.log(`${app.get('port')} 에서 서버실행중!!`))
매우 간단한 API
를 만들어 보았다.
Web socket 의 배경
HTTP
는 통신을 위해 사용되는 Protocol
이다. 이 Protocol
을 사용하여, Client
요청에 의해 Server
로 부터 응답을 받아 통신할수 있도록 해준다
HTTP
통신은 일반적으로 요청하고 응답을 하면, 통신이 끝나게 되는 방식으로 이루어져 있다.
이렇게 한번만 통신을 받고 끝내는것은, 전체페이지를 갱신하게 되므로, 일부분만 갱신하고 싶다면 좋은방법은 아닐것이다.
이러한 방식을 획기적으로 바꾼 부분이 AJAX
로, Javascript
에서 응답
으로 data
를 받아 DOM
으로 그려주는 방식을 채택하여 처리한다.
AJAX
는 Asynchronouse JAvascript XML
의 약자로써, 자바스크립트 비동기로 data
를 받은 API
라고 생각하면 된다.
과거에 JSON
이라는 획기적은 방법이 있기전에는 XML
을 통해 data
를 받아 처리했던 시절에 만들어진 API
라 약자에 XML
이 포함된다.
현재는 JSON
포멧으로 통신이 많이 이루어지므로, 거의 대부분은 JSON
으로 처리한다.
간단하게, 단지 HTTP
통신만을 사용하여 처리하면, 전체페이지를 다시 받아 갱신하게 되므로, data
로 받아 DOM
으로 해당 부분을 그려주면 그로인한 Network Overhad
역시 적게 이루어진다.
또한, Javascript
의 Async
로 작동하니, 통신이 조금 오래 걸리더라도 대기없이 기존의 코드를 실행시킬수 있다.
이는 더 효율적인 통신이 가능하게 되었다는 것이다.
다시한번 말하지만, HTTP
방식은 Client
에서 요청을 하면 이에 반응하여 Server
에서 응답을 해주는 방식이다.
하지만, 만약 Client
의 요청을 받아야지만, Server
에서 보내는 방식이 아니라 Server
에서 먼저 응답을 줄수 있는 상황이 생길 수 있다.
이렇게, Client
의 요청에 반응을 하지 않고, 필요한때 Server
에서 data
를 보낼 수 있도록 만드는 기술을 양방향 통신
이라한다.
이러한 해결책으로 HTTP
에서도 여러가지 대안들이 나왔었다. 대표적으로 총 3가지가 있다.
Polling
, Long Polling
, Streaming
이다.
Polling
Polling
은 주기적으로 HTTP
통신을 보내는 방식이다. 일정 주기마다 서버에 계속 요청하므로, Event
발생하지 않더라도 지속 응답 및 요청 작없이 필요하다. 이는 불필요한 응답과 요청이 이루어진다는 것이므로 Overhead
이다.
Long Polling
Long Polling
은 기존의 Polling
보다 더 길게 일정시간 동안 요청을 대기시키는 방식이다. Polling
의 단점을 해결하기 위해 Client
에서 요청을 보낸이후에, 정해진 일정시간동안 Event
가 발생할때까지 Server
의 응답을 지속 대기 시킨다.
Event
발생이후, 응답이 이루어지면 이전의 연결을 끊고, 새로운 요청을 받는다.
Streaming
Streaming
은 서버가 요청을 항상 받을 수 있도록 지속적으로 대기시키는 방식을 말한다.
Striming
은 한번 Server
와 연결되면, Server
에서 Event
가 발생했을때, 일방적으로 Data
를 받을수 밖에 없다
즉, Client
에서 서버에 data
를 보내기 어려운 구조이다.
위의 방식은 송수신이 동시에 이루어지기 보다는 request
가 있은 이후 response
가 가능한 구조이다.
이렇게, 양방향 통신이 가능하지만, 동시에 송수신이 불가능한 구조를 Half-Duplex
라고 한다.
위처럼 동작하지 않고, 동시에 송수신이 가능하도록 만든 구조를 Full-Duplex
라고 한다. 기존의 3가지 방식은 전부 단방향 통신을 양방향 처럼 보이도록 만든 Half-Duplex
이며, 진정한 양방향 통신(Full-Duplex
) 를 지원하지는 못한다.
이러한 해결책으로 Web Socket
이라는 새로운 Protocol
이 탄생하게 된다.
Web socket
Web Socket
은 처음 연결시에만 HTTP
요청을 보낸다. 그런다음 handshake
과정이 성공적으로 이루어지게 되면, 이후 부터는 HTTP
통신이 아닌 Web Soket Protocl
로 변경되어 통신하게 된다.
이전의 Half-Duplex
같은 경우는 HTTP
통신이므로 매번 요청시 Header
를 같이 포함해서 보내게 된다.
그로 인해 overhead
발생이 생길수 있지만, Web-Socket
의 경우 이 Header
가 상당히 작게 이루어져 있어 이러한 overhead
로 부터 자유롭다.
첫 연결시에 HTTP
이 이루어지면, connection
이 지속적으로 이루어져 있어 송수신시 re connection
할 필요없이 한의 connection
만으로 통신이 가능하다는 장점 역시 존재한다.
ws
를 처리하기 위해 편리하게 만들어진 모듈인 socket.io
를 사용하여 채팅기능을 구현할 수 있다.
이에 대한 socket.io
는 조금 깊이 공부할 필요가 있으므로, 추후 더 정리하도록 한다.