내 웹 채팅과 WebSocket
같은 채팅 화면을 라이브러리 서버와 직접 만든 TCP 서버에 연결해 봅니다.
선택학습 (필수 아님) · 두 브라우저에서 대화하면 첫 성공입니다. 프로토콜이 궁금할 때만 두 번째 파트로 이어가세요. 각 파트를 모두 끝내거나 교사에게 완료 확인을 받을 필요는 없습니다.
웹소켓 프로젝트 ZIP 다운로드 · 자율 프로젝트 목록
소켓 채팅과 HTTP를 해 봤다면 연결하기 좋습니다. Node.js 24 이상과 브라우저를 준비하고, 압축을 푼 10-자율프로젝트/01-websocket 폴더에서 실행합니다.
파트 1 · 라이브러리로 먼저 채팅하기
npm ci
npm run start:library내 채팅 화면을 탭 두 개에서 엽니다. 한쪽에서 Hello를 보내고 다른 쪽에서도 보이는지 확인하세요. 처음에는 영문·숫자·기호·공백으로 짧게 보냅니다. 이 실험은 내 컴퓨터에서 실행하며 포털의 교재 화면 자체가 채팅 서버는 아닙니다.
탭 A의 WebSocket.send → 서버의 수신 함수 → 연결된 탭들로 전송
→ 탭 B의 message 이벤트 → 화면에 표시public/index.html의 send와 message, 01-library/server.mjs의 수신·전달 부분을 찾아보세요. 서버에서 전달할 문장 앞에 짧은 표식을 붙이는 등 한 곳만 바꾸고, 서버를 다시 시작해 확인합니다.
여기까지 해도 충분합니다. 두 탭에서 대화하고 “화면은 어디서 실행되고 메시지는 어디를 거치는가?”를 설명할 수 있으면 첫 결과가 남았습니다.
연결되었는데 다른 탭에 안 보인다면
두 탭의 주소가 모두 http://127.0.0.1:8090인지, 연결됨 표시가 있는지 확인하세요. 터미널에서 서버를 껐다 켰다면 각 탭에서 다시 연결합니다. 서버의 message 함수가 받은 값과 각 연결에 보내는 값을 따로 살펴보면 어느 지점에서 멈췄는지 찾기 쉽습니다.
파트 2 · 같은 화면, 직접 만든 서버
브라우저의 WebSocket은 앞서 만든 단순 TCP 채팅 서버에 그대로 연결되지 않습니다. 연결을 시작하는 규칙과 메시지를 감싸는 프레임 규칙을 서로 알아야 합니다. 이번 예제는 HTTP/1.1 연결 협상 뒤 같은 TCP 연결로 WebSocket 프레임을 주고받습니다. WebSocket의 구조
터미널에서 기존 서버를 Ctrl+C로 끄고 다음을 실행합니다. 두 서버가 같은 포트를 쓰므로 동시에 켜지 않습니다.
npm run start:raw같은 주소의 두 탭에서 다시 연결하기를 누르거나 새로고침하고 Hello를 보냅니다. 화면 코드는 그대로인데 이번에는 02-protocol/server.mjs가 TCP 수신 바이트를 읽습니다.
아래 중 궁금한 지점 하나만 골라 보세요. 완성 예제가 있으므로 처음부터 빈 파일에 전체를 작성할 필요는 없습니다.
| 작은 완성점 | 찾아볼 곳 | 해 볼 질문 |
|---|---|---|
| 연결이 열리는 이유 찾기 | server.mjs의 HTTP 헤더·101 응답 | 일반 HTTP 응답과 무엇이 다를까? |
Hello를 프레임에서 복원하기 | frames.mjs의 길이·마스킹 처리 | 문장 앞 바이트들은 무슨 역할일까? |
| 조각을 다르게 나누어 같은 결과 얻기 | check-frames.mjs의 입력 배열 | 한 번에 두 프레임이 오거나 한 바이트씩 오면 어떨까? |
명세는 필요한 부분만 보기
| 지금 생긴 질문 | 공식 문서에서 볼 부분 |
|---|---|
| 브라우저가 언제 연결 성공으로 볼까? | RFC 6455 §4.2.2 · 서버의 연결 응답 |
| 메시지 길이와 종류는 어디에 있을까? | §5.2 · 프레임 형식 |
| 브라우저가 보낸 본문을 어떻게 복원할까? | §5.3 · 클라이언트 마스킹 |
전부 번역하거나 외울 필요는 없습니다. 질문 하나를 정하고 문서의 해당 필드와 코드 한 곳을 맞춰 보세요. 마스킹은 TLS 암호화와 다릅니다. ws://로 보내는 이 실험은 전송 내용을 비밀로 보호하지 않습니다. WebSocket과 TLS
연결 응답에서 무엇부터 보면 좋을까요?
브라우저 개발자 도구의 Network에서 /chat의 요청과 응답 헤더를 봅니다. Upgrade, Connection, Sec-WebSocket-Key, Sec-WebSocket-Accept를 코드와 대응시키세요. 응답을 일부러 바꿔 보면 화면의 연결 결과도 바뀌는지 관찰할 수 있습니다. 변경 전 코드를 보관하고 한 번에 한 필드만 바꿉니다.
조각을 다르게 나눠도 같은 두 문장이 나올까?
npm run check:frames이 확인 도구는 Hello·World 프레임을 붙이거나 한 바이트씩 나누어 같은 두 문장을 복원하는지 보여 줍니다. 네트워크 패킷 캡처가 아니라 수신 조각을 직접 나눈 입력 실험입니다. 원하면 배열에서 나누는 위치 하나를 바꿔 보세요.
TCP의 data 이벤트와 WebSocket 프레임은 같은 단위가 아닙니다. 부족한 바이트는 모으고, 완성된 프레임만 꺼내며, 남은 바이트는 다음 프레임에 사용합니다. 앞서 배운 줄바꿈으로 메시지 나누기에서 메시지 끝을 찾던 일을 이번에는 프레임 길이로 해 봅니다.
정상 예제와 비교할 확인 도구가 필요하다면
npm test프레임 해석과 연결·전송의 확인 결과를 봅니다. 실패했다고 전체 코드를 바꾸기보다 실패한 입력 하나를 골라 “몇 바이트까지 모였는가?”, “완성된 프레임 길이는 얼마인가?”를 확인해 보세요.
이번 구현의 범위
직접 만든 서버는 짧은 ASCII 문장과 길이 125바이트 이하의 단일 프레임을 다루는 학습용 부분 구현입니다. TCP 수신 조각의 분리·합침은 처리하며, 연결 종료와 Ping/Pong도 비교할 수 있습니다. 긴 길이 형식·여러 WebSocket 프레임으로 나눈 메시지·바이너리·한글 텍스트·TLS는 후속 탐구로 남겨 둡니다. 모든 WebSocket 기능을 구현한 서버는 아닙니다.
“같은 규칙을 지키면 서버 구현을 바꿔도 화면은 그대로 쓸 수 있다”를 확인했다면 충분합니다. 막혔을 때는 질문 네 줄을 AI나 교사와 함께 정리해 보세요.