본문 바로가기
C.W.K.
Stream
Lesson 04 of 08 · published

연결 단절 처리

~11 min · fastapi, disconnect, cleanup

Level 0Poller
0 XP0/60 lessons0/10 achievements
0/120 XP to next level120 XP to go0% complete

WebSocketDisconnect 가 종료 신호야

클라이언트가 정상적으로 닫았든 갑자기 끊겼든, 다음 receive_* 호출에서 WebSocketDisconnect 예외가 발생해. 예외의 .code 에는 닫기 코드, .reason 에는 닫기 프레임의 이유가 들어 있어. 세션이 끝났음을 알려 주는 단일 기준이야.

정리 작업은 finally 블록에서

연결할 때 준비한 모든 것, 즉 연결 관리자 등록, 심박 작업, 열린 DB 행을 여기서 정리해야 해. 흐름은 연결 → 등록 → try 안의 반복과 예외 처리 → 등록 해제야. 등록 해제를 건너뛰면 고아 참조가 남고, 규모가 커질 때 WebSocket 서버의 메모리 누수로 이어져.

다른 예외도 발생해

메시지 처리기의 애플리케이션 버그가 별도 예외를 던질 수도 있어. 이 경우를 따로 잡아 클라이언트에 구조화된 오류를 보내고 연결을 깔끔하게 닫아.

Code

연결부터 정리까지의 전체 패턴·python
from fastapi import WebSocket, WebSocketDisconnect

@app.websocket('/ws')
async def chat(websocket: WebSocket):
    await websocket.accept()
    user_id = await register(websocket)  # your manager
    try:
        async for msg in websocket.iter_json():
            await handle(websocket, user_id, msg)
    except WebSocketDisconnect as e:
        log.info('client gone: code=%s reason=%s', e.code, e.reason)
    except Exception as e:
        log.exception('handler error')
        try:
            await websocket.close(code=1011, reason='internal error')
        except Exception:
            pass  # already closed
    finally:
        await unregister(user_id)
e.code 에 따라 처리하기·python
except WebSocketDisconnect as e:
    if e.code == 1000:
        log.info('clean close')
    elif e.code == 1001:
        log.info('client navigated away')
    elif e.code == 1006:
        log.warning('abnormal close — laptop lid or NAT timeout, probably')
    else:
        log.warning('disconnect %s: %s', e.code, e.reason)

External links

Exercise

에코 서버를 고쳐 연결과 단절 때마다 active connections: N 카운터를 기록해. 시험 클라이언트 강제 종료, 프로세스 종료, 정상 닫기를 각각 실행하고 세 경우 모두 카운터가 0 으로 돌아오는지 확인해. 돌아오지 않는다면 finally 처리가 잘못된 거야.

Progress

Progress is local-only — sign in to sync across devices.
이 페이지에서 버그를 발견하셨거나 피드백이 있으세요?문제 신고

댓글 0

🔔 답글 알림 (로그인 필요)
로그인댓글을 남기려면 로그인해 주세요.

아직 댓글이 없어요. 첫 댓글을 남겨보세요.