Today Sangmin Learned
article thumbnail
728x90

오늘 공부한 것은, Socket.io를 사용해서 실시간으로 채팅을 주고받는 DM 기능과 이름 옆에 3:57 PM, 11:18 PM과 같은 방식으로 보내는 시간을 표현하는 것을 구현하였다.

빨리 클론코딩을 끝내야 프로젝트를 시작할 수 있는데, 깊은 이해를 요구하기 때문에 진도가 좀 더디다. 빠르게 해봐야겠다.

위와 같은 페이지는, 내가 나에게 보내는 것으로 설정해뒀으나, 페이지를 두개 놓고 할 경우에는 실시간 채팅이 가능하다. 

좀 느리긴 하지만 가능하다. 신기하지 않은가??

1. useSocket custom Hook

기본적으로 socket.io의 사용은 이 useSocket에서 시작된다. Hook은 화면에 어떤 것을 건드리는 게 아니라 로직만 다루는 경우에 보통 사용한다(화면이 들어가더라도 상관은 없다.) 기존에 백엔드 URL을 요청 보낼때마다 썼던 것과는 다르게 backUrl이라는 변수에 넣었는데, 그 이유는 실제 서비스를 릴리즈한다고 가정할 때 그 페이지 URL에 맞춰서 모든 요청에 대한 URL을 바꿔줘야 하는 번거로움을 방지하기 위함이다.

 

sockets는, 내부의 key 값이 string으로 되어있는, SocketIOClient.Socket 타입을 가진 배열 객체이다.

useSocket은 문자열 타이핑을 한 파라미터 workspace를 가진, 반환값이 undefined 혹은 SocketIOClient.Socket 객체인 Hook이다.

 

- disconnect의 경우는, SocketIOClient.Socket 객체가 가진 기본 속성인 disconnect()를 사용한다. 여기서는, 워크스페이스가 있을 경우, 그러니까 연결이 되어있다면 그 연결을 끊고 소켓을 삭제하는 명령을 가진다.

그게 아니고 workspace가 없다면, 당연히 undefined를 리턴해야 한다. 그 아래에는, 워크스페이스는 있으나 소켓에 연결이 되지 않은 경윈 !sockets[workspace]의 경우 위에서 변수로 저장했던 backUrl과, 파라미터로 문자열 타이핑한 worpsace를 활용하여 쿼리문에 따른 위치에 socket을 활용한 연결을 시도한다. 연결할 때 우리는 HTTP도 사용하게 되는데, transports 설정을 통해 연결 시에 HTTP는 제하고 웹소켓만 쓰도록 지시할 수 있다.

 

2. Workspace 레이아웃

레이아웃에서는, 위에서 만든 useSocket을 불러온 뒤 useEffect문을 사용한다. useEffect는 React에서 기본적으로 제공하는 Hook으로, deps([])가 바뀔 때 내부 return문을 실행한다는 뜻이다. socket, 채널 데이터, 유저 데이터가 바뀔 때 if문을 실행하는데, 채널데이터와 유저데이터 그리고 소켓이 존재하는 경우(소켓은 undefined일 수도 있기 때문이다.) 소켓을 콘솔에 띄운 뒤 socket.emit을 통해 id와 채널(의 id) 정보를 담아서 login 이벤트를 전송한다. 

그리고, 그 아래 useEffect문에서는, workspace와 disconnect의 값이 바뀔 때 소켓 연결 해제를 해준다는 뜻으로, 워크스페이스를 이동할 때 기존 워크스페이스를 정리해준다는 뜻이다. 이게 없으면 내가 A 워크스페이스에서 B 워크스페이스로 옮기고 거기에서 말을 했을 때, A와 B 워크스페이스 둘 다로 데이터가 전송이 된다.

 

즉, 워크스페이스 레이아웃에서는 DM을 위한 기본적인 환경 세팅 정도만 하게 된다.

이전에 DM 페이지에 관한 내용을 포스팅했으므로 여기서는 DM 페이지는 생략하고 DM 페이지에서 불러오는 Chat 컴포넌트와 ChatList 만 다룬다

3. Chat 컴포넌트

이 Chat이 아래에서 다룰 ChatList에 뜨게 된다. 우리가 ChatBox에 적는 내용을 보냈을 때 이 Chat 컴포넌트가 ChatList 컴포넌트에 뜨게 되는 것이다. 이전 포스팅에서 우리가 적은 내용이 뜨지 않은 이유는 우리가 적은 내용을 다루는 컴포넌트와 띄우는 컴포넌트가 없었기 때문이다.

Chat 컴포넌트는 딱 이 부분만 해당한다.

ChatWrapper는 Slack 스타일링을 차용했고, 이전 포스팅에서 했던대로 gravatar retro 디자인을 가져왔다. 여기에서 우리가 볼 부분은 data 파라미터와 dayjs 부분이다(각각 22행과 20행). Day.js는 날짜 라이브러리인데, 이렇게 주간 다운로드횟수를 보면 무려 572만회이다. 사실 날짜 라이브러리는 대부분 Moment.js를 사용하는데, Day.js는 immutable하면서 Moment.js의 API를 그대로 사용한다. 게다가 다국어도 지원을 하므로 기존의 것과도 호환에 문제가 없다. 최근에 뜨고 있는 라이브러리라고 보면 된다.

data.createdAt은, 데이터가 만들어진 날짜에 해당하는데, 이를 적용하지 않으면 아래와 같이 가독성이 구린 상태로 나타난다. 심지어 KST도 아니라서 국가에 따라 timezone 조정도 필요하다. 그것을 라이브러리가 해주는 것이다.

그 외에 22행에 데이터의 컨텐츠, 그러니까 우리가 ChatBox에 입력한 값이 들어가게 되어 위 사진과 같은 결과물이 완성이 되는 것이다. 이제 이 Chat 컴포넌트를 ChatList 컴포넌트에 연결시킴으로써 채팅창에 우리가 적은 내용이 뜰 수 있게 한다.

4. ChatList 컴포넌트

ChatList는, 우리가 적고 보내는 내용이 뜨는 곳의 컴포넌트이다. 움짤에서 우리가 보냈을 때 gravatar와 함께 뜨는 영역이라고 생각하면 된다. 파라미터는 chatData가 들어가는데, 이 chatData는 IDM이라는, 타입스크립트 사용을 위해 따로 정의해둔 인터페이스를 가져와서 사용했다.

export interface IDM {
  id: number;
  SenderId: number;
  Sender: IUser;
  ReceiverId: number;
  Receiver: IUser;
  content: string;
  createdAt: Date;
}

이렇게 불러온 IDM의 chatData를 map 함수를 통해 파라미터 chat에 대해 id를 키로 가지고 chat을 데이터로 갖는 Chat 컴포넌트를 소환하면 되는 것이다.

'today i learned' 카테고리의 다른 글

today i learned 7/17  (0) 2021.07.17
today i learned 7/16  (0) 2021.07.16
today i learned 7/15  (0) 2021.07.15
today i learned 7/14  (0) 2021.07.14
today i learned 7/13  (0) 2021.07.13
profile

Today Sangmin Learned

@steadily-worked

포스팅이 좋았다면 "좋아요❤️" 또는 "구독👍🏻" 해주세요!