WebSocket 디버깅이 어렵다고? Postman으로 쉽게 해결하는 방법

배고픈코알라·2025년 4월 9일
post-thumbnail

안녕하세요, 여러분! 저는 백엔드 개발을 공부하기 시작한 초보 개발자입니다. 최근에 실시간 통신 기능을 구현하면서 WebSocket에 대해 알게 되었는데요, 처음에는 정말 어려웠습니다. 특히 API는 테스트하기 쉬운데 WebSocket은 어떻게 테스트해야 할지 몰라서 고민이 많았어요. 그러다 Postman으로 WebSocket을 디버깅할 수 있다는 것을 알게 되었고, 오늘은 제가 배운 내용을 여러분과 공유하려고 합니다!

WebSocket이란 무엇인가요?

WebSocket은 양방향 통신을 지원하는 네트워크 프로토콜로, 실시간성과 효율성 면에서 큰 장점이 있습니다. 채팅 앱이나 실시간 알림 기능을 만들 때 정말 유용하죠. 기존의 HTTP는 클라이언트가 요청을 보내고 서버가 응답하는 단방향 통신인데 반해, WebSocket은 연결이 한 번 수립되면 서버와 클라이언트가 자유롭게 데이터를 주고받을 수 있어요. 정말 편리하죠?

Postman으로 WebSocket 디버깅하기

postman

저는 API 테스트할 때 항상 Postman을 사용했는데, WebSocket도 테스트할 수 있다는 사실을 알고 정말 기뻤어요! Postman v8.0부터 WebSocket 연결을 지원한다고 하니, 여러분도 최신 버전을 사용하고 계신다면 바로 시작할 수 있습니다.

🔍 Postman에서 WebSocket 디버깅 단계

  1. Postman 열기 - 버전이 8.0 이상인지 확인하세요. 저는 처음에 구버전을 사용하다가 연결이 안 돼서 한참 헤맸어요...
  2. 새 WebSocket 요청 생성하기 - 왼쪽 상단의 New 버튼을 클릭하고 WebSocket Request를 선택합니다.
  3. WebSocket URL 입력하기 - 예를 들어 ws://localhost:8765 같은 형식으로 입력하고 Connect 버튼을 클릭합니다.
  4. 메시지 보내기 - 연결이 성공하면 Message 입력란에 데이터를 입력하고 Send 버튼을 클릭합니다.
  5. 응답 확인하기 - 타임라인에서 서버의 응답을 실시간으로 확인할 수 있습니다.
    Postman에서 WebSocket 디버깅

💻 실제 사용 예시

제가 Python으로 간단한 WebSocket 서버를 만들어서 테스트했을 때의 경험을 공유할게요:

# 간단한 Python WebSocket 서버 예제
#!/usr/bin/env python3
import asyncio
import websockets
import json
import datetime
import logging
import inspect

# 로깅 설정
logging.basicConfig(
    level=logging.INFO,
    format='%(asctime)s - %(levelname)s - %(message)s'
)

# 연결된 클라이언트 저장
connected_clients = set()
connection_count = 0

# websockets 라이브러리 버전 확인 및 핸들러 함수 적응
websockets_version = websockets.__version__
logging.info(f"Using websockets version: {websockets_version}")

# 주요 처리 로직
async def _handle_client_logic(websocket):
    """클라이언트 연결 처리를 위한 핵심 로직"""
    global connection_count
    client_id = connection_count
    connection_count += 1
    
    # 새 클라이언트를 연결 목록에 추가
    connected_clients.add(websocket)
    logging.info(f"Client {client_id} connected. Total clients: {len(connected_clients)}")
    
    try:
        # 환영 메시지 전송
        await websocket.send(json.dumps({
            "type": "welcome",
            "message": "Welcome to WebSocket server!",
            "client_id": client_id,
            "timestamp": datetime.datetime.now().isoformat()
        }))
        
        # 메시지 지속적으로 수신
        async for message in websocket:
            try:
                # 수신된 원본 메시지 기록
                logging.info(f"Received from client {client_id}: {message}")
                
                # JSON 파싱 시도
                try:
                    data = json.loads(message)
                    # 응답 구성
                    response = {
                        "type": "response",
                        "received_data": data,
                        "client_id": client_id,
                        "timestamp": datetime.datetime.now().isoformat()
                    }
                except json.JSONDecodeError:
                    # 유효한 JSON이 아닐 경우, 일반 텍스트 응답 전송
                    response = {
                        "type": "response",
                        "received_text": message,
                        "client_id": client_id,
                        "timestamp": datetime.datetime.now().isoformat()
                    }
                
                # 응답 전송
                await websocket.send(json.dumps(response))
                logging.info(f"Response sent to client {client_id}")
                
            except Exception as e:
                logging.error(f"Error processing message: {str(e)}")
                await websocket.send(json.dumps({
                    "type": "error",
                    "message": str(e),
                    "timestamp": datetime.datetime.now().isoformat()
                }))
                
    except websockets.exceptions.ConnectionClosed as e:
        logging.info(f"Client {client_id} disconnected: {str(e)}")
    finally:
        # 클라이언트 연결 해제 시 목록에서 제거
        if websocket in connected_clients:
            connected_clients.remove(websocket)
        logging.info(f"Client {client_id} removed. Total clients: {len(connected_clients)}")

