Nest는 SQl, NoSQL 모든 데이터베이스와 통합할 수 있다. 그런데 유독 nodejs는 NoSQL인 MongoDB를 사용하는 경우가 많다. MongoDB가 JSON과 유사한 BSON 객체로 데이터를 저장한다는 점, MongoDB의 ODM 중 가장 유명한 Mongoose가 nodejs 위에서 동작한다는 점 때문에 그런 것 같다. MongoDB는 계정 생성만 해 두고 사용해 본 적이 없어서 겸사겸사(?) NoSQL도 사용해 볼 겸 MongoDB를 연결해 보려고 한다.
ODM은 Object Document Mapping의 줄임말이다. 객체와 문서를 1대1 매칭한다는 뜻이다. Object는 자바스크립트의 객체, Document는 몽고디비의 문서이다. ODB은 문서를 DB에서 조회할 때 자바스크립트 객체로 바꿔 준다. 그리고 몽고디비의 ODM으로 가장 많이 사용되는 게 바로 몽구스다. 🐭
npm install --save @nestjs/mongoose mongoose
⁝
import { MongooseModule } from '@nestjs/mongoose';
@Module({
imports: [CatsModule, MongooseModule.forRoot('몽고디비URI')],
⁝
몽구스 설치가 완료되었으면 몽구스의 module을 app.module에 import 해 주고 몽고디비 URI를 넣어 준다. URI를 얻는 방법은 아래와 같다.
cluster 들어가기connect 버튼 클릭Connect your application 버튼을 클릭
그런데 URI를 복사하여 MongooseModule.forRoot('몽고디비URI')에 붙여넣으면 URI가 날것의 주소 그대로 노출되고 만다. URI는 반드시 노출을 막아야 하기 때문에 환경 변수를 설정해 줄 필요가 있다.
환경 변수 설정을 위해서는 별도의 설치와 import가 필요하다. (공식 홈페이지 TECHNIQUES의 Configuration 참고)
$ npm i --save @nestjs/config
⁝
import { ConfigModule } from '@nestjs/config';
@Module({
imports: [ ConfigModule.forRoot(), MongooseModule.forRoot('몽고디비URI')]
⁝
설치와 import를 마치면 환경변수 관리 파일 .env를 사용할 수 있다. .env 파일은 프로젝트 폴더 가장 상위 루트에서 생성해 주면 된다. 이렇게 생성된 파일에 아까 복사했던 몽고디비 URI 값을 MONGODB_URI = "복사했던 몽고디비 URI 값" 형태로 저장한다.
날것의 URI가 들어 있던 app.module 파일의 MongooseModule.forRoot('몽고디비URI') 중 '몽고디비URI' 부분을 process.env.MONGODB_URI로 수정해 준다. 첫 번째 인자 설정을 마쳤으면 이제 두 번째 인자를 넣어 줄 차례다.
완성된 코드로 보면 아래와 같다.
⁝
@Module({
imports: [
ConfigModule.forRoot(),
MongooseModule.forRoot(process.env.MONGODB_URI, {
useNewUrlParser: true, // 몽구스에서 필요로 하는 두 번째 인자 -1
useUnifiedTopology: true, // 몽구스에서 필요로 하는 두 번째 인자 -2
}),
CatsModule,
],
controllers: [AppController],
providers: [AppService],
})
⁝
몽고디비 URI 외에도 포트 넘버 등을 환경 변수에 넣어 관리할 수 있다. main에서 사용하고 있는 포트 넘버를 .env에 넣고 설정을 해 보았다.
async function bootstrap() {
const app = await NestFactory.create(AppModule);
app.useGlobalFilters(new HttpExceptionFilter());
const PORT = process.env.PORT; // .env에 저장된 포트 넘버
await app.listen(PORT);
}
개발할 때 몽구스의 쿼리를 로그로 찍어 줄 수 있다. app.module 파일에 몽구스를 import * as mongoose from 'mongoose';로 import한다. 그리고 AppModule 클래스에서 export 하는 코드 mongoose.set('debug', true)를 작성한다. 이렇게 하면 쿼리가 로그로 찍힌다.
하지만 프로덕션 배포를 하게 될 때엔 해당 로그가 필요없다. 개발 모드와 프로덕션 모드를 구분해 주기 위해서 환경변수를 사용해 준다. .env에 MODE = 'dev'로 구분해 주는 코드를 작성했다.
app.module로 다시 이동해서 processe.env.MODE가 'dev'일 때만 로그가 찍히도록 삼항 조건 연사자를 이용한다. 완성된 클래스 코드와 찍힌 쿼리는 아래와 같다.
export class AppModule implements NestModule {
private readonly idDev: boolean = process.env.MODE === 'dev' ? true : false;
configure(consumer: MiddlewareConsumer) {
consumer.apply(LoggerMiddleware).forRoutes('*');
mongoose.set('debug', this.idDev);
}
}
// 찍힌 쿼리 적기
개발할 때는 true가, 아닐 때에는 false 되어서 쿼리가 찍히지 않게 된다.
느낀점
포스팅을 정리하면서 환경 변수를 왜 사용하는지에 대한 이해를 할 수 있었다. 노출되면 안 될 중요한 정보들은 환경 변수에 담자.
몽고디비를 연결할 때, 몽구스의 쿼리를 보고자 설정할 때 모두 app.module과 관련이 있다. .env에서 환경변수를 설정하고 app.module로 가자.