Node.js · 2025-12-16

Socket.io로 실시간 채팅 서비스 구현하기

Socket.io와 Node.js를 사용해 기본 실시간 채팅 서버와 클라이언트 구조, 이벤트 흐름, 배포·보안 고려사항을 초보자도 이해하기 쉽게 정리한 설명

작성일 : 2025-12-16 ㆍ 작성자 : 관리자
post
목차

개요

실시간 채팅은 사용자 경험을 크게 향상시킨다. Socket.io는 WebSocket을 포함한 여러 전송 방식을 추상화해서 손쉽게 실시간 통신을 구현하게 한다. 이 글에서는 Socket.io 채팅 예제와 함께 Node.js 실시간 채팅 만들기 과정을 처음부터 단계별로 설명한다. 코드는 최소한의 구성으로 동작하도록 설계했다.

사전 준비

필수 환경

  • Node.js (LTS 권장)
  • npm 또는 yarn
  • 기본적인 JavaScript 및 HTML 지식

패키지 설치

프로젝트 폴더에서 Express와 Socket.io를 설치한다. 이 단계가 Node.js 실시간 채팅 만들기의 첫걸음이다.

npm init -y
npm install express socket.io

서버 구현

간단한 Express + Socket.io 서버

아래 코드는 기본적인 서버 구조다. 클라이언트 연결, 메시지 수신, 브로드캐스트를 처리한다.

const express = require('express');
const http = require('http');
const { Server } = require('socket.io');

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

app.use(express.static('public'));

io.on('connection', (socket) => {
  console.log('사용자 연결:', socket.id);

  // 접속 이벤트
  socket.on('join', (nick) => {
    socket.nickname = nick || '익명';
    socket.broadcast.emit('sys', `${socket.nickname}님이 입장했습니다.`);
  });

  // 메시지 수신
  socket.on('message', (msg) => {
    const payload = { from: socket.nickname || '익명', text: msg };
    io.emit('message', payload);
  });

  // 접속 해제
  socket.on('disconnect', () => {
    io.emit('sys', `${socket.nickname || '사용자'}님이 퇴장했습니다.`);
  });
});

server.listen(3000, () => console.log('서버 실행: http://localhost:3000'));

이 구조는 Socket.io 채팅 예제의 핵심 흐름을 보여준다. 서버는 클라이언트 이벤트를 받고, 필요하면 전체에 브로드캐스트한다.

클라이언트 구현

기본 HTML 및 클라이언트 스크립트

public/index.html 파일에 클라이언트 코드를 둔다. Socket.io 클라이언트 라이브러리는 서버에서 제공하는 스크립트를 사용한다.

<!doctype html>
<html lang="ko">
  <head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <title>Socket.io 채팅 예제</title>
    <style>
      body{font-family:Arial;margin:16px}
      #log{height:300px;border:1px solid #ccc;padding:8px;overflow:auto}
    </style>
  </head>
  <body>
    <h1>실시간 채팅</h1>
    <div id="log"></div>
    <input id="nick" placeholder="닉네임" />
    <input id="msg" placeholder="메시지" />
    <button id="send">전송</button>

    <script src="/socket.io/socket.io.js"></script>
    <script>
      const socket = io();
      const log = document.getElementById('log');
      const nick = document.getElementById('nick');
      const msg = document.getElementById('msg');
      const send = document.getElementById('send');

      function append(text){
        const el = document.createElement('div');
        el.textContent = text;
        log.appendChild(el);
        log.scrollTop = log.scrollHeight;
      }

      // 입장 알림 전송
      send.addEventListener('click', () => {
        if(!socket.connected) return;
        socket.emit('join', nick.value);
        socket.emit('message', msg.value);
        msg.value = '';
      });

      // 서버 이벤트 처리
      socket.on('message', (data) => append(`${data.from}: ${data.text}`));
      socket.on('sys', (data) => append(`* ${data}`));
    </script>
  </body>
</html>

위 코드는 최소한의 채팅 인터페이스다. Socket.io 튜토리얼의 기본 개념인 연결, 이벤트 전송, 수신을 모두 포함한다.

이벤트 설계와 메시지 흐름

권장 이벤트 구조

  • join: 닉네임이나 룸 정보 전달
  • message: 사용자 메시지 전달
  • sys: 시스템 알림 전달(입장/퇴장 등)

이벤트 이름을 간단명료하게 유지하면 확장 시 관리가 쉬워진다. 각 이벤트는 검증 로직을 거쳐 악의적 입력을 차단해야 한다.

실무 고려사항

스케일링

단일 프로세스는 소수의 연결에 적합하다. 다중 인스턴스 환경에서는 Socket.io 어댑터(예: Redis)를 사용해 이벤트를 공유해야 한다. 로드 밸런서 사용 시에는 세션 무결성을 위해 sticky session 또는 토큰 기반 인증을 고려한다.

보안

  • HTTPS 적용으로 중간자 공격 방지
  • 입력 값 검증으로 XSS·인젝션 차단
  • 인증 토큰을 통해 허가된 사용자만 연결 허용

확장 아이디어

  • 룸(채널) 기능 추가로 그룹 채팅 지원
  • 메시지 영속화를 위한 데이터베이스 연동
  • 읽음 표시, 타이핑 알림 등 UX 개선 기능

문제 해결 팁

  • 연결 문제: 브라우저 콘솔과 서버 로그를 함께 확인
  • 메시지 누락: 어댑터 설정과 네트워크 지연 검사
  • 리소스 관리: 불필요한 이벤트 리스너 제거

정리

이 글은 Socket.io 채팅 예제 중심으로 Node.js 실시간 채팅 만들기 과정을 설명했다. 서버와 클라이언트의 핵심 코드, 이벤트 설계, 확장과 보안 고려사항을 포함한다. 처음 구현할 때는 단순 구조로 시작해 기능을 점진적으로 추가하는 방법이 안정적이다. 보다 큰 트래픽을 다루려면 Redis 어댑터, HTTPS, 인증 구조를 적용하는 것을 권장한다.

Socket.io 채팅 예제 Node.js 실시간 채팅 만들기 Socket.io 튜토리얼 Socket.io Node.js 채팅 웹소켓 실시간 통신 채팅앱 만들기