티스토리 뷰

몽고디비는 유명하고 널리사용되는 noSQL 중 하나이다. node.js 서버에 mongoDB를 연결하려면,

  1. 몽고디비 공식홈페이지에서 가입 후, 클러스터를 생성해줘야 한다. 
  2. 클러스터가 생성되었으면 connect 버튼을 눌러 Connect to your application의 `Drivers`를 눌러주면 된다.
  3. Connection with MongoDB Driver 스텝에서 2번째에 보면 `npm install mongodb` 라는 명령어와 함께 몽고디비 라이브러리를 설치하라고 나와있지만 `mongoose` 를 설치해주면 된다. 
  4. 3번째 스텝에 Add your connection string into your application code라고 붙여넣을 코드가 있는데 복사해서 password부분만 내가 지정한 엑세스가능한 비번으로 변경해주면 된다. 
  5. 4번에서 복사한 코드는 .env 파일에 `DATABASE_URL`정도로 이름을 짓고 값을 넣어주면 된다. 이후 몽구스를 통해 연결할 시 해당 주소가 필요하다. 

🤔mongodb vs mongoose 

둘 다 node.js에서 몽고디비를 다루기 위한 라이브러리이다. 둘 중에 하나를 선택하여 사용할 수 있다. 

전자(몽고디비)를 선택하면 몽고디비 드라이버를 직접 사용하면서 좀 더 저수준의 접근 방법을 사용할 수 있다. 

후자(몽구스)는 mongoDB 데이터를 js객체로 매핑하여 데이터 유효성 검사, 쿼리 작성 등을 보다 쉽게 처리할 수 있다.

 

mongoose에서 모델(스키마를 기반으로 만들어진 데이터 모델) 이름은 일반적으로 대문자로 시작하는 단어를 사용하며 mongoDB에서 컬렉션 이름이 소문자로 시작하는 것과 대조적이다.

데이터베이스에서 `스키마`는 데이터 구조를 정의하고 이를 따르르 제한 사항을 설정하는 방법을 의미한다. 일반적으로 스키마는 데이터 베이스 테이블, 컬렉션, 문서 등의 구조와 속성을 정의한다. 스키마는 데이터의 무결성과 일관성을 유지하기 위해 사용된다. 

예시로 아래의 코드를 보면서 설명하자면,

module.exports = mongoose.model("User", userSchema);
  • mongoose.model(첫번째인자, 두번째인자) 메서드에서 첫 번째 인자는 모델 이름을 가리키고 mongoose에서 모델은 스키마를 기반으로 생성되며, 데이터를 mongoDB 컬렉션과 매핑시키는 역할을 한다. 모델 이름은 컬렉션 이름의 단수형으로 사용된다. 즉, `User`은 `users` 컬렉션과 매핑된다.
  • 몽구스에서 `스키마`는 데이터 모델을 정의하는 JS객체를 의미한다. 몽구스를 사용하면 스키마를 정의하여 데이터 모델을 생성하고, 해당 모델을 사용하여 mongoDB 데이터베이스와 상호작용할 수 있다. 스키마는 데이터 모델의 필드 및 해당 필드에 적용되는 유효성 검사, 기본값, 유니크 제약 조건 등을 정의한다.
  • 따라서, 스키마와 모델을 서로 다른 개념이지만 `몽구스`에서는 스키마를 기반으로 모델을 생성하므로 밀접한 관련이 있다.

🐱‍👤mongoose-sequence 를 사용하여 고유값 필드 추가하기

mongoose 외에도 `yarn add mongoose-sequence` 를 추가적으로 설치해줘야 한다. 몽구스를 통해서 증감하는 고유 식별자를 자동으로 생성하기 위함이다. 

models/Note.js 

const mongoose = require("mongoose");
const AutoIncrement = require("mongoose-sequence")(mongoose);
// user에 들어가는 Id는 몽구스관련, 이 Id값의 참조 ref로 어떤 스키마(내가 만든 스키마)를 참조하는 지 알려준다.

// ? 몽고디비에서 제공하는 타임스탬프를 쓰기위해 두번째 객체로 옵션을 넘겨준다.