# 다양한 버전의 websockets 라이브러리 지원
async def handle_client(websocket, path=None):
    """다양한 버전의 websockets 라이브러리를 지원하는 처리 함수"""
    # path 매개변수 무시하고 주요 로직 함수 호출
    await _handle_client_logic(websocket)

async def main():
    # WebSocket 서버 시작
    host = "localhost"
    port = 8765
    
    # serve 함수의 서명을 확인하여 호출 방법 결정
    server = await websockets.serve(handle_client, host, port)
    
    logging.info(f"WebSocket server started at ws://{host}:{port}")
    logging.info(f"You can connect using Postman's WebSocket client")
    
    # 서버 실행 유지
    await server.wait_closed()

if __name__ == "__main__":
    try:
        asyncio.run(main())
    except KeyboardInterrupt:
        logging.info("Server terminated by user")

이 서버를 실행한 후 Postman에서 ws://localhost:8765로 연결하고 "hello,word"라는 메시지를 보냈더니, 서버에서 "서버에서 응답: hello,word"라고 응답이 왔어요. 실시간으로 메시지가 오가는 것을 확인할 수 있어서 정말 신기했습니다!

🚀 Apidog: WebSocket 디버깅의 새로운 대안

Postman으로 WebSocket을 테스트하는 방법을 알게 된 것은 좋았지만, 최근에 Apidog라는 더 좋은 도구를 발견했어요. 처음에는 그냥 또 하나의 API 테스트 도구겠거니 했는데, 사용해보니 정말 놀라웠습니다!

Apidog는 Postman과 비슷하게 WebSocket 디버깅을 지원하지만, 사용법이 더 직관적이고 UI가 더 깔끔해서 초보자인 저도 쉽게 사용할 수 있었어요. 특히 마크다운으로 문서를 작성하고 팀원들과 공유할 수 있는 기능이 정말 유용했습니다.

Apidog의 장점

  • 통합 플랫폼 - API 문서, 디버깅, 목업, 자동화 테스트를 한 곳에서 할 수 있어요
  • 직관적인 인터페이스 - 복잡한 설정 없이 바로 사용할 수 있어요
  • 팀 협업 기능 - 문서를 온라인으로 공유하고 함께 작업할 수 있어요
  • 다양한 프로토콜 지원 - REST API, WebSocket, GraphQL 등 다양한 프로토콜을 지원해요

Apidog

🤔 개인적인 생각

처음 WebSocket을 접했을 때는 정말 어렵게 느껴졌는데, 적절한 도구를 사용하니 생각보다 쉽게 디버깅할 수 있었습니다. Postman은 많은 개발자들이 이미 사용하고 있어서 익숙하다는 장점이 있지만, Apidog는 더 통합된 경험을 제공한다는 점에서 매력적이에요.

앞으로 실시간 통신 기능은 더 많은 애플리케이션에서 중요해질 것 같아요. 채팅, 알림, 실시간 데이터 업데이트 등 사용자 경험을 향상시키는 기능들이 계속 늘어나고 있으니까요. 그래서 WebSocket 같은 기술과 이를 테스트할 수 있는 도구들을 잘 알아두면 정말 유용할 것 같습니다.

여러분도 WebSocket 디버깅에 도전해보세요! 생각보다 어렵지 않아요. 궁금한 점이나 경험이 있으시면 댓글로 공유해주세요. 함께 배우고 성장했으면 좋겠습니다! 😊

0개의 댓글