# 튜토리얼: 실시간 채팅방

## Content

이 튜토리얼은 `js-collaboration`을 사용하여 실시간 채팅방을 구축하는 방법을 개발자에게 안내합니다. 다음을 수행합니다:

* 공유된 방 내에서 peer-to-peer 통신 설정
* 즉시 메시지 송수신
* 메시지 브로드캐스팅을 위한 서버/클라이언트 조정 구현

## 사전 준비

* Node.js v16+ 및 npm 설치
* JavaScript와 터미널 작업에 대한 기본 지식

## 1단계: 프로젝트 초기화

1. **프로젝트 폴더 생성**`chat-room`이라는 새 디렉터리를 만들고 해당 디렉터리로 이동합니다:

    ```bash
    mkdir chat-room
    cd chat-room
    ```
2. **Node.js 프로젝트 초기화**
    다음 명령을 실행하여 `package.json` 파일을 생성합니다:

    ```bash
    npm init -y
    ```

    `package.json`을 편집하여 ESM 모듈을 활성화하고 다음 스크립트를 추가합니다:

    ```json
    {
      "name": "chat-room",
      "version": "1.0.0",
      "type": "module",
      "scripts": {
        "start": "node server.js",
        "build": "webpack"
      },
      "dependencies": {}
    }
    ```
3. **필요한 패키지 설치**서버와 클라이언트에 필요한 패키지를 설치합니다:

    ```bash
    npm install @mescius/js-collaboration @mescius/js-collaboration-client express
    ```

    프론트엔드 번들링을 위한 npm 패키지 설치:

    ```bash
    npm install webpack webpack-cli --save-dev
    ```
4. **Webpack 설정 파일 생성**프로젝트 루트 디렉터리에 `webpack.config.js` 파일을 생성하고 다음 내용을 추가합니다:

    ```javascript
    import path from "path";
    import { fileURLToPath } from "url";
    
    const __dirname = path.dirname(fileURLToPath(import.meta.url));
    
    export default {
      entry: "./public/client.js",
      output: {
        path: path.resolve(__dirname, "public"),
        filename: "client.bundle.js"
      },
      mode: "development"
    };
    ```
5. **기본 디렉터리 구조 생성**
    * 루트 디렉터리에 `server.js` 파일 생성
    * 루트 디렉터리에 `public` 폴더 생성 후 `index.html`, `styles.css`, `client.js` 파일 추가

    디렉터리 구조는 다음과 같습니다:

    ```bash
    / (project root)
    ├── public/
    │   ├── index.html      # 메인 페이지
    │   ├── styles.css      # 스타일 파일
    │   └── client.js       # 클라이언트 로직
    ├── server.js           # 서버 로직
    ├── package.json        # 프로젝트 설정
    └── webpack.config.js   # Webpack 설정
    ```

## 2단계: 서버 설정

클라이언트 연결, 메시지 송수신 및 브로드캐스팅을 처리하는 간단한 서버를 생성합니다.`server.js` 파일에 다음 코드를 추가합니다:

```javascript
import express from "express";
import { createServer } from "http";
import { Server } from "@mescius/js-collaboration";

const app = express();
const httpServer = createServer(app);

const server = new Server({ httpServer });

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

server.on("connect", ({ connection, roomId }) => {
    console.log(`${connection.id} joined room ${roomId}`);
    connection.broadcast(`${connection.id} joined the chat room`, "", true);
});

server.on("message", ({ connection, data, roomId }) => {
    console.log(`Received message from ${connection.id}: ${data}`);
    connection.broadcast(`${connection.id}: ${data}`, "", true);
});

server.on("disconnect", ({ connection, roomId }) => {
    console.log(`${connection.id} left room ${roomId}`);
    connection.broadcast(`${connection.id} left the chat room`, "", true);
});

httpServer.listen(8080, () => {
    console.log("Server running at http://localhost:8080");
});
```

**코드 설명**

