Next.js 서버 컴포넌트에서 mongoose 연결 오류

한호수 (The Lake)·2023년 5월 4일
0
post-thumbnail

Next 13.4.4 버전에서는 mongoose가 server-external-packages.json에 추가되어 serverComponentsExternalPackages 옵션에 명시적으로 추가하지 않아도 적용됩니다. mongoose 7버전 에러도 조치되었습니다.
https://github.com/vercel/next.js/blob/canary/packages/next/src/lib/server-external-packages.json

개요

Next.js 13버전에서 기존 getServerSideProps 메소드를 통해 mongoose를 연결해서 사용하다가 서버 컴포넌트를 사용하게 되면서 발생한 오류입니다.

문제

next.js 에서 서버 컴포넌트가 아닌 getServerSideProps 메소드에서 실행했을때는 정상적으로 실행되었었는데 서버 컴포넌트에서는 오류를 발생시켰습니다. 코드는 아래와 같습니다.

// database/client.ts
import { connect, connection, ConnectOptions } from "mongoose";

const options = {
  useUnifiedTopology: true,
  useNewUrlParser: true,
};

async function dbConnect() {
  if (!connection.readyState) {
    if (!process.env.MONGO_URI) return;
    console.log("Connecting to DB...");
    connect(process.env.MONGO_URI, options as ConnectOptions);
  }
}
export default dbConnect;
// page.tsx
import dbConnect from "@/util/database/client";
import User from "@/util/database/schema/User";

export default async function Home() {
  await dbConnect(); // DB 연결 함수 실행
  await User.find(); // User collection에서 데이터를 모두 가져옴

  return <div>home</div>;
}

ERROR

Module parse failed: The top-level-await experiment is not enabled (set experiments.topLevelAwait: true to enabled it) ... 중략

원인

해당 에러의 원인을 찾기위해 구글링을 했지만 mongoose 7버전에서 발생한 에러라는 결과는 찾았지만 정확한 에러는 찾지 못했습니다. 에러를 보자면 신규 문법인 top level await가 활성화되지 않았다는 에러여서 next.config.js에서 기능을 추가해서 해결하였습니다.

// next.config.js
/** @type {import('next').NextConfig} */
const nextConfig = {
  webpack(config) {
    config.experiments = { ...config.experiments, topLevelAwait: true }; // 추가
    return config;
  },
};
module.exports = nextConfig;

해당 에러는 해결되었지만 다른 에러가 또 발생하였습니다.

Error [TypeError]: Cannot read properties of undefined (reading 'prototype')...

원인은 서버 컴포넌트는 서버에서 동작하게 되는데 next에서 서버측에서 동작할 라이브러리들을 번들링할때 포함되지않아서 발생하는 에러로 생각됩니다.

해결법

해결방법은 nextConfig의 experimental 옵션에 serverComponentsExternalPackages 값을 추가함으로써 해결 할 수 있었습니다.

// next.config.js
/** @type {import('next').NextConfig} */
const nextConfig = {
  experimental: {
    appDir: true,
    serverComponentsExternalPackages: ["mongoose"], // 추가
  },
  webpack(config) {
    config.experiments = { ...config.experiments, topLevelAwait: true };
    return config;
  },
};
module.exports = nextConfig;

serverComponentsExternalPackages 옵션을 사용하면 Next.js의 서버 사이드 렌더링(SSR) 기능을 사용할 때, 서버 측에서 필요한 외부 패키지(라이브러리)를 지정하고 번들링하여 사용하게 됩니다.

Reference

next.js 공식문서
https://beta.nextjs.org/docs/api-reference/next-config#servercomponentsexternalpackages
stackoverflow 질문
https://stackoverflow.com/questions/75697312/import-mongoose-lib-in-api-directory-in-next-js-13-2-app-directory-gives-errorㅈ

profile
항상 근거를 찾는 사람이 되자

0개의 댓글