이번 프로젝트에서 가장 핵심이 되었던 기능 중 하나인 채팅 기능을 구현했던 과정에 대해서 정리해보고자 한다.
Websocket 통신 방식은 HTTP 통신 방식과는 차이가 있었고, 처음 해보는 기능이라 학습과 병행하면서 진행했어야 했는데
그러다 보니 개념에 대한 이해를 다소 부실하게 하면서, 기능 구현에만 집중하다 보니 부족한 부분이 굉장히 많았다고 생각한다.
해당 정리 내용은 frontend 측 입장에서 어떻게 사용하는지를 작성한 글이기 때문에,
backend나 전체적인 socket.io의 원리 부분들은 다른 글을 참고하길 바란다.
라이브러리 설치 및 세팅
우선 내 글을 보고 도움을 받을 분들을 생각해 미리 내 개발 환경에 대해서 정리를 해보겠다.
node ver : 20.1.0
stack : React, Typescript
npm install socket.io-client
우선 Websocket 방식의 통신을 위해서 필요한 라이브러리를 설치해야 한다.
나는 전체적인 통신이 아닌 클라이언트 측을 담당하는 부분이 필요했기에 socket.io-client라는 라이브러리를 설치했다.
라이브러리 설치 후 통신에 필요한 socket 파일을 세팅했다.
socket.io-client에서 제공하는 io라는 함수에는 두 개의 인자가 들어갈 수 있는데,
첫번째 인자에는 Websocket 통신을 할 수 있는 URI가 들어가고,
통신할 때 적용할 수 있는 다양한 옵션은 두번째 인자에 넣을 수 있다.
물론 옵션이기 때문에 아무것도 넣지 않아도 에러가 발생하지는 않지만, 첫번째 인자에는 꼭 값을 넣어줘야 한다.
나같은 경우는 통신을 할 때마다 서버에 토큰이 필요하다고 해서
extraHeaders 라는 옵션에 토큰을 입력해 주었다.
이렇게 세팅하면 실제 사용하고자 하는 로직에서 토큰을 일일히 넣어주지 않아도 돼서 편했다
io 함수에 필요한 인자를 입력한 뒤, 해당 반환값을 socket이라는 변수에 담아 export 해줬다.
실제 사용할 때는 이 socket이라는 변수를 이용해서 작업을 진행하게 된다.
사용한 방식
이번 프로젝트에서 사용된 메서드는 emit과 on, off가 되겠다.
emit은 클라이언트에서 서버로 데이터를 보내는데 사용되는 메서드다.
여기서 가장 중요한 부분은 바로 첫번째 인자에 들어가는 내용이다.
이 부분은 우리가 REST API를 사용했을 때, endpoint가 다르면 올바른 통신이 되지 않는 것 처럼 서버측과 맞춰서 입력해야 하는 값이다.
두번째 인자에는 전달하고자 하는 데이터를 보내주고, 세번째 인자는 통신에 성공한 경우에 진행되는 콜백함수를 입력했다.
위의 코드에서는 'create-room'이라고 해서 실시간 채팅을 할 수 있도록 채팅 방을 만드는 메세지를 사용했다.
채팅방 페이지에서는 useEffect를 통해 같은 방에서 다른 유저가 작성한 메세지를 받을 수 있도록 on 메서드를 사용했다.
on 메서드의 첫번째 인자에는 이벤트 이름이, 두번째 인자에는 콜백함수를 받도록 되어있다.
위 코드에서는 message라는 이벤트를 수신하게 되면 messageHandler라는 함수를 실행하도록 되어있다.
결국 on 메서드를 사용하게 되면 message라는 이벤트를 감지하도록 열어둔다는 얘기가 될 것 같다.
off 메서드 역시 첫번째 인자에 이벤트 이름이, 두번째 인자에는 콜백함수가 들어가있다.
off 메서드는 이벤트를 더 이상 수신하지 않겠다라는 의미를 갖고 있는데
useEffect에 clean up effect 로 사용하도록 구성해서 해당 채팅방을 나갔을 때 더 이상 수신하지 않도록 구현했다.
위 코드를 보면 chat이라는 state가 변경될 때 마다 on 메서드가 다시 실행되도록 구현했는데,
이 부분은 아래 메세지를 발송하는 코드와 함께 설명해 보겠다.
메세지를 전송할 때 emit 메서드를 사용했다.
여기서 주목할 부분은 이벤트 이름이 message라는 것이다.
메세지를 전송할 때 message라는 이벤트 이름을 사용하면 서버에 전달이 되고,
다시 서버에서 message라는 이벤트 이름을 클라이언트에게 전달해서 message 이벤트를 감지하고 있던
on 메서드에 의해 새로운 메세지를 화면에 표시할 수 있게 되는 것이다.
근데 여기서 또 중요한건 서버에 해당 메세지를 보내고 난 뒤, chat이라는 state를 변경시켜준다는 것이다.
이게 왜 중요하냐면 위에 useEffect를 사용한 부분을 보면 의존성 배열에 chat state를 감지하도록 설정했는데
chat이 변경되면 clean up effect로 message 이벤트 수신을 잠시 차단하게 된다.
🙋🏻♂️ : 아니 어차피 on 메서드를 그대로 두면 서버가 보내주는 데이터를 받아서 state 변경하면 될 거 같은데 왜 이렇게 함?
물론 나도 이렇게 생각했는데, 통신 상황에 따라서 내가 작성한 메세지가 바로 보이지 않게 될 수 있는 경우도 있는거 아닐까 해서
통신에 성공하면 작성한 내용을 chat이라는 state에 바로 넣어주고,
이 과정에서 useEffect의 의존성 배열에 chat을 넣어줘서 내가 보낸 메세지가 두번 입력되지 않도록 구현했다.
(사실 이게 맞는지는 더 테스트 해봐야 알 것 같다)
암튼 이렇게 내가 채팅 기능을 구현한 방식에 대해서 간략하게 정리해 봤다.
클라이언트에서 라이브러리를 사용해서 몇개의 메서드만 이용해서 사용한 방식이기 때문에
대부분에 채팅에서 요구하는 다양한 기능들은 제대로 구현되지 않지만,
정말 기본적인 실시간 채팅은 구현이 되는것을 확인할 수 있었던 시간이었다.
레퍼런스
- socket.io 라이브러리 공식문서 [ 이동 ]
- 채팅 기능 구현에 참고한 블로그 글 [ 이동 ]
'Personal > Dev_log' 카테고리의 다른 글
[Saida Lab] 첫 서비스 배포, 그 4주간의 기록 (0) | 2024.03.13 |
---|---|
[Project] 우리동네_6주차 로그 (0) | 2023.09.02 |
[Project] 우리동네_5주차 로그 (0) | 2023.09.01 |
[Project] 우리동네_4주차 로그 (0) | 2023.08.31 |
[Project] 우리동네_3주차 로그 (1) | 2023.08.30 |