- 웹 소켓은 실시간 양방향 데이터 전송을 위한 기술로, WS라는 프로토콜을 사용한다.
- Socket.IO는 웹 소켓을 편리하게 사용할 수 있도록 도와주는 라이브러리이다.
"dependencies": {
"cookie-parser": "^1.4.6",
"dotenv": "^16.0.1",
"express": "^4.18.1",
"express-session": "^1.17.0",
"morgan": "^1.9.1",
"nunjucks": "^3.2.1",
"ws": "^8.2.3"
},
- 위 코드를 참고하여 package.json 파일을 작성하고, 패키지를 설치한다.
- https://github.com/zerocho/nodejs-book의 소스코드를 참고하여 .env와 app.js, routes/index.js 파일을 작성한다.
- npm i ws 명령어를 통해 ws 모듈을 설치한다.
- app.js에서 웹 소켓을 익스프레스 서버에 연결하고, socket.js 파일을 작성한다.
- 웹 소켓 서버에 이벤트 리스너를 붙인다. 웹 소켓은 이벤트 기반으로 작동된다.
- 클라이언트와 서버가 웹 소켓 연결을 맺을 때 connection 이벤트가 발생한다.
- 웹 소켓 객체에는 message, error, close 이벤트 리스너를 연결한다.
- 웹 소켓에는 connecting(연결 중), open(열림), closing(닫는 중), closed(닫힘) 네 가지 상태가 존재한다.
- npm i socket.io@2 명령어를 통해 Socket.IO를설치한다.
- socket.io 패키지를 불러와 익스프레스 서버와 연결한다. 그리고 이벤트 리스너를 붙인다.
- 클라이언트가 접속하면 connection 이벤트가 발생하고, 콜백으로 소켓 객체를 제공한다.
- ws 모듈과 다르게 http 프로토콜을 사용한다.
- Socket.IO는 먼저 폴링 방식으로 서버와 연결하고, 웹 소켓을 사용할 수 있으면 웹 소켓으로 업그레이드한다.
- npm i mongoose multer axios color-hash 명령어를 통해 필요한 모듈을 설치한다.
- 채팅방 스키마를 만든다. 방 제목, 최대 수용 인원, 방장, 비밀번호, 생성 시간 등을 받는다.
- 채팅 스키마를 만든다. 채팅방 아이디, 채팅을 한 사람, 채팅 내역, GIF 이미지 주소, 채팅 시간을 저장한다. 채팅방 아이디 필드는 채팅방 스키마와 연결한다.
- schema/index.js에서 몽고디비와 연결한다.
- app.js에서 서버와 몽구스를 연결한다.
- https://github.com/zerocho/nodejs-book의 소스코드를 참고하여 html 파일과 css 파일들을 작성한다.
- main.html에서 io.connect 메서드의 주소 뒤에 /room 네임스페이스를 붙인다.
- /room 네임스페이스를 붙이면 서버에서 /room 네임스페이스를 통해 보낸 데이터만 분류해 받을 수 있다.
- chat.html에서는 io.connect 메서드의 주소 뒤에 /chat 네임스페이스를 붙인다.
- socket.js에 웹 소켓 이벤트를 연결한다.
- of 메서드는 Socket.IO에 네임스페이스를 부여하는 메서드이다.
- /room 네임스페이스와 /chat 네임스페이스 각각에 이벤트 리스너를 붙인다.
- Socket.IO에서 세션에 접근하기 위해 app.js와 socket.js 간에 express-session 미들웨어를 공유한다.
- socket.js에서 io.use 메서드에 미들웨어를 장착한다.
- socket.js에서 socket.to(방 아이디) 메서드로 특정 방에 데이터를 보낼 수 있다.
- https://github.com/zerocho/nodejs-book의 소스코드를 참고하여 라우터를 작성한다.
- GET / 라우터는 채팅방 목록 메인 화면을 렌더링한다.
- POST /room 라우터는 채팅방을 만드는 라우터이다.
- GET /room/:id 라우터는 채팅방을 렌더링하는 라우터이다.
- DELETE /room/:id 라우터는 채팅방을 삭제하는 라우터이다.
- chat.html 파일에 서버에서 보내는 채팅 데이터를 받을 소켓 이벤트 리스너를 작성한다.
- routes/index.js에서 GET /room/:id 라우터를 방 접속 시 기존 채팅 내역을 불러오도록 수정한다.
- 채팅을 데이터베이스에 저장하는 POST /room/:id/chat 라우터를 생성한다.
- GIF 이미지를 전송하기 위해 chat.html에서 이미지를 선택해 업로드하는 이벤트 리스너를 추가한다.
- 이미지 파일을 데이터베이스에 저장하는 POST /room/:id/gif 라우터를 작성한다.
- app.js에서 이미지를 제공할 폴더를 express.static 미들웨어로 연결한다.
빈칸 채우기 문제 - (빈칸을 드래그해서 답을 확인해 보세요)
1. 웹 소켓과 HTTP는 같은 포트를 사용할 수 ( 있다. )
3. 웹 소켓을 지원하지 않는 브라우저에서 실시간 통신을 구현하기 위해 ( Socket.IO )를 사용할 수 있다.
4. ( 네임스페이스 )를 통해 서버에서 보낸 데이터를 분류해 받을 수 있다.
5. ( of ) 메서드는 Socket.IO에 네임스페이스를 부여하는 메서드이다.
6. Socket.IO에서 ( 세션 )에 접근하기 위해 app.js와 socket.js 간에 ( express-session ) 미들웨어를 공유한다.
7. GIF 이미지를 전송하기 위해 app.js에서 이미지를 제공할 폴더를 ( express.static ) 미들웨어로 연결한다.
코드 문제
1. 다음 이벤트 리스너의 빈칸에 알맞은 코드를 작성하시오. (웹 소켓 연결 시 발생할 이벤트)
// socket.js
...
const wss = new WebSocket.Server({ server });
wss.on(/*여기에 코드를 작성*/, (ws, req) => { // 웹소켓 연결 시
const ip = req.headers['x-forwarded-for'] || req.socket.remoteAddress;
console.log('새로운 클라이언트 접속', ip);
ws.on('message', (message) => { // 클라이언트로부터 메시지
console.log(message.toString());
});
...
답 :
(더보기로 확인)
2. Socket.IO에 /room 네임스페이스와 /chat 네임스페이스를 부여하는 코드를 작성하시오. (변수명은 각각 room과 chat으로 한다.)
// socket.js
const SocketIO = require('socket.io');
module.exports = (server, app) => {
const io = SocketIO(server, { path: '/socket.io' });
app.set('io', io);
/*여기에 코드를 작성*/
...
답:
const room = io.of('/room');
const chat = io.of('/chat');
(더보기로 확인)
출처: 조현영 , 『Node.js 교과서』 개정판 3판, 길벗, 12.1장 ~ 12.7장
[Node.js 1팀] 15장 AWS와 GCP로 배포하기 (0) | 2024.01.19 |
---|---|
[노드 1팀] 11장. 노드 서비스 테스트하기 (1) | 2024.01.05 |
[Node.js 1] 10장 웹 API 서버 만들기 (0) | 2023.12.29 |
[Node.js 1] 9장 익스프레스로 SNS 서비스 만들기 (1) | 2023.12.22 |
[노드 1팀] 8장. 몽고디비 (1) | 2023.12.01 |