배경 설명

내부 API 이용 서비스의 특징

고려할 내용

  1. ASGI 서버 선택

    1. Django Channels의 공식 서버인 daphne를 사용 가능
  2. settings.py에서 ASGI_APPLICATION을 지정

    1. settings.py에 config.asgi.application과 같이 지정
    2. Django Channels를 사용한다면 ASGI_APPLICATION에서 Channels 라우팅(ProtocolTypeRouter)을 설정해야 함(프로토콜에 따라 다른 라우팅 규칙 적용)
  3. 비동기 View / Consumer 구현 방식 결정

    1. 가장 일반적인 방식은 Channels의 AsyncWebsocketConsumer를 사용하는 것
    2. receive()도 async def receive(self, text_data) 형태로 비동기 함수 정의
    3. WebSocket 메시지 전송도 await self.send(…)로 처리해서 동시에 여러개의 메시지를 병렬적으로 보낼 수 있게 함
  4. 내부 API와의 WebSocket 스트리밍 통신

    1. 아래와 같은 예시 코드를 이용해 Django↔프론트, Django↔내부API 모두 웹소켓으로 비동기 연결하여 Django 서버가 메시지 중계

      1. 키포인트: while True 안에서 await ws.recv()로 내부 API의 슽리밍 데이터를 받고, 곧바로 await self.send(…)로 프론트에 내보내는 것
      from channels.generic.websocket import AsyncWebsocketConsumer
      import asyncio
      import json
      import websockets # 비동기 라이브러리
      
      class ChatConsumer(AsyncWebsocketConsumer):
      	async def connect(self):
      		await self.accept()
      		
      	async def receive(self, text_data):
      		user_data = json.loads(text_data)
      		query = user_data.get("query")
      		
      		# 내부 API와 WebSocket 연결
      		async with websockets.connect("wss://internal-llm.example.com/stream") as ws:
      			await ws.send(json.dumps({"query":query}))
      			
      			# 내부 LLM이 토큰 단위, 단계 단위로 메시지 스트리밍
      			while True:
      				try:
      					msg = await asyncio.wait_for(ws.recv(), timeout=10.0)
      				except asyncio.TimeoutError:
      					# 타임아웃 처리
      					break
      				except websockets.ConnectionClosed:
      					# 연결 종료
      					break
      					
      				# 받은 메시지를 그대로 프론트에 전송
      				await self.send(msg)
      				
      	async def disconnect(self, close_code):
      		pass
      

o1 pro가 안내해준 테스트 시나리오

추가적으로 고려할 것

주의할 점