Home > Backend > HTTP vs WebSocket: 웹 애플리케이션에서의 통신 방식 비교

HTTP vs WebSocket: 웹 애플리케이션에서의 통신 방식 비교
Backend

HTTP vs WebSocket: 웹 애플리케이션에서의 통신 방식 비교


웹 애플리케이션 개발 시, 클라이언트와 서버 간의 통신 방식으로 가장 많이 사용되는 프로토콜은 HTTPWebSocket입니다.
두 프로토콜 모두 데이터를 주고받는 데 사용되지만, 그 방식과 목적은 다릅니다.
이 글에서는 HTTP와 WebSocket의 주요 차이점과 각각의 장단점, 그리고 Python으로 구현한 간단한 예시 코드를 통해 웹 애플리케이션에서의 사용 사례를 알아보겠습니다.

1. HTTP란?


HTTP(Hypertext Transfer Protocol)는 클라이언트(주로 웹 브라우저)와 서버 간의 요청-응답 기반 통신 프로토콜입니다.
클라이언트가 서버에 요청을 보내면, 서버는 이에 대한 응답을 보내주는 방식입니다.

HTTP의 작동 원리

클라이언트가 서버에 요청을 보내면, 서버는 그 요청에 대해 응답하고 연결을 끊습니다. 다음 요청이 필요할 때는 다시 연결이 설정됩니다.
이 방식은 단순하지만, 실시간 통신이 필요한 경우에는 효율적이지 않을 수 있습니다.

HTTP

HTTP의 주요 특징

  • 요청-응답 방식: 클라이언트가 요청을 보내야만 서버가 응답할 수 있습니다.
  • 비연결성: 각 요청은 독립적이며, 요청이 완료되면 연결이 종료됩니다.
  • 무상태성: 서버는 각 요청에 대해 상태를 따로 유지하지 않으므로, 요청은 매번 새롭게 처리됩니다.

HTTP의 장점

  • 단순성과 보편성: HTTP는 간단하면서도 거의 모든 브라우저와 웹 서버에서 지원됩니다.
  • 캐싱 가능: 정적 리소스(HTML, CSS, 이미지 등)를 캐싱하여 성능을 향상시킬 수 있습니다.
  • 보안성: HTTPS를 통해 TLS(SSL) 보안을 쉽게 적용할 수 있습니다.

HTTP의 단점

  • 실시간 통신에 부적합: 클라이언트가 요청하기 전까지 서버는 데이터를 보낼 수 없으므로 실시간 통신에 한계가 있습니다.
  • 오버헤드 발생: 매 요청마다 연결을 새로 설정하기 때문에 요청이 많아지면 성능 저하가 발생할 수 있습니다.

2. WebSocket이란?


WebSocket은 클라이언트와 서버 간에 양방향 통신을 가능하게 전이중(Full-Duplex)방식 프로토콜입니다.
HTTP와 달리 연결이 설정된 후에는 연결이 유지되며, 클라이언트와 서버가 서로 실시간으로 데이터를 주고받을 수 있습니다.

WebSocket 작동 원리

초기에는 HTTP 핸드셰이크 과정을 통해 연결을 합니다.
연결이 성공하면 HTTP에서 WebSocket으로 변경하는 프로토콜 스위칭이 이루어 집니다.
이후 클라이언트와 서버는 연결이 종료되기 전까지 데이터를 실시간으로 주고받을 수 있습니다.

WebSocket

WebSocket의 주요 특징

  • 양방향 통신: 클라이언트와 서버가 동시에 데이터를 주고받을 수 있습니다.
  • 지속적인 연결: WebSocket은 연결이 설정된 이후에는 끊김 없이 계속 연결 상태를 유지하며 데이터가 교환됩니다.
  • 실시간 통신: WebSocket은 주로 실시간 데이터 전송이 필요한 경우에 사용됩니다. 예를 들어, 채팅 애플리케이션이나 실시간 주식 거래 시스템에서 유용합니다.

WebSocket의 장점

  • 실시간 데이터 전송: 연결이 지속되므로 실시간으로 데이터를 주고받을 수 있습니다.
  • 낮은 오버헤드: HTTP처럼 매번 연결을 끊고 다시 설정하는 것이 아니라, 한 번 연결 후 데이터를 지속적으로 주고받기 때문에 네트워크 오버헤드가 적습니다.
  • 효율적인 양방향 통신: 양방향으로 자유롭게 데이터를 주고받을 수 있어, 실시간 상호작용이 필요한 서비스에 적합합니다.

