Python 고급

Python WebSockets를 이용한 실시간 통신

PyExplorer 2025. 1. 5. 10:45
728x90

Python WebSockets를 이용한 실시간 통신

소개

웹 개발에서 실시간 통신은 사용자 경험을 혁신적으로 향상시키는 중요한 요소입니다. 실시간 알림, 채팅 애플리케이션, 협업 도구 등 많은 서비스가 실시간 통신 기술을 활용합니다. Python은 이러한 실시간 통신을 구현하기 위한 강력한 도구인 WebSockets 모듈을 제공합니다.

이 글에서는 WebSockets의 기본 개념을 이해하고, Python에서 websockets 라이브러리를 활용하여 실시간 통신 애플리케이션을 구축하는 방법을 학습하겠습니다.


WebSockets란?

WebSockets는 HTML5에서 소개된 프로토콜로, 클라이언트와 서버 간의 양방향 통신을 실현합니다. HTTP 요청/응답 모델과 달리, WebSocket 연결은 한 번 설정되면 클라이언트와 서버가 지속적으로 데이터를 주고받을 수 있습니다.

WebSockets의 주요 특징

  • 양방향 통신: 클라이언트와 서버 모두 데이터를 자유롭게 송수신 가능.
  • 효율성: HTTP와 달리 요청-응답 오버헤드가 적어 네트워크 자원을 절약.
  • 실시간성: 낮은 지연 시간으로 실시간 애플리케이션에 적합.

Python WebSockets 라이브러리

Python의 websockets는 WebSocket 서버와 클라이언트를 손쉽게 구현할 수 있는 가벼운 라이브러리입니다.

설치

pip install websockets

기본 예제: 에코 서버와 클라이언트

먼저, WebSocket 서버와 클라이언트를 구현하는 간단한 예제를 살펴보겠습니다.

1. 에코 서버

import asyncio
import websockets

async def echo(websocket, path):
    async for message in websocket:
        print(f"클라이언트로부터 메시지 수신: {message}")
        await websocket.send(f"서버 에코: {message}")

start_server = websockets.serve(echo, "localhost", 8765)

asyncio.get_event_loop().run_until_complete(start_server)
asyncio.get_event_loop().run_forever()

설명

  • websockets.serve(): WebSocket 서버를 생성합니다.
  • 클라이언트로부터 메시지를 수신하고 동일한 메시지를 다시 보냅니다.

2. 에코 클라이언트

import asyncio
import websockets

async def client():
    async with websockets.connect("ws://localhost:8765") as websocket:
        await websocket.send("안녕하세요, 서버!")
        response = await websocket.recv()
        print(f"서버로부터 응답: {response}")

asyncio.get_event_loop().run_until_complete(client())

설명

  • websockets.connect(): WebSocket 서버에 연결합니다.
  • 서버에 메시지를 전송하고, 응답을 수신합니다.

실시간 채팅 애플리케이션 구축

이제 실시간 채팅 애플리케이션을 만들어보겠습니다. 이 애플리케이션은 여러 클라이언트가 서로 메시지를 주고받을 수 있도록 설계됩니다.

1. 채팅 서버 구현

import asyncio
import websockets

connected_clients = set()

async def chat_handler(websocket, path):
    # 새로운 클라이언트를 추가
    connected_clients.add(websocket)
    try:
        async for message in websocket:
            print(f"수신 메시지: {message}")
            # 연결된 모든 클라이언트에 메시지 전송
            await asyncio.gather(*[client.send(message) for client in connected_clients])
    except websockets.exceptions.ConnectionClosed:
        print("클라이언트 연결 해제")
    finally:
        connected_clients.remove(websocket)

start_server = websockets.serve(chat_handler, "localhost", 8765)

asyncio.get_event_loop().run_until_complete(start_server)
asyncio.get_event_loop().run_forever()

설명

  • connected_clients: 현재 연결된 클라이언트를 추적하는 집합.
  • 모든 클라이언트에 메시지를 브로드캐스트합니다.

2. 채팅 클라이언트 구현

import asyncio
import websockets

async def chat_client():
    async with websockets.connect("ws://localhost:8765") as websocket:
        print("채팅에 연결되었습니다. 메시지를 입력하세요.")

        async def send_messages():
            while True:
                message = input(">>> ")
                await websocket.send(message)

        async def receive_messages():
            async for message in websocket:
                print(f"[받음]: {message}")

        # 송수신 작업을 병렬로 실행
        await asyncio.gather(send_messages(), receive_messages())

asyncio.get_event_loop().run_until_complete(chat_client())

설명

  • asyncio.gather(): 메시지 송신과 수신을 동시에 처리합니다.
  • 사용자가 입력한 메시지를 서버로 전송하고, 서버로부터 메시지를 수신하여 출력합니다.

고급 주제: 인증 및 보안

실제 애플리케이션에서는 보안이 중요합니다. WebSockets에서도 인증 및 데이터 암호화를 구현할 수 있습니다.

1. WebSocket 연결에 토큰 인증 추가

import asyncio
import websockets

async def authenticate(websocket, path):
    token = await websocket.recv()
    if token != "secure_token":
        await websocket.close(reason="Unauthorized")
        return
    await websocket.send("인증 성공")

start_server = websockets.serve(authenticate, "localhost", 8765)

asyncio.get_event_loop().run_until_complete(start_server)
asyncio.get_event_loop().run_forever()

2. SSL을 사용한 안전한 연결

ssl 모듈을 사용하여 WebSocket 연결을 암호화할 수 있습니다.

import ssl
import pathlib
import asyncio
import websockets

ssl_context = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER)
ssl_context.load_cert_chain(
    pathlib.Path("cert.pem"),
    pathlib.Path("key.pem")
)

start_server = websockets.serve(echo, "localhost", 8765, ssl=ssl_context)

asyncio.get_event_loop().run_until_complete(start_server)
asyncio.get_event_loop().run_forever()

마무리

WebSockets는 실시간 애플리케이션 개발에 매우 유용한 도구입니다. 이 글에서는 Python의 websockets 라이브러리를 사용하여 기본적인 에코 서버/클라이언트, 실시간 채팅 애플리케이션, 그리고 보안 기능을 추가하는 방법을 배웠습니다.

실제 프로젝트에서 WebSockets를 활용해 보며 학습한 내용을 실천해보세요! 더 나아가 Django, Flask와 같은 프레임워크와 통합하여 강력한 애플리케이션을 구축할 수도 있습니다.

여러분의 프로젝트에 도움이 되기를 바랍니다.

728x90