1. 클라이언트(프론트엔드) 설정
실시간 채팅 애플리케이션을 Vue.js 기반으로 구축하기 위해 socket.io-client와 Vue.js 통합을 돕는 vue-socket.io-extended 라이브러리를 사용합니다.
1.1. 의존성 설치
먼저, 필요한 라이브러리들을 프로젝트에 설치합니다.
npm install vue-socket.io-extended socket.io-client --save
1.2. Socket.IO 클라이언트 초기화
main.js 파일 또는 별도의 플러그인 파일에서 Socket.IO 클라이언트를 설정하고 Vue 인스턴스에 등록합니다. 이를 통해 Vue 컴포넌트 내에서 this.$socket을 통해 Socket.IO 인스턴스에 접근할 수 있게 됩니다.
import Vue from 'vue';
import { io } from 'socket.io-client'; // socket.io-client에서 io 함수 임포트
import VueSocketIOExtension from 'vue-socket.io-extended'; // Vue.js용 Socket.IO 확장 플러그인
// 서버와 연결할 엔드포인트 지정.
// Vue CLI 개발 서버의 프록시 설정에 따라 상대 경로를 사용할 수 있습니다.
const connectionEndpoint = '/';
const socketConnection = io(connectionEndpoint, {
autoConnect: true // Vue 앱 시작 시 자동으로 연결 시도
});
Vue.use(VueSocketIOExtension, socketConnection);
// Vue 애플리케이션 초기화 (예시)
// new Vue({
// render: h => h(App),
// }).$mount('#app');
io('/')는 현재 호스트의 루트 경로로 Socket.IO 연결을 시도합니다. 개발 환경에서는 Vue CLI의 프록시 설정을 통해 백엔드 Socket.IO 서버로 라우팅됩니다.
1.3. 개발 서버 프록시 설정 (CORS 처리)
프론트엔드 개발 서버(예: localhost:8080)가 백엔드 Socket.IO 서버(예: localhost:3000)와 다른 도메인 또는 포트를 사용할 경우, 교차 출처 리소스 공유(CORS) 문제를 해결하기 위해 프록시 설정을 추가해야 합니다.
vue.config.js 파일을 생성하거나 수정하여 다음과 같이 Socket.IO 요청을 위한 프록시를 설정합니다:
const { defineConfig } = require('@vue/cli-service');
module.exports = defineConfig({
devServer: {
host: 'localhost', // 개발 서버 호스트
port: 8080, // 개발 서버 포트 (기본값)
proxy: {
'/socket.io': { // '/socket.io' 경로로 들어오는 모든 요청을 프록시
target: 'http://localhost:3000', // 백엔드 Socket.IO 서버 주소
ws: true, // WebSocket 프록시 활성화
changeOrigin: true, // 대상 서버의 호스트 헤더를 변경하여 CORS 문제 해결
},
},
},
});
이 설정은 프론트엔드에서 /socket.io로 시작하는 모든 요청을 http://localhost:3000으로 전달하며, WebSocket 연결도 지원합니다.
1.4. Vue 컴포넌트에서 Socket.IO 사용
이제 Vue 컴포넌트 내에서 Socket.IO 이벤트를 보내거나 받을 수 있습니다. 예를 들어, 사용자가 채팅방에 입장했음을 서버에 알리는 로직은 다음과 같이 구현할 수 있습니다.
<template>
<div class="chat-container">
<h1>실시간 채팅</h1>
<!-- 메시지 목록, 입력 필드 등 채팅 UI 요소 -->
</div>
</template>
<script>
export default {
name: 'ChatComponent',
created() {
this.sendUserEntryNotification();
},
methods: {
sendUserEntryNotification() {
// 로컬 스토리지 등에서 현재 사용자 정보를 가져옵니다.
const userPayload = localStorage.getItem('currentUser') || '익명 사용자';
// 'userJoined' 이벤트를 서버에 방출 (emit)합니다.
// 서버는 이 이벤트를 받아 사용자 접속을 처리할 수 있습니다.
this.$socket.client.emit('userJoined', {
message: '사용자가 채팅에 참여했습니다.',
userIdentifier: userPayload,
});
console.log('채팅 서버에 사용자 참여 알림을 보냈습니다:', userPayload);
}
// 추가적인 메시지 전송 및 수신 로직 구현 가능
// sendMessage() {
// this.$socket.client.emit('sendMessage', { content: '안녕하세요!', targetClientId: '...' });
// }
},
sockets: { // VueSocketIOExtension을 통해 자동으로 연결되는 이벤트 리스너
connect() {
console.log('Socket.IO 서버에 연결되었습니다!');
},
disconnect() {
console.log('Socket.IO 서버와 연결이 끊어졌습니다.');
},
receiveMessage(data) { // 서버로부터 'receiveMessage' 이벤트를 수신
console.log('새 메시지 수신:', data);
// 받은 메시지를 UI에 추가하는 로직 구현
},
serverNotification(data) { // 서버로부터의 일반 알림
console.log('서버 알림:', data.text);
}
}
}
</script>
2. 서버(백엔드) 설정
백엔드에서는 Node.js와 socket.io 라이브러리를 사용하여 Socket.IO 서버를 구축합니다.
2.1. 의존성 설치
프로젝트에 socket.io를 설치합니다.
npm install socket.io --save
2.2. Socket.IO 서버 모듈 생성
별도의 파일(예: ./socket/chatSocketServer.js)에 Socket.IO 서버 초기화 로직을 정의합니다.
// ./socket/chatSocketServer.js
const SocketIO = require('socket.io');
/**
* HTTP 서버 인스턴스를 받아 Socket.IO 서버를 초기화합니다.
* @param {object} httpServer - Node.js HTTP 서버 인스턴스
*/
function initializeSocketServer(httpServer) {
const io = SocketIO(httpServer, {
cors: { // 클라이언트와의 CORS 문제를 해결하기 위한 설정
origin: 'http://localhost:8080', // 프론트엔드 개발 서버 주소
methods: ['GET', 'POST'], // 허용할 HTTP 메서드
credentials: true
}
});
// 'connection' 이벤트: 새로운 클라이언트가 Socket.IO 서버에 연결될 때 발생
io.on('connection', (clientSocket) => {
console.log(`새로운 클라이언트 연결: ${clientSocket.id}`);
// 모든 연결된 클라이언트에게 새로운 사용자 접속을 알림
io.emit('serverNotification', { text: `사용자 (${clientSocket.id.substring(0, 4)}...)가 접속했습니다.` });
// 'userJoined' 이벤트 리스너: 클라이언트가 채팅방 입장 시 보낸 이벤트 처리
clientSocket.on('userJoined', (data) => {
console.log(`클라이언트 (${clientSocket.id})로부터 사용자 참여 알림 수신:`, data.userIdentifier);
// 추가적인 로직: 사용자 목록 업데이트, 이전 메시지 전송 등
});
// 'sendMessage' 이벤트 리스너: 클라이언트가 메시지를 보낼 때 처리
clientSocket.on('sendMessage', (messageData) => {
console.log(`클라이언트 (${clientSocket.id})로부터 메시지 수신:`, messageData.content);
// 메시지 브로드캐스팅 또는 특정 대상에게 전송
if (messageData.targetClientId && io.sockets.sockets.has(messageData.targetClientId)) {
// 특정 클라이언트에게만 메시지 전송 (Private Message)
io.to(messageData.targetClientId).emit('receiveMessage', {
sender: clientSocket.id,
content: messageData.content,
timestamp: new Date().toISOString(),
isPrivate: true
});
} else {
// 모든 클라이언트에게 메시지 브로드캐스트 (Public Chat)
io.emit('receiveMessage', {
sender: clientSocket.id,
content: messageData.content,
timestamp: new Date().toISOString(),
isPrivate: false
});
}
});
// 'disconnect' 이벤트 리스너: 클라이언트 연결이 끊어질 때 발생
clientSocket.on('disconnect', (reason) => {
console.log(`클라이언트 (${clientSocket.id}) 연결 해제: ${reason}`);
io.emit('serverNotification', { text: `사용자 (${clientSocket.id.substring(0, 4)}...)가 연결을 해제했습니다.` });
});
// 기타 이벤트 리스너 추가 가능 (예: 'hasRead' 메시지 읽음 처리)
clientSocket.on('messageRead', (messageId) => {
console.log(`클라이언트 (${clientSocket.id})가 메시지 ${messageId}를 읽었습니다.`);
// 데이터베이스에 읽음 상태 업데이트 등
});
});
console.log('Socket.IO 서버가 성공적으로 초기화되었습니다.');
}
module.exports = { initializeSocketServer };
2.3. Express 애플리케이션에 Socket.IO 서버 통합
Express.js와 같은 HTTP 서버 프레임워크와 함께 Socket.IO를 사용하려면, Socket.IO를 Express 앱이 아닌 Node.js의 기본 HTTP 서버 인스턴스에 연결해야 합니다.
app.js 또는 서버 진입점 파일에서 다음과 같이 Socket.IO 서버를 통합합니다.
// app.js 또는 server.js
const express = require('express');
const http = require('http');
const { initializeSocketServer } = require('./socket/chatSocketServer'); // Socket.IO 모듈 임포트
const app = express();
const PORT = process.env.PORT || 3000;
// Express 미들웨어 설정 (필요시)
// app.use(express.json());
// app.use(express.urlencoded({ extended: true }));
// HTTP 서버 생성: Express 앱을 처리
const httpServer = http.createServer(app);
// Socket.IO 서버 초기화: 생성된 HTTP 서버 인스턴스에 연결
initializeSocketServer(httpServer);
// Express 라우트 설정 (필요시)
app.get('/', (req, res) => {
res.send('채팅 서버가 실행 중입니다.');
});
// HTTP 서버 리스닝
httpServer.listen(PORT, () => {
console.log(`Express 및 Socket.IO 서버가 포트 ${PORT}에서 실행 중입니다.`);
});
module.exports = app;
이제 클라이언트와 서버 간에 실시간 양방향 통신이 가능한 채팅 환경이 구축되었습니다.