실시간 채팅 앱 만들기 with Socket.io – 완성까지 한번에!

프로젝트 소개 및 목표

실시간 채팅 앱 만들기 with Socket.io는 웹소켓 기술을 활용하여 양방향 실시간 통신을 구현하는 프로젝트입니다. 이 프로젝트를 통해 사용자 간 즉각적인 메시지 교환, 온라인 상태 표시, 타이핑 인디케이터 등 현대적인 채팅 앱의 핵심 기능을 모두 구현할 수 있습니다. Socket.io는 웹소켓을 기반으로 하되 자동 재연결, 폴백 메커니즘 등 실무에 필요한 기능을 제공하여 안정적인 실시간 애플리케이션 개발을 가능하게 합니다. 이 가이드를 따라하면 포트폴리오에 추가할 수 있는 완성도 높은 채팅 앱을 만들 수 있으며, 실시간 웹 기술에 대한 깊은 이해를 얻을 수 있습니다.

필요한 기술 스택

이 프로젝트를 구현하기 위해서는 다음 기술 스택이 필요합니다:

  • 백엔드: Node.js, Express.js, Socket.io
  • 프론트엔드: HTML5, CSS3, JavaScript (Vanilla JS 또는 React)
  • 데이터베이스: MongoDB 또는 PostgreSQL (메시지 저장용)
  • 추가 도구: npm/yarn, nodemon (개발 서버 자동 재시작)

초보자도 따라할 수 있도록 기본적인 JavaScript와 Node.js 지식만 있으면 충분합니다. 데이터베이스는 선택사항이며, 먼저 메모리 기반으로 구현한 후 나중에 추가할 수 있습니다.

프로젝트 셋업

프로젝트를 시작하기 전에 개발 환경을 설정해야 합니다. 먼저 새로운 디렉토리를 만들고 npm 프로젝트를 초기화합니다:

mkdir realtime-chat-app
cd realtime-chat-app
npm init -y
npm install express socket.io
npm install --save-dev nodemon

package.json 파일을 열어 scripts 섹션에 개발 서버 실행 스크립트를 추가합니다:

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

프로젝트 폴더 구조는 다음과 같이 구성합니다:

realtime-chat-app/
├── server.js
├── public/
│   ├── index.html
│   ├── style.css
│   └── client.js
└── package.json

단계별 구현 과정

1단계: Express 서버 및 Socket.io 설정

먼저 server.js 파일을 생성하고 기본 서버를 설정합니다. Socket.io는 HTTP 서버 위에서 동작하므로 Express 앱을 HTTP 서버로 감싸야 합니다:

const express = require('express');
const http = require('http');
const socketIO = require('socket.io');
const path = require('path');

const app = express();
const server = http.createServer(app);
const io = socketIO(server);

// 정적 파일 제공
app.use(express.static(path.join(__dirname, 'public')));

// 사용자 목록 저장 (메모리)
const users = new Map();

// Socket.io 연결 이벤트
io.on('connection', (socket) => {
  console.log('새로운 사용자 연결:', socket.id);

  // 사용자 연결 해제
  socket.on('disconnect', () => {
    const username = users.get(socket.id);
    users.delete(socket.id);
    io.emit('user-disconnected', { username, userCount: users.size });
    console.log('사용자 연결 해제:', socket.id);
  });
});

const PORT = process.env.PORT || 3000;
server.listen(PORT, () => {
  console.log(`서버가 포트 ${PORT}에서 실행 중입니다.`);
});

2단계: 실시간 메시지 송수신 구현

실시간 채팅 앱 만들기 with Socket.io의 핵심은 메시지를 실시간으로 주고받는 것입니다. server.js에 메시지 처리 로직을 추가합니다:

