Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[feat/CK-187] Error-Boundary를 활용한 에러핸들링(초안) #148

Merged
merged 15 commits into from
Sep 14, 2023

Conversation

NaveOWO
Copy link
Collaborator

@NaveOWO NaveOWO commented Sep 12, 2023

📌 작업 이슈 번호

CK-187

✨ 작업 내용

에러 핸들링을 위한 ErrorBoundary를 만들었습니다. 선언적으로 에러를 처리하기 위해 에러의 종류별로 에러바운더리를 따로 만들어줬어요.

  • NotFoundErrorBoundary : 404에러가 났을 때 해당 fallback을 띄워줍니다
  • ServerErrorBoundary : 500번대 에러가 났을 때 해당 fallback을 띄워줍니다
  • RuntimeErrorBoundayr : api에러가 아닌 런타임 에러가 났을 때 해당 fallback을 띄워줍니다
  • CriticalErrorBoundary : 이 전에 잡히지 않은 모든에러 (서버 터져서 응답이 아예 안올 때, 네트워크 에러, 오프라인 등)를 처리합니다.

위의 모든 ErrorBoundary는 AsyncBoundary에 Suspense와 함께 묶여있어요. 해당 에러가 아니면 상위 컴포넌트로 error를 계속 throw해줍니다.

  • 401에러는 애초에 인터셉터에서처리가 돼서 따로 처리하지 않았어요.
  • 403에러는 우리 서비스에서 날 일이 없어요. (로그인이 필요한 페이지는 애초에 접근이 안됨 + get에서는 로그인 한 사람만 볼 수 있는 데이터가 없어요!!)그래서 일단 따로처리하지 않고, 403에러는 런타임에러로 취급합니다.
  • 400번대 에러는 서버에서 아주 친절하게 에러메세지를 보내주고있어서 해당 메세지를 alert처리했습니다. (queryClinet에서 전역으로)
2023-09-13.3.55.56.mov
2023-09-13.3.56.29.mov

💬 리뷰어에게 남길 멘트

에러 핸들링을 위한 초석을 다진 코드라서 많이 부족해요..!! 일단 사용자 피드백을 위해 서비스가 돌아갈 정도로 코드를 짜놓았는데, 담주 내로 고도화 시켜보겠습니다앗
😭부족한부분😭

  • ErrorBoundary의 props와 state의 타입이 any입니다. 단순히 프롭을 옵셔널로 받는게 아니라 상황에 따라 각기 다른 타입을 선언해줘야해서 타입 선언은 조금 미뤄놓았어요..!
  • 에러의 리셋로직이 죽어도 안먹혀서 reload처리 했습니다.. 현재는 에러가 처리되었을 때 딱히 상태를 유지해야하는 부분이 없어서 그냥 뒀는데 이것도 수정하겠습니닷
  • fallback컴포넌트가 단순히 메인페이지로 이동하게 되어있는데 이것도 동적으로 바꿔볼 수 있을 것 같아요.
  • get로직이랑 mutate로직을 나눠서 에러 핸들링을 해야할 것 같은데 지금은 한꺼번에 되어있어요
  • 필요한 곳마다 일일히 asyncBoundary를 감싸줘야하는데 지금은 일단 app을 감싸고 있어요

이밖에도 부족해보이는 부분 말씀해주시면 반영해보겠습니다앙

🚀 요구사항 분석

@NaveOWO NaveOWO changed the title Feature/ck 187 [feat/CK-187] Error-Boundary를 활용한 에러핸들링(초안) Sep 13, 2023
@NaveOWO NaveOWO requested review from jw-r and sh981013s September 13, 2023 06:44
@NaveOWO NaveOWO self-assigned this Sep 13, 2023
@NaveOWO NaveOWO added feature 🔅 Improvements or additions to documentation FE 👨‍👨‍👧 FrontEnd labels Sep 13, 2023
Copy link
Collaborator

@sh981013s sh981013s left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

크으으.. 진짜 난이도 빡셌겠네요!! 넘 고생하셨고 몇가지 부분만 확인 부탁드려요!

pr 메세지에 남긴 적용해야 할 개선사항들은 다음 스프린트에 해봅시다!

<RuntimeErrorBoundary>
<ServerErrorBoundary>
<NotFoundErrorBoundary>
<Suspense fallback={<Spinner />}>{children}</Suspense>
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

이렇게 되면, Suspense 가 전체 라우터를 감싸는 것 같은디 어느 하나 로딩 상태가 걸리면 전체 화면에 항상 스피너가 돌지는 않았나여? 😀

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

