본문 바로가기
Front-End/Next.js

MongoDB 데이터베이스 globalThis 타입 지정

by MS_developer 2023. 8. 3.

 

최근 TypeScript를 기반으로 한 Next.js를 공부하고 있는데, 기본적인 부분에서 겪었던 의외의 어려움이 있어 간략하게 포스팅을 작성하려고 한다.

 

Next.js 개발 시 파일을 저장할 때마다 JS 파일들이 재실행되기 때문에 MongoClient.connect() 코드가 동시에 여러 번 실행될 수 있고, 이로 인해 DB입출력이 매우 느려지는 것을 방지하기 위해 다음과 같은 코드를 구성했다.

 

import { MongoClient } from "mongodb";
const DB_URI = process.env.DB_CONN_STRING || "";
let connectToDB;

if (process.env.NODE_ENV === "development") {
  if (!global._mongo) {
    global._mongo = new MongoClient(DB_URI).connect();
  }
  connectToDB = global._mongo;
} else {
  connectToDB = new MongoClient(DB_URI).connect();
}
export { connectToDB };

 

이후 해당 코드를 사용하고자 하는 페이지에 { connectToDB }를 import 하고, 문법에 맞게 사용한다면 DB에 정상적으로 접근하고 있는 것을 알 수 있었다.

 

 

정상적으로 코드가 작동되는 것과 반대로 한 가지 눈에 거슬리는 에러가 발생하는데, 바로 type 에러다.

 

먼저 인덱스 시그니쳐(Index Signature)에 대해 알아보았다.

 

찾아본 정의에 의하면 인덱스 시그니쳐란 "미리 알 수 없는 필드들의 형태를 정의하는 방법 (An index signature is a way to define the Shape of fields which are not known ahead of time.)"이라고 한다.

 

즉, "인덱스 시그니처가 없으므로"라는 말은 해당 필드의 형태가 정의되어 있지 않다는 말이고, 이는 곧 타입을 지정하지 않았다는 말과 같다.

 

타입스크립트를 사용하는 가장 큰 이유가 바로 사전에 "타입 지정"을 함으로써 보다 편한 디버깅과 협업을 전제로 하는 것인데, 위 에러는 global._mongo 변수는 타입이 지정되어 있지 않아 "any" 형식을 지정해 놓았다는 말과 같다. 이는 타입스크립트를 사용하는 이유를 무색하게 만드는 행동이라고 좋게(?) 말해주고 있는 것이다.

 

그렇다면 어떻게 해결해야 될까?

 

간단하다.

 

global로 선언된 변수의 타입을 별도로 지정해 주면 된다.

 

이를 위해 src > @types > global.d.ts 파일을 생성한 후, 아래 코드를 추가하면 된다.

 

import type { MongoClient } from 'mongodb'

declare global {
  namespace globalThis {
    var _mongo: Promise<MongoClient>
  }
}

 

생각해 보면 사실 간단한 문제다.

 

타입스크립트를 사용하는데 전역(global) 변수를 선언했다. -> 전역 변수도 (당연히) 변수다. -> 타입스크립트는 변수에 타입을 지정해줘야 한다. 안 그러면 쓰는 의미가 없다. -> 그러므로 전역 변수에도 타입을 지정해 준다.

 

처음에는 단순히 VS code에 뜨는 에러가 눈에 거슬려서 고치려고 한 거였는데, 알고 보니 의외로 기본적이고 중요한 에러였다.

 

앞으로는 글로벌 변수를 사용한다면 그에 맞는 타입을 지정해 주는 것도 신경 써야겠다.

댓글