목록 보기
MongoDB 4.4에서 5.0으로 업그레이드 하기
기타

MongoDB 4.4에서 5.0으로 업그레이드 하기

그린데이터
그린데이터
2022년 2월 18일

한국그린데이터에서는 MongoDB를 메인 DB로 사용하고 있습니다. DB의 안정성은 매우 중요하기에 인프라 관리를 위임할 수 있는 Cloud 서비스 Atlas를 이용중입니다. MongoDB 5.0 업그레이드알림 MongoDB Atlas 서비스에 가입하고 메일링 리스트를 구독 중인데, 작년부터 지속적으로 오고 있는 메일이 하나 있었습니다. 바로 Shared clusters (M0/M2/M5) 인스턴스들의 버전 업그레이드 소식입니다. 2021년 7월 13일에 5.0이 릴리즈되었고, 2022년 2월 중순에 버전 업그레이드를 진행하니, 약 7개월의 여유를 준것입니다. 물론 한국그린데이터는 해당 인스턴스보다 상위의 Dedicated cluster 인스턴스를 사용하고 있기에 영향을 받는 부분은 아니었지만, 5.0으로 업그레이드 되면서 향상 된 성능과 새로운 기능들을 사용해보고자 업그레이드를 결정하게 되었습니다. 그와 더불어 NestJS의 버전 업그레이드(7.6에서 8.2로)도 함께진행했습니다. 프로젝트에서 NestJS가 더 큰 비중을 차지하고 있지만, 업그레이드 시 크게 수정해야 될 부분이 없어서 주 내용을 MongoDB 업그레이드로 다루겠습니다. NestJS는 업그레이드 당시 Stable해 보이는 8.2.6를 기준으로 모든 dependency를 맞췄습니다. package.json npm dependency 버전맞추기 @nestjs/core 8.2.6를 기준으로 해당 패키지와 호환되는 버전을 찾아서정리했습니다. 그 중 mongoose의 경우 처음에는 6.1.2 버전을 사용했는데, 이슈가 발생하여 6.1.7로 변경하게 되었습니다. mongoose 6.1.2 버전과 6.1.7 버전 모두 MongoDB Node.js Driver 4.2.2를 사용하고 있어서 최신 버전의 MongoDB 5.2까지 호환이됩니다. MongoDB Node.js Driver 버전 별 MongoDB 지원현황 @nestjs/microservices MQTT v5 Shared Subscription 기능을 사용하기 위해 코드를 수정하여 사용 중입니다. (이 글을 참고하세요 — NestJS에서 MQTT 5 Shared Subscription 기능사용하기) "@nestjs/cli": Ŝ.2.0", "@nestjs/common": Ŝ.2.6", "@nestjs/core": Ŝ.2.6", "@nestjs/jwt": Ŝ.0.0", "@nestjs/microservices": "file:./custom_modules/nestjs/microservices.tar.gz", "@nestjs/mongoose": ŝ.0.2", "@nestjs/passport": Ŝ.1.0", "@nestjs/platform-express": Ŝ.2.6", "@nestjs/platform-socket.io": Ŝ.2.6", "@nestjs/schedule": ŕ.0.2", "@nestjs/schematics": Ŝ.0.5" "@nestjs/swagger": ř.2.0", "@nestjs/testing": Ŝ.2.6", "@nestjs/websockets": Ŝ.2.6", "@types/cron": ŕ.7.3", "@types/express": Ř.17.13", "@types/express-serve-static-core": Ř.17.28", "@types/jest": ൣ.0.3", "@types/node": ൘.11.21", "@types/passport": ŕ.0.7", "@types/serve-static": ŕ.13.10", "@types/supertest": Ŗ.0.11", "@types/utf8": ŗ.0.1", "@typescript-eslint/eslint-plugin": ř.10.2", "@typescript-eslint/parser": ř.10.2", "class-transformer": Ŕ.4.0", "class-validator": Ŕ.13.2", "eslint": Ŝ.8.0", "eslint-config-prettier": Ŝ.3.0", "eslint-plugin-import": Ŗ.25.4", "eslint-plugin-prettier": Ř.0.0", "express": Ř.17.2", "jest": ൣ.3.1", "mongoose": Ś.1.7", "mqtt": Ř.3.4", "passport": Ŕ.5.2", "passport-jwt": Ř.0.0", "passport-local": ŕ.0.0", "prettier": Ŗ.5.1", "reflect-metadata": Ŕ.1.13", "rimraf": ŗ.0.2", "rxjs": ś.4.0", "source-map-support": Ŕ.5.21", "supertest": Ś.2.2", "swagger-ui-express": Ř.3.0", "ts-jest": ൣ.0.7", "ts-loader": ŝ.2.6", "ts-node": ൒.4.0", "tsconfig-paths": ŗ.11.0", "typescript": Ř.3.5", "webpack": ř.68.0" 위의 dependency 기준으로 기존의 코드가 정상적으로 동작하는지 확인해 봤는데, 여러가지 에러가 발생했습니다. 해당 에러들을 하나씩 소개하고 어떻게 수정했는지알아보겠습니다. Mongoose 버전 변경에 따른 에러대응 Deprecated 된 설정제거 아래와 같은 에러가발생했습니다. MongoParseError: options usefindandmodify, usecreateindex are not supported 해당 내용은 MongooseModule에 넘기는 옵션으로 들어가던것이었습니다. MongooseModule.forRoot( uri, ( useNewUrlParser: true, useCreateIndex: true, useUnifiedTopology: true, useFindAndModify: false ) ) 검색 해 본 결과 mongoose 6 버전부터 해당 옵션은 사라지고, 기본 내장하겠다는 내용이있었습니다. useNewUrlParser, useUnifiedTopology, useFindAndModify, and useCreateIndex are no longer supported options. Mongoose 6 always behaves as if useNewUrlParser, useUnifiedTopology, and useCreateIndex are true, and useFindAndModify is false. Please remove these options from yourcode. 출처: https://mongoosejs.com/docs/migrating_to_6.html#no-more-deprecation-warning-options bulkWrite return type변경 upsertBulk를 구현하기 위해서 updateOne과 bulkWrite를 조합해서 사용했는데, bulkWrite의 return type이 변경되어 type 에러를 내고있었습니다. // 변경 전 BulkWriteOpResultObject // 변경 후 BulkWriteResult Document _id type 명시적으로지정 mongoose 사용 시에는 문제가 없었는데, migrate-mongodb 패키지를 이용할 때에는 mongoose가 아닌 Native MongoDB Driver를 사용합니다. 이때 collection에 데이터를 삽입할 때 _id가 type이 ObjectId가 아닌 경우에는 type 에러가발생합니다. 한국그린데이터는 API 호출의 편의를 위해서 MongoDB를 사용할 때 _id를 ObjectId가 아닌 string으로 선언하여 사용하고 있습니다. (API 호출 시 body 또는 query로 넘어온 id를 매번 ObjectId로 변환 후 검색해야 하는 수고를덜어줍니다.) Schema 선언 시 아래와 같이 하면 기본 값으로 string 형태의 _id가 생성됩니다. @Prop(( type: String, default: () => String(new Types.ObjectId()), )) _id: string 그런데 Native MongoDB Driver를 사용할 때에는 문제가됩니다. migrate-mongodb를 이용해서 seed 데이터를 삽입하는 코드가 사용되는데, 해당 코드를 수정해야했습니다. const companies = [ ( _id: �aab6722f001c951759', name: 'ABC', createdAt: new Date(񟭌-05-31 11:59:39'), updatedAt: new Date(񟭌-05-31 11:59:39'), ), ( _id: �aab6722f001c951760', name: 'XYZ', createdAt: new Date(񟭌-05-31 11:59:39'), updatedAt: new Date(񟭌-05-31 11:59:39'), ), ] // 변경 전 await db .collection(collectionName) .insertMany(companies) // 변경 후 await db .collection<( _id: string )>(collectionName) .insertMany(companies) Mongoose 6.1.2버그 Aggregate 코드에서 $group을 함수를 사용할 때 다음과 같은 에러가발생합니다. Property '_id' is incompatible with index signature. 아무리 찾아봐도 $group 함수의 스펙이 변경되거나 한 것이 아닌데, 동작하지 않아서 검색해 본 결과 mongoose 6.1.2의 버그였고, 6.1.3부터는 해결되었다고 합니다. 그래서 다른 패키지들과 호환성이 좋은 6.1.7 버전으로변경하였습니다. 개발 환경변경 Local Local에서는 Docker를 이용하여 MongoDB를 사용 중이었습니다. 그래서 Docker Hub에서 받아오는 이미지를 5.0 버전으로수정했습니다. FROM mongo:5.0 Dev, Prod Dev, Prod에서는 MongoDB Atlas를 사용하고 있기에, 설정을변경했습니다. 변경하고자 하는 Cluster에 접속한 후 더보기 버튼 > Edit Configuration을 선택합니다. Additional Settings > Select a Version 에서 MongoDB 5.0을 선택하면됩니다. 사용하는 인스턴스 종류, 용량에 따라서 완료까지의 시간이 서로 다르니, 반드시 여유있게 진행해 주세요. 그리고 한 번 업그레이드 시 다운그레이드가 불가능 하니 신중하게 실행해주세요. 마무리 이렇게 Local 에서 업그레이드가 완료 된 상태에서 문제 없이 동작하는 것을 확인했다면, Dev에 배포하여 최종 테스트를 한 후 Prod에배포합니다. 그리고 Mongo 5.0에서 제공하는 새로운 기능을 시험해봅니다. 참고 MongoDB Compatibility Define MongoDB _id-Type asString Migrating from 5.x to6.x Mongoose 6 $group with Typescript -> Property _id is incompatible with index signature MongoDB 4.4에서 5.0으로 업그레이드 하기 was originally published in GreenDataKR on Medium, where people are continuing the conversation by highlighting and responding to this story.

댓글 0

댓글을 작성하려면 로그인이 필요합니다.

댓글을 불러오는 중...