Python/Python 심화

Python asyncio를 활용한 비동기 네트워크 통신

임베디드 친구 2025. 8. 6. 19:52
728x90
반응형

Python asyncio를 활용한 비동기 네트워크 통신

Python에서 비동기 프로그래밍은 고성능 네트워크 애플리케이션 개발을 위해 필수적입니다. asyncio는 Python에서 비동기 작업을 처리하기 위한 표준 라이브러리로, 효율적인 네트워크 통신을 가능하게 합니다. 이번 포스팅에서는 asyncio를 활용해 비동기 네트워크 통신을 구현하는 방법을 살펴보겠습니다.


1. asyncio란?

asyncio는 Python 3.4부터 포함된 표준 라이브러리로, 비동기 I/O 작업을 지원합니다. 주로 네트워크 애플리케이션이나 I/O 바운드 작업에서 유용하며, 다음과 같은 기능을 제공합니다:

  • 비동기 작업 실행
  • 이벤트 루프 관리
  • 네트워크 소켓 관리
  • 비동기 HTTP 서버/클라이언트

asyncio는 코루틴을 기반으로 작동하며, asyncawait 키워드를 사용하여 비동기 작업을 작성할 수 있습니다.


2. asyncio 기본 사용법

2.1 코루틴과 이벤트 루프

코루틴은 Python의 비동기 함수로 async def로 정의됩니다. await 키워드를 사용하면 다른 비동기 작업이 완료될 때까지 기다릴 수 있습니다.

import asyncio

async def say_hello():
    print("Hello")
    await asyncio.sleep(1)
    print("World")

asyncio.run(say_hello())

실행 결과:

Hello
(1초 대기)
World

2.2 이벤트 루프

이벤트 루프는 비동기 작업을 스케줄링하고 실행하는 역할을 합니다. asyncio.run() 함수는 내부적으로 이벤트 루프를 생성하고 실행합니다.


3. 비동기 네트워크 통신

asyncio를 사용하면 TCP와 UDP 프로토콜을 비동기적으로 처리할 수 있습니다. 여기서는 TCP 서버와 클라이언트를 구현하는 방법을 알아봅니다.

3.1 TCP 서버 구현

TCP 서버는 클라이언트 요청을 수신하고 처리하는 역할을 합니다.

import asyncio

async def handle_client(reader, writer):
    data = await reader.read(100)
    message = data.decode()
    addr = writer.get_extra_info('peername')

    print(f"Received {message} from {addr}")

    response = f"Server received: {message}"
    writer.write(response.encode())
    await writer.drain()

    print("Closing the connection")
    writer.close()
    await writer.wait_closed()

async def main():
    server = await asyncio.start_server(handle_client, '127.0.0.1', 8888)

    addr = server.sockets[0].getsockname()
    print(f"Serving on {addr}")

    async with server:
        await server.serve_forever()

asyncio.run(main())

설명:

  • handle_client: 클라이언트 연결을 처리합니다.
  • start_server: TCP 서버를 시작합니다.

3.2 TCP 클라이언트 구현

TCP 클라이언트는 서버에 메시지를 보내고 응답을 수신합니다.

import asyncio

async def tcp_client():
    reader, writer = await asyncio.open_connection('127.0.0.1', 8888)

    message = "Hello, Server!"
    print(f"Sending: {message}")
    writer.write(message.encode())
    await writer.drain()

    data = await reader.read(100)
    print(f"Received: {data.decode()}")

    print("Closing the connection")
    writer.close()
    await writer.wait_closed()

asyncio.run(tcp_client())

설명:

  • open_connection: 서버와의 TCP 연결을 엽니다.
  • writer.write: 데이터를 서버로 보냅니다.
  • reader.read: 서버로부터 데이터를 읽습니다.

4. 고급 예제: 채팅 서버 구현

간단한 채팅 서버와 클라이언트를 구현해 보겠습니다.

4.1 채팅 서버

import asyncio

clients = []

async def broadcast(message):
    for writer in clients:
        writer.write(message.encode())
        await writer.drain()

async def handle_client(reader, writer):
    addr = writer.get_extra_info('peername')
    clients.append(writer)
    print(f"New connection from {addr}")

    try:
        while True:
            data = await reader.read(100)
            if not data:
                break
            message = data.decode()
            print(f"{addr} says: {message}")
            await broadcast(f"{addr} says: {message}")
    except ConnectionResetError:
        print(f"Connection with {addr} lost")
    finally:
        clients.remove(writer)
        writer.close()
        await writer.wait_closed()

async def main():
    server = await asyncio.start_server(handle_client, '127.0.0.1', 8888)
    print("Chat server started")

    async with server:
        await server.serve_forever()

asyncio.run(main())

4.2 채팅 클라이언트

import asyncio

async def chat_client():
    reader, writer = await asyncio.open_connection('127.0.0.1', 8888)

    async def send_messages():
        while True:
            message = input("You: ")
            writer.write(message.encode())
            await writer.drain()

    async def receive_messages():
        while True:
            data = await reader.read(100)
            print(f"Server: {data.decode()}")

    await asyncio.gather(send_messages(), receive_messages())

asyncio.run(chat_client())

5. 결론

asyncio를 사용하면 Python에서 효율적인 비동기 네트워크 애플리케이션을 구현할 수 있습니다. 이번 포스팅에서는 기본적인 사용법부터 TCP 서버/클라이언트, 그리고 채팅 애플리케이션까지 다양한 예제를 다뤘습니다. 이 예제를 바탕으로 더 복잡한 네트워크 애플리케이션을 구현해 보세요!

728x90
반응형