-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
[Server] shared-checklist 소켓 구현 (#78)
- Loading branch information
1 parent
f795888
commit 304ea79
Showing
6 changed files
with
150 additions
and
6 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
109 changes: 109 additions & 0 deletions
109
server/src/shared-checklists/shared-checklists.gateway.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,109 @@ | ||
import { | ||
ConnectedSocket, | ||
MessageBody, | ||
OnGatewayConnection, | ||
OnGatewayDisconnect, | ||
SubscribeMessage, | ||
WebSocketGateway, | ||
WebSocketServer, | ||
} from '@nestjs/websockets'; | ||
import { parse } from 'url'; | ||
import * as WebSocket from 'ws'; | ||
|
||
/** | ||
* 웹소켓 통신을 통해 클라이언트들의 체크리스트 공유를 관리하는 게이트웨이. | ||
*/ | ||
@WebSocketGateway({ path: '/share-checklist' }) | ||
export class SharedChecklistsGateway | ||
implements OnGatewayConnection, OnGatewayDisconnect | ||
{ | ||
@WebSocketServer() server: WebSocket.Server; | ||
|
||
// 각 checklist ID별로 연결된 클라이언트들을 추적하기 위한 맵 | ||
private clients: Map<string, Set<WebSocket>> = new Map(); | ||
|
||
/** | ||
* 클라이언트가 연결을 시도할 때 호출되는 메서드. | ||
* 연결된 클라이언트에 sharedChecklistId를 할당하고 관리한다. | ||
* @param client 연결된 클라이언트의 웹소켓 객체 | ||
*/ | ||
handleConnection(@ConnectedSocket() client: WebSocket, ...args: any[]) { | ||
const request = args[0]; | ||
const { query } = parse(request.url, true); | ||
const sharedChecklistId = query.cid as string; | ||
|
||
// 클라이언트에 할당된 sharedChecklistId를 바탕으로 클라이언트 관리 | ||
if (sharedChecklistId) { | ||
client['sharedChecklistId'] = sharedChecklistId; | ||
if (!this.clients.has(sharedChecklistId)) { | ||
this.clients.set(sharedChecklistId, new Set()); | ||
} | ||
this.clients.get(sharedChecklistId)?.add(client); | ||
} | ||
} | ||
|
||
/** | ||
* 클라이언트 연결이 해제될 때 호출되는 메서드. | ||
* 해당 클라이언트를 관리 목록에서 제거한다. | ||
* @param client 연결 해제된 클라이언트의 웹소켓 객체 | ||
*/ | ||
handleDisconnect(@ConnectedSocket() client: WebSocket) { | ||
const sharedChecklistId = client['sharedChecklistId']; | ||
if (sharedChecklistId && this.clients.has(sharedChecklistId)) { | ||
const clientsSet = this.clients.get(sharedChecklistId); | ||
clientsSet?.delete(client); | ||
// 더 이상 해당 sharedChecklistId에 연결된 클라이언트가 없으면 맵에서 제거 | ||
if (clientsSet?.size === 0) { | ||
this.clients.delete(sharedChecklistId); | ||
} | ||
} | ||
} | ||
|
||
/** | ||
* 특정 sharedChecklistId를 가진 클라이언트들에게 이벤트와 데이터를 브로드캐스트한다. | ||
* 메시지를 보낸 클라이언트는 브로드캐스트에서 제외한다. | ||
* @param sharedChecklistId 브로드캐스트 대상의 checklist ID | ||
* @param event 브로드캐스트할 이벤트 이름 | ||
* @param data 전송할 데이터 | ||
* @param excludeClient 브로드캐스트에서 제외할 클라이언트 | ||
*/ | ||
private broadcastToChecklist( | ||
sharedChecklistId: string, | ||
event: string, | ||
data: any, | ||
excludeClient: WebSocket, | ||
) { | ||
const clients = this.clients.get(sharedChecklistId); | ||
if (clients) { | ||
clients.forEach((client) => { | ||
if (client !== excludeClient && client.readyState === WebSocket.OPEN) { | ||
client.send(JSON.stringify({ event, data })); | ||
} | ||
}); | ||
} | ||
} | ||
|
||
/** | ||
* 'sendChecklist' 이벤트를 처리하고, 해당 sharedChecklistId를 가진 다른 클라이언트들에게 | ||
* 'listenChecklist' 이벤트를 브로드캐스트한다. | ||
* @param client 메시지를 보낸 클라이언트의 웹소켓 객체 | ||
* @param data 클라이언트로부터 받은 데이터 | ||
* @returns 이벤트 처리 결과를 나타내는 객체 | ||
*/ | ||
@SubscribeMessage('sendChecklist') | ||
async handleSendChecklist( | ||
@ConnectedSocket() client: WebSocket, | ||
@MessageBody() data: string, | ||
) { | ||
const sharedChecklistId = client['sharedChecklistId']; | ||
if (sharedChecklistId) { | ||
this.broadcastToChecklist( | ||
sharedChecklistId, | ||
'listenChecklist', | ||
data, | ||
client, | ||
); | ||
} | ||
return { event: 'sendChecklist', data: data }; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -778,6 +778,14 @@ | |
multer "1.4.4-lts.1" | ||
tslib "2.6.2" | ||
|
||
"@nestjs/platform-ws@^10.2.10": | ||
version "10.2.10" | ||
resolved "https://registry.yarnpkg.com/@nestjs/platform-ws/-/platform-ws-10.2.10.tgz#d6a4df6bebcf85e27fd437cf764d29921a924889" | ||
integrity sha512-x9L7jixAEtbNjP9hIm9Fmx+kL9ruFQLu2cUb0EdSNtwK/efAJZ3+Taz9T8g/Nm5DG4k0356X6hmRk74ChJHg9g== | ||
dependencies: | ||
tslib "2.6.2" | ||
ws "8.14.2" | ||
|
||
"@nestjs/schematics@^10.0.0", "@nestjs/schematics@^10.0.1": | ||
version "10.0.3" | ||
resolved "https://registry.yarnpkg.com/@nestjs/schematics/-/schematics-10.0.3.tgz#0f48af0a20983ffecabcd8763213a3e53d43f270" | ||
|
@@ -803,6 +811,15 @@ | |
dependencies: | ||
uuid "9.0.0" | ||
|
||
"@nestjs/websockets@^10.2.10": | ||
version "10.2.10" | ||
resolved "https://registry.yarnpkg.com/@nestjs/websockets/-/websockets-10.2.10.tgz#f4aee5956adcb767a26d5a3e138f82a807b8e488" | ||
integrity sha512-L1AkxwLUj/ntk26jO1SXYl3GRElQE6Fikzfy/3MPFURk0GDs7tHUzLcb8BC8q8u5ZpUjBAC2wFVQzrY5R0MHNw== | ||
dependencies: | ||
iterare "1.2.1" | ||
object-hash "3.0.0" | ||
tslib "2.6.2" | ||
|
||
"@nodelib/[email protected]": | ||
version "2.1.5" | ||
resolved "https://registry.yarnpkg.com/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz#7619c2eb21b25483f6d167548b4cfd5a7488c3d5" | ||
|
@@ -4196,6 +4213,11 @@ object-assign@^4, object-assign@^4.0.1, object-assign@^4.1.1: | |
resolved "https://registry.yarnpkg.com/object-assign/-/object-assign-4.1.1.tgz#2109adc7965887cfc05cbbd442cac8bfbb360863" | ||
integrity sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg== | ||
|
||
[email protected]: | ||
version "3.0.0" | ||
resolved "https://registry.yarnpkg.com/object-hash/-/object-hash-3.0.0.tgz#73f97f753e7baffc0e2cc9d6e079079744ac82e9" | ||
integrity sha512-RSn9F68PjH9HqtltsSnqYC1XXoWe9Bju5+213R98cNGttag9q9yAOTzdbsqvIa7aNm5WffBZFpWYr2aWrklWAw== | ||
|
||
object-hash@^2.0.1: | ||
version "2.2.0" | ||
resolved "https://registry.yarnpkg.com/object-hash/-/object-hash-2.2.0.tgz#5ad518581eefc443bd763472b8ff2e9c2c0d54a5" | ||
|
@@ -5643,6 +5665,11 @@ write-file-atomic@^4.0.2: | |
imurmurhash "^0.1.4" | ||
signal-exit "^3.0.7" | ||
|
||
[email protected]: | ||
version "8.14.2" | ||
resolved "https://registry.yarnpkg.com/ws/-/ws-8.14.2.tgz#6c249a806eb2db7a20d26d51e7709eab7b2e6c7f" | ||
integrity sha512-wEBG1ftX4jcglPxgFCMJmZ2PLtSbJ2Peg6TmpJFTbe9GZYOQCDPdMYu/Tm0/bGZkw8paZnJY45J4K2PZrLYq8g== | ||
|
||
xtend@^4.0.0: | ||
version "4.0.2" | ||
resolved "https://registry.yarnpkg.com/xtend/-/xtend-4.0.2.tgz#bb72779f5fa465186b1f438f674fa347fdb5db54" | ||
|