io.on('connection', (socket) => {
  // 사용자 이름 설정
  socket.on('set-username', (username) => {
    users.set(socket.id, username);
    socket.emit('username-set', { success: true, username });
    io.emit('user-connected', { username, userCount: users.size });
  });

  // 채팅 메시지 수신 및 브로드캐스트
  socket.on('chat-message', (data) => {
    const username = users.get(socket.id);
    const messageData = {
      username: username || 'Anonymous',
      message: data.message,
      timestamp: new Date().toISOString()
    };
    // 모든 클라이언트에게 메시지 전송
    io.emit('chat-message', messageData);
  });

  // 타이핑 상태 전송
  socket.on('typing', () => {
    const username = users.get(socket.id);
    socket.broadcast.emit('user-typing', { username });
  });

  socket.on('stop-typing', () => {
    socket.broadcast.emit('user-stop-typing');
  });
});

3단계: 프론트엔드 UI 구현

public/index.html 파일을 생성하여 채팅 인터페이스를 만듭니다:

<!DOCTYPE html>
<html lang="ko">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>실시간 채팅 앱</title>
  <link rel="stylesheet" href="style.css">
</head>
<body>
  <div class="container">
    <div id="username-form" class="username-form">
      <h2>채팅방 입장</h2>
      <input type="text" id="username-input" placeholder="사용자 이름 입력" maxlength="20">
      <button id="join-btn">입장하기</button>
    </div>

    <div id="chat-container" class="chat-container" style="display: none;">
      <div class="chat-header">
        <h2>실시간 채팅</h2>
        <span id="user-count">0명 접속 중</span>
      </div>
      <div id="messages" class="messages"></div>
      <div id="typing-indicator" class="typing-indicator"></div>
      <div class="input-area">
        <input type="text" id="message-input" placeholder="메시지를 입력하세요...">
        <button id="send-btn">전송</button>
      </div>
    </div>
  </div>
  <script src="/socket.io/socket.io.js"></script>
  <script src="client.js"></script>
</body>
</html>

4단계: 클라이언트 JavaScript 로직

public/client.js 파일을 만들어 Socket.io 클라이언트를 구현합니다:

const socket = io();

const usernameForm = document.getElementById('username-form');
const usernameInput = document.getElementById('username-input');
const joinBtn = document.getElementById('join-btn');
const chatContainer = document.getElementById('chat-container');
const messagesDiv = document.getElementById('messages');
const messageInput = document.getElementById('message-input');
const sendBtn = document.getElementById('send-btn');
const typingIndicator = document.getElementById('typing-indicator');
const userCount = document.getElementById('user-count');

let currentUsername = '';
let typingTimer;

// 사용자 이름 설정
joinBtn.addEventListener('click', () => {
  const username = usernameInput.value.trim();
  if (username) {
    socket.emit('set-username', username);
  }
});

socket.on('username-set', (data) => {
  if (data.success) {
    currentUsername = data.username;
    usernameForm.style.display = 'none';
    chatContainer.style.display = 'block';
    messageInput.focus();
  }
});

// 메시지 전송
sendBtn.addEventListener('click', sendMessage);
messageInput.addEventListener('keypress', (e) => {
  if (e.key === 'Enter') sendMessage();
});

function sendMessage() {
  const message = messageInput.value.trim();
  if (message) {
    socket.emit('chat-message', { message });
    messageInput.value = '';
    socket.emit('stop-typing');
  }
}

// 타이핑 인디케이터
messageInput.addEventListener('input', () => {
  socket.emit('typing');
  clearTimeout(typingTimer);
  typingTimer = setTimeout(() => {
    socket.emit('stop-typing');
  }, 1000);
});

// 메시지 수신
socket.on('chat-message', (data) => {
  const messageEl = document.createElement('div');
  messageEl.className = data.username === currentUsername ? 'message own' : 'message';
  messageEl.innerHTML = `
    <strong>${data.username}</strong>
    <p>${escapeHtml(data.message)}</p>
    <span class="time">${formatTime(data.timestamp)}</span>
  `;
  messagesDiv.appendChild(messageEl);
  messagesDiv.scrollTop = messagesDiv.scrollHeight;
});