맞아요오..!!! 이 AsyncBoundary를 필요한 곳에 부분적으로 감싸줘야하는데 아직 완성이 되지 않아서 일단 app 전체를 감싸줬어요!


const moveMainPage = () => {
navigate('/');
window.location.reload();
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

😅 ㅋㅋㅋㅋㅋㅋㅋㅋ

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

..ㅎㅎ 수정하겠습니다아

Comment on lines +25 to +28
const moveMainPage = () => {
navigate('/');
window.location.reload();
};
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

중복되는 것 같은디 훅으로 빼봐도 좋을 듯 싶네요!

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

앗 어차피 저 reload부분이 리셋로직으로 대체될꺼라서 임시방편으로 그냥 뒀는데요..!! 훅이 필요할까요!?

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

앗 그걸 몰랐네요! 일단 다음에 바로 수정하죠!

Comment on lines +47 to +50
<S.Container>
<S.ElephantImage src={elephantImage} alt='crying-elephant' />
<S.RuntimeTitle>Error</S.RuntimeTitle>
<S.RuntimeText>
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

마크업 계층구조도 반복되는 느낌이 드는데, HOC 와 같은 방식을 추후에 적용해보든건 어떨까여??

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

호호~ 좋은 생각이에요 고려해보겠습니다!!


if (hasError && error) {
return <ErrorBoundaryFallback errorMessage={error.message} />;
// eslint-disable-next-line react/no-unused-class-component-methods
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

eslint config 파일에서 처리하는건 어떨까요??

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

네엡 없앨께욧!

return <ErrorBoundaryFallback errorMessage={error.message} />;
// eslint-disable-next-line react/no-unused-class-component-methods
resetError = () => {
// eslint-disable-next-line react/destructuring-assignment
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

eslint config 파일에서 처리하는건 어떨까요??

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

넵!!


class ServerErrorBoundary extends ErrorBoundary {
componentDidCatch(error: any, _errorInfo: ErrorInfo): void {
const status = /5\d{2}/;
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

regex 모아둔곳으로 빼는건 어떨까요??

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

아핫 넵!!

onError: (e) => {
const error = e as any;
if (error.response.status === 400) {
alert(error.response.data.message);
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

alert 말고 다른 방식은 없을까요??!

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

토스트로 바꿔볼께요~!!

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

엉 이거 토스트로 변경하려구 했는데, 애초에 우리가 만들어둔 토스트 자체가 ToastProvider 안에서만 쓸 수 있는데 이 queryClient는 그 밖에서 선언되고있어서 이 계층에서 토스트 사용은 불가능하더라구요..!! 일단 alert로 두고 토스트를 사용할 방법을 고민해볼께요

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

오오.. 맞네요 진짜! 고민해보죠!!

Copy link
Collaborator

@jw-r jw-r left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

네이브 어려운 부분이었는데 정말 고생하셨어요!

부엉이가 이미 잘 달아주셔서 제 리뷰는 코맨트만 확인해주시면 될 것 같아요🤩

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

넘 좋네요!

부엉이 말대로 중복만 조금 제거해주면 더 좋을 것 같아요🤩

import ErrorBoundary from './ErrorBoundary';

class CriticalErrorBoundary extends ErrorBoundary {
componentDidCatch(_error: any, _errorInfo: ErrorInfo): void {}
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

매개변수명이 _error인 이유가 있을까요?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

사용하지 않는 매개변수때문에 린트가 징징대서 _를 넣어줬어요..!! 추후에 에러 처리 로직이 들어가야하는 부분이라서요!!

import ErrorBoundary from './ErrorBoundary';

class RuntimeErrorBoundary extends ErrorBoundary {
componentDidCatch(_error: any, _errorInfo: ErrorInfo): void {}
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

없어도 무방한 라인이라는 생각이 들어요🤩

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

저도그래요! 지워보겠습니다~!

@sh981013s sh981013s self-requested a review September 14, 2023 13:00
Copy link
Collaborator

@sh981013s sh981013s left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

고생하셨으요~~

@sh981013s sh981013s merged commit d00b3e4 into develop-client Sep 14, 2023
@sh981013s sh981013s deleted the feature/CK-187 branch September 14, 2023 13:01
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
FE 👨‍👨‍👧 FrontEnd feature 🔅 Improvements or additions to documentation
Projects
Status: Done
Development

Successfully merging this pull request may close these issues.

4 participants