반응형
미니 프로젝트를 진행하면서 채팅,실시간 화면공유, 화상채팅 기능을 추가하다보니 자연스럽게 소켓에 대해 다루게 됐다.
근데....너무 어렵다 소켓! 프로젝트를 위한 기본 템플릿은 잘 되어있어서 기능 구현 자체는 어렵지 않았는데, 기능을 추가, 리팩토링, 에러 캐치를 하다보니 복사 붙여넣기로는 한계가 생겨버렸다 ,, 😥
계속 공부중이고, 당장 필요한 내용을 위주로 정리한 걸 적어보려한다. 공부하면 모르는게 또 생기고 또 생기고 언제쯤 소켓이 쉬워질까요...?
잘못된 정보가 있으면 언제든 알려주세요!!
1. 소켓 (Socket)
1) 등장
- OSI 7계층의 한계
- 프로토콜 구현을 위한 구현부 함수가 필요해짐
- 소켓에서 이러한 함수들의 body를 제공하여 별도의 구현없이 소켓 사용 → 일관된 방식의 네트워크 프로그래밍 환경을 제공
- 분산 시스템의 등장
2) 개념
- 컴퓨터 네트워킹에서 프로세스간 통신(IPC)인 양방향 통신을 가능하게 하는 인터페이스
- 프로토콜, ip주소, 포트넘버로 정의
- 일반적으로 TCP/IP 프로토콜 사용
3) 소켓 통신 흐름
- 소켓 상태
- CLOSED : 초기상태
- LISTEN : 서버 소켓이 연결 대기 중
- SYN_SENT : 클라이언트가 서버로 연결 요청을 보냄
- ESTABLISHED : 연결 성공 상태
- CLOSE_WAIT : 연결 종료 대기
- 서버 : 클라이언트 소켓의 연결 요청을 대기하고, 연결 요청이 오면 클라이언트 소켓을 생성하여 통신이 가능하게 함
- 클라이언트 : 서버와 연결을 요청하고 데이터 송수신.
[server socket]
socket() // 소켓 생성
bind() // ip와 port번호를 설정
listen() // 클라이언트 접근 요청에 수신 대기열을 만들어 몇개의 클라이언트를 대기 시킬지 결정
accept() // 클라이언트와의 연결을 기다림
[client socket]
socket() //소켓 열기, 소켓의 종류를 선택
connect() // 통신을 할 서버의 ip와 서비스port번호에 통신 시도, 요청의 결과가 돌아오면 함수실행 종료
//통신을 시도시, 서버가 accept()함수를 이용하여 클라이언트의 socket descriptor을 반환
send() / recv() // 클라이언트와 서버가 서로 read/write 반복, 요청의 결과가 들어와야 실행이 종료
4) 종류
- TCP 소켓: 연결지향성(신뢰성 보장), 대량 데이터 처리
- UDP 소켓: 비연결형, 빠른 데이터 전송, 실시간 멀티미디어 처리
2. 웹소켓 (WebSocket)
- HTTP 기반의 프로토콜 확장으로 양방향 실시간 통신 제공
- 원래의 HTTP는 단방향 통신으로 응답 후 바로 연결 종료 -> 실시간 통신이 어려움
- HTTP 핸드셰이크 이후 TCP 연결 위에서 통신
- HTML5 이후에 나타난 기술
- 이전에 구현된 서비스는 Socket.IO / SockJS / STOMP 등 사용
- 동작 방법 : 핸드셰이킹 -> 프레임 단위 통신
3. Socket.IO
1) 개념
- 웹소켓과 폴백 기술(Long Polling, JSON Polling, XHR Polling 등)을 조합한 실시간 통신 라이브러리
- Long Polling : 클라이언트가 서버에 지속적으로 HTTP요청을 보내 실시간 통신을 흉내냄
- JSON Polling : 주로 CORS 문제가 있는 환경에서 사용 , <script>태그를 동적으로 삽입하여 데이터 요청
- XHR Polling : XMLHTTPRequest를 이용한 폴백 방식
- Node.js 환경에서 개발된 클라이언트와 서버간의 저지연, 양방향, 이벤트 기반 통신을 가능하게 하는 라이브러리
- Engine.IO프로토콜 위에서 동작
- Socket.IO가 Engine.IO 프레임 안에 애플리케이션 데이터를 담아 전송→ Socket.IO는 Engine.IO의 전송메커니즘을 추상화하여 사용할 수 있음
- 자동 재연결, 이벤트 기반으로 데이터 전송 처리, 네임스페이스와 룸지원 , 브라우저 호환성의 장점을 가짐
2) 패킷
- Socket.IO패킷 타입패킷 타입 값
CONNECT 0 네임스페이스에 연결하는 동안 사용 DISCONNECT 1 네임스페이스에서 연결을 끊을 때 EVENT 2 반대쪽으로 데이터를 전송할 때 ACK 3 이벤트를 확인할 때 CONNECT_ERROR 4 연결할 동안 BINARY_EVENT 5 반대쪽으로 바이너리 데이터를 전송할 때 BINARY_ACK 6 바이너리 데이터가 포함된 이벤트 확인 - Engine.IO패킷 타입패킷 타입 값
OPEN 0 연결 성공 CLOSE 1 연결 종료 PING 2 서버 또는 클라이언트가 연결 상태를 확인하기 위해 전송 PONG 3 PING패킷의 응답 MESSAGE 4 애플리케이션 데이터가 포함된 일반 메시지, Socket.IO의 패킷을 캡슐화하여 전송 UPGRADE 5 전송 프로토콜 업그레이드 요청 (웹소켓으로 변경 등) NOOP 6 주로 테스트용으로, 아무 동작을 하지 않는 패킷 - 패킷 인코딩 : Socket.IO 패킷타입+네임스페이스 + 데이터 → (캡슐화) → Engine.IO 프레임 (4) + [ 기존 인코딩 결과 ]
- { type: EVENT, namespace: "/", data: ["foo"] } → 2["foo"] → 42[”foo”]
3) 연결 과정
- 클라이언트가 CONNECT패킷을 보냄
- 서버는 연결이 성공하면 CONNECT, 실패하면 CONNECT_ERROR를 보냄
- 연결이 성공되면 데이터 교환 시작
- DISCONNECT 패킷을 보내 네임스페이스에 대한 연결 종료
4) 주요 메서드
- on : 이벤트 리스너 등록 / emit : 이벤트 트리거 & 데이터 전송 / removeListener : 이벤트 리스너 제거
- 서버: io.on(), io.emit(), socket.broadcast.emit().
- 클라이언트: socket.on(), socket.emit().
4. React에서 Socket.IO 사용하기
- React의 컴포넌트 라이프 사이클과 함께 사용되어 실시간 통신 상태를 UI에 반영
- 보통 useEffect를 사용하여 마운트 될 때 소켓을 생성하고, 언마운트 될 때 해제(socket.off)
- 커스텀 훅을 만들어 관리할 수 있음 (연결, 이벤트 처리, 이벤트 트리거 분리 가능)
- 클라이언트에서 서버 연결, 서버에서 특정 포트에서 연결 대기 -> 이벤트 리스너 등록 -> 이벤트 트리거 -> 소켓 연결 해제
useEffect(() => {
// 소켓 연결
const newSocket = io('http://localhost:3000');
setSocket(newSocket); //연결된 소켓 상태 관리
// 서버에서 메시지 받기 (이벤트 구독)
newSocket.on('message', (data: string) => {
setMessages((prevMessages) => [...prevMessages, data]);
});
return () => {
// 컴포넌트 언마운트 시 소켓 연결 해제
newSocket.disconnect();
};
}, []);
const sendMessage = () => {
if (socket && message.trim()) {
// 서버로 메시지 보내기 (이벤트 트리거)
socket.emit('message', message);
setMessage('');
}
};
개념은 봐도 봐도 어렵다 어려워,, 다음 게시물 부터는 GPT를 괴롭혀서 만든 예제 문제로 실습을 해보며 익혀볼 예정 !
'공부 기록 > 개념정리' 카테고리의 다른 글
[객체 지향] JAVA _ interface , abstract (0) | 2024.04.19 |
---|---|
[객체 지향] JAVA _ 접근 제어자, static, 객체와 클래스 (0) | 2024.04.19 |
박싱 vs 언박싱 , 타입 캐스팅 (0) | 2024.04.07 |
인코딩 vs 디코딩 , 직렬화(serialization) (0) | 2024.04.07 |
JVM (자바 가상 머신) (0) | 2024.03.30 |