modulersYJ / ganoverflow-front

2 stars 2 forks source link

feat-chat: `chatMain - 채팅 이어하기` 기능 구현 & `REQUEST` 함수 param & endPoint url 조합처리 수정 #65

Closed ABizCho closed 1 year ago

ABizCho commented 1 year ago

feat-chat: chatMain의 채팅 이어하기 기능 구현

1. 채팅 이어하기 버튼으로 트리거될 onClickContinueChat 핸들러 함수 구현


2. 채팅 이어하기 후, 저장 시 sendChatPost 대신 평가될 putChatPost 요청함수 구현


3. saveChatModal의 input 폼 두개 category, title에 대해 loadChatStatus.loadedMeta에 의해 관리되는 title, category를 defaultValue로 설정


4: Need To Fix : #64

채팅 이어하기 자체의 문제는 없지만, put = 수정 요청 집행 시 포스트 메타데이터가 비어있을 수 있다는 사실을 사용자가 인지하지 못할 수 있기 때문에 bug로 식별하였고, 추후 문제 원인 식별 및 수정 예정입니다.


5. 관련 BackEnd branch & PR : Back - feat-chat: 채팅 이어하기 관련 수정 기능 chatpost - put (by Id) 구현 등




feat: routeModule의 REQUEST함수의 endpoint, params 중복 /해결

기존 REQUEST함수는 const url = params ? ${endPoint}/${params} 모습으로 url을 생성하여 params와 / 중복되는 문제 존재했음 -> endpoint/로 끝났을 경우 제거하고 합성하도록 수정했습니다!

@hongregii 시간나실 떄 확인 한번 부탁드려요~!

vercel[bot] commented 1 year ago

The latest updates on your projects. Learn more about Vercel for Git ↗︎

Name Status Preview Comments Updated (UTC)
ganoverflow ✅ Ready (Inspect) Visit Preview 💬 Add feedback Aug 10, 2023 4:18am
ganoverflow-front ✅ Ready (Inspect) Visit Preview 💬 Add feedback Aug 10, 2023 4:18am
hongregii commented 1 year ago

큰 흐름은 이해했어요. [채팅 이어하기] 누르고 저장 누르면 PUT으로 보내고, 그래서 POST / PUT 요청으로 나누는거까지요! 그런데 그 recoilState 3가지는 좀 더 자세한 설명이 필요할 것 같습니다. 추가로 각 변수의 역할만 알려주세요! 그리고 실제로 수정했을 때 버그가 몇가지 있는것 같아서 그거까지 확인하고 merge하는게 좋을 것 같습니다.

제가 파악한건 PUT으로 요청이 가고 200 / 201을 받은 건 맞는데,

확인해주시고 커멘트 주세요! 수정 어려운 부분 있으면 리팩데이에 같이 하시죠! @ABizCho

ABizCho commented 1 year ago

@hongregii 꼼꼼히 봐주셔서 감사합니다! 🙇‍♂️🙇‍♂️🙇‍♂️


전혀 식별하지 못했던 5. 이어하기 -> 저장 한 다음에 [게시판]에 갔다 [채팅]으로 오니까 [이어하기]버튼만 남아있는 현상 과 같은 문제도 확인해주셔서 수정할 수 있었습니다! ㅋㅋㅋ..ㅠ 어제 좀 급하게 일단 PR 올려놓자는 생각에 이것저것 놓친부분이 많았네요 사전에 더 꼼꼼히 확인할 수 있도록 반성해야겠어요..

어쨌든! 아래에 제안해주신 주제들 인덱싱하여, 각각에 대한 설명 혹은 새 커밋에서의 조치 달아두었어요




1. recoilState 3가지는 좀 더 자세한 설명이 필요할 것 같습니다. 추가로 각 변수의 역할만 알려주세요!

우선 보셔서 아시겠지만, loadChatStatusState는 리코일로 관리되는 전역상태입니다!

