ORM(Object-relational mapping)과 Model

ORM

ORM은 Object-Relational Mapping의 약어입니다.

전통적으로 프로그램이 DB를 조작하기 위해서는 명령어(DB query string)를 생성하여 DB에 명령을 주고 결과를 받았습니다. 이와 다른 개념으로 DB를 프로그램의 객체(object)에 연결(map)하여 주는 것이 ORM입니다.

ORM은 DB data와 프로그램의 object를 연결하며 DB와 프로그래머 사이의 중간 역할을 해줍니다. 프로그래머는 DB에 직접 명령을 내리지 않고 연결된 객체의 함수를 사용해서 DB에 명령을 내리게 됩니다.

장점

  • 프로그래머가 해당 DB 언어를 몰라도 DB에 명령을 내릴 수 있다.

단점

  • DB에 직접 명령을 내리지 않고 한단계 거쳐가기 때문에 그만큼 속도가 느려진다.
  • ORM이 지정해 놓은 명령만 내릴 수 있다. 이때문에 하나의 목적을 수행하기 위해 ORM의 함수를 여러번 사용해야 하는 경우도 있다. 이 경우 속도가 느려진다.

단점이 더 많은 것 같지만 사실 하드웨어의 발달속도가 소프트웨어에 발달속도보다 빠르기 때문에 점점 프로그램의 성능보다는 프로그래머의 개발 효율이 더 중요하게 여겨지는 추세입니다. 물론 그래도 성능이 최우선이 되어야 하는 경우도 있기 때문에 판단은 본인이 합시다.

Model

ORM은 프로그램이 DB를 객체에 연결하는 것 차제를 뜻하며, model(모델)은 이때 연결 된 객체입니다. 이 model에 DB에 명령을 내릴 수 있는 함수들이 담겨 있으며 프로그래머는 model의 함수를 사용하여 DB에 명령을 내리게 됩니다.

Model의 Schema

Schema(스키마)는 모델의 대상에 대한 구체적인 구조를 뜻합니다.
DB에 학생들에 대한 정보를 담고 있는 table혹은 collection이 있다고 예를 들면, 이 table/collection에 data/document를 추가나 삭제 등 명령을 내릴 수 있는 object가 Model이며, 이 table/collection의 구조(예를 들어, 나이, 이름 등등)가 Schema가 됩니다.

예제를 통해 알아봅시다

Node.js와 Mongoose를 이용하여 만든 코드의 예를 보며 구체적으로 알아봅시다. 이름나이가 있는 학생의 collection을 ORM을 통해 document를 쓰고 읽는 코드를 만듭니다. 이 예제는 NodeJS과 NPM이 설치되어 있어야 실행할 수 있습니다.

1. 컴퓨터의 터미널 프로그램(cmd, bash 등)을 실행하고 예제 프로젝트를 위한 폴더를 만듭니다.

2. 예제 프로젝트 폴더에서 아래 명령어를 입력하여 Mongoose package를 다운로드합니다. Mongoose는 ORM을 위한 library입니다. 

$ npm install mongoose

node_modules라는 폴더가 생성되었으면 다음으로 넘어갑니다.

3. example.js 파일을 생성하고 아래를 입력합니다.

// example.js

var mongoose = require('mongoose');
var dbUrl = /* DB_STRING */;

var studentSchema = mongoose.Schema({
  name: {type:String, required:true},
  age: {type:Number, required:true}
});
var Student = mongoose.model('student',studentSchema);

mongoose.Promise = global.Promise;
mongoose.connect(dbUrl);
var db = mongoose.connection;

