본문 바로가기

프론트엔드

Vercel log를 통해 Next.js 500 error 원인 분석하기

  • 프로젝트: 채식 지도(가명)
  • 키워드: Next.js, vercel, logging, realtime log, firebase
  • 상황
    1. mock으로 개발 중이었던 유저 피드백 데이터를 firestore에 저장된 실제 데이터로 교체하고자한다.
    2. 먼저 firebase를 package.json에 추가하고, firebase initialize 파일을 작성한다.
        // firebase/index.ts
      import { initializeApp } from '@firebase/app';
      import { getFirestore } from '@firebase/firestore';
      
      initializeApp({
        apiKey: process.env.NEXT_PUBLIC_FIREBASE_API_KEY,
        authDomain: process.env.NEXT_PUBLIC_FIREBASE_AUTH_DOMAIN,
        databaseURL: process.env.NEXT_PUBLIC_FIREBASE_DATABASE_URL,
        projectId: process.env.NEXT_PUBLIC_FIREBASE_PROJECT_ID,
        storageBucket: process.env.NEXT_PUBLIC_FIREBASE_STORAGE_BUCKET,
        messagingSenderId: process.env.NEXT_PUBLIC_FIREBASE_MESSAGING_SENDER_ID,
        appId: process.env.NEXT_PUBLIC_FIREBASE_APP_ID,
      });
      
      export const firestore = getFirestore();
    3. 그 후 Next.js의 getServerSideProps에서 firestore의 feedback 데이터를 불러와 pre-render한다.
        // firebase/feedback.ts
      import { addDoc, collection, getDocs, limit, orderBy, query } from 'firebase/firestore';
      import { firestore } from '@/firebase/index';
      import { Feedback } from '@TS/feedback';
      
      export const feedbackListCollection = collection(firestore, 'feedbackList');
      
      export async function getFeedbackListFromFirestore(): Promise<Feedback[]> {
        const initialFeedbackList: Feedback[] = [];
      
        const querySnapshot = await getDocs(
          query(feedbackListCollection, orderBy('timestamp', 'desc'), limit(SOME_MAGIC_NUMBER)),
        );
        querySnapshot.forEach((doc) => {
          initialFeedbackList.push(doc.data() as Feedback);
        });
      
        return initialFeedbackList;
      }
      
      // pages/feedback.tsx
      ...
      export const getServerSideProps: GetServerSideProps = async () => {
        return {
          props: {
            initialFeedbackList: await getFeedbackListFromFirestore(),
          },
        };
      };
    4. localhost에서 피드백 페이지가 잘 렌더링 되는 것과 next build가 되는 것까지 확인한다.
      firestore 데이터가 표시됨
      next build가 성공함
    5. 실제 vercel 배포 후 preview test 웹사이트에서 확인해보니 500 에러가 발생한다.
      500 에러
  • 해결 과정
    1. 개발자 도구를 열어보니 의미를 알 수 없는 에러밖에 확인할 수 없었다. (Failed to load resource: the server responded with a status of 500 ())
      하지만 500에러 인것으로 보아 getServerSideProps 도중에 오류가 나 pre-render에 실패한 것이라고 추측은 가능했다.
    2. firebase에서 원인을 알 수 없는 오류가 난 것으로 보고, getFeedbackListFromFirestore 함수에 try/catch문을 감싸보았지만 문제는 여전했다.
    3. 로컬 환경과 빌드는 둘 다 정상적이고, 배포 후에만 오류가 나는 것이라 디버깅할 방법이 막막하여 구글링을 해보았다. 꽤나 많은 글을 뒤져보아도 답이 안나오던 와중 한 레딧을 발견했다.
      https://www.reddit.com/r/nextjs/comments/j4i5c1/500_internal_server_error_on_vercel_deploy_how_to/
      You can view your error logs by going to your Vercel dashboard, clicking on your project, and then clicking "View Function Logs". This will show errors happening in realtime.
    4. vercel 사이트에서 'functions'라는 탭에 들어간 후, 에러 로그를 확인할 수 있었다.
      overview 옆 functions 탭
      error log

      그 후 해당 에러를 Next.js 커뮤니티에서 발견하였다. https://github.com/vercel/next.js/issues/32527

    5. 이슈에서 해결한 방법대로 firebase를 downgrade하니 문제가 쉽게 해결되었다!
        "firebase": "9.4.0"​


  • 의의
    1. 버그의 원인을 추적하는 과정에서 에러 처리와 로깅의 중요성을 다시금 깨달았다.