크게는 아래와 같이 statusloadedMeta를 관리해요.

type LoadChatStatusStateType = {
  status: TLoadChatStatus;
  loadedMeta?: TLoadedMeta;
};

1. status

보다 용이한 유지보수를 위해, enum으로 세개의 타입을 지정해뒀어요! 사용하는 측에서는 TLoadChatStatus.을 찍어서 어떤 타입이 있는지 확인하고 사용할 수 있으니 보다 용이한 타입결정 & 더 엄밀한 타입검사 가 가능할 것이라고 기대했습니다!

export enum TLoadChatStatus {
  F = "F",
  SHOWING = "SHOWING",
  UPDATING = "UPDATING",
}

각각을 설명드리자면,

  1. F = 사이드바를 통해 특정 Chatpost를 클릭하여 ChatMain에 로드하지 않은 상태 - (default)

  2. SHOWING = 사이드바를 통해 Chatpost를 클릭하여 해당 포스트를 ChatMain에 로드한 상태

    • 즉, 사이드바의 특정 포스트 클릭 시, onClickLoadThisPost 핸들러에 의해 SHOWING으로 변경됩니다.
  3. UPDATING = SHOWING 상태에서 채팅 이어하기를 클릭하여, 채팅 이어하기를 수행중인 상태


loadChatStatusstatus는 주요하게 아래 두 조건부 기준자로 사용됩니다.

  1. 채팅 이어하기 버튼의 조건부 렌더링 기준 ( === TLoadChatStatus.SHOWING)
  2. onClickSaveChatpostExecputChatPost 조건부 요청 기준 ( === TLoadChatStatus.UPDATING)



2. loadedMeta

loadChatStatusloadedMeta는 주요하게 아래와 같은 역할을 위해 관리되어요

  1. UPDATING상태에서 채팅 저장하기 클릭 시, saveChatModal에 불러온 챗포스트의 메타데이터를 기본적으로 넣어주기 위해 로드한 챗포스트의 메타데이터 저장하는 역할
    • ( title, category ) 가 이에 관여합니다.



  1. onClickSaveChatpostExec에서 putChatPost 요청에 필요한 folderId, chatPostId를 유지, 전달
    • ( folderId, chatPostId )가 이에 관여합니다.

따라서, loadChatStatusState.loadedMeta는 아래와 같은 타입으로 정의돼있습니다.

type TLoadedMeta = {
  folderId: number | undefined;
  chatPostId: string | undefined;
  title: string | undefined;
  category: string | undefined;
};



충분히 설명이 되었을지 모르겠네요ㅎ... 추가적인 설명이 필요하신 부분은 또 코멘트로 남겨주세요!

가능한 한 관리포인트를 줄이기 위해 해당 state에 관련된 상태들을 객체로 묶어 관리/활용 하도록 해봤습니다..! 더 세련된 방법이 있을지 다음 오프에서 함께 고민해주시면 감사하겠슴다!



2. [Resolved!] 실제로 새로고침을 하거나 / 사이드바의 다른 채팅으로 갔다 돌아왔을 때에는 추가된 채팅이 안들어가있더라구요!

정말이네요..! title, category만 신경쓰다보니, 가장 중요한 추가된 채팅을 전혀 신경쓰지 못했네요 확인 감사합니다!

이 부분은 백엔드의 chatpost 컨트롤러의 put 함수(=putOneById 함수)에 chatPairs를 갱신하는 로직이 없었던 것이 원인이었네요! 이와 관련한 백엔드 수정사항 커밋을 PR에 추가해두었습니다~! +08.10 : feat-chat: chatpost put 미비한 기능 완성 & chatpost - findOne 정렬 추가



3. [ pending ] 그리고 제목만 수정했을 때 사이드바쪽에 fetch 한번 더 해줘야 할 것 같아요. put 성공해도 그대로입니다. window.location.reload()정도 해줘도 될것 같네요

