Dechive Knowledge Cube
Dechive
← 목차로 돌아가기
Published at

Notion API 에러 해결의 종결

Notion CMS 구축 시 발생하는 'databases.query' 함수 누락 이슈와 V5 아키텍처 대응 전략

1. 서론: 왜 Notion을 CMS로 선택했는가?

Next.js 14(App Router) 환경에서 개인 포트폴리오 및 실험실(Lab) 페이지를 구축하며, 콘텐츠 관리 시스템(CMS)으로 Notion을 채택했습니다. Notion은 직관적인 UI를 제공하며, 별도의 백엔드 어드민 페이지를 구축할 필요 없이 API를 통해 데이터를 불러올 수 있다는 장점이 있기 때문입니다.

하지만, 시중에 나와 있는 표준 문서(Official Docs)와 강의를 그대로 적용하는 과정에서 예상치 못한 치명적인 런타임 에러에 직면했습니다. 이 글은 특정 Notion API 클라이언트 환경(Strict Mode/Enterprise V5)에서 발생하는 이슈와 그 해결 과정을 상세히 기술합니다.


2. 문제 상황 (The Problem)

2.1. 표준 구현 방식

일반적인 notionhq/client 라이브러리 사용법은 다음과 같습니다.

// 일반적인 접근 방식 (표준 문서)
const response = await notion.databases.query({
  database_id: process.env.NOTION_DATABASE_ID,
  filter: { ... },
  sorts: [ ... ],
});

2.2. 발생한 에러

위 코드를 실행했을 때, 다음과 같은 TypeError가 발생하며 서버가 중단되었습니다.

2.3. 1차 분석

처음에는 단순한 환경 변수(Environment Variable) 누락이나 API Key 권한 문제로 의심했으나, 디버깅 결과는 달랐습니다.

  • notion 클라이언트 객체는 생성되었으나, 그 안에 databases.query 메서드 자체가 존재하지 않음.
  • 반면 databases.retrieve 메서드는 정상적으로 동작함.
  • 이는 제가 사용 중인 Notion Integration 환경이 표준 퍼블릭 API가 아닌, 엄격한 타입(Strict Notion Client) 혹은 데이터 소스(Data Source) 기반의 V5 아키텍처를 따르고 있음을 시사했습니다.


    3. 원인 분석 (Root Cause Analysis)

    심층 디버깅 결과, 해당 환경에서는 데이터베이스에 접근하는 방식이 근본적으로 달랐습니다.

  • Legacy/Standard 방식: Database ID를 통해 직접 query를 날려서 데이터를 가져옴.
  • Strict/V5 방식: Database ID는 단지 껍데기(메타데이터)일 뿐이며, 실제 데이터는 **Data Source*라는 별도의 계층에 존재함.
  • 즉, **"데이터베이스에 쿼리를 날려라"**라는 명령어(databases.query)가 성립하지 않으며, **"데이터베이스에서 데이터 소스 ID를 찾고 → 그 소스에 쿼리를 날려라"**라는 2단계 프로세스가 필요했습니다.


    4. 해결 솔루션 (The Solution)

    문제를 해결하기 위해 두 단계의 비동기 로직을 수행하는 **Wrapper Function(헬퍼 함수)**을 구현했습니다.

    4.1. 프로세스 설계

  • Step 1: databases.retrieve를 호출하여 DB의 메타데이터를 조회한다.
  • Step 2: 응답값 내부의 data_sources 배열에서 고유한 id를 추출한다.
  • Step 3: 추출한 ID를 사용하여 dataSources.query (비표준 메서드)를 실행한다.
  • 4.2. TypeScript 구현 코드

    이 로직을 모든 페이지(블로그, 프로젝트, 실험실)에서 재사용할 수 있도록 queryV5Database라는 유틸리티 함수로 추상화했습니다.

    import { Client } from '@notionhq/client';
    
    // 1. Strict Mode 클라이언트 타입 재정의 (표준 SDK에 없는 메서드 선언)
    interface StrictNotionClient {
      databases: {
        retrieve: (args: { database_id: string }) => Promise<{ 
          id: string; 
          data_sources?: { id: string }[] 
        }>;
      };
      dataSources: {
        query: (args: {
          data_source_id: string;
          filter?: object;
          sorts?: object;
        }) => Promise<any>; // CustomQueryResponse
      };
    }
    
    const notion = new Client({ auth: process.env.NOTION_API_KEY });
    const strictNotion = notion as unknown as StrictNotionClient;
    
    /**
     * V5 호환성 해결을 위한 쿼리 래퍼 함수
     * databases.query 대신 retrieve -> dataSources.query 패턴을 사용
     */
    async function queryV5Database(databaseId: string, sorts?: object[], filter?: object) {
      // Step 1: DB 정보 조회 및 Data Source ID 추출
      const db = await strictNotion.databases.retrieve({ database_id: databaseId });
      const dataSourceId = db.data_sources?.[0]?.id;
    
      if (!dataSourceId) {
        throw new Error(`[Fatal] Data Source ID not found for DB: ${databaseId}`);
      }
    
      // Step 2: 실제 데이터 쿼리 실행
      return await strictNotion.dataSources.query({
        data_source_id: dataSourceId,
        sorts,
        filter,
      });
    }

    5. 적용 결과 (Result)

    이 헬퍼 함수를 적용한 후, 기존에 실패하던 모든 데이터 페칭 로직이 정상화되었습니다.

  • 블로그 포스트: 상태(Status)가 'Published'인 글만 정확히 필터링.
  • 프로젝트(Lab): 커버 이미지, 태그, 제목 등 모든 속성(Property) 매핑 성공.
  • 성능: 2번의 API 호출이 발생하지만, Next.js의 ISR(Incremental Static Regeneration)과 결합하여 사용자 경험에는 전혀 영향을 주지 않음.
  • Before (Error)

    TypeError: strictNotion.databases.query is not a function

    After (Success)

    [Next.js] Compiling /lab/bdo-crafting ...
    [Notion] Successfully retrieved 128 items from Data Source.

    6. 결론 및 인사이트

    Notion API는 매우 강력하지만, 모든 환경이 동일하지 않습니다. 특히 튜토리얼이나 공식 문서만 의존하다 보면, 이와 같은 환경 특이적인(Environment-specific) 아키텍처 이슈에서 며칠을 허비할 수 있습니다.

    핵심 요약:

  • databases.query가 없다고 당황하지 말 것.
  • 내가 사용하는 환경이 Data Source 기반인지 확인할 것.
  • "조회(Retrieve) 후 쿼리(Query)" 패턴으로 우회하면 해결 가능하다.
  • 이 글이 저와 같은 에러(strictNotion...)로 고통받는 개발자들에게 명확한 이정표가 되기를 바랍니다.


    #Nextjs#NotionAPI#CMS#Troubleshooting

    댓글 0

    • 아직 댓글이 없어요. 첫 번째 주인공이 되어보세요! ✨