[next.js, react] 크로스 브라우징 이슈 해결 (feat. ErrorBoundary, polyfill)

·2023년 6월 11일
2

개발 기록

목록 보기
55/68

청첩장 고객님께 문의가 들어왔다. 일부 지인들의 핸드폰에서는 청첩장이 뜨지 않는다는 것이다.

그러면서 화면을 캡처해서 보여주셨는데 이런 문구가 있었다. Next.js에서 띄운 메시지인데 클라이언트 측 오류로 브라우저 콘솔을 확인하라는 것이다. 하지만 모바일에서는 브라우저 콘솔을 확인할 수 없다.

일부 지인의 핸드폰에서 발생한다고 하니 크로스 브라우징 문제 같은데 에러 메시지도 확인할 수 없고 해당 문제가 발생하는 핸드폰 기종도 가지고 있지 않았다.

그러다 아이폰 크로스 브라우징을 체크할 수 있는 사이트를 알게되서 해당 오류를 재현해 볼 수 있었다.

다음으로 뭐 때문에 크로스 브라우징이 되지 않는지 찾아야 했다. 어떻게 하나 하고 있었는데 ErrorBoundary 개념을 알게 되었다. React 16에서 도입된 ErrorBoundary는 하위 컴포넌트에서 발생한 에러를 캐치해 처리할 수 있다.

당장 문제를 해결해야 해서 목적은 에러 메시지를 고객님의 핸드폰 화면에 띄우는 것이었다.

import React, { ErrorInfo } from 'react';

interface ErrorState {
  error: Error | null;
  errorInfo: ErrorInfo | null;
}

class ErrorBoundary extends React.Component<any, ErrorState> {
  constructor(props: any) {
    super(props);

    // Define a state variable to track whether is an error or not
    this.state = { error: null, errorInfo: null };
  }

  componentDidCatch(error: Error, errorInfo: ErrorInfo) {
    // You can use your own error logging service here
    this.setState({
      error: error,
      errorInfo: errorInfo,
    } as ErrorState);
  }
  render() {
    // Check if the error is thrown
    if (this.state.error) {
      // You can render any custom fallback UI
      return (
        <div>
          <section>
            <h2>React Component Error!</h2>
            <aside>
              <p>{this.state.error && this.state.error.toString()}</p>
            </aside>
            <aside>
              <p>
                {this.state.errorInfo && this.state.errorInfo.componentStack}
              </p>
            </aside>
          </section>
        </div>
      );
    }

    // Return children components in case of no error

    return this.props.children;
  }
}

export default ErrorBoundary;

(코드 출처가 기억나지 않는다...)

componentDidCatch 메서드는 아직 함수형 컴포넌트에서는 사용할 수 없어서 클래스 컴포넌트로 선언해야 한다. 이렇게 컴포넌트를 선언하고

//_app.tsx

    <ErrorBoundary>
		...다른 컴포넌트
    </ErrorBoundary>

최상위에 감싸줬다.

이렇게 처리하고 고객님께 다시 캡처를 부탁드렸다.

에러 메시지를 확인할 수 있었다! 읽어보니 배열 메서드 at이 없어서 난 문제여서 폴리필을 추가해서 문제를 해결했다.

import 'core-js/es/array/at';

정말 해결?

create-next-app으로 프로젝트를 시작했기 때문에 배열 메서드가 트랜스 파일링이 안 되는 것이 이상하다고 생각했다. 찾아보니 Next.js가 사용하는 SWC에서 트랜스 파일링도 하고있다고 한다. 그래서 생각된 원인이 SWC에서 트랜스 파일링을 한다는 것을 모르고 sass를 사용하려고 바벨을 설정했었는데 그러면서 두 가지를 동시에 사용해서 에러가 발생하지 않았을까라고 가설세웠다. 이 가설이 맞다면 현재 방법은 정확한 해결법은 아닐 것이다. 현재 에디터를 개발 중이고 당장의 문제는 해결이 되었기 때문에 우선순위에 밀려 이 가설을 빨리 확인해보지 못한게 아쉽지만, 잊지 않기 위해 여기에 적어뒀다.

(내용 추가)
Next.js - SWC disabled
다른 이슈 해결하다 보게 된 내용인데 공식 문서에서 .babelrc을 사용하면 SWC가 동작하지 않는다고 한다. 아래의 sass 바벨 설정을 다른 방법으로 수정할 수 있는지를 확인하는 게 우선적으로 필요한 것 같다.

//.babelrc
{
  "presets": [
    [
      "next/babel",
      {
        "styled-jsx": {
          "plugins": ["@styled-jsx/plugin-sass"]
        }
      }
    ]
  ]
}

Sentry 도입

이런 상황에 사용할 수 있는 도구가 있다는 것을 알게 되었다. 얼마 안남은 에디터 개발까지 하고 나면 Sentry를 도입해서 에러 로그를 받을 수 있도록 해야겠다.
Sentry로 우아하게 프론트엔드 에러 추적하기

0개의 댓글