[MongoDB 기초] 윈도우 설치부터 Java에서 사용까지!


MongoDB 윈도우 설치부터 Java에서 활용까지!





MongoDB란?

몽고DB 는 오픈소스 document database로, NoSQL 데이터베이스 중에서 매우 주요한 위치에 있습니다. 몽고DB는 C++로 쓰였으며, 크로스 플랫폼(cross-platform)을 지원합니다. 또한 높은 성능, 용이성, 쉬운 확장성을 제공하는 document oriented DB입니다. 몽고DB를 이해하기 위해서는 컬렉션(collection)과 도큐먼트(document)이라는 개념을 알아야 합니다.


컬렉션은 몽고DB 도큐먼트의 그룹입니다. RDBMS 테이블과 동등한 개념입니다. 하나의 데이터베이스 내에 존재하며, 컬렉션은 스키마를 강제로 규정하지 않습니다. 하나의 컬렉션 내에 있는 도큐먼트들은 서로 다른 필드들을 가질 수 있습니다. 전형적으로, 하나의 컬렉션 내에 있는 도큐먼트들은 유사하거나 연관된 목적을 가집니다.


도큐먼트는 key-value 쌍의 묶음입니다. 도큐먼트는 동적인 스키마(dynamic schema)를 가지고 있습니다. 동적인 스키마라는 것은 같은 컬렉션 안에 있는 도큐먼트들이 모두 똑같은 필드 혹은 구조를 가져야할 필요가 없다는 것을 의미하며, 컬렉션의 도큐먼트들 안에 있는 공통 필드들(common fields)은 다른 유형의 데이터를 가질 수 있습니다.


