Schema hasn't been registered for model 문제 해결하기 Thumbnail

mongodb populate 문제

5 min read
문제해결기능추가

Schema hasn't been registered for model 문제 해결하기

문제

Schema hasn't been registered for model \"Post\".\nUse mongoose.model(name, schema)

이번에 시리즈 디테일 페이지를 개발하면서 생긴 문제의 에러 메시지이다.

문제 코드

현재 블로그의 시리즈에서 시리즈 디테일 페이지(/series/블로그-개발기)로 이동할 경우 시리즈의 디테일과 속한 포스트 목록을 보여주는 페이지가 나온다.

로컬에서는 잘 작동했는데 Vercel 배포 버전에서는 오류가 발생했다.

오류 화면오류 화면

스키마와 Post 이야기가 있기 때문에 DB Model과 관련이 있겠구나 생각했다. 하지만 두 스키마 정의 코드에는 문제가 없었다.

posts: [{ type: Schema.Types.ObjectId, ref: 'Post' }],

이런 식으로 ref 정의도 잘 되어있었고, 모델 이름도 틀리지 않게 작성했기 때문이다.

실제 문제

실제 문제는 아래 코드에서 발생했다. 얼핏 보면 문제가 없어보이지만 문제는 Populate 하는 부분에서 발생했다.

populate는 ObjectId를 기준으로 해당 모델의 데이터를 치환해주는 역할을 수행한다. 아래 코드에서는 Post 모델을 불러와서 검색한 결과를 치환해주는 작용을 한다.

하지만 코드에서는 Post 모델을 불러오고 있지 않았다.

import { NextResponse } from 'next/server';
import dbConnect from '@/app/lib/dbConnect';
import Series from '@/app/models/Series';

export async function GET(
  request: Request,
  { params }: { params: { slug: string } }
) {
  try {
    await dbConnect();

    const series = await Series.findOne({ slug: params.slug }).populate({
      path: 'posts',
      options: { sort: { date: 1 } },
    });

    if (!series) {
      return NextResponse.json(
        { error: '해당 시리즈를 찾을 수 없습니다.' },
        { status: 404 }
      );
    }

    return NextResponse.json(series, {
      status: 200,
      headers: {
        'Cache-Control': 'public, max-age=60, s-maxage=60',
      },
    });
  } catch (error: any) {
    return NextResponse.json(
      { error: error.message || '시리즈 조회에 실패했습니다.' },
      { status: 500 }
    );
  }
}

문제 해결

위 코드에 아래 한 줄을 추가하는 것으로 해결이 됐다.

import '@/app/models/Post';

import Post from 'xxx' 대신 import '@/app/models/Post' 를 사용한 이유는 import Post 문을 사용할 경우 트리쉐이킹이 적용되는지 배포판에서는 적용이 되지 않았다.

그래서 바로 import 해주는 방식으로 작성하고 나서 문제는 해결되었다.

결과

시리즈 디테일 페이지를 만들었다. 원래는 검색 쿼리로 시리즈 내부 포스트 필터링만 했었는데 벨로그처럼 시리즈 페이지가 있으면 좋을 것 같아서 만들어 본 기능이다. 시리즈 디테일 페이지 모습시리즈 디테일 페이지 모습

📌 Table of Contents

0
추천 글