# Server Middleware

## Content

**Middleware**는 서버가 연결 및 메시지를 처리하기 위한 핵심 메커니즘으로, 연결 수립이나 메시지 수신과 같은 이벤트가 훅(hook)에 도달하기 전에 사용자 정의 로직을 실행하는 데 사용됩니다. 서버 자체에는 비즈니스 로직이 없으며, 미들웨어를 통해 특정 기능을 구현합니다.
서버가 제공하는 미들웨어 메커니즘을 통해 개발자는 연결 및 메시지 처리 로직을 **사용자 정의**할 수 있습니다. 이 문서에서는 그 사용 방법과 특징을 설명합니다.

## **사용 예시**

* 사용자 인증
* 권한 검증
* 로그 관리

## 등록

[server.use](/spreadjs/api/v19/collaboration/js-collaboration/classes/Server#use) API를 사용하여 미들웨어를 등록합니다. 두 가지 방식이 지원됩니다.

1. 단일 등록

```typescript
server.use('connect', async (context, next) => {
    console.log('Client connecting:', context.connection.id);
    await next();
});
server.use('message', async (context, next) => {
    console.log('Message received:', context.data);
    await next();
});
```

2. 일괄 등록

```typescript
server.use({
    connect: async (context, next) => {
        console.log('Client connecting:', context.connection.id);
        await next();
    },
    message: async (context, next) => {
        console.log('Message received:', context.data);
        await next();
    }
});
```

## 실행 순서

여러 개의 미들웨어가 등록된 경우, 등록된 순서대로 실행됩니다.

```typescript
server.use('connect', (context, next) => {
    console.log('Middleware1');
    await next();
});
server.use('connect', (context, next) => {
    console.log('Middleware2');
    await next();
});
server.use('connect', (context, next) => {
    console.log('Middleware3');
    await next();
});
server.on('connect', () => {
    console.log('Hook');
});
// 출력 결과
//Middleware1
//Middleware2
//Middleware3
// Hook
```

## 에러

`next` 메서드가 `error` 파라미터와 함께 호출되면 다음과 같은 동작이 발생합니다.

* 이후 미들웨어 실행이 중단됩니다.
* 서버의 내장 에러 핸들러가 실행되며, 에러가 클라이언트로 반환되어 클라이언트의 `error` 이벤트가 트리거됩니다.
* `connect` 미들웨어의 경우, 연결 요청이 거부됩니다(연결이 아직 수립되지 않았으므로 connect 훅은 호출되지 않습니다).

```typescript
// server side
server.use('connect', async (context, next) => {
    console.log('Middleware1');
    await next();
});
server.use('connect', async (context, next) => {
    console.log('Middleware2');
    await next(new Error('test middleware error'));
});
server.use('connect', async (context, next) => {
    console.log('Middleware3');
    await next();
});
server.on('connect', () => {
    console.log('Hook');
});

// 출력:
//Middleware1
//Middleware2
```

**클라이언트에서 오류 수신**

```typescript
// client side
connection.on('error', (error) => {
    console.log(error.message); // will output "test middleware error"
});
```

## 단락 종료

미들웨어 내에서 `next()` 함수가 호출되지 않으면 다음과 같은 동작이 발생합니다.

* 이후 미들웨어 실행이 중단되며, 이벤트 처리 흐름이 실행되지 않습니다.
* `connect` 미들웨어의 경우, 반드시 `next()`를 호출해야 합니다. 호출하지 않으면 연결 요청이 타임아웃될 때까지 대기하다가 종료됩니다.
* `message` 미들웨어의 경우, 단락 처리를 사용해 처리 흐름을 조기에 종료할 수 있습니다.

```typescript
// Server side
server.use('message', async (context, next) => {
    console.log('Middleware1');
    await next();
});
server.use('message', async (context, next) => {
    console.log('Middleware2');
    // Short-circuit: next() is not called
});
server.use('message', async (context, next) => {
    console.log('Middleware3');
    await next();
});
server.on('message', () => {
    console.log('Hook');
});

// 출력:
// Middleware1
// Middleware2
```

## 인터페이스

```typescript
export interface IMiddlewares {
    connect?: IMiddleware<IConnectMiddlewareContext>;  // 연결 시
    message?: IMiddleware<IMessageMiddlewareContext>;  // 클라이언트로부터 메시지 수신 시
}
```

## 다음 단계

미들웨어를 사용한 인증 및 권한 검증에 대해서는 [사용자 인증 및 권한](/spreadjs/docs/v19/spreadjs-collaboration-server/collaboration-framework/js-collaboration/user-authentication-and-permissions)을 참고하세요.