[sw정글 16주차]<나만무> 생각보다 삐그덕거린 DM제작

Date:     Updated:

카테고리:

태그:

📨DM

🚀interface vs type

다이렉트 메시지 관련 코드를 보며 아래와 같은 코드들을 보게되었다.

// chat state
export interface ChattingDto {
  room_id: number;
  type: RoomType | undefined;
  identifier: string;
  room_name: string;
  participant: Array<UserResponseDto>;
  chatting: Array<ChattingResponseDto>;
  last_read_chat_id: number;
}

// 현재 채팅방의 정보를 바꿀 때 요청
export interface ChangeChattingRoomDto {
  room_id?: number;
  room_name?: string;
  participant?: Array<UserResponseDto>;
  last_read_chat_id?: number;
}

// 서버에서 채팅방 리스트에 대한 정보를 받아올 때
export interface RoomListResponse {
  room_id: number;
  type: RoomType;
  identifier: string;
  room_name: string;
  participant: Array<number>;
  last_chat: string;
  not_read_chat: number;
  last_read_chat_id: number;
  updatedAt: Date;
}

‘interface는 어떻게 쓰는거지…?’라는 의문이 들었다. ‘아니 그런데.. 타입이 이미 있잖아..!!’라는 생각도 들었다. react와 타입스크립트를 3일만에 끝내고 프로젝트를 하려고 하니 기초적인 부분을 정말 모르고 있구나라는 생각에 고뇌에 빠졌다.

너무 기초없이 코드를 짜고있나?라는 생각을 했지만, 이 또한 기초를 쌓는 과정이라고 생각하자 마음이 편해졌다.

첫번째 차이점,

InterfaceType은 거의 유사한 특징을 가지고 있었다. 하지만 Interface는 같은 이름으로도 확장이 가능하다는 점이 달랐다.(선언적확장이라고 하는데 누가 이런식으로 이름을 지었는지는 모르겠다. Docs에서 뒤적여 보니 declaration-merging 이라고 하는 것 같다. Interface는 똑같은 이름으로 확장이 가능하다는 차이가 있는 것 같다.) 같은 Interface이름으로 명식적으로(declaration) 합쳐나가니까(merging) 선언적 확장이라는 어려워보이는 말이 붙게된 것 같다.

두번째 차이점,

Type은 Computed Value를 사용할 수 있다는 것이다.

[key in names]: string

뭐 이런 것들을 Type안에서는 쓸 수 있지만, Interface안에서는 쓸 수 없다는 차이가 있다는 것이다.

결론적으로, 우리 프로젝트 규모에서 메세징 프로토콜에서의 Type을 확장해서 쓸일도 없고, (사실 선언적 확장이 어떤 상황에서 쓰이는지 잘 모르겠다) 몇몇글들에서 성능을 위해 Inteface를 쓰는것이 더 좋다고 하지만, 좀 더 찾아본 결과 요새는 개선되었기 때문에 차이가 없는 것 같다.(Docs에는 반영이 안되어있다고 한다)

따라서, 우리 프로젝트는 Type을 사용하던 Interface를 사용하던 상관이 없을 것 같았고, 교보재가 있는 Interface를 사용하여 그 작동모습을 확인하는 것이 단기적 목표로 더 적절해 보였다.

📨DM설계

다시 DM설계로 돌아왔다. 어떤 정보를 넘겨주고 받아야 하는지 머리가 아팠다. 좋은 교보재가 있었지만, 우리 프로젝트와는 조금 다른점들이 있었다. 예를들면, 우리는 1:1채팅만 관리할 터인데, 그룹 채팅방을 만든다던지, 상대의 프로필 이미지르 지속적으로 채팅방에 띄워준다던지 등 우리의 프로젝트와는 조금 맞지 않는 부분이 있었다. 게다가… redux-saga를 사용해서 값들을 받아왔다. 필요하면 react-query를 사용할 예정이였고, 불필요하게 러닝커브가 큰 react-saga를 도입할 필요가 없어보였다.

교보재의 코드는 axios로 api를 짜고, saga로 땡겨오고, 그리고 이를 store에 저장하는 것으로 보였다. 그런데 리액트 쿼리를 사용하면, axios로 땡겨온 api를 바로 store에 넣을 수 있을 것 같았다. 따라서 redux-saga는 사용하지 않기로 하였다. 저번주에 store에서 fetch로 정보를 가져와서 업데이트하려고 했을때, pure 함수, 즉 순수함수가 아니라는 오류를 보았던 것 같다. 그 때, 미들웨어가 완충재 역할을 해주는 ‘느낌’이였는데, redux-saga가 그러한 역할을 해주는 것으로 보였다. 저번주의 공부가 오늘 공부의 이해를 가능하게 도와준 느낌이다.

redux