// 사용자 연결/해제
socket.on('user-connected', (data) => {
  userCount.textContent = `${data.userCount}명 접속 중`;
  addSystemMessage(`${data.username}님이 입장했습니다.`);
});

socket.on('user-disconnected', (data) => {
  userCount.textContent = `${data.userCount}명 접속 중`;
  addSystemMessage(`${data.username}님이 퇴장했습니다.`);
});

// 타이핑 표시
socket.on('user-typing', (data) => {
  typingIndicator.textContent = `${data.username}님이 입력 중...`;
});

socket.on('user-stop-typing', () => {
  typingIndicator.textContent = '';
});

// 유틸리티 함수
function addSystemMessage(message) {
  const msgEl = document.createElement('div');
  msgEl.className = 'system-message';
  msgEl.textContent = message;
  messagesDiv.appendChild(msgEl);
}

function escapeHtml(text) {
  const div = document.createElement('div');
  div.textContent = text;
  return div.innerHTML;
}

function formatTime(timestamp) {
  const date = new Date(timestamp);
  return date.toLocaleTimeString('ko-KR', { hour: '2-digit', minute: '2-digit' });
}

5단계: 스타일링 추가

public/style.css 파일을 생성하여 채팅 앱을 꾸밉니다:

* {
  margin: 0;
  padding: 0;
  box-sizing: border-box;
}

body {
  font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
  background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
  height: 100vh;
  display: flex;
  justify-content: center;
  align-items: center;
}

.container {
  width: 90%;
  max-width: 600px;
}

.username-form, .chat-container {
  background: white;
  border-radius: 10px;
  padding: 20px;
  box-shadow: 0 10px 40px rgba(0, 0, 0, 0.2);
}

.username-form h2 {
  margin-bottom: 20px;
  color: #333;
}

.username-form input {
  width: 100%;
  padding: 12px;
  border: 2px solid #ddd;
  border-radius: 5px;
  font-size: 16px;
  margin-bottom: 10px;
}

.username-form button, #send-btn {
  width: 100%;
  padding: 12px;
  background: #667eea;
  color: white;
  border: none;
  border-radius: 5px;
  font-size: 16px;
  cursor: pointer;
  transition: background 0.3s;
}

.username-form button:hover, #send-btn:hover {
  background: #5568d3;
}

.chat-header {
  display: flex;
  justify-content: space-between;
  align-items: center;
  padding-bottom: 15px;
  border-bottom: 2px solid #eee;
  margin-bottom: 15px;
}

.messages {
  height: 400px;
  overflow-y: auto;
  padding: 10px;
  background: #f9f9f9;
  border-radius: 5px;
  margin-bottom: 10px;
}

.message {
  margin-bottom: 15px;
  padding: 10px;
  background: white;
  border-radius: 8px;
  box-shadow: 0 2px 5px rgba(0, 0, 0, 0.1);
}

.message.own {
  background: #667eea;
  color: white;
  margin-left: auto;
  max-width: 80%;
}

.message strong {
  display: block;
  margin-bottom: 5px;
  font-size: 14px;
}

.message p {
  margin: 5px 0;
  word-wrap: break-word;
}

.message .time {
  font-size: 11px;
  opacity: 0.7;
}

.system-message {
  text-align: center;
  color: #999;
  font-size: 13px;
  margin: 10px 0;
}

.typing-indicator {
  height: 20px;
  color: #667eea;
  font-size: 13px;
  font-style: italic;
}

.input-area {
  display: flex;
  gap: 10px;
}

#message-input {
  flex: 1;
  padding: 12px;
  border: 2px solid #ddd;
  border-radius: 5px;
  font-size: 14px;
}

#send-btn {
  width: 100px;
}

테스트 및 배포

개발 서버를 실행하여 애플리케이션을 테스트합니다:

npm run dev

브라우저에서 http://localhost:3000 을 열고 여러 탭에서 접속하여 실시간 메시지 교환을 테스트합니다. 배포는 Heroku, Vercel, DigitalOcean 등 다양한 플랫폼을 사용할 수 있습니다. Heroku 배포 예시:

