Go 언어를 활용한 WebSocket 통신 구현 가이드

WebSocket은 하나의 TCP 연결을 통해 클라이언트와 서버 사이의 양방향 통신을 가능하게 하는 프로토콜입니다. 기존의 HTTP 방식이 클라이언트의 요청이 있어야만 서버가 응답할 수 있는 단방향 구조였다면, WebSocket은 서버가 클라이언트에게 실시간으로 데이터를 푸시할 수 있는 전이중 통신(Full-duplex) 환경을 제공합니다.

과거에는 실시간 데이터를 처리하기 위해 Ajax 폴링(Polling) 방식을 주로 사용했습니다. 하지만 폴링 방식은 주기적으로 HTTP 요청을 보내야 하므로 헤더 정보로 인한 네트워크 오버헤드가 발생하고 서버 리소스 낭비가 심하다는 단점이 있습니다. 반면 WebSocket은 연결이 한 번 확립되면 가벼운 프레임 구조를 통해 통신하므로 대역폭을 절약하고 지연 시간을 최소화할 수 있습니다.

Go 언어에서 WebSocket을 구현하기 위해 필요한 패키지를 다음과 같이 설치합니다.

go get golang.org/x/net/websocket

서버 측 구현: main.go

아래 코드는 클라이언트로부터 메시지를 받아 특정 조건에 따라 응답을 반환하는 간단한 에코(Echo) 서버의 구현 예시입니다.

package main

import (
	"fmt"
	"golang.org/x/net/websocket"
	"html/template"
	"net/http"
)

// socketProcessor는 WebSocket 메시지를 처리합니다.
func socketProcessor(conn *websocket.Conn) {
	for {
		var clientData string
		// 메시지 수신
		if err := websocket.Message.Receive(conn, &clientData); err != nil {
			fmt.Println("연결 종료 또는 오류:", err)
			break
		}

		fmt.Printf("클라이언트 전송 내용: %s\n", clientData)

		var responseMsg string
		switch clientData {
		case "이름":
			responseMsg = "Server: 제 이름은 Go-Bot입니다."
		case "날씨":
			responseMsg = "Server: 오늘은 코딩하기 좋은 날씨입니다."
		default:
			responseMsg = "Server: " + clientData + " (자동 응답)"
		}

		// 메시지 송신
		if err := websocket.Message.Send(conn, responseMsg); err != nil {
			fmt.Println("데이터 전송 실패:", err)
			break
		}
	}
}

// renderIndex는 메인 HTML 페이지를 반환합니다.
func renderIndex(w http.ResponseWriter, r *http.Request) {
	tmpl, _ := template.ParseFiles("index.html")
	tmpl.Execute(w, nil)
}

func main() {
	const addr = "127.0.0.1:9000"
	
	http.Handle("/ws", websocket.Handler(socketProcessor))
	http.HandleFunc("/", renderIndex)

	fmt.Printf("서버 시작: http://%s\n", addr)
	if err := http.ListenAndServe(addr, nil); err != nil {
		panic("서버 구동 실패: " + err.Error())
	}
}

클라이언트 측 구현: index.html

브라우저에서 서버에 접속하여 WebSocket 연결을 테스트하기 위한 HTML 및 JavaScript 코드입니다.

<!DOCTYPE html>
<html lang="ko">
<head>
    <meta charset="UTF-8">
    <title>WebSocket Test</title>
</head>
<body>
    <h2>Go WebSocket 실시간 채팅</h2>
    <div>
        <input type="text" id="inputField" placeholder="메시지를 입력하세요">
        <button onclick="deliverMessage()">전송</button>
    </div>
    <div id="log" style="margin-top: 20px; border: 1px solid #ccc; padding: 10px;"></div>

    <script type="text/javascript">
        let socket;
        const endpoint = "ws://127.0.0.1:9000/ws";
        const logDisplay = document.getElementById('log');

        window.onload = function() {
            socket = new WebSocket(endpoint);

            socket.onopen = function() {
                writeLog("시스템: 서버에 연결되었습니다.");
            };

            socket.onmessage = function(event) {
                writeLog("수신: " + event.data);
            };

            socket.onclose = function() {
                writeLog("시스템: 연결이 종료되었습니다.");
            };

            socket.onerror = function(error) {
                writeLog("오류: " + error.message);
            };
        };

        function deliverMessage() {
            const input = document.getElementById('inputField');
            if (socket && input.value) {
                socket.send(input.value);
                writeLog("발신: " + input.value);
                input.value = "";
            }
        }

        function writeLog(message) {
            const p = document.createElement("p");
            p.textContent = message;
            logDisplay.appendChild(p);
        }
    </script>
</body>
</html>

위의 서버 코드를 실행한 후 브라우저에서 서버 주소로 접속하면 WebSocket을 통한 실시간 데이터 송수신을 확인할 수 있습니다. 브라우저의 개발자 도구(F12) 콘솔이나 네트워크 탭을 활용하면 실제 데이터 패킷이 오가는 과정을 더 자세히 관찰할 수 있습니다.

태그: go websocket Network backend JavaScript

7월 26일 15:21에 게시됨