Sandcorp샌드코프 · 웹·AI 제품 개발

새 프로젝트 받는 중 · 갱신 2026.11sandcorp.co.krGitHub

← 팁

웹소켓·실시간메모리

연결 정리는 finally에서 「어떻게 끝나든 정확히 한 번」

프레임워크의 disconnect 콜백은 예외로 끝나면 불리지 않을 수 있다. 진입점을 try/finally로 감싸고 두 번 정리하지 않게 표시를 둔다.

웹소켓 서버에서 같은 구성의 프로세스끼리 메모리와 접속 수가 점점 벌어진다. 클라이언트는 이미 떠났는데 서버에는 그 연결의 그룹 구독과 상태가 남아 있다. 좀비 연결이다.

원인은 정리를 프레임워크 콜백에만 맡긴 것이다. Django Channels는 consumer가 예외로 끝나면 websocket_disconnect를 부르지 않는다. 다른 프레임워크도 비슷한 구멍이 있다. 정상 종료 경로에서만 정리가 돌고, 예외 경로에서는 빠진다.

consumer 진입점을 try/finally로 감싸 어떻게 끝나든 정리가 돌게 하고, 정상 종료 때 콜백과 겹쳐 두 번 하지 않게 표시를 둔다.

from channels.generic.websocket import AsyncWebsocketConsumer

class RoomConsumer(AsyncWebsocketConsumer):
    _cleaned = False

    async def __call__(self, scope, receive, send):
        try:
            await super().__call__(scope, receive, send)
        finally:
            await self.cleanup()

    async def disconnect(self, code):
        await self.cleanup()

    async def cleanup(self):
        if self._cleaned:
            return
        self._cleaned = True
        room = getattr(self, "room", None)
        if room:
            await self.channel_layer.group_discard(room, self.channel_name)

이미 끊긴 상대에게 보내다 나는 예외(ClientDisconnected 등)는 삼키고 「닫는 중」으로 표시해, 정리 도중 또 다른 예외가 나지 않게 한다.

문의 →