Node.js 백엔드 스터디(7) - 몽고DB 사용하기
몽고DB 에 대한 나의 경험
이 전에 나의 경험은 Next.js와 몽고DB로 애플코딩의 Next.js 강좌를 참고하여, 공부한 내용을 블로그에 기록하고, Azure에 배포했던 경험까지 있다.
아래는 이전에 수행했던 링크이며, 중복되는 내용 외에 새로 알게된 내용 위주로 정리하려고 한다.
- 몽고DB 를 다루었었던 이전의 링크
1. 데이터베이스 기본 용어
기초 용어
- 테이블: 특정 주제에 대한 행과 열로 이루어진 데이터의 모음.
- 로우(row): 관계형 데이터베이스의 테이블에서 단일 구조 데이터 항목을 의미. 레코드라고 부름.
- 컬럼(column): 관계형 데이터베이스의 테이블에서 특정한 자료의 값 혹은 테이블에서 열을 의미.
- 기본키(Primary Key): 프라이머리키는 중복된 값을 가질 수 없다.데이터를 식별하는 데 필요한 키.
- 외래키(Foreign Key): 두 테이블을 연결하는데 사용하는 키.
- RDB(관계형 데이터베이스): 모든 데이터를 2차원의 테이블에 저장. 서로 다른 테이블 간에 조인 혹은 외래키로 관계를 맺을 수 있음.
- 스키마(schema): 데이터베이스 테이블의 명세를 기술한 데이터. 예를 들어, user라는 테이블을 생성 시 해당 테이블에는 문자열 20자 user_name, 숫자 4자리 age 등.
- 모델(model): 데이터베이스의 특정 테이블과 테이블에 있는 컬럼들의 형태를 정의한 클래스. user 테이블에 대하여 모델을 만든다면 User 클래스를 만들고, 변수로 string UserName, int age를 선언.
- 컬랙션(collection): 컬렉션은 몽고DB에서 사용하는 용어이며, 도큐먼트의 집합을 컬렉션이라고 한다. 관계형 데이터베이스의 테이블과 동일한 의미로 사용.
- 조인(join): 두 개 이상의 테이블 또는 컬렉션을 조합하여 데이터를 보여주는 기법.
- 트랜잭션(transaction): 데이터 변경을 수행하는 작업 단위.
알아두면 좋은 용어
- 클러스터(cluster): 데이터 처리량을 높일 목적으로 데이터를 여러 서버(샤드)에 저장하는 기법
- 샤드(shard): 큰 데이터베이스를 작은 단위로 분할하는 기능. 샤드를 사용하여 데이터를 작은 단위로 분할하여 노드(데이터를 가지고 있는 서버)에 분산시켜서 저장할 수 있다. 샤드를 사용하면 대규모 데이터베이스를 다루는 시스템에서 성능과 확장성을 향상시킬 수 있다.
순서 1. 몽고DB 연결하기
몽고디비 커넥션을 위해, 포털에 접속 Connect 메뉴를 통해 connection string을 아래와 같이 받아 Node 코드에서 실행한다.
const { MongoClient, ServerApiVersion } = require('mongodb');
// 1. 몽고DB 연결 정보
const uri = "mongodb+srv://<username>:<password>@cluster0.vbpuhau.mongodb.net/?retryWrites=true&w=majority";
// 2. 몽고DB 클라이언트 객체 생성
const client = new MongoClient(uri, {
serverApi: {
version: ServerApiVersion.v1,
strict: true,
deprecationErrors: true,
}
});
async function run() {
try {
// 3. 몽고DB 접속
await client.connect();
// 4. 연결 성공확인 위해 핑 1 보내기
await client.db("admin").command({ ping: 1 });
console.log("Pinged your deployment. You successfully connected to MongoDB!");
} finally {
// 5. 성공, 실패할 경우 연결 종료
await client.close();
}
}
run().catch(console.dir);
// 출력 결과
Pinged your deployment. You successfully connected to MongoDB!
몽고DB Connect를 위한, userName과 password 확인
아래 메뉴에서 user를 생성하거나 계정을 관리할 수 있다.
순서 2. 데이터베이스 정보를 출력 - 1
// test-connection2.js
const { MongoClient, ServerApiVersion } = require('mongodb');
const uri = "mongodb+srv://<username>:<password>@cluster0.vbpuhau.mongodb.net/?retryWrites=true&w=majority";
const client = new MongoClient(uri);
async function run() {
await client.connect();
const adminDB = client.db('test').admin(); // 1. admin DB 인스턴스
const listDatabases = await adminDB.listDatabases(); // 2. 데이터베이스 정보 가져오기
console.log(listDatabases);
console.log(listDatabases.databases[0]); // 이전에 생성해놓은 데이터베이스(forum)이 출력
console.log(listDatabases.databases[1]); // 기본적으로 생성되어있는 디폴트 데이터베이스(admin)이 출력
console.log(listDatabases.databases[2]); // 기본적으로 생성되어있는 디폴트 데이터베이스(local)이 출력
return "OK";
}
run() // 3. 실행 함수
.then(console.log)
.catch(console.error)
.finally(() => client.close());
// 출력 결과
{databases: Array(3), totalSize: 1888542720, totalSizeMb: 1801, ok: 1, $clusterTime: {…}, …}
{name: 'forum', sizeOnDisk: 221184, empty: false}
{name: 'admin', sizeOnDisk: 294912, empty: false}
{name: 'local', sizeOnDisk: 1888026624, empty: false}
OK
- admin()함수는 admin DB의 인스턴스를 가져올 수 있게 한다.
- admin DB인스턴스에는 listDatabases() 함수가 있고, 해당 함수를 실행하면 데이터베이스를 반환한다. 위 코드의 경우, 내가 이전에 생성했던 DB(forum)이 있기 때문에 기본 디폴트 DB(admin, local)와 함께 3개의 DB가 출력되었다.
★ 순서 3. 몽고DB - CRUD API 만들기
const MongoClient = require('mongodb').MongoClient;
// test로 데이터베이스 이름을 변경
const url = "mongodb+srv://<username>:<password>@cluster0.vbpuhau.mongodb.net/test?retryWrites=true&w=majority";
// 1. MongoClient 생성
const client = new MongoClient(url, { useNewUrlParser: true });
async function main() {
try {
// 2. 커넥션을 생성하고 연결 시도
await client.connect();
console.log('MongoDB 접속 성공');
// 3. test 데이터베이스의 person 컬렉션 가져오기
// 만약, test 데이터베이스와 person 컬렉션이 없다면 새로 생성
const collection = client.db('test').collection('person');
// 4. 문서 하나 추가
await collection.insertOne({ name: 'Andy', age: 30 });
console.log('문서 추가 완료');
// 5. 문서 찾기
const documents = await collection.find({ name: 'Andy' }).toArray();
console.log('찾은 문서:', documents);
// 6. 문서 갱신하기
await collection.updateOne({ name: 'Andy' }, { $set: { age: 31 } });
console.log('문서 업데이트');
// 7. 갱신된 문서 확인하기
const updatedDocuments = await collection.find({ name: 'Andy' }).toArray();
console.log('갱신된 문서: ', updatedDocuments);
// 8. 문서 삭제하기
// await collection.deleteOne({ name: 'Andy' });
// console.log('문서 삭제');
// 연결 끊기
await client.close();
} catch (err) {
console.error(err);
}
}
main();
// 출력 결과
MongoDB 접속 성공
문서 추가 완료
찾은 문서: (1) [{…}] // {_id: ObjectId, name: 'Andy', age: 31}
문서 업데이트
갱신된 문서: (1) [{…}] // {_id: ObjectId, name: 'Andy', age: 31}
1번. (설명 생략)
2번. (설명 생략)
3번. client.db(‘test’)는 test 데이터베이스를 사용한다는 뜻이고 collection(“person”)은 person 컬렉션을 사용한다는 뜻이다. 데이터베이스가 생성되어 있지 않으면 새로 생성한다.
4번. 문서를 하나 추가할 때는 insertOne() 함수를 사용하며 인수로는 JSON 형식의 객체를 넣는다.
5번. 문서 찾기에는 find() 함수를 사용한다. 예제에서는 이름이 ‘Andy’인 문서를 찾고, 결괏값이 여러 개일 수 있으므로 toArray() 함수를 사용해 배열로 반환한다.
6번. 문서를 갱신할 때는 갱신할 도큐먼트를 찾는 데 사용할 JSON 객체를 첫 번째 인수로 넣고, 두번째 인수에는 $set의 값으로 업데이트할 값을 넣는다. $set은 몽고디비의 연산자로 값을 필드에 지정할 때 사용한다.
몽고DB의 연산자
연산자 | 설명 |
---|---|
$set | 도큐먼트의 속성값을 변경할 때 사용 |
$unset | 도큐먼트의 속성을 삭제할 때 사용 |
$rename | 도큐먼트의 속성의 이름을 변경할 때 사용 |
$inc | 필드의 값을 증가시킬 때 사용 |
$mul | 필드의 값에 곱하기를 할 때 사용 |
$min | 지정한 값과 현잿값 중 작은 값을 선택 |
$max | 지정한 값과 현잿값 중 큰 값을 선택 |
$currentDate | 현재 날짜와 시간을 필드에 업데이트 |
$addToSet | 배열 필드가 아직 없는 경우 해당 필드에 값을 추가 |
$pop | 배열 필드에서 첫 번째 혹은 마지막 값을 삭제 |
$pull | 배열 필드에서 모든 값을 삭제 |
$push | 배열 필드의 끝에 값을 추가 |
$each | 여러 개의 값을 추가해 배열 필드를 수정 |
몽고DB-콤파스 사용
유니티와의 협업 프로젝트에서 몽고DB를 콤파스를 설치하여 확인했던 기억이 있다. 콤파스와 같은 GUI 프로그램을 사용하면 더 간편하게 확인할 수 있다. 사용법은 간단하기에 생략하겠다.
정리
‘★ 순서 3. 몽고DB - CRUD API 만들기’의 코드는 실무 DB를 만들 때, 참고하면 좋을 것 같아 큰 도움이 되었다. 프로젝트 시, 참고하도록 하자.
참고
다음에 다루게 될 것
- 몽구스를 사용해 CRUD 만들기
댓글남기기