MongoDB 처음 써보기

Damon Kwon·2022년 1월 20일
0

MongoDB를 아시나요

목록 보기
1/2
post-thumbnail

요즘 면접 보느라 매일매일 쏘다니는 중인데

👨 : 님? MongoDB 써봄?
👽 : 아.. 아뇨..!
👨 : (왜 왔냐는 듯이) ? 아 그러시면 mongoDB 관련 질문은 안하고...

후... 또 나의 빈부분이 꿰뚫리는 것 같았다.
그럼 간단하게 CRUD 정도만 해볼까? 하며 여러 블로그를 탐색하기 시작했다.

  1. MongoDB 소개, 설치 및 데이터 모델링
  2. 몽고+고랭으로 CRUD 구현하기
  3. MongoDB limit( ), skip() 메서드 이용해서 페이지네이션하기
  4. MongoDB 스키마 디자인: one-to-N 관계

Gopher였던 내게 가장 도움이 됐던 것은 2번, 몽고+고랭으로 CRUD 구현하기 였다. 물론 특정 언어를 너무 사랑하지 말라던 그.. 유명하신 분의 말이 있긴 하지만, 학부때 C++좀 했고.. 보안 하면서 Python도 좀 했으니.. 지금은 Go를 조금 사랑해도 되지 않을까요 선생님? (근데 왜 이렇게 Java는 정이 안들까)

각설하고, MongoDB 설치부터 간단한 쿼리 정도를 다뤄보겠다.

1. 설치

는 그냥 홈페이지에서 받으세요. 설치 짱쉬움 다운로드 링크

2. RDBMS랑 MongoDB 비교

근데 다 비교하면 너무 오래걸리니까 짧게 비교함. 30초도 안걸림.
RDBMS랑 MongDB는 명칭이랑 형태가 조금 다름.

NoSQL은 대개 Key/Value 형식의 구조를 가짐. 생긴거 보자마자 JSON 생각나야함.
MongoDB도 전통적인 NoSQL이라서 Key/Value 형식의 데이터 집합임.
위에서 말하는 Document라는게 결국 {}중괄호로 둘러싸인 하나의 Key/Value인거임.

			오 구조체처럼 생겼네

RDBMS

RDBMS에서 Table은 가로(라벨) 세로(속성)을 이용한 데이터 집합을 가짐.

사진 너무 괜찮아서 가져옴

MongoDB

근데 MongoDB는 그런거 없이, Key/Field 형식의 데이터 형식을 모아 하나의 Document가 됨. Document가 여러개 모이면 Collection이라고 함.

형태는 다른데 장단점이 있나?
어차피 MongoDB 글이니까 MongoDB 장단점만 보면,

  1. 수평 확장 가능한 분산 시스템
  2. Schema-less
  3. 완화된 ACID
  4. Open Source

RDBMS도 수평확장 가능한데 태생이 수평 확장을 지원하기 위해 만든 애들이 아니라서 좀 더 불편하다고 함. 근데 이미 30초도 지났고, 이런거 다 따지다간 데이터 저장하고 불러오는 정도로 끝내려던 글이 너무 길어질 것 같아서 여기서 뚝 끊겠음.
이 분 블로그에 글 잘 나와있음. 나머지는 여기서 보셈 (https://kciter.so/posts/about-mongodb)

3. Code Implementation

1. DB 연결

우선 DB부터 연결해야된다. MongoDB의 기본 포트는 27017이므로, 아래와 같이 입력하여 연결해준다.

func ConnectDB() (client *mongo.Client, err error) {
	clientOptions := options.Client().ApplyURI("mongodb://localhost:27017")
	client, err = mongo.Connect(context.TODO(), clientOptions)
	if err != nil {
		return nil, err
	}

	err = client.Ping(context.TODO(), nil)
	if err != nil {
		return nil, err
	}
	return
}
  1. options.Client() : 클라이언트에 연결할 정보를 입력한다.
  2. mongo.Connect() : Mongo 서버에 접속하고 client를 반환한다.
  3. client.Ping() : 잘 연결 되었는지 확인한다.

나중엔 auth를 위해 mongo server에 id, pw도 만들어줘야 하지만 지금은 안했다.

2. Write Data

아까 Key/Value 형태로 저장해야된다고 언급했다.
그리고 구조체 처럼 생겼다는 말도 살짝 흘렸다.

이를 통해 struct를 만들고 Field만 잘 맞춰준다면 Json 패키지로 마샬, 언마샬, 인코딩, 디코딩이 가능하지 않을까? 라는 생각이 들어야 된다.
맞음. 잘 된다.

{
  uuid:"dbslqjtjfdbslzmdkdlepsxlvlzpdltusdlfksmsdltkdgksanswkduf"
  name:"damon"
  age:100
  address:"서울 어딘가"
}

이렇게 생긴 json 파일이 있다고 하자.
이걸 Decoding하려면 아래와 같은 구조체를 만들어주면 된다.

type User struct{
	UUID	string	`json:"uuid"`
	Name 	string	`json:"name"`
	Age 	int64	`json:"age"`
 	Address	string	`json:"address"`
}

어쨌든 저 json 파일을 mongodb에 저장하려고한다면!

func Write(writeDB *mongo.Collection, docs User) {
	// 대충 공공api 비스무리한거로 json파일 받아왔다는 가정 하에
	err = json.NewDecoder(resp.Body).Decode(docs)
   
	num, err := writeDB.CountDocuments(nil, bson.M{"uuid": docs[i].uuid})
	if num > 0 {
		continue
	}

	_, err = writeDB.InsertOne(context.TODO(), docs[i])
	if err != nil {
		return
	}
}
  1. type User struct : json key/field와 동일한 구조의 구조체를 만들어준다.
  2. json.NewDecoder().Decode() : json파일을 구조체에 매핑한다.(디코딩)
  3. collection.CountDocuments() : Collection에 중복되는 uuid가 있는지 검사한다.
  4. collection.InsertOne() : Collection에 Document를 추가한다.

Write 쉽죠? 데이터 꺼내 쓸 때도 짱 쉽다.

3. Load Data

func Load(col *mongo.Collection, page int64) (docs []User) {
	findOptions := options.Find()
	findOptions.SetSort(bson.D{{"created_at", -1}})
	findOptions.SetLimit(20)
	findOptions.SetSkip((page - 1) * 20)

	res, err := col.Find(context.Background(), bson.D{}, findOptions)
	if err != nil {
		return
	}

	err = res.All(nil, &docs)
	if err != nil {
		return
	}
	return docs
}

그냥 꺼내기만 하면 좀 그러니까 옵션을 줘봤다.

  1. SetSort() : 생성 시간 정렬(오름차순, 내림차순)
  2. SetLimit() : 찾는 개수는 x개로 제한
  3. SetSkip() : 어느 위치부터 찾을건지 설정

그리고 실제 찾을 때는

  1. collection.Find(옵션들) : 데이터 찾기
  2. Find().ALl() : 디코딩

위와 같이 찾을 수 있었다. 솔직히 mongodb 처음 배우는 사람도 이정도는 30분이면 코딩할 수 있을거라 생각한다.

근데 왜 나는 과제 낼 때 skip 옵션 안쓰고 모든 데이터를 다 구조체로 디코딩한 다음 인덱싱했을까? 내자마자 30분이따가 바로 생각나는건 왜일까?

매일 매일 이불킥 할 거리 만들어내는 난 진짜 레전드다...

profile
👽 DevMyong, 신입 백엔드 개발자 🌊 myong.dev@gmail.com

0개의 댓글