이 부분은 희안하네요..

gof-put-isFetched


GG요!! -> GG요!!ㅋㅋㅋ 로 수정 image image



분명, fetch로직을 타는것으로 확인했고 정상적인 데이터를 fetch해오는 것 같은데 이상하게 렌더 갱신이 안되네요..! 공부를 위해서라도 중요하게 짚고 넘어가볼 문제인 것 같아 현상 진단 및 공유드릴게요!



현재 put 수행 시 Flow :

  1. 채팅 이어하기 ->
  2. 이름 수정 ->
  3. 저장클릭 ->
  4. PUT 요청 ->
  5. foldersData - case2) fetchFolderData 수행(setFolder수행 포함) ->
  6. Container.tsx의 useDidMountEffect 발동 - 불필요 부수효과



물론 6번의 useDidMountEffect 이하는 불필요한 부수효과이지만, 4번에 의해 5번이 트리거되며 fetchFolderData가 평가되며 아래와 같은 로직이 수행됩니다. 이는, 새로 가져온 폴더데이터에 대한 setFoldersData 수행을 포함합니다.

fetchFolderData의 평가부 일부

  const chatFoldersByUser = await getFoldersByUser(user.id, authData);
  console.log("fetched FolderData! - 요청 후 정합성", chatFoldersByUser);
  setFoldersData(chatFoldersByUser);



위 영상에서도 확인할 수 있다시피, 5번의 fetchFolderDataput으로 옳게 수정한 title을 포함한 updatedFoldersData를 가져온 것을 로그상 확인했습니다.

image

-> flow상으로 진단해보자면, set에 의해 분명 사이드바가 제대로 업데이트되어야겠는데,,, 어째서 갱신되지 않는걸까요?! 기묘하네요...



아래는 진단을 위한 flow 중 핵심 일부 코드블록입니다!

chat/page.tsx

...

  // foldersData - case 2)
  useEffect(() => {
    if (chatSavedStatus === "T" && accessToken) {
      console.log("useEffect foldersData - case 2)");
      fetchFolderData(accessToken, setFoldersData, setAuthData);  // <- 이게 `fetched FolderData! - 요청 후 정합성`로그 찍음
    }
  }, [chatSavedStatus, accessToken]);

...


chat/components/Dnd/Container.tsx

...
    // 첫 마운트 무시 커스텀 훅
    useDidMountEffect(() => {
      if (isFolderUpdated) {
        setIsFolderUpdated(false);
        return;
      }

      const updateFolders = async () => {
        // folder 변경사항(폴더 추가, 제거, 포스트 소속 이동) 서버로 PUT
        const updatedFoldersWithPosts = await putFoldersByUser(
          userData.id,
          foldersData,
          {
            accessToken,
            userId: userData.id,
          }
        );
        console.log(updatedFoldersWithPosts);
        setFoldersData(updatedFoldersWithPosts); // 데이터 정합성을 위한 folder state update
      };

      updateFolders();
      setIsFolderUpdated(true);
    }, [foldersData]);

...



4. [Pending] UX적으로 이어하기 -> 저장 -> [저장 완료] alert 같은거도 필요

이 부분은 분명 필요하겠지만, 우선 사이드바에 파일이 추가되거나, 내용이 수정되는 것으로 대충이나마 확인 가능한 상태라고 생각하여 최우선순위로 두지는 않겠습니다! 다음 PR중에 반영하는것으로 우선 계획해둘게욥 우선순위가 높다고 생각되시면 의견주세요!



5. [Resolved!] 이어하기 -> 저장 한 다음에 [게시판]에 갔다 [채팅]으로 오니까 [이어하기]버튼만 남아있는 현상

해당 문제는

사용자가 사이드바의 챗포스트를 클릭하여 상태로 관리되는 loadChatStatus.statusSHOWING으로 바뀐 후, 헤더 네비게이션 등을 통해 다른 페이지를 다녀 온 이후에도, 해당 상태가 초기화(loadChatStatus.status <= F) 로 초기화시키는 조치가 이뤄지지 않아 발생한 문제였네요!

사실, chat에서 너무 많은 상태를 사용하고 있고, 상태간 어느정도 의존성과 복잡도가 생기다보니 관리 및 추적이 꽤나 난해해진 것으로 느껴지네요.. 이 상태범벅을 어떻게 리팩토링하면 좋을지 오프때 함께 논의해주시면 감사하겠습니다..!

어쨌든 해결책으로 간단하게, Chat 페이지 첫 마운트 시, loadChatStatus를 초기화 하도록 하였고 해결된 것을 확인했습니다!

chat/page.tsx

  useEffect(() => {
    console.log("loadChatStatus 초기화");
    setLoadChatStatus({ status: TLoadChatStatus.F, loadedMeta: undefined });
  }, []);



6. [pending] Still Need to fix : #64


ABizCho commented 1 year ago

@hongregii 홍래님 이슈에서 말씀해주신대로, 우선 위의 코멘트 중 pending상태 중 중요도가 높은 3, 6번에 대한 resolve를 최우선 목표로 해소하고, 이후 머지하는 것으로 생각하겠습니다요

hongregii commented 1 year ago

@ABizCho 네넵! 그럼 이 PR은 close 하고 수정된거로 다시 올려주시면 감사하겠습니다~~

1. [4번]항목에 대해

우선순위에서 밀린 [4번] "수정완료 alert"는요, 디버깅에도 유용할거 같아서 일단 PUT요청에서 201 응답 받거나 해당 함수 끝났을때 alert만 띄워주는 식으로 (일단은) 가시는게 어떨까요? 왜냐면 제가 수정하고 저장 눌렀을때 이게 요청이 간건 맞는지 그거부터 확인하느라.. 네트워크 까보고 그랬거든요 ㅋㅋㅋ

이게 Recoil 쓰면서 로직이 워낙 복잡해져서.. 완벽히 잡는데까지는 쫌 걸릴거같은데, 다음 수정 PR때 alert 한줄만 추가해주셨으면 합니다! (어디까지나 임시고, 구현 완료 되면 또 고민해보시죠!)

2. 깃헙에서 files changed 만 보고 파악하는게 어렵네요...ㅋㅋㅋ 전에 이렇게 봐주신 성우님께 감사를

아 그리고 코드 안에서 큰 흐름만 주석으로 설명해주시면 좋을거같아요~~ 이게 기능/로직이 워낙 까다로워서 PR상에서 파일명만 보고 무슨 컴포넌트에서 무슨 로직이 작동되고 있구나~ 를 파악하기가 쫌 어려웠네요! 결국 제 로컬에서 feat-chat 브랜치를 땡겨와서 켜보고 쫌 파악했습니다 (ㅋㅋㅋ)

그 간단한 기능 (걍 저장 / dark 모드) 같은거는 바로바로 이해가 되는데 이번거 같은거는 변경점이 많아서 따라가기가 어려웠네요!

3. type enum 사용한다거나 하는 다른 부분은 다 좋습니다!

ABizCho commented 1 year ago

@hongregii 넵 확인 감사합니다~ 그럼 해당 PR은 닫아두고 추후 PR에 이 PR참조걸어둘게요~!

  1. alert : 말씀하신대로 네트워크 까보는게 너무 익숙해져서 더 간단한 방법을 그냥 생각안하게됐었네요ㅋㅋ 추후 PR에 간단한 alert 달아둘게요!

  2. 넵! 확실히 chat이 좀 비대해져서 주석 없이는 이해하시기 어려웠을 것 같아요.ㅋㄱㅋㄱ 까서 봐주셔서 감사합니다..! 담부터 굵직한 로직에는 주석 달아두겠습니다!