db.once("open",function () {

  Student.create({name:"June",age:20},function(error,student){
     console.log("Student.create:",student);

     Student.find({},function(error,students){
        console.log("Student.find:",students);
     });
     
  })

});

 /* DB_STRING */ 부분에는 자신의 MongoDB 접속 URI(mongodb://dbuser:[email protected]:39195/abce1234 이런식으로 생겼습니다)에 ""을 씌워서 넣어줍니다. MongoDB 접속 URI가 없다면 mlab.com가입 및 온라인 Mongo DB 생성을 통해 만들 수 있습니다.

4. 아래 명령어로 프로그램을 실행합니다.

$ node example.js

5. 실행 결과입니다.


이름이 June이고 나이가 20인 document가 하나 생성되었고, Student.find에는 새로 생성된 데이터가 보입니다.(_id는 document의 고유 아이디, __v는 version key로 mongoose가 자동으로 생성합니다)

ctrl+c를 누르면 프로그램을 종료할 수 있습니다. 이 코드는 학생을 하나 만들고, 학생 전체 리스트를 보여주기 때문에 다시 실행하면 Student.find에는 계속 학생이 하나씩 늘어납니다.

이 예제를 가지고 ORM과 model, schema를 알아봅시다.

1. Mongoose는 ORM을 사용하게 해주는 library입니다. 예제에서 mongoose를 사용하여 학생 model을 만들었고 model을 통해 DB를 간접적으로 조작하였으므로 이 예제는 ORM을 사용하고 있습니다.(틀린표현: Mongoose는 ORM입니다/이 예제 프로그램은 ORM입니다)

var studentSchema = mongoose.Schema({  name: {type:String, required:true},
  age: {type:Number, required:true}
});
var Student = mongoose.model('student',studentSchema);

2. 학생은 name(String, required)과 age(Number, required)의 schema를 가지고 있습니다. 그리고 이 schema를 사용해서 student model을 만들었습니다. 즉 schema는 model의 구조및 설정이며, model은 실제 DB에 접근할 수 있는 객체입니다. Model 객체는 주로 첫글자를 대문자로 표시합니다.

  Student.create({name:"June",age:20},function(error,student){
     console.log("Student.create:",student);
  })
  .then(function(){
    Student.find({},function(error,students){
       console.log("Student.find:",students);
    });  });

3. Mongoose의 Model.create함수와 Model.find함수를 사용해서 실제 DB를 조작하는 부분입니다.
Mongoose의 Model.create함수는 해당 모델의 collection에 document를 하나 생성합니다. Model.create의 callback 함수는 두개의 parameter를 인자로 받는데, 첫번째 인자는 error(만약 있다면)이고 두번째 인자는 생성된 document입니다. 두번째 인자는 document 하나가 들어오게 되므로 두번째 인자는 단수로 student이라고 썼습니다.
Mongoose의 Model.find함수는 해당 모델의 collection에서 조건에 맞는 자료들을 찾습니다. Model.find의 callback 함수는 두개의 parameter를 인자로 받으며 첫번재 인자는 error(만약 있다면), 두번째 인자는 찾은 document의 배열입니다. 현재 찾는 조건이 없으므로({}) 해당 collection 내 모든 document를 찾게 됩니다. 두번째 인자는 배열이 들어오게 되므로 복수형인 students로 썼습니다.(조건에 맞는 document가 하나 혹은 없더라고 무조건 배열이 들어옵니다.)

ORM, model, schema의 정의위 예제에서 Student(첫글자가 대문자, 단수), student(첫글자가 소문자, 단수), students(첫글자가 소문자, 복수)의 차이가 이해가 되시나요?

댓글

박광중 2017.09.22
마지막 행 "Model을 담은 변수는 주로 단수로 표시하며, 첫글자를 대문자로 표시합니다"  예시를 추가해 주시면 이해가 한 층 좋을 듯 합니다. 감사합니다.
I
Ian H 2017.09.22
@박광중,
제안을 주셔서 감사합니다. 본문 내용이 부족한것 같아 내용을 추가하였습니다.
김종하 2017.12.08
document 하나가 들어오게 되므로 두번째 인자는 단수로 studnet이라고 썼습니다.
student 오타 났습니다.
I
Ian H 2017.12.08
@김종하,
매의 눈이시네요^^;; 수정하였습니다. 알려주셔서 감사합니다!
q
qnfzks55 2018.04.03
WARNING: The `useMongoClient` option is no longer necessary in mongoose 5.x, please remove it. 라고 에러가나는데 useMongoClient 를 삭제해도 오류가뜨네요! 
I
Ian H 2018.04.06
@qnfzks55,
useMongoClient와 별개로 create이 promise를 return하지 않게 업데이트가 되었네요. 두가지 문제 모두 본문 코드에 수정하였습니다.
문서에 기여해 주셔서 감사합니다^^
이수혁 2018.07.19
3. example.js 파일을 생성하고 아래를 입력합니다. 이건 어디에 생성하는거죠?
이수혁 2018.07.19
app.js 있는 곳에 생성하는건가요? 
I
Ian H 2018.07.23
@이수혁,
이 글의 예제는 ORM을 알아보기 위한 독립된 예제입니다.
새로 폴더를 만든 후 그 폴더 안에서 예제를 만드시면 됩니다.
댓글쓰기

이 글에 댓글을 다시려면 SNS 계정으로 로그인하세요. 자세히 알아보기

UP