const noteSchema = new mongoose.Schema(
  {
    user: {
      type: mongoose.Schema.Types.ObjectId,
      required: true,
      ref: "User",
    },
    title: {
      type: String,
      required: true,
    },
    text: {
      type: String,
      required: true,
    },
    completed: {
      type: Boolean,
      default: false,
    },
  },
  {
    timestamps: true,
  }
);

noteSchema.plugin(AutoIncrement, {
  inc_field: "ticket",
  id: "ticketNums",
  start_seq: 500,
});

module.exports = mongoose.model("Note", noteSchema);
  • Note 모델을 생성하는 스키마 코드이다. user에 들어가는 type값이 참조하는 값은 User 스키마이기 때문에 몽고디비에서 자동으로 생성해주는 _id의 값보다 명시적으로 Note에 ticket이라는 필드를 추가하여 500부터 증감하는 고유값을 부여한다.
  • 몽구스의 스키마 객체에 두번째 인자로는 옵션 값을 줄 수 있는데 이는 몽구스에서 제공하는 기본 기능이다. `timestamps` 옵션을 사용하면 createdAt 과 updatedAt 필드가 자동으로 생성되며, 이 필드들은 해당 도큐멘트가 생성되거나 업데이트된 시간을 기록한다. 
  • AutoIncrement 기능은 기본적으로 mongoDB에서 제공하지 않는 기능으로, 자동으로 증가하는 일련번호를 필드에 추가할 수 있다. 이는 데이터베이스에 새로운 데이터를 추가할 때 고유 식별자를 자동으로 생성하는 데 유용하다.

config/dbConn.js

몽고디비 연결을 위한 코드
const mongoose = require("mongoose");

const connectDB = async () => {
  try {
    await mongoose.connect(process.env.DATABASE_URI);
  } catch (error) {
    console.log("error occurs in DBConnection", error);
  }
};

module.exports = connectDB;
  • .env 파일에 환경변수로 저장해놓은 DATABASE_URI를 mongoose.connect()의 인자로 넘겨준다.

🐱‍👤mongoDB를 연결하고 이벤트 로그를 통한 연결 상태 확인

server.js

connectDB 함수와 mongoose를 임포트해온다.

//(중략)

const { logger, logEvents } = require("./middleware/logger"); //logEvents 함수 사용
const connectDB = require("./config/dbConn");
const mongoose = require("mongoose");

connectDB(); //DB를 연결하고

const PORT = process.env.PORT || 3500;

app.use(logger);

app.use(cors(corsOptions));

app.use(express.json());

app.use(cookieParser());

app.use("/", express.static(path.join(__dirname, "public")));

app.use("/", require("./routes/root"));


app.all("*", (req, res) => {
  res.status(404);
  if (req.accepts("html")) {
    res.sendFile(path.join(__dirname, "views", "404.html"));
  } else if (req.accepts("json")) {
    res.json({ message: "404 Not Found" });
  } else {
    res.type("txt").send("404 Not Found");
  }
});

// logger와 다르게 app을 시작하라고 말하기 전에 사용하기 때문에 listen 위에 위치
app.use(errorHandler);

//node.js 어플리케이션이 mongoDB와 연결되어있을 때 알림받는 방법 설정
mongoose.connection.once("open", () => {
  console.log("Connected to MongoDB");
  app.listen(PORT, () => console.log(`server is running on ${PORT}`));
});

mongoose.connection.on("error", (err) => {
  console.log(
    "error on mongoDB connection",
    logEvents(`${err.no}: ${err.code}\t${err.syscall}\t${err.hostname}`),
    "mongoErrLog.log"
  );
});
  • `mongoose.connection.once()` 은 몽구스를 사용하여 몽고디비와 최초 연결이 성공했을 때 발생하는 이벤트를 처리하는 코드이다. once()메서드는 이벤트가 한 번만 발생할 때 사용한다. 
  • `mongoose.connection.on()`은 몽구스를 사용하여 몽고디비와 연결이 실패하거나, 중간에 끊겼을 때 발생하는 이벤트를 처리하는 코드이다. on() 메서드는 이벤트가 여러 번 발생할 때 사용한다.
  • 연결이 실패한 경우에는 logger파일에서 가져온 logEvents()함수를 사용하여 에러에 대한 정보를 mongoErrLog.log라는 이름의 로그 파일에 저장한다. 
댓글