사진출처 : (https://yamoo9.github.io/)

(저번주에 고생했던 내용: 위 그림에서, 리듀서에 비동기적 함수를 집어넣으면 순수함수를 넣어달라고 에러를 띄운다)

하지만, store에서 데이터를 가져오는게 아니라면, 다음과 같은 방법을 쓸 수 있는것으로 보였다.

  1. useEffect로 걸어서 sotre에 업데이트 시킨다.
  2. 미들웨어(saga, thunk)를 사용한다.
  3. react-query로 가져온다.

일단 useEffect로 axios를 이용하여 서버의 데이터를 가져오고, 필요한 정보들은 store에 저장해서 사용할 수 있는 상태를 1차목표로 삼고 달렸다. 리서치 결과 saga는 쓸일이 없다고 판단되었기 때문이다.

📨DM구현

4일로 예상했던 DM이 벌써, 6일째 시간을 잡아먹고 있다. 서버-클라의 변수명이 맞지 않아서, 서버-클라가 필요한 정보에 대해 이해하고 있는 부분이 달라서 불필요한 디버깅을 하게 되었다. 수연누나의 말마따나, 서버와 클라를 간단히 만질 수 있다면 한명이 하나의 기능을 도맡아서 서버-클라를 오가며 작성하는게 더 효율적이었을 것 같다. 구현방법에 대해 의견이 맞지 않아 +3일을 더 사용하게 되었다. DM의 시작부터 완성까지 약 9일정도의 시간을 투입하게 되었다. 생각보다 길어지는 구현 기간이 압박으로 다가왔던 것 같다.

최종적으로, 채팅리스트를 불러올 때는 다음과 같은 interface를 사용하게 되었다. 이부분이 얼마나 자주 손이 갔냐면…

export interface RoomListResponse {  //중선커밋
  _id?: string;                   //수연커밋
  myInfo: UserResponseDto;        //희산커밋
  friendInfo: UserResponseDto;    //희산커밋
  message: string;                //희산커밋  
  status: IChatRoomStatus;        //희산커밋
  roomId: string;                 //기운커밋
  unreadCount?: number;           //송이커밋
  updatedAt: Date | null;         //희산커밋
}                                   //중선커밋

깃렌즈로 찍어본 결과, 하나의 인터페이스의 라인커밋 주인이 전부 다 다르다😅. 모두가 필요하고 생각한 정보가 달랐기에, 불편함을 느껴서 너도나도 inteface를 수정한 것이다. 한편으로는 (팀장 입장에서)팀원들 전원이 서버와 클라를 오가며 고통스러워 하는 모습을 보며 뿌듯하기도 했다.

물론 불필요한 의사소통비용으로 프로젝트 진행이 늦어지는건 괴로웠지만, 팀원들 전원이 클라와 서버에 대해 이해를 할 수 있는 좋은 기회였던 것 같다.

“야… 서버 제대로 짰어?? 내가 본다??”

“클라 확실히 받고 있는거야?? 난 제대로 짰는데…!!”

🚀react-query 찍먹

DM이 어느정도 잘 받아와 지자 react-query로 코드를 바꾸어 봤다. 간단한 코드 몇줄을 수정하자, 서버에 계속 polling을 하며 데이터를 실시간으로 받아오는 모습을 볼 수 있었다. 하지만 서버에 부하가 갈것을 고려해, 코드를 다시 원복시켰다. 기운이형이, 추후 socket으로 서버에서 직접 메시지를 보내주는 좋은방법을 떠올렸기에 react-query도 다시 넣어주었다. 로직상 문제가 없어보였기에, socket을 잘 사용함으로써 react-query를 굳이 사용하지 않고도 실시간 업데이트를 잘 만들어 낼 수 있을 것 같았다.

📨DM꾸미기

채팅룸이 잘 작동하자 송이누나에게 채팅방 내부를 잘 짜달라는 부탁을 했다. figma로 친구메시지와 나의메시지의 화면표시 분리, 채팅블럭 등의 코드와 디자인 등 큰 틀을 짜서 넘겼다.

image

하지만 react-chat-ui라는 좋은 라이브러리를 찾아왔다.

image

채팅길이에 따라 채팅 블럭의 크기를 유동적으로 가져가는 코드를 짜는게 귀찮을 것이라고 생각했는데, 적절한 라이브러리를 잘 찾아와 주었다. 따라서 다음과 같이 깔끔한 UI를 만들어 낼 수 있었다.

chat

🚀마무리발표

마무리 발표를 끝마쳤다. 친구 추가, 프로필 설정, 미디어 스트림 제어 등등 부가적인 기능을 추가해서 마무리발표까지 마쳤다. 기술적으로 부족하다는 피드백보다는, 발표 방법에 대한 피드백을 들을 수 있었다. 부정적인 피드백들이였지만, 한편으로는 발표 시나리오에 대해서 조금만 신경 쓴다면, 좋은 결과가 있을 것이라는 뜻으로 해석되었다.

이제 1주일 남았다. 1주일 뒤면 모든것이 끝난다. 멘토님과의 회의 결과, docker를 이용한 포트 분리, 결제, DM고도화, 알림 등을 만들어 보면 좋을 것 같다는 피드백을 주셨다. 원래 계획이였던, 모바일을 포기하면 훨씬 많은 것들을 만들 수 있으리라 생각이 들었다. 일단 당면해 있는 버그들을 잡고, 팀원들이 도전해 보고 싶은 기능들을 만들어 보면 좋지 않을까 싶다.



😵배우면서 깨달은 내용을 정리해 보았습니다. 틀린 것 같은 개념을 아래 댓글에 달아주시면 감사합니다😵

🌜 Thank you for reading it. Please leave your comments below😄

맨 위로 이동하기

swjungle survive 카테고리 내 다른 글 보러가기

댓글 남기기