아래는 흔히 알고 있는 mysql, oracle 과 같은 RDBMS와 몽고DB에서 쓰이는 용어들을 대응시켜 놓은 테이블입니다.

 RDBMS

 MongoDB

 데이터베이스

 데이터베이스

 테이블

 컬렉션(Collection)

 튜플/로우

 도큐먼트(Document)

 컬럼

 필드

 테이블 조인

 Embedded Documents

 기본키(Primary Key)

 기본키(Primary key (몽고 DB는 자체적으로 _id라는 디폴트 키를 제공함)



왜 몽고 DB를 써야할까?

1. 데이터가 JSON 스타일의 도큐먼트 형태로 저장됩니다.(Document Oriented Storage)

2. 모든 속성에 대한 인덱싱

3. 복제와 높은 사용성

4. Auto-Sharding

5. 풍부한 쿼리

6. Fast In-Place Updates

7. 몽고DB에 대한 전문적인 지원



어디에서 몽고 DB를 써야할까?

1.빅 데이터

2. 컨텐츠 관리와 전달

3. 모바일 및 소셜 인프라

4. 사용자 데이터 관리

5. 데이터 허브



윈도우에 설치하기

몽고DB를 윈도우에 설치해봅시다. 몽고DB에 윈도우를 설치하기 위해서는, 

우선 https://www.mongodb.org/downloads에서 최신 릴리즈를 다운로드 해야합니다. 물론, 사용하고 있는 윈도우 버전에서 구동될 수 있는 버전을 다운로드 받아야합니다. 윈도우 버전을 알기 위해서 cmd를 켜고 다음 명령어를 입력합니다.


제가 사용하고 있는 윈도우는 64비트이므로 64비트 버전을 받겠습니다. 참고로, 몽고DB 32비트 버전은 2GB보다 작은 데이터베이스만 지원하므로 테스트나 평가 목적으로 사용하는 경우에만 적절하다고 할 수 있습니다. 다운로드를 받기위해 위에서 링크를 건 사이트에 접속하여 윈도우 다운로드 목록을 봤더니 총 4가지가 있습니다.





64bit용은 총 3가지가 있습니다. 이 중에 저는 맨 위에 있는 'Windows 64-bit 2008 R2+' 를 다운로드 하겠습니다. 이 버전은 윈도우 서버 2008 R2, 윈도우7 (64비트), 그 이상 버전에서 사용할 수 있습니다. Windows 64-bit legacy는 윈도우 비스타, 윈도우 서버 2003, 윈도우 서버 2008에서 사용할 수 있습니다만 최신에 향상된 성능은 포함하고 있지 않습니다. 몽고DB를 사용하기 위해서는 윈도우 서버 2008 R2 이상 64bit를 사용하는 것이 좋겠습니다.

 


데이터 저장경로 설정하기

다운로드 받은 msi 파일을 실행하여 설치합니다. 그리고 해야할 일이 있습니다. 몽고DB는 파일을 저장하기 위한 폴더가 필요합니다. 디폴트 경로는 c:\data\db이므로 이 경로에 폴더를 만들어주어야 합니다. 만약 특정한 경로를 지정해주고 싶다면 별도의 작업이 필요합니다. cmd를 켜서 MongoDB 폴더 내에 있는 bin 디렉터리로 이동하여 저장 경로를 저장해줍니다.


  1. C:\MongoDB\Server\3.2\bin>mongod.exe --dbpath "C:\MongoDB\data"

저는 C:\MongoDB\data라는 디렉토리를 생성하여 패스로 설정해주었습니다. 여기서 주의해야할 점은 디폴트 경로인 C:\data\db 디렉토리 대신에 다른 디렉토리를 저장경로로 사용한다면, 접속시에 매번 위에 있는 dbpath 설정 명령어를 입력해주어야 한다는 것입니다. 만약 입력해주지 않고, C:\data\db 디렉토리도 없다면 접속할 수 없다는 에러메시지가 뜹니다. 


디폴트 경로인 여기까지 했으면 이제 테스트를 해볼 수 있습니다. mongo.exe를 입력하여 실행을 하면 테스트 계정으로 접속이 됩니다. 그 후 db.test.save({a:1})을 입력해봅니다. 그런 후 db.test.find()를 입력해보면 방금전에 입력했던 데이터가 저장된 것을 확인할 수 있습니다. 그리고 RDBMS의 PK에 해당하는 값인 _id가 자동생성 된 것을 확인할 수 있습니다.


  1. C:\MongoDB\Server\3.2\bin>mongo.exe
  2. 2016-03-25T09:52:11.590+0900 I CONTROL  [main] Hotfix KB2731284 or later update
  3. is not installed, will zero-out data files
  4. MongoDB shell version: 3.2.4
  5. connecting to: test
  6. > db.test.save({a:1})
  7. WriteResult({ "nInserted" : 1 })
  8. > db.test.find()
  9. { "_id" : ObjectId("56f4a5503d2a112ce69c2dd6")"a" : 1 }



Document의 _id

_id는 12바이트의 16진수의 숫자이며 모든 도큐먼트에 대해 고유함을 보장합니다. 도큐먼트를 생성할 때 _id를 직접 줄 수도 있고, 그렇지 않다면 몽고DB가 고유한 id를 부여해줍니다. 자동적으로 만들어지는 id를 보자면, 처음 4바이트는 현재 시간, 그 다음 3바이트는 기기 id, 그 다음 2바이트는 몽고DB 서버의 프로세스 아이디이며, 나머지 3바이트는 단순히 증가하는 값입니다.



RDBMS와 MongoDB 비교

테스트로 key-value 한쌍으로 이루어진 컬렉션을 넣어봤지만, 사실 몽고DB의 장점은 RDBMS에 저장하려면 여러 테이블에 나누어서 저장하고 조인해서 사용해야하는 복잡한 형태의 데이터를 한 컬렉션에 저장할 수 있다는 것입니다. 예를 들어서 게시판을 위한 DB를 설계한다고 했을 때, RDBMS를 이용하면 아래의 그림과 같이 적어도 2~3개 이상의 테이블이 필요합니다.

반면 몽고DB는 한 게시물에 관련있는 게시물 원본, 댓글, 태그 내용을 한 컬렉션에 JSON형태로 저장할 수 있습니다. 


  1. {
  2.    _id: ObjectId(3er54ad8902c)
  3.    title: '안녕하세요.',
  4.    content: '하하 오랜만이네요.',
  5.    seq: 101,
  6.    writer: 'sejin101'
  7.    tags: ['안부''안녕'],
  8.    comments: [
  9.       {
  10.          user: 'user1',
  11.          message: '오랜만!!',
  12.          ddtm: '20160301152300'
  13.       },
  14.       {
  15.          user: 'user2',
  16.          message: '하이',
  17.          ddtm: '20160302182300'
  18.       }
  19.    ]
  20. }

여기서 주목해야할 점은 RDBMS와의 차이입니다. 위에서 보았듯이 RDBMS를 이용하면 하나의 게시물을 불러오기 위해서 최소한 3개의 테이블을 조인해야 합니다. 저장할 때도 마찬가지로, 한 게시물에서 어떤 행위가 일어나느냐에 따라서 각각 다른 테이블에 저장해야합니다. 그러나 몽고DB는 위의 형태처럼 하나의 컬렉션에 게시물에 대한 정보를 저장할 수 있으며, 따라서 정보를 불러올 때 복잡한 조인을 거치지 않고 단지 컬렉션 하나만 불러오면 됩니다. 


위의 ERD처럼 기존 RDBMS는 테이블의 개수와 테이블들 간의 관계를 보여주는 전형적인 스키마 디자인이 있습니다. 그러나 몽고DB는 관계(relationship)라는 개념이 없습니다. 



RDBMS과 비교한 몽고DB의 이점

그렇다면 RDBMS와 비교한 몽고DB의 이점은 무엇일까요?


1. 스키마가 없다. 몽고DB는 도큐먼트 데이터베이스로 하나의 컬렉션이 다른 도큐먼트들을 가지고 있습니다. 도큐먼트들의 필드 개수, 컨텐츠, 사이즈는 각각의 도큐먼트들마다 다를 수 있습니다.

2. 단일 오브젝트 구조가 명확하다.

3. 복잡한 조인이 없다.

4. 몽고DB는 거의 SQL만큼 강력한 도큐먼트 기반의 쿼리 랭귀지(query language)를 사용하여 역동적인 쿼리를 지원한다.

5. 튜닝


6. 크기변경이 용이하다.


7. 애플리케이션 오브젝트를 데이터베이스 오브젝트로 변환하거나 매핑시킬 필요가 없다.


8. 작업물을 저장하기 위해서 내부 메모리를 사용하기 때문에, 데이터의 접근이 더욱 빠르다.



몽고DB 실행하기

1.데이터베이스 생성

이제 웬만큼 기초 개념도 정리하고, 접속 테스트도 해봤으니 실제 응용으로 들어가보겠습니다. 

몽고DB에서는 use DATABASE_NAME 명령어를 사용해서 데이터베이스를 생성합니다. 이 명령어는 새로운 데이터베이스를 만들며, 이미 만들어진 경우라면 기존의 데이터베이스를 반환합니다.


1. use 키워드를 이용하여 원하는 이름으로 데이터베이스를 생성합니다. 저는 mydb로 생성하였습니다.

2. db 명령어를 이용하여 현재 사용중인 데이터베이스를 조회합니다.

3. show dbs 명령어를 이용하여 전체 데이터베이스 목록을 확인할 수 있습니다. 방금 전 생성한 데이터베이스가 목록에 뜨지 않는 이유는 데이터가 하나도 저장되어 있지 않기 때문입니다.

4. insert() 메소드를 이용하여 생성한 데이터베이스에 데이터를 저장해줍니다.

5. 다시 목록 조회를 하면 생성한 데이터베이스가 뜨는것을 확인할 수 있습니다.

6. find() 메소드를 이용하여 mydb에 있는 데이터를 조회하면, 방금전에 저장한 데이터를 확인할 수 있습니다.

7. 생성한 데이터베이스는 db.dropDatabase() 명령어로 삭제할 수 있습니다.



2.컬렉션 생성


1. db.createCollection() 명령어로 collection1 이라는 컬렉션을 만들었습니다. 

2. show collections 명령어로 현재 컬렉션 목록을 확인할 수 있습니다.

3. 컬렉션을 만들 때, 선택적으로 옵션값을 파라미터로 줄 수 있습니다.

4. db.createCollection(name, options) 명령어로 컬렉션을 생성할 수 있습니다. 두 개의 파라미터에 대한 설명은 다음과 같습니다.

 - name(String) : 생성될 컬렉션의 이름

 - options(Document): (선택적) 메모리 사이즈나 인덱싱에 관한 설정을 지정


collections을 생성할 때 options는 선택적이기 때문에, 생략해도 무방합니다. 옵션에서는 다음과 같은 항목을 설정할 수 있습니다.

 필드

타입 

설명 

 capped

Boolean true라면, 컬렉션의 한도를 지정할 수 있습니다. 한도가 정해진 컬렉션(capped collection)은 사이즈가 고정된 컬렉션으로 지정한 맥시멈 사이즈에 도달하면 오래된 엔트리를 자동으로 덮어씌웁니다. 만약에 이 값을 true로 지정했다면, size 파라미터를 같이 설정해주어야 합니다.

 autoIndexId

Booleantrue라면, _id 필드에 자동으로 인덱스를 생성합니다. 디폴트값은 false입니다.

 size

number 

한도가 지정된 컬렉션의 사이즈를 지정합니다. 만약 capped 속성이 true 라면, 이 필드 또한 함께 지정해주어야 합니다. 

 max

number

한도가 지정된 컬렉션에서 도큐먼트의 최대값(maximum number)을 지정합니다. 

도큐먼트를 insert할 때, 몽고DB는 첫번째로 한도가 지정된 컬렉션의 사이즈 필드를 체크하고, 그 다음으로 max 필드를 체크합니다.


컬렉션을 수동으로 만들 수 있지만, 사실 별도로 만들 필요가 없습니다. 왜냐하면 도큐먼트를 저장할 때 자동으로 컬렉션이 생성되기 때문입니다. RDBMS로 말하자면 create table을 하지 않고, insert문을 실행하여 row를 추가하면 그 형태의 table이 만들어지는 것이라고 이해하면 좀 더 쉬울 것 같습니다.


5. db.COLLECTION_NAME.drop() 명령문으로 데이터베이스의 컬렉션을 삭제할 수 있습니다. 만약 입력한 컬렉션명이 존재한다면 true를 반환하고, 존재하지 않는 컬렉션명을 입력하면 false가 반환됩니다.




3.몽고DB의 데이터 타입

몽고DB에서는 다양한 데이터타입을 지원합니다.


데이터타입

 설명 

 String

데이터를 저장할 때 가장 흔하게 사용되는 데이터타입으로, 몽고DB에서 String은 UTF-8 인코딩방식을 사용합니다.

 Integer

숫자로된 값을 저장할 때 사용되며, 사용하는 서버에 따라서 Integer는 32bit 혹은 64bit가 될 수 있습니다.   

 Boolean

true/false 값을 저장할 때 사용됩니다. 

 Double

소수값을 저장할 때 사용됩니다. 

 Min/Max keys

가장 높거나 가장 낮은 BSON 엘리먼트와 값을 비교할 때 사용됩니다.

 Arrays

하나의 key에 배열,리스트 혹은 여러개의 값을 저장할 때 사용됩니다.

 Timestamp

ctimestamp. 도큐먼트가 변경되거나 추가될 때 기록을 위해 사용되면 편리합니다.

 Object

embedded document에 사용됩니다. 

 Null

Null 값을 저장할 때 사용됩니다. 

 Symbol

String과 동일하게 사용되지만, 보편적으로 특정한 symbol 타입을 사용한 언어를 위해 예약되어 있습니다. 

 Date 

현재 날짜와 시간을 UNIX 시간 포맷으로 저장할 때 사용됩니다. Date object를 만들어서 년,월,일을 입력하여 특정한 날짜와 시간을 지정할 수 있습니다. 

 Object ID

도큐먼트의 ID를 저장하기 위한 데이터타입입니다. 

 Binary Data

바이너리 데이터를 저장할 때 사용합니다. 

 Code

도큐먼트 안에 자바스크립트 코드를 저장할 때 사용됩니다. 

 Regular expression

정규표현식을 저장할 때 사용합니다. 



4. Document 삽입

컬렉션에 데이터를 저장하기 위해서는 insert() 혹은 save()메소드를 이용할 수 있습니다.


1. insert() 메소드에 파라미터로 도큐먼트를 입력하여 저장합니다. 만약 여러건의 도큐먼트라면 배열 형태로 한번에 저장할 수도 있습니다. ex) insert([{document1}, {document2}])

