[BACK-011][실무] 끊기지 않고 주고받는 실시간 통신 만들기 > IT 기술 공유

본문 바로가기
사이트 내 전체검색

IT 기술 공유

[BACK-011][실무] 끊기지 않고 주고받는 실시간 통신 만들기

페이지 정보

profile_image
작성자 기술팀장
댓글 0건 조회 97회 작성일 26-09-05 13:34

본문

[이번 수업]
채팅이나 작업 진행률처럼 서버 변화를 즉시 알려야 할 때 WebSocket을 씁니다. HTTP로 연결을 협상한 뒤 브라우저와 서버가 메시지를 자유롭게 주고받습니다. 로컬 에코 서버로 연결·메시지·종료를 익힙니다.

[선수지식]
HTTP 요청·응답, JavaScript 이벤트, JSON, Node.js 실행법을 알고 있어야 합니다.

[학습목표]
1. 짧은 HTTP 요청과 오래 유지되는 WebSocket 연결을 구분한다.
2. 브라우저와 서버 사이에서 JSON 메시지를 주고받는다.
3. 인증, 입력 제한, 연결 감시, 재연결을 포함한 운영 기준을 세운다.

[핵심개념]
연결은 HTTP Upgrade 핸드셰이크(통신 시작 조건을 맞추는 절차)로 시작합니다. 성공하면 양쪽이 독립적으로 텍스트나 이진 메시지를 보냅니다. `ws://`는 평문, `wss://`는 TLS로 보호된 연결이므로 운영에는 `wss://`를 씁니다.

드문 알림에는 HTTP 조회나 서버 전송 이벤트가 더 단순합니다. 메시지 방향, 지연, 동시 연결 수, 프록시의 유휴 제한을 보고 고르세요. ping/pong으로 연결 생존을 확인하고 재접속 간격을 점차 늘려 서버 몰림을 줄입니다. 송신이 소비보다 빠른 역압(backpressure)은 큐와 전송량 제한으로 다룹니다.

[따라하기]
빈 폴더에서 `npm init -y`와 `npm install ws`를 실행합니다. server.mjs를 만듭니다.
```javascript
import { WebSocketServer } from "ws";
const wss = new WebSocketServer({ port: 8080 });
wss.on("connection", socket => {
  socket.on("error", console.error);
  socket.on("message", (data, isBinary) => {
    if (isBinary) return socket.close(1003, "text only");
    if (data.length > 1024) return socket.close(1009, "too large");
    let input;
    try { input = JSON.parse(data.toString()); }
    catch { return socket.close(1007, "invalid json"); }
    const text = typeof input.text === "string" ? input.text.slice(0, 100) : "";
    socket.send(JSON.stringify({ type: "echo", text }));
  });
});
console.log("서버: ws://localhost:8080");
```
client.html을 만듭니다.
```html
<!doctype html><meta charset="utf-8"><button id="send">보내기</button><pre id="log"></pre>
<script>
const log = document.querySelector("#log");
const ws = new WebSocket("ws://localhost:8080");
ws.addEventListener("open", () => log.textContent += "연결됨\n");
ws.addEventListener("message", e => log.textContent += e.data + "\n");
document.querySelector("#send").addEventListener("click", () => {
  if (ws.readyState === WebSocket.OPEN)
    ws.send(JSON.stringify({ type: "hello", text: "안녕하세요" }));
});
</script>
```
첫 터미널에서 `node server.mjs`를 실행합니다. 둘째 터미널에서 macOS·Linux는 `python3 -m http.server 8000`, Windows는 `py -m http.server 8000`을 실행한 뒤 `http://localhost:8000/client.html`을 엽니다. 예상 결과는 ‘연결됨’ 뒤 버튼을 누를 때 `{"type":"echo","text":"안녕하세요"}`가 표시되는 것입니다.

[흔한 실수]
연결 성공만 보고 종료·오류를 처리하지 않거나 타이머·구독을 해제하지 않으면 누수가 납니다. 메시지 도착 순서를 업무 완료 순서로 가정하지 마세요. 중요한 작업에는 메시지 ID, 승인 응답, 중복 방지와 최종 상태 확인을 넣습니다.

[보안 주의]
연결 성공은 권한을 뜻하지 않습니다. 운영 서버는 허용한 Origin인지 확인하고 사용자를 인증하며, 메시지마다 대상 자원의 권한을 검사합니다. JSON 스키마, 최대 크기, 메시지 빈도, 연결 수를 제한하고 로그에는 토큰과 개인정보를 남기지 않습니다. 실습은 본인 소유의 로컬·격리 환경에서만 실행하세요.

[직접 해볼 과제]
서버가 `ping` 유형을 받으면 현재 시각을 담은 `pong` JSON을 보내게 만들고, 잘못된 유형에는 오류 메시지를 반환하세요. 새로고침과 서버 재시작 때 상태 변화도 기록합니다.

[확인문제]
1. WebSocket 핸드셰이크가 끝난 뒤 HTTP 요청·응답과 달라지는 점은 무엇인가요?
2. 실제 서비스에서 `ws://` 대신 `wss://`를 써야 하는 이유는 무엇인가요?
3. 연결 인증 후에도 메시지마다 권한 검사가 필요한 이유는 무엇인가요?

[다음 학습]
BACK-012에서 입력 검증, 저장소, 오류 처리, 자동 테스트를 묶어 테스트 가능한 API 서비스 프로젝트를 완성합니다.

[공식 참고 자료]
https://www.rfc-editor.org/rfc/rfc6455
https://websockets.spec.whatwg.org/
https://developer.mozilla.org/en-US/docs/Web/API/WebSocket
https://github.com/websockets/ws

댓글목록

등록된 댓글이 없습니다.

회원로그인

회원가입

사이트 정보

회사명 : 회사명 / 대표 : 대표자명
주소 : OO도 OO시 OO구 OO동 123-45
사업자 등록번호 : 123-45-67890
전화 : 02-123-4567 팩스 : 02-123-4568
통신판매업신고번호 : 제 OO구 - 123호
개인정보관리책임자 : 정보책임자명

접속자집계

오늘
777
어제
5,103
최대
16,772
전체
771,831
Copyright © 소유하신 도메인. All rights reserved.