* express와 http를 사용해 HTTP 서버 생성
* `@mescius/js-collaboration`의 [Server](/spreadjs/api/v19/collaboration/js-collaboration/classes/Server) 클래스로 동시 작업 서버 초기화
* connect, message, disconnect 이벤트 등록
* [connection.broadcast() ](/spreadjs/api/v19/collaboration/js-collaboration/classes/Connection#broadcast)로 메시지를 모든 클라이언트에 전송하며 `includeSelf: true`로 발신자도 메시지 확인 가능

## 3단계: 클라이언트 설정

HTML과 JavaScript 클라이언트를 작성하여 서버에 연결하고 채팅 기능을 구현합니다.

1. **HTML 파일 작성 (`public/index.html`)**
2. **클라이언트 JavaScript 작성 (`public/client.js`)**

    ```javascript
    import { Client } from "@mescius/js-collaboration-client";
    
    const client = new Client();
    const connection = client.connect("chatroom");
    
    connection.on("message", (data) => {
      const chatDiv = document.getElementById("chat");
      const message = document.createElement("p");
      message.textContent = data;
      chatDiv.appendChild(message);
      chatDiv.scrollTop = chatDiv.scrollHeight;
    });
    
    window.sendMessage = function () {
      const input = document.getElementById("message");
      const message = input.value.trim();
      if (message) {
        connection.send(message);
        input.value = "";
      }
    };
    ```

    **코드 설명**
    * `@mescius/js-collaboration-client`의 [Client ](/spreadjs/api/v19/collaboration/js-collaboration-client/classes/Client) 클래스로 클라이언트 생성 후 "chatroom"에 연결
    * [connection.on("message")](/spreadjs/api/v19/collaboration/js-collaboration-client/classes/Connection#on)로 서버 메시지 수신 후 화면에 표시
    * `sendMessage()` 함수로 입력값을 서버에 전송
3. **스타일 작성 (`public/styles.css`)**

    ```css
    html, body {
      height: 100%;
      margin: 0;
      padding: 0;
      font-family: Arial, sans-serif;
      background-color: #f0f2f5;
    }
    
    .container {
      height: 100vh;
      display: flex;
      flex-direction: column;
      background: #fff;
      box-shadow: 0 0 10px rgba(0, 0, 0, 0.1);
    }
    
    h1 {
      font-size: 24px;
      color: #333;
      padding: 15px;
      margin: 0;
      text-align: center;
      border-bottom: 1px solid #ddd;
    }
    
    #chat {
      flex: 1;
      overflow-y: auto;
      background: #fafafa;
      padding: 15px;
    }
    
    #chat p {
      margin: 10px 0;
      padding: 10px;
      background: #e9ecef;
      border-radius: 5px;
      word-wrap: break-word;
    }
    
    .input-area {
      display: flex;
      padding: 15px;
      border-top: 1px solid #ddd;
      background: #f9f9f9;
    }
    
    #message {
      flex: 1;
      padding: 10px;
      border: 1px solid #ccc;
      border-radius: 5px;
      font-size: 14px;
      margin-right: 10px;
    }
    
    button {
      padding: 10px 20px;
      background: #007bff;
      color: white;
      border: none;
      border-radius: 5px;
      cursor: pointer;
      font-size: 14px;
    }
    
    button:hover {
      background: #0056b3;
    }
    ```

## 4단계: 실행 및 테스트

1. **클라이언트 코드 번들링**

    ```bash
    npm run build
    ```
2. **서버 실행**

    ```bash
    npm run start
    ```

    출력: `Server running at http://localhost:8080.`
3. **브라우저에서** http://localhost:8080 방문 후 채팅방 인터페이스 확인
4. **기능 테스트**
    * 여러 브라우저 창을 열어 다중 사용자 시뮬레이션
    * 메시지 입력 후 "Send" 클릭 → 모든 창에서 실시간 메시지 표시
    * 창을 닫으면 다른 창에서 사용자 퇴장 알림 표시

## 다음 단계

[튜토리얼: 인증 추가](/spreadjs/docs/v19/spreadjs-collaboration-server/collaboration-framework/js-collaboration/tutorial-real-time-chat-room/tutorial-add-authentication)