2. insert()와 save()메소드의 차이는 다음과 같습니다. 만약 _id를 별도로 지정하지 않는다면 save()메소드는 insert()와 동일한 역할을 합니다. 만약 _id를 지정한다면 save()메소드는 그 특정한 _id를 포함하는 도큐먼트의 모든 데이터를 입력한 데이터로 바꿔버립니다(replace).



5. Document 조회


1. find() 메소드를 사용하여 저장된 데이터를 조회할 수 있습니다.

2. pretty() 메소드를 덧붙이면 조회된 데이터들을 포맷팅한 형식으로 보여줍니다.

3. findOne() 메소드는 하나의 도큐먼트만 반환합니다.



6. MongoDB에서의 WHERE 절

 연산

syntax 

예시 

RDBMS 등가

 같음(Equality)

 {<key>:<value>}

 db.mydb.find({name:"sejin"})

 WHERE name = "sejin"

 보다 작음(Less Than)

 {<key>:{$lt:<value>}}

 db.mydb.find({age:{$lt:30}})

 WHERE age < 30

 같거나 작음(Less Than Equals)

 {<key>:{$lte:<value>}}

 db.mydb.find({age:{$lte:30}})

 WHERE age <= 30

 보다 큼(Greater Than)

 {<key>:{$gt:<value>}}

 db.mydb.find({age:{$gt:30}})

 WHERE age > 30

 같거나 큼(Greater Than Equals)

 {<key>:{$gte:<value>}}

 db.mydb.find({age:{$gte:30}})

 WHERE age >= 30

 같지 않음(Not Equals)

 {<key>:{$ne:<value>}}

 db.mydb.find({age:{$ne:30}})

 WHERE age != 30




