# Presence

## Content

`spread-sheets-collaboration`은 [js-collaboration-presence](/spreadjs/docs/spreadjs-collaboration-server/collaboration-framework/js-collaboration-presence)를 기반으로 하며, SpreadJS Sheets 동시 작업 편집 시나리오에 특화된 Presence 기능을 제공합니다. 이 기능은 **사용자 Presence 상태를 실시간으로 표시**(예: 커서 위치, 선택 영역)하여 다른 동시 작업 사용자의 작업 상태를 쉽게 파악할 수 있도록 하고, 동시 작업 효율을 향상시킵니다. Workbook과 Presence는 [setPresences](/spreadjs/api/classes/GC.Spread.Sheets.Collaboration.Collaboration#setpresences) / [getPresences](/spreadjs/api/classes/GC.Spread.Sheets.Collaboration.Collaboration#getpresences) 또는 [bindPresence](/spreadjs/api/collaboration/spread-sheets-collaboration-client/README#bindpresence)를 통해 연동할 수 있습니다.

## 핵심 기능: 실시간 사용자 상태 공유

### 기능 설명

현재 활성 워크시트에서, 동일한 활성 시트에서 작업 중인 모든 동시 작업 사용자의 선택 영역 또는 선택된 셀을 실시간으로 렌더링합니다.

* 각 사용자에게는 고유한 색상이 할당되며, 선택 영역의 우측 상단에 사용자 이름이 표시됩니다.

![use-presence.e9da53.png](https://gcdocumentsitekrblob.blob.core.windows.net/document-site-files/images/36b63360-fb01-457c-a448-c3ce32aaf454/use-presence.e9da53-20260107.a4ecf9.png)

### 적용 시나리오

* 다중 사용자 편집 시, 다른 사용자가 작업 중인 셀이나 영역을 명확히 확인하여 충돌을 방지할 수 있습니다.
* 재무 스프레드시트 등에서 다른 동시 작업 사용자의 편집 위치를 실시간으로 확인하여 팀 동시 작업을 원활하게 합니다.

## 인터페이스

### ISelections

**[ISelections](/spreadjs/api/collaboration/spread-sheets-collaboration-client/interfaces/ISelections)** 인터페이스는 Workbook에서 특정 선택 영역 정보를 표현하는 객체 구조를 정의합니다.

```typescript
//* typedef GC.Spread.Sheets.Collaboration.ISelections
/**
 * @property {GC.Spread.Sheets.Range[]} [selections]
 * @property {string} [sheetId]
 */
export interface ISelections {
    selections?: GC.Spread.Sheets.Range[];
    sheetId?: string;
}
```

**속성 설명**

| 속성명 | 타입 | 설명 |
| --- | --- | --- |
| selections (선택) | [GC.Spread.Sheets.Range](/spreadjs/api/classes/GC.Spread.Sheets.Range)[] | SpreadSheets의 모든 선택 영역 |
| sheetId (선택) | string | 선택 영역이 위치한 시트 ID |

### IStatus

**[IStatus](/spreadjs/api/modules/GC.Spread.Sheets.Collaboration#istatus)** 인터페이스는 모든 상태 객체의 구조를 정의합니다.

```typescript
//* typedef GC.Spread.Sheets.Collaboration.IStatus
/**
 * @property {GC.Spread.Sheets.Collaboration.ISelections} [selections]
 */
export interface IStatus {
    selections?: GC.Spread.Sheets.Collaboration.ISelections;
}
```

**속성 설명**

| 속성명 | 타입 | 설명 |
| --- | --- | --- |
| selections | [ISelections](/spreadjs/api/collaboration/spread-sheets-collaboration-client/interfaces/ISelections) | 모든 선택 상태 |

### IPresence

**[IPresence](/spreadjs/api/collaboration/spread-sheets-collaboration-client/interfaces/IPresence)** 인터페이스는 Workbook에서 사용자 Presence 상태 객체의 구조를 정의합니다.

```typescript
//* typedef GC.Spread.Sheets.Collaboration.IPresence
/**
 * @property {GC.Spread.Common.IUser} [user]
 * @property {GC.Spread.Sheets.Collaboration.IStatus} [status]
 */
export interface IPresence {
    user: GC.Spread.Common.IUser;
    status: GC.Spread.Sheets.Collaboration.IStatus;
}
```

**속성 설명**

| 속성명 | 타입 | 설명 |
| --- | --- | --- |
| user (선택) | [GC.Spread.Common.IUser](/spreadjs/api/interfaces/GC.Spread.Common.IUser) | 사용자 객체 정보 |
| status (선택) | [GC.Spread.Sheets.Collaboration.IStatus](/spreadjs/api/modules/GC.Spread.Sheets.Collaboration#istatus) | Presence 상태 정보 |

### IBindPresenceOptions

[IBindPresenceOptions](/spreadjs/api/collaboration/spread-sheets-collaboration-client/interfaces/IBindPresenceOptions) 인터페이스는 [bindPresence](/spreadjs/api/collaboration/spread-sheets-collaboration-client/README#bindpresence)를 위한 설정 옵션을 정의합니다.

```typescript
export interface IBindPresenceOptions {
    onPresencesUpdate?: (presences?: IPresence[]) => void
}
```

**속성 설명**

| 속성명 | 타입 | 설명 |
| --- | --- | --- |
| onPresencesUpdate (선택) | (presences?: IPresence[]) => void | bindPresence를 통해 Presence가 갱신된 후 호출되는 콜백 |

## 메서드

### setPresences

[setPresences](/spreadjs/api/classes/GC.Spread.Sheets.Collaboration.Collaboration#setpresences) 메서드는 사용자 Presence 상태 정보를 설정합니다.

```typescript
function setPresences(presences: GC.Spread.Sheets.Collaboration.IPresence[]): void
```

**매개변수**

* **presences (`GC.Spread.Sheets.Collaboration.IPresence[]`)**: 설정할 사용자 Presence 상태 목록

**예제**

```typescript
let presences = [{
	user: {
		id: '1',
		name: 'User1',
		color: '#FF0000'
	},
	status: {
		selections: {
			selections: [new GC.Spread.Sheets.Range(0, 0, 1, 1)],
			sheetId: 'sheet1'
		}
	}
}];
spread.collaboration.setPresences(presences);
```

### getPresences

[getPresences](/spreadjs/api/classes/GC.Spread.Sheets.Collaboration.Collaboration#getpresences) 메서드는 현재 Presence 정보를 가져옵니다.

```typescript
function getPresences(): GC.Spread.Sheets.Collaboration.IPresence[]
```

**반환값**

* **presences (`GC.Spread.Sheets.Collaboration.IPresence[]`)**: 현재 Presence 정보

**예제**

```typescript
const presences = spread.collaboration.getPresences();
```

### bindPresence

[bindPresence](/spreadjs/api/collaboration/spread-sheets-collaboration-client/README#bindpresence) 메서드는 Presence, 사용자 정보, 권한 정보를 현재 Workbook에 바인딩하여, Presence와 사용자 정보 및 권한을 동시에 간편하게 연결합니다.

```typescript
export interface IUserWithPermission extends GC.Spread.Common.IUser {
    permission?: IPermission;
}
export declare function bindPresence(
    workbook: any,
    presence: Presence<IPresence>,
    user: IUserWithPermission,
    options?: IBindPresenceOptions
): Promise<void>;
```

**매개변수**

* **workbook (`GC.Spread.Sheets.Workbook`)**: Workbook 인스턴스
* **presence (`IPresence`)**: Presence 인스턴스
* **user (`IUserWithPermission`)**: 권한 정보를 포함한 사용자 정보
* **options (`IBindPresenceOptions`)**: 사용자 Presence 바인딩 옵션

**반환값**

* **Promise**: 바인딩이 완료되면 resolve되는 Promise

**예제**

```typescript
import { Client } from "@mescius/js-collaboration-client";
import { Presence } from "@mescius/js-collaboration-presence-client";
import { bindPresence, IUserWithPermission } from 'spread-sheets-collaboration-client';

const conn = new Client('ws://localhost:8080/').connect('room1');
const presence = new Presence(conn);

const user: IUserWithPermission = {
    id: '1',
    name: "user1",
    permission: {
        mode: GC.Spread.Sheets.Collaboration.BrowsingMode.edit,
    }
}

bindPresence(workbook, presence, user);
```

## 사용 방법

### 클라이언트 측

1. NPM 패키지 설치

```bash
npm install @mescius/js-collaboration-client @mescius/js-collaboration-presence-client @mescius/spread-sheets-collaboration-client
```

2. Presence 인스턴스 생성

```typescript
import { Client } from "@mescius/js-collaboration-client";
import { Presence } from "@mescius/js-collaboration-presence-client";

const conn = new Client('ws://localhost:8080/').connect('room1');
const presence = new Presence(conn);
```

3. Workbook과 Presence 바인딩 (사용자 정보 없음)

이 방식은 사용자 정보를 포함하지 않습니다. 사용자 정보가 필요한 경우 4단계 방식을 사용하십시오.

```typescript
const presences: IPresence[] = Object.values(presence.otherStates);
workbook.collaboration.setPresences(
    presences.map(p => ({ user: p.user, status: p.status }))
);
```

4. 사용자 인스턴스 생성 후 Workbook, Presence, 사용자 바인딩

>type=note
> 예제용 코드입니다. **실제 운영 환경의 사용자 정보로 교체하십시오.**

```typescript
import { bindPresence, IUserWithPermission } from 'spread-sheets-collaboration-client';

var seed = new Date().valueOf() + "";
const user: IUserWithPermission = {
    id: seed,
    name: "user" + seed,
    permission: {
        mode: GC.Spread.Sheets.Collaboration.BrowsingMode.edit,
    }
}
bindPresence(workbook, presence, user);
```

### 서버 측

서버 측 사용 방법은 [Presence Server](/spreadjs/docs/spreadjs-collaboration-server/collaboration-framework/js-collaboration-presence/presence-server)와 동일합니다.

## API

* `spread-sheets-collaboration-client`

```typescript
/**
 * 동시 작업 시스템의 사용자 정의
 */
export interface IUserWithPermission extends GC.Spread.Common.IUser {
    permission?: IPermission;
}
/**
 * 워크시트 선택 영역 데이터 정의
 */
export interface ISelections {
    selections?: Range[];
    sheetId?: string;
}
/**
 * 사용자 Presence 정보 정의
 */
export interface IPresence {
    user: GC.Spread.Common.IUser;
    status: { selections?: ISelections };
}
/**
 * Workbook과 Presence 바인딩
 */
export declare function bindPresence(
    workbook: any,
    presence: Presence<IPresence>,
    user: IUserWithPermission,
    options?: IBindPresenceOptions
): void;
/**
 * Presence 바인딩 옵션
 */
export interface IBindPresenceOptions {
    onPresencesUpdate?: (presences?: IPresence[]) => void;
}
```

* `GC.Spread.Sheets.Collaboration`

```typescript
setPresences(presences: IPresence[]): void;

getPresences(): GC.Spread.Sheets.Collaboration.IPresence[];
```