안녕하세요, 프론트엔드 개발자 설탕시럽입니다.
이번에 프로젝트를 시작하게 되었고 실시간 채팅 기능을 구현하게 되었는데, 그 과정에서 react에서 Web API를 이용한 websocket 처리하는 방식에 관한 경험을 공유하려고 합니다!
1. Websocket?
websocket은 http 프로토콜과 달리 실시간으로 서버와 클라이언트가 양방향 통신을 지원하여, 양방향 모두 자유롭게 데이터를 보낼 수 있는 프로토콜입니다. http/https처럼 ws/wss를 통해 웹소켓과 보안이 강화된 웹 소켓을 이용할 수 있습니다. 위에서 설명한 데로 실시간 채팅과 화상회의 기능 구현을 위해 websocket 방식을 적용하게 되었습니다.
2. React in WebSocket
websocket은 웹 API에서 지원해주기 때문에 별도의 써드파티 API나 라이브러리를 가져올 필요 없이 아래와 같은 방식으로 선언 및 사용할 수 있습니다. (해당 글에서 websocket의 자세한 문법에 대해서는 다루지 않습니다. React에서 websocket을 적용하는 과정에서 발생하는 에러와 그 원인에 관련된 내용이 주 이므로, 궁금하신 분들은 구글에 따로 검색해 보시거나 추후 포스트를 작성할 일 있으면 작성하겠습니다.)
const ws = new WebSocket('ws://URL');
vanila JavaScript에서 WebSocket을 호출하는 방식을 참고해서 아래와 같은 방식으로 WebSocket을 호출을 시도했습니다.
export const Home = () => {
const ws = new WebSocket('ws://URL');
return(<>
<span>WebSocket Test Page</span>
</>)
}
축약된 코드지만 핵심은, 로컬 변수와 같은 방식으로 WebSocket을 선언하면 'is not defined' 에러 메시지가 발생합니다. WebSocket이 정의되어 있지 않다는 점에서 전혀 이해할 수 없어서 검색을 통해 예제코드들을 살펴보니 모두 useEffect, componentDidMount 내부에서 선언해서 사용하고 있었습니다.
2.1 로컬 변수처럼 선언하면 안 되는 이유
WebSocket is not defined와 같은 에러가 발생하는 이유는 node에 있었습니다. node는 자바스크립트 런타임으로 nodeJS 만의 추가적인 기능을 지원하는 엔진에 document와 같이 빠진 기능들도 있다. WebSocket 또한 node에서 기능이 빠져있었기에 해당 컴포넌트를 호출하는 시점에 node 엔진에서만 동작하는 코드에서는 WebSocket을 지원하지 않고 에러가 발생하게 됩니다. 따라서 아래와 같은 방식으로 코드를 변경하면 코드가 원활하게 동작합니다.
2.2 useEffect 내부에서 정의하기
const socket = useRef<WebSocket>();
useEffect(() => {
const _socket = new WebSocket('wss://umbrellawss.fly.dev/');
socket.current = _socket;
}, []);
useEffect를 사용하여 websocket을 처리했고 event를 처리하는데 문제가 없을 줄 알았습니다... 하지만, client에서 다시 server로 메시지를 전송할 때 생성된 WebSocket이 필요했기 때문에 useEffect 바깥에 선언되어 사용했어야 했습니다.
useEffect 내부의 WebSocket 객체를 가져오기 위해, useState를 이용하려고 했습니다. 하지만 WebSocket이 처음 선언된 이후로 변경될 상태가 없었고, useEffect 내부에서 상태값을 불러서 사용할 수 없었기에 useRef를 로컬 변수처럼 사용하는 형식으로 처리했습니다.
3. 마무리
처음 WebSocket is undefined라는 에러를 발견했을 때, useEffect내부에서는 동작하고 외부에서는 동작하지 않을 때 상당 시간을 헤매고 다양한 포스트를 찾아보며 이해하려고 했습니다. 제가 확인한 정보를 정리해 보면,
1. nodeJS 자바스크립트 엔진에는 WebSocket이 정의되어 있지 않고, 브라우저 WebAPI에 정의되어 있다.
2. 컴포넌트를 처음 호출하는 시기에는 NodeJS 자바스크립트 엔진에서만 코드가 동작하고, 렌더링 된 후 동작하는 useEffect에서는 Web API에 정의된 기능까지 동작한다.
3. 따라서, 별도의 라이브러리 설치나 호출 없이 WebSocket 통신을 위해서는 useEffect 내부에서 정의해야 한다.
다음 포스트에서는 useEffect가 아닌 custom hook을 정의해서 WebSocket 통신하는 방법과 두 방법의 특징에 대해 공부하고 포스트 해보겠습니다.
References
https://www.kianmusser.com/articles/react-where-put-websocket/
'React' 카테고리의 다른 글
useState 딥다이브 (0) | 2023.06.04 |
---|---|
JSX (0) | 2023.05.17 |
React의 특징과 장점, 적용 예제 까지! (0) | 2023.05.16 |
Axios Custom Hook TypeScript 환경으로 만들기 (0) | 2023.05.08 |
react-hook-form과 yup 라이브러리 적용 하기 (0) | 2023.02.12 |