WebSocket의 단점

  • 복잡한 서버 관리: 지속적인 연결을 유지하기 때문에 서버에서 더 많은 리소스를 사용하게 됩니다.
  • 보안 관리 필요: WebSocket 자체는 HTTP만큼 보안 기능이 표준화되어 있지 않으므로 별도의 보안 설정(WSS)을 통해 보안을 강화해야 합니다.
  • 캐싱 불가: 실시간 데이터를 다루기 때문에, 캐싱이 적합하지 않습니다.

3. HTTP와 WebSocket의 차이점


특징 HTTP WebSocket
통신 방식 요청-응답 (클라이언트 주도) 양방향 통신 (서버 및 클라이언트 주도)
연결 방식 비연결성 지속적인 연결 유지
오버헤드 높은 오버헤드 (매번 연결) 낮은 오버헤드 (한 번 연결 후 유지)
사용 사례 정적 리소스, 비동기 요청 실시간 채팅, 실시간 데이터 교환

4. HTTP vs WebSocket: 언제 무엇을 사용해야 할까?


  • HTTP를 사용하는 경우:
    • 페이지 로드나 정적 파일을 제공할 때.
    • 간헐적인 데이터 요청, 예를 들어 API 요청 등을 처리할 때.
    • 캐싱이 중요한 경우.
  • WebSocket을 사용하는 경우:
    • 실시간 상호작용이 필요한 애플리케이션 (예: 실시간 채팅, 주식 거래 시스템).
    • 클라이언트와 서버가 양방향으로 데이터를 지속적으로 주고받아야 하는 경우.

5. Python을 이용한 예시 코드


HTTP 서버 예시 (Python)

Python에서는 http.server 모듈을 사용해 간단한 HTTP 서버를 구현할 수 있습니다.

HTTP 서버 코드:

from http.server import BaseHTTPRequestHandler, HTTPServer

class SimpleHTTPRequestHandler(BaseHTTPRequestHandler):
    def do_GET(self):
        # 응답 상태 코드 설정
        self.send_response(200)
        # 헤더 설정
        self.send_header('Content-type', 'text/html')
        self.end_headers()
        # 응답 본문 작성
        self.wfile.write(b"Hello, World! This is an HTTP response.")

def run(server_class=HTTPServer, handler_class=SimpleHTTPRequestHandler):
    server_address = ('', 8000)  # 포트 8000에서 실행
    httpd = server_class(server_address, handler_class)
    print("HTTP 서버가 시작되었습니다.")
    httpd.serve_forever()

if __name__ == '__main__':
    run()

이 코드는 포트 8000에서 간단한 HTTP 서버를 실행합니다. 브라우저에서 http://localhost:8000으로 접속하면 “Hello, World! This is an HTTP response.”라는 메시지를 볼 수 있습니다.

HTTP 클라이언트 코드:

requests 라이브러리를 사용해 HTTP 요청을 보낼 수 있습니다.

import requests

response = requests.get('http://localhost:8000')
print(f"응답 상태 코드: {response.status_code}")
print(f"응답 본문: {response.text}")

WebSocket 서버 예시 (Python)

websockets 라이브러리를 사용해 WebSocket 서버와 클라이언트를 구현할 수 있습니다.

WebSocket 서버 코드:

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)
print("WebSocket 서버가 시작되었습니다.")
asyncio.get_event_loop().run_forever()

WebSocket 클라이언트 코드:

import asyncio
import websockets

async def send_message():
    async with websockets.connect("ws://localhost:8765") as websocket:
        message = input("메시지를 입력하세요: ")
        await websocket.send(message)
        print(f"전송한 메시지: {message}")
        
        response = await websocket.recv()
        print(f"수신한 응답: {response}")

# 클라이언트 실행
asyncio.get_event_loop().run_until_complete(send_message())

이 예시에서 WebSocket 서버는 클라이언트로부터 메시지를 받아서 동일한 메시지를 다시 클라이언트로 보내는 간단한 에코 서버입니다.

6. 결론


HTTP는 정적 리소스 제공이나 간헐적인 데이터 요청에 적합한 반면, WebSocket은 실시간 데이터 교환이 필요한 애플리케이션에 적합합니다.
두 프로토콜의 특성을 잘 이해하고, 애플리케이션의 요구 사항에 맞게 적절한 통신 방식을 선택하는 것이 중요합니다