// Procfile 생성
web: node server.js

// Git 초기화 및 배포
git init
heroku create my-chat-app
git add .
git commit -m "Initial commit"
git push heroku main

환경 변수는 .env 파일로 관리하고, CORS 설정을 추가하여 보안을 강화합니다. 프로덕션 환경에서는 Redis를 사용하여 여러 서버 인스턴스 간 Socket.io 이벤트를 동기화할 수 있습니다.

마무리 및 확장 아이디어

실시간 채팅 앱 만들기 with Socket.io 프로젝트를 완성했습니다! 기본 기능 외에도 다음과 같은 확장 기능을 추가할 수 있습니다: 프라이빗 메시지 (DM), 채팅방 여러 개 생성, 파일 및 이미지 전송, 이모지 지원, 메시지 검색 기능, 사용자 프로필 사진, 읽음 표시, 알림 기능 등입니다. MongoDB를 연동하면 채팅 기록을 영구 저장할 수 있고, JWT를 사용한 인증을 추가하면 더욱 안전한 채팅 앱을 만들 수 있습니다. 이 프로젝트는 포트폴리오에 훌륭한 자료가 되며, 실시간 웹 기술의 이해도를 크게 높여줍니다.

📚 함께 읽으면 좋은 글

1

실시간 채팅 앱 만들기 with Socket.io – 완성까지 한번에!

📂 프로젝트 아이디어
📅 2025. 11. 11.
🎯 실시간 채팅 앱 만들기 with Socket.io

2

실시간 채팅 앱 만들기 with Socket.io – 완성까지 한번에!

📂 프로젝트 아이디어
📅 2025. 11. 9.
🎯 실시간 채팅 앱 만들기 with Socket.io

3

실시간 채팅 앱 만들기 with Socket.io – 완성까지 한번에!

📂 프로젝트 아이디어
📅 2025. 11. 5.
🎯 실시간 채팅 앱 만들기 with Socket.io

4

실시간 채팅 앱 만들기 with Socket.io – 완성까지 한번에!

📂 프로젝트 아이디어
📅 2025. 11. 4.
🎯 실시간 채팅 앱 만들기 with Socket.io

5

실시간 채팅 앱 만들기 with Socket.io – 완성까지 한번에!

📂 프로젝트 아이디어
📅 2025. 10. 29.
🎯 실시간 채팅 앱 만들기 with Socket.io

💡 위 글들을 통해 더 깊이 있는 정보를 얻어보세요!

📢 이 글이 도움되셨나요? 공유해주세요!

여러분의 공유 한 번이 더 많은 사람들에게 도움이 됩니다 ✨

🔥 공유할 때마다 블로그 성장에 큰 힘이 됩니다! 감사합니다 🙏

💬 여러분의 소중한 의견을 들려주세요!

실시간 채팅 앱 만들기 with Socket.io 관련해서 궁금한 점이 더 있으시다면 언제든 물어보세요!

💡
유용한 정보 공유

궁금한 점 질문

🤝
경험담 나누기

👍
의견 표현하기

⭐ 모든 댓글은 24시간 내에 답변드리며, 여러분의 의견이 다른 독자들에게 큰 도움이 됩니다!
🎯 건설적인 의견과 경험 공유를 환영합니다 ✨

🔔 블로그 구독하고 최신 글을 받아보세요!

📚
다양한 주제
17개 카테고리

정기 업데이트
하루 3회 발행

🎯
실용적 정보
바로 적용 가능

💡
최신 트렌드
2025년 기준

🌟 프로젝트 아이디어부터 다양한 실생활 정보까지!
매일 새로운 유용한 콘텐츠를 만나보세요 ✨

📧 RSS 구독 | 🔖 북마크 추가 | 📱 모바일 앱 알림 설정
지금 구독하고 놓치는 정보 없이 업데이트 받아보세요!

답글 남기기