WebSocket은 브라우저와 서버 간의 실시간 양방향 통신을 가능하게 하는 프로토콜입니다. 전통적인 HTTP 통신에는 요청을 보내는 클라이언트와 데이터 교환에 응답하는 서버가 포함됩니다. 반면 WebSocket을 사용하면 초기 연결이 설정되면 클라이언트와 서버 모두 새 연결을 반복적으로 설정할 필요 없이 서로 메시지를 보내고 받을 수 있습니다.
최근 OpenAI Realtime API, Hume AI와 같은 대화형 서비스가 보편화되면서 WebSocket에 대한 수요가 증가할 것으로 예상됩니다. 이 기사에서는 WebSocket 사용 방법에 대한 기본 사항을 소개하고 관련 비동기 처리에 대해 살펴봅니다.
Python에서는 아래와 같이 WebSocket을 사용할 수 있습니다.
import asyncio import websockets uri = "ws://..." async def hello(): async with websockets.connect(uri) as websocket: await websocket.send("Hello, Server!") response = await websocket.recv() print(f"Server says: {response}") asyncio.run(hello())
이전 코드에서 사용된 async 및 wait는 비동기 처리를 나타냅니다. 비동기 처리는 여러 작업을 동시에 실행할 때 특히 효과적입니다.
import asyncio async def task1(): print("Task 1: Start") await asyncio.sleep(2) # Wait for 2 seconds print("Task 1: End") async def task2(): print("Task 2: Start") await asyncio.sleep(1) # Wait for 1 second print("Task 2: End") async def main(): await asyncio.gather(task1(), task2()) asyncio.run(main())
await를 사용하는 함수에서는 현재 작업이 완료되기를 기다리는 동안 다른 작업을 실행할 수 있습니다. 이를 통해 작업 간 효율적인 전환이 가능합니다.
멀티스레딩도 여러 작업을 처리하지만 스레드 활용 방식에는 차이가 있습니다.
멀티스레딩은 CPU 집약적이거나 차단 작업을 수행할 때 효과적입니다. 그러나 스레드 전환(컨텍스트 전환)으로 인한 오버헤드와 메모리 소모 증가 등의 단점이 있습니다.
대조적으로, 비동기식 처리는 스레드에 의존하지 않기 때문에 컨텍스트 전환으로 인한 오버헤드를 줄입니다. 그러나 작업량이 많은 경우 다른 작업을 기다려야 할 수도 있습니다. 따라서 API 요청과 같은 IO 바인딩 작업에 적합합니다.
(계산 집약적이거나 정확한 타이밍이 필요한 작업의 경우 멀티프로세싱이 더 효과적인 경우가 많습니다. 멀티스레딩과 달리 멀티프로세싱을 사용하면 여러 작업을 동시에 실행할 수 있습니다.)
예를 들어 OpenAI Realtime API를 사용하여 마이크에서 실시간으로 오디오를 수신하고 오디오 데이터를 API로 보내는 경우 멀티스레딩과 비동기 처리를 조합하여 사용할 수 있습니다.
import asyncio import threading import queue import pyaudio import websockets # Use a queue to share data between threads audio_queue = queue.Queue() # Thread to capture audio using PyAudio def audio_stream(): p = pyaudio.PyAudio() stream = p.open(format=pyaudio.paInt16, channels=1, rate=44100, input=True, frames_per_buffer=1024) print("Start recording...") while True: data = stream.read(1024) audio_queue.put(data) # Asynchronous function to send audio data via WebSocket async def send_audio(): uri = "ws://localhost:8765" async with websockets.connect(uri) as websocket: while True: # Get audio data from the queue data = audio_queue.get() if data is None: break await websocket.send(data) print("Sent audio data") # Start the audio capture thread and run the asynchronous task def main(): audio_thread = threading.Thread(target=audio_stream) audio_thread.start() # Run the WebSocket sending task asyncio.run(send_audio()) if __name__ == "__main__": main()
오디오 캡처 프로세스는 차단 작업이므로 스레딩을 사용하여 별도의 스레드에서 실행됩니다. 이와 대조적으로 API와의 상호 작용과 같은 IO 바인딩 작업이 포함된 오디오 데이터 전송은 비동기 처리를 사용하여 수행됩니다. (참고: PyAudio는 콜백을 사용하여 비차단 방식으로 실행할 수도 있습니다. )
이 글에서는 WebSocket과 비동기 처리를 소개했습니다.
OpenAI Realtime API로 작업하는 동안 이러한 개념이 특히 혼란스럽다는 것을 발견하여 이를 개인 메모로 정리했습니다. 오류를 발견하거나 의견이 있으시면 알려주시면 감사하겠습니다.
끝까지 읽어주셔서 감사합니다.
부인 성명: 제공된 모든 리소스는 부분적으로 인터넷에서 가져온 것입니다. 귀하의 저작권이나 기타 권리 및 이익이 침해된 경우 자세한 이유를 설명하고 저작권 또는 권리 및 이익에 대한 증거를 제공한 후 이메일([email protected])로 보내주십시오. 최대한 빨리 처리해 드리겠습니다.
Copyright© 2022 湘ICP备2022001581号-3