오히려 좋아..

상황이 나쁘게만 흘러가는 것 같을 때 외쳐보자.. .

궁금한 마음으로 포트폴리오 보기

Web Programming/NestJS

[NestJS] Mongoose Cache 적용

junha6316 2022. 4. 25. 21:56

nestjs는 기본적으로 모듈화를 지향한다. 클라이언트(프론트 엔드 아님) 에서 사용할 부분만 보여주고 나머지 로직은 보여주지 않는 캡슐화를 지향하는 것이다. 그래서 기존에 작성되어 있는 NodeJS 패키지들을 NestJS에서 사용하기 위해 패키지를 다시 작성하거나 캡슐화를 하지않고 사용해야한다. 하지만 캡슐화를 하지 않고 사용하자니 도메인 로직 코드에 패키지에 대한 의존성이 끊임없이 전파되는 것을 보면 참을 수가 없는분노가 치밀어 오른다. 그렇다고 패키지를 모듈화 해서 다시 작성하자니 부담스러운게 사실이다. 오늘은 모듈화 하지않고 적당한 캡슐화를 할 수 있는 방법을 cachegoose 패키지를 통해 설명하려고 한다.

 

1. Mongoose Cache

cachegoose는 mongodb로 날라가는 쿼리를 자동으로 캐싱해주는 패키지이다. 따로 캐싱에 대해 신경 쓸 필요 없이 아래처럼 .cache만 붙여주면 자동으로 캐싱을 해준다.

users.findMany().cache(10)

하지만 충격적이게도 2022.04.25 기준 mongoose-cache는 nestJS에 맞게 만들어진 패키지가 존재하지 않는다. 그렇다면 도대체 어떻게 사용해야하는 것일까. 일단 가장 간단하게 아래와 같은 방법을 생각해볼 수 있다. 앱이 시작하는 위치에서 mongoose-cache를 import 해주는 것이다. 하지만 이런식으로 하다보면 기존 패키지를 오버라이드해 사용하는 패키지를 선언할 때마다 main.ts에 추가하게 될 것이고  실제로 mongodb에서 연결하는 모듈과 분리되어 매번 찾게되는 문제가 존재한다. 

// main.ts

import cachegoose from "recachegoose";
import mongoose from "mongoose";

async function bootstrap() {

  cachegoose(mongoose, {
            url: config.get("REDIS_URL"),
            auth_pass: config.get("REDIS_PASSWORD"),
          })
  const app = await NestFactory.create(AppModule, {});
  setNestApp(app);

  const port = process.env.PORT || 3000;
  console.log("Server running at http://127.0.0.1:" + port + "/");
  await app.listen(port);
}
bootstrap();

이를 해결하기 위해 아래와 같은 방법을 사용해 볼 수 있다.

 

2. mongoose Connection 사용

Mongoose에서 실제로 mongodb와 커넥션을 맺는 모듈에서 forRootAsync를 사용하면 connection을 커스터마이즈 할 수 있다.

아래 코드의 connectionFactory를 참고하길 바란다. 

// mongo.module.ts

@Module({
  imports: [
    MongooseModule.forRootAsync({
      imports: [ConfigModule],
      inject: [ConfigService],
      useFactory: (config: ConfigService) => ({
        connectionFactory: (connection) => {
          const mongoose = connection.base;
          mongoose.set("debug", process.env.NODE_ENV != "prod");
          cachegoose(mongoose, {
            url: config.get("REDIS_URL"),
            auth_pass: config.get("REDIS_PASSWORD"),
          });
          return connection;
        },
      }),
    })]
    })    
 export class MongoDataServiceModule {}

이런식으로 작성하면 비슷한 패키지끼리 묶을 수 있어 아까전 main.ts에 모두 몰빵하는 방식보다는 덜 의존성이 전파되는 방식이다.

위와 같은 방식으로 다른 패키지에도 적용할 수 있다.자 이제는 무지성으로 main.ts에 적용하지말고 꼭 모듈화와 캡슐화를 지키길 바란다.

 

감사합니다 땡큐