1. find() 메소드 안에 찾을 조건 도큐먼트 형식으로 입력합니다. 

2. AND 조건은 콤마로 연결합니다.

3. OR 조건은 $or 키워드를 사용합니다. or 조건들을 배열 형식으로 입력합니다.

4. AND 조건과 OR 조건을 함꼐 사용할 때는 맨 아래의 두 구문처럼 쓸 수 있습니다.



7. Java에서 MongoDB사용하기

Java 프로그램에서 몽고DB를 사용하기 전에, MongoDB JDBC 드라이버를 준비해야합니다. 당연히 Java도 설치되어있어야겠죠? 그럼 이제 MongoDB JDBC 드라이버를 설치해보겠습니다. 저는 3.2.2 버전을 다운로드 하였습니다.(3.2.2 버전 다운로드 링크

리스트가 나오는데, 이 중에서 'mongo-java-driver-3.2.2.jar'를 다운로드 받으면 됩니다.


테스트할 Java Class를 만들고 코딩을 해보겠습니다. 다운받은 jar 파일은 라이브러리에 추가해줍니다.

3.2.2 버전에서는 예전에 2.x 버전과 접속하는 방법이 조금 달라졌습니다. 이전에는 DB라는 클래스를 사용해서 접속을 했었는데, 이제는 MongoDatabase라는 인터페이스를 사용합니다. 14라인 후에 조금 당황을 했는데, 그 이유는 컬렉션을 생성하지 않았기 때문입니다. getCollection()메소드에 파라미터로 컬렉션명을 입력해야 하는데 저는 컬렉션을 만들지 않았기 때문에 파라미터로 뭘 입력해야하는지 당황스러웠습니다. 구글링을 해보니 이런 경우가 나오지 않아 고민하던 중, 밑져야 본전이다! 생각하고 데이터베이스명을 넣었더니 결과가 잘 나왔습니다. 


전체 Document를 가지고 와서 루프를 돌며 Json 형태의 String으로 결과를 출력해보았더니, 만들었던 데이터들이 정상적으로 출력되었습니다.


조회뿐만 아니라 Java를 이용하여 데이터를 조작하는 것도 가능합니다. 그 부분은 저도 API를 살펴보며 직접 해봐야겠습니다.(몽고DB API링크) 이 포스트를 쓰면서 저도 공부가 많이 되었는데, 이 포스트를 읽는 분들에게도 조금이나마 도움이 되기를 바라며 포스트를 마치겠습니다. 감사합니다!! 






 


New Multi-Channel Dynamic CMS