디버깅할 때 어떻게 해야하나?

YEONGHUN KO·2024년 2월 24일
0

ETC

목록 보기
30/31
post-thumbnail

funChat앱의 테스트 코드를 작성하면서 undefined 문제로 디버깅을 해보았다.

해보면서 깨달은것은. 디버깅도 주먹구구식으로 무작정하지 말고 나만의 디버깅 방법을 정리해서 체계적으로 디버깅을 해보자는 생각이 들었다.

그래서 나름대로 디버깅 방법을 정리해본다.

1. 손수 거슬러올라가보면서 로그 찍어보고 현재 상태를 글로 적어보기.

대시보드에서 메시지 인풋에 메시지를 적고 submit버튼을 눌러 메시지가 잘 전송되고 보낸 메시지가 ChatContainer에 잘 쌓이는지 테스트하려고 했다.

근데 보낸 메시지가 쌓였다면 Container에 표시되어 findByText로 찾을 수 있어야 하는데 에러가 났다.

Uncaught TypeError: Cannot destructure property length of 'undefined'

보니깐 useAddTextMessageQuery 안에 있는 previouseMessages가 undefined라는 뜻이다.

참고 코드

///Applications/chat-app-client/src/hooks/useQueryAccount.ts/mutaion/onMutate 
const queryKeysWithChatUser = queryKeys.messages(
  userInfo?.id as number,
  currentChatUser?.id as number,
);

 let previouseMessages = queryClient.getQueryData(
    queryKeysWithChatUser,
 ) as [string, IMessage[]][];

if (previouseMessages.length <= 0) { // ==> 요기에 벌레가 숨어있다.
  previouseMessages.push([newDate, [newMessageFormat]]);
} else {
  const lastDateGroup = previouseMessages[previouseMessages.length - 1];
  const lastDate = lastDateGroup[0];
  const lastDateGroupMessages = lastDateGroup[1];

  if (newDate === lastDate) {
    lastDateGroupMessages.push(newMessageFormat);
  } else {
    previouseMessages.push([newDate, [newMessageFormat]]);
  }
}

자 그럼 여기서 어떻게 디버깅 하느냐??

하나하나 거슬러 올라가면 된다. 나름대로 디버깅 callStack을 만들어보자

6. queryClient.getQueryData(
  queryKeysWithChatUser,
)
5. previouseMessages
4. onMutate
3. useAddTextMessageQuery
2. addTextMessage
1. handleSendMessage

queryKeysWithChatUser 쿼리키로 api가 호출되거나 캐시세팅이 된적이 없다는 뜻.

그래서 쿼리를 콘솔 로그로 찍어보았다.

==> queryKeysWithChatUser in useAddTextMessageQuery [ 'messages', 3, undefined ]

오잉?! currentChatUser?.id가 undefined라는 뜻. 다행히도 간단하게 해결가능한 버그이다.

const currentChatUser = useStore(
  useLocalStorage,
  (state: ILocalStorage) => state.currentChatUser,
);

근데 테스트코드가 아닌 실제 개발환경에서는 문제없이 작동한다.

즉, 테스트 코드안에서 컴포넌트를 랜더링하는 과정에서 어떤 컴포넌트가 랜더링이 안되었거나 , 아니면 모킹이 안되었다는 판단을 했다.

결론부터 얘기하면, useStore에서 id가 나오도록 모킹하지 않았다. 모킹을 완료하니 잘된다!

그리고 글로 적어보는 과정에서 갑자기 버그가 명확해질 수 있다.

왜냐면 문제를 그림이나, 도표, 글로 시각화하면 상황을 더 명확하게 바라볼 수 있게 되기 때문.

위에 정리한 것 처럼 코드나 글을 통해 문제의 상태를 명확히 하는 것!

2. vscode breaking point 활용

vscode에서 리액트앱에 breaking point를 걸어 개발자 도구 처럼 call stack을 하나한 거스르면서 변수값을 확인하는 방법이 있다.

vscode 디버깅방법 참고

3. 완전히 백지인 test환경을 따로 만들어 거기서 테스트하기

Test.tsx를 만들고 거기에 딱 문제의 컴포넌트 또는 훅만 추가해 고립테스트를 실제 진행하는 방식이다.

react-query suspense와 react Suspense가 제대로 작동을 하지 않아 이 방법으로 해결했던 경험이 있다.

4. vscode의 "jest" extension이용

jest extension을 설치하면 .test.ts 안에서 초록색 재생 버튼이 활성화 된다. 여기에서 오른쪽 마우스를 클릭하면 debug test가 나온다.

테스트에 랜더링되는 컴포넌트안에서 break point를 걸어두고 debug test를 하면 2번처럼 call stack이 쌓이는 과정을 일일이 눈으로 확인가능하다.

이때 mocking 한 함수나 모듈을 볼 수 있다는 점에서 2번과 차이가 있다.

그럼 어떤 방법을 언제 사용해야하느냐??

1번 방법

대부분 이경우로 해결이 되는 것 같다. 고전적인 방법이지만 빠르고 쉽게 확인이 가능해서 그렇다.

2번 방법

수백개의 데이터를 사용하다가 버그가 나면 2번을 추천.
map처럼 여러개의 데이터를 반복적으로 looping과정에서 발생한 버그라면 요 방법이 낫다고 생각.

3번 방법

컴포넌트와 훅이 긴밀하게 연결되어있고 컴포넌트와 훅을 동시에 테스트해야하는 경우.

4번 방법

테스트 코드를 돌아가는 과정에서 디버깅이 가능하다.
아니면, 내가 디버깅을 한다고 했을때, 버그와 관계없는 함수나 모듈은 모두 모킹하고,버그와 관련이 있는 함수와 모듈만 남겨두어 테스트를 하고 싶을때도 사용가능한 방법인거 같다.

profile
'과연 이게 최선일까?' 끊임없이 생각하기

0개의 댓글