처음 내가 socket.io를 접했을때에는 단순히 emit으로 보내고 on으로 받으면 되는거 아닌가? 쉽네 ㅋ 했다.
그리고 그날부터 삼일동안 머리를 싸매고만다. 지금부터 겪은 고난을 하나씩 말해보겠다.
상황은 브라우저를 두개 띄워놓은 상황이다
1. 채팅 중복렌더링, 소켓 중복생성
문제
- 내가 채팅을 "안녕"한개만 보내면 "안녕"한개만 오는것이 정상이다. 그런데 두개,세게,네개씩 불어나는것이었다.
노력
- 구글링을 해보니 socket-io-client에 Socket타입이 있는것이다. 그래서 Record타입을 통해 특정 소켓객체를 객체리터럴에 저장해봄
정답
- 타입스크립트의 strict-mode에 의해 여러 소캣객체에의해 중복렌더링되는것이 문제였고 소켓객체생성을 기존에 컴포넌트안에서 하던것을 외부로 빼내었더니 해결되었다.

2. 실시간 채팅 연결 disconnect
문제
- 중간에 브라우저 콘솔로 연결이 중단되었다는 빨간줄이 수십줄이 뜸
노력
- 처음에는 채팅이 보내지지 않는 현상에 대해 뭐가 잘못되었는지 모르겠어서 새로고침을 해보고 useEffect훅의 의존성 배열을 바꿔도보고(socket을 빼보기도하고 넣어보기도하고 등)했다.
- 뭐가 문제인지 싶어 별도로 클라이언트와 서버사이에 3초마다 핑을 교환하는 코드를 짜보았다.
정답
-
실시간 채팅연결이 중단되는 이유는 아주 여러가지지만 나의 컴퓨터에서의 이유는 핑에서 알아냈다.
-
난 분명 3초마다 한번씩 핑을 보내기로했는데 갑자기 핑이 한번에 50개, 100개가 오다가 연결이 끊어지는것을 발견했다.
-
그리하여 어떻게하면 연결을 복구할 수 있는지 방법을 찾아보았고
-
socket-io옵션에 아래와같은 옵션이 있다는것을 발견했고, 클라이언트측에 적용시켜주었다.
reconnection: true,
reconnectionAttempts: 5
-
위의 문제를 해결하고나니 채팅창 입장시 기존의 채팅이 렌더링 되지않아서 useEffect의 의존성 배열에 기존 채팅관련한 데이터를 넣어주어해결

3. 채팅창 새로고침해야 채팅 렌더링 진행

문제
- 난 기존에는 emit으로 보내고 on으로 받지않았다. rtk-query로 주고 서버측에서 라우터를 거친후 같은 네임스페이스의 룸으로 채팅을 뿌려주는식이었다. 그렇게 했던 이유는 난 기존까지 서버측과 통신은 항상 rtk-query로 하였고 서버통신코드가 한 파일에 모여있는것이 좋다라고 생각을 했기때문이다.
- 하지만 기능구현이 끝나고 테스트를 해본결과 채팅전송 버튼클릭시 새로고침이 발생하고 메시지 창이 렌더링되는것이다.
- 첫 채팅 프로젝트였던 난 "어찌되었건 보내지고 받아지네?"라는 생각을 잠시 하였지만 카카오톡을 쓰던 난 뭔가 이상함을 느꼈다.
노력
- mysql을 켜서 채팅이 데이터베이스에 저장되는지 확인
- 서버측 라우터, 클라이언트측 전송함수, 소켓함수 등등 여기저기 console찍어보기
- 기존 form tag를 div태그로 교환해보기
정답
- 사실 이건 실시간 통신이 되고있던것이 아니었다.
- 말그대로 내가 서버로 채팅을 보내고, 저장후 데이터를 다시 클라이언트측으로 보내어 렌더링 하는방식이었던것이다. 그래서 새로고침을 해야만 채팅을 볼 수 있던것이다 (socket에 연결되어있지도 않았음)
- 난 서버측 namespace에 url을 포함시켜놨었는데 순수 namespace만 남겨두었다.
- 클라이언트측에서 채팅을 보낼땐 namespace까지 포함시켜놓았다(라우터 형태의 namespace라고 생각하면 편할듯)
- 정말 기본적인 내용(form을 submit하면 기본동작이 새로고침 된다는사실)을 까먹고 쓰고있던것이다 그래서 e.preventDefault(); 코드를 통해 새로고침을 막았다(인풋을 받고 데이터를 날리는 태그는 form안에 쓰는게 맞겠다싶어 div로 교환하지않음)
- 또한 난 네임스페이스를 숫자로 지정했었는데 숫자로 하면 안되는것이었다.그래서 새로고침해야만 서버에서 가져온 기록으로 채팅이 보이는 원리였고 난 그래서 namespace 코드를 수정하였다.


4. 서버 세션공간을 통한 유저확인 기능
문제
- 난 세션에 공간을 만들어서 세션쿠키를통해 사용자를 인증해서 사용자 정보를 세션에 저장해서 서버=>클라이언트 로 뭉쳐서 데이터를 보내줄 생각이었다.
- 하지만 세션미들웨어를 공유하는 코드를 짯지만 세션에는 undefined만 출력되었다.
해결방법
- 세션으로 해결하고싶었지만 다른방법이 떠올랐다
- 클라이언트 => 서버측으로 소켓연결이벤트를 보낼때 처음부터 유저정보를 담아서 보내는 방법이다 그리하여 query 옵션으로 유저정보를 담아 보내었다.


5. 채팅시 자동 스크롤
문제
- 기능구현은 하였는데 스크롤이 너무 딱딱하게 하강되는 현상발견
해결
- useRef를 통해 속성에 접근하여 스크롤하는 함수구현

6. cascade옵션 미작동

문제
정답
- 이유는 모르겠지만 1:N관계에서 1과 N모두에 옵션을 적용해주어야 작동을 하였다.
7. 채팅 진행중에 채팅방 재입장시 기존의 채팅중 일부를 받아오지 못하는현상
문제
- 프론트쪽은 리액트로 채팅창을 구현하였다. 하지만 채팅창에 입장시 기존의 채팅중 가장 최근에 채팅을 받아오지 못하는 현상이 발생하였다.

이유
- 리액트는 멀티 페이지 애플리케이션이 아닌 싱글 페이지 애플리케이션 입니다. 따라서 뷰 렌더링은 브라우저가 담당하고 웹 애플리케이션을 브라우저에 불러와서 실행시킨 후에 사용자와의 인터랙션이 발생하면 필요한 부분만 자바스크립트를 사용하여 업데이트하는 방식입니다. 따라서 처음 한번만 받아오고 나머지는 필요한 데이터만 받아와서 교체하는 방식입니다. 새로고침을 최소화시키는 방식이란 것입니다.
- 그래서 채팅창에서 가장 최근의 채팅은 브라우저입장에서 바뀐것이 아니라고 판단하였던것입니다.
해결
- react router dom을 사용하면 새로고침을 하지않으니 window.location.href를 사용하여 처음한번은 새로고침을 시켜주었습니다.

