-
Golang에서 MongoDB 연결하기 - MongoDB Go Driver 설치IT 생활/Go 프로그래밍 2020. 7. 6. 00:45
안녕하세요 류똥구입니다.
Golang에 대한 간단한 문법 공부를 하고 웹프레임워크도 설치했었는데요. 이제는 간단하게나마 Golang으로 웹서버를 만들수 있겠죠? 개인프로젝트로 만들 웹서비스는 Golang으로 backend를 개발하고 웹 데이터베이스로 MognoDB를 사용하고 frontend로는 react를 이용하려고 합니다.
이전 홈서버로 사용하는 제 맥미니에서 docker로 MongoDB를 설치하는 것을 포스팅했었는데요.
그래서 오늘은 Golang에서 MongoDB를 연결하여 사용하는 것에 대해서 다뤄보려고 합니다.
MongoDB의 공식 블로그의 내용을 따라가면서 설명하도록 하겠습니다.
https://www.mongodb.com/blog/post/mongodb-go-driver-tutorial
MongoDB Go Driver 설치
MongoDB에서 Golang을 위해서 MongoDB connection 패키지인 MognoDB Go Driver를 제공하고 있는데요. MongoDB 블로그의 설명에 따르면 MognoDB Go Driver가 상용에서 사용해도 될 정도의 완성도라고 합니다.
아래 명령으로 MognoDB Go Driver를 설치합니다.
$ go get go.mongodb.org/mongo-driver/mongo
MongoDB Go Driver 패키지 사용
설치한 MongoDB Go Driver는 다른 패키지들과 마찬가지로 import해서 사용하면 되며 go.mongodb.org/mongo-driver/<패키지 이름> 로 import 해서 사용할 수 있습니다.
package main import ( "context" "fmt" "log" // MongoDB driver import "go.mognodb.org/mongo-driver/mongo" "go.mongodb.org/mongo-driver/mongo/options" ) func main() { // DB 작업 코드 추가 }
MongoDB Go Driver에 대한 정보는 MongoDB에서 제공하고 있으므로 자세히 알아보고 싶으신 분들은 아래 링크를 참고 하시면 됩니다.
https://godoc.org/go.mongodb.org/mongo-driver
MongoDB 연결
MongoDB Go Driver의 mongo.Connect() 함수를 이용하면 MongoDB에 연결할 수 있습니다. mongo.Connect() 함수에는 매개변수로 context와 options.ClientOptions가 필요합니다.
package main import ( "context" "fmt" "log" // MongoDB driver import "go.mognodb.org/mongo-driver/mongo" "go.mongodb.org/mongo-driver/mongo/options" ) func main() { // 접속할 MongoDB 주소 설정 clientOptions := options.Client().ApplyURI("mongodb://localhost:27017") // MongoDB 연결 client, err := mongo.Connect(context.TODO(), clientOptions) if err != nil { log.Fatal(err) } // 연결 확인 err = client.Ping(context.TODO(), nil) if err != nil { log.Fatal(err) } fmt.Println("Connected to MongoDB!") // MongㅐDB 연결 종료 err = client.Disconnect(context.TODO()) if err != nil { log.Fatal(err) } fmt.Println("Connection to MongoDB closed.") }
여기까지 작성한 프로그램이 정상적으로 실행이 된다면 MongoDB에 연결이 되는 것을 확인 할 수 있습니다.
그럼 이제 MongoDB에 데이터 작업을 해보도록 합시다.
BSON 사용
mongoDB에서는 데이터를 JSON형식을 사용하여 표현합니다. JSON은 텍스트 기반의 데이터 형식이라 DB에서 저장할 데이터 형식으로 바로 사용하기 무리가 있습니다. 그래서 mongoDB에서는 JSON 형식의 데이터를 바이너리로 변환하여 저장합니다. 이렇게 바이너리로 변환하여 사용하는 JSON을 Binary-encoded JSON이라 하여 BSON이라 부릅니다. BSON에서는 JSON으로 표현되는 자료형을 문자열뿐만 아니라 int, long, date, floating point, decimal128로 표현하여 보다 효율적으로 저장할 수 있고 데이터 처리를 효과적으로 할 수 있게 해줍니다.
Go driver에서는 BSON을 두 가지 D type과 raw type으로 처리합니다. Raw 타입은 이름 그대로 BSON 데이터를 byte로 처리할 때 사용합니다. BSON 문서 전체를 Golang 형식으로 변환후 처리하지 않고 문서 내 항목을 따로 읽어서 처리할 때 raw 타입을 사용합니다. D type은 Golang의 자료형과 mongoDB의 자료형과 연결지을 때 사용합니다. D type에는 다음 4가지가 있습니다.
- D: 순서를 가지는 BSON 문서 (slice)
- M: 순서를 갖지않는 BSON 문서 (map)
- A: 순서를 가지는 BSON 배열
- E: D type (BSON 문서) 내의 한 항목
BSON에 대한 자세한 내용은 MongoDB의 문서를 참고하시기 바랍니다.
https://www.mongodb.com/docs/manual/reference/bson-types/
다음은 "name"의 값이 "Alice" 또는 "Bob"인 문서를 찾는 filter 문서 예시를 나타냅니다.
bson.D{{ "name", bson.D{{ "$in", bson.A{"Alice", "Bob"} }} }}
CRUD 동작 구현
Golang에서 DB에 연결 후 자료를 추가하거나 수정하는 작업을 하게 됩니다. MongoDB Go driver에서는 Collection 타입을 이용하여 데이터베이스에 자료 조회, 생성, 수정, 삭제를 할 수 있습니다.
문서 생성
MongoDB에 저장할 문서 (데이터) 형태를 구조체로 정의하고 MongoDB driver를 통해서 생성을 할 수 있습니다.
package main import ( "context" "fmt" "log" // MongoDB driver import "go.mongodb.org/mongo-driver/mongo" "go.mongodb.org/mongo-driver/mongo/options" ) // MongoDB에 저장할 데이터 type Trainer struct { Name string Age int City string } func main() { // 접속할 MongoDB 주소 설정 clientOptions := options.Client().ApplyURI("mongodb://localhost:27017") // MongoDB 연결 client, err := mongo.Connect(context.TODO(), clientOptions) if err != nil { log.Fatal(err) } // 연결 확인 err = client.Ping(context.TODO(), nil) if err != nil { log.Fatal(err) } fmt.Println("Connected to MongoDB!") // "test" 데이터베이스 내 trainers라는 콜렉션과 연결 collection := client.Database("test").Collection("trainers") // MongoDB에 저장할 데이터 생성 ash := Trainer{"Ash", 10, "Pallet Town"} // MongoDB에 데이터 저장 createResult, err := collection.InsertOne(context.TODO(), ash) if err != nil { log.Fatal(err) } fmt.Println("Inserted a single document: ", createResult.InsertedID) // MongoDB 연결 종료 err = client.Disconnect(context.TODO()) if err != nil { log.Fatal(err) } fmt.Println("Connection to MongoDB closed.") }
위 예시에서는 트레이너의 이름, 나이 그리고 사는 곳을 포함하는 구조체를 사용하여 Ash라는 트레이너 데이터를 생성하였다.
MongoDB driver로 "test"라는 database 내에 "trainers"라는 콜렉션에 연결을 해 줍니다. 콜렉션은 관계형 DB의 테이블과 같이 데이터 (문서)를 저장하는 곳이라고 생각하면 됩니다. MongoDB 내에 "test" database가 존재하지 않으면 새로 database를 생성하고 콜렉션도 존재하지 않는다면 문서를 생성할 때 같이 생성됩니다. InsertOne 함수로 생성한 트레이너 데이터를 MongoDB에 생성 (저장)하게 됩니다. 여러 개의 데이터를 저장하기 위해서는 InsertMany 함수를 사용하면 되고 데이터로 배열을 전달하면 됩니다.
작성한 Go 프로그램을 실행하고 나서 MongoDB에 접속하면 위와 같이 트레이너 정보가 생성되어 있는 것을 알 수 있습니다.
문서 수정
문서 수정은 UpdateOne 함수를 통해서 할 수 있습니다. UpdateOne 함수는 문서 조회를 위한 필터와 수정 내역을 매개변수로 받습니다.
package main import ( "context" "fmt" "log" // MongoDB driver import "go.mongodb.org/mongo-driver/bson" "go.mongodb.org/mongo-driver/mongo" "go.mongodb.org/mongo-driver/mongo/options" ) // MongoDB에 저장할 데이터 type Trainer struct { Name string Age int City string } func main() { // 접속할 MongoDB 주소 설정 clientOptions := options.Client().ApplyURI("mongodb://localhost:27017") // MongoDB 연결 client, err := mongo.Connect(context.TODO(), clientOptions) if err != nil { log.Fatal(err) } // 연결 확인 err = client.Ping(context.TODO(), nil) if err != nil { log.Fatal(err) } fmt.Println("Connected to MongoDB!") // "test" 데이터베이스 내 trainers라는 콜렉션과 연결 collection := client.Database("test").Collection("trainers") // MongoDB에서 수정할 데이터 조건 및 수정 내역 filter := bson.D{{"name", "Ash"}} update := bson.D{ {"$inc", bson.D{ {"age", 1}, }}, } // MongoDB에 데이터 업데이트 updateResult, err := collection.UpdateOne(context.TODO(), filter, update) if err != nil { log.Fatal(err) } fmt.Printf("Matched %v documents and updated %v documents.\n", updateResult.MatchedCount, updateResult.ModifiedCount) // MongoDB 연결 종료 err = client.Disconnect(context.TODO()) if err != nil { log.Fatal(err) } fmt.Println("Connection to MongoDB closed.") }
bson.D를 통해서 조회 조건 filter를 생성하였다. filter를 통해서 name값이 "Ash"인 문서만 추려내게 됩니다.
이후 $inc로 "age"의 값을 1증가 시키는 명령을 update로 만들어 줬습니다.
트레이너 "Ash"의 age값이 11로 1증가 한 것을 확인 할 수 있습니다.
문서 조회
MongoDB에 저장되어 있는 문서를 조회할 때는 Find함수를 사용하면 됩니다. Find함수를 이용하면 조회 조건에 맞는 모든 문서를 Cursor로 반환합니다. Cursor를 통해서 순회하면서 반환된 문서값을 decoding하여 값을 참조할 수 있습니다.
단일문서를 조회할 때는 FindOne함수를 사용하면 됩니다.
package main import ( "context" "fmt" "log" // MongoDB driver import "go.mongodb.org/mongo-driver/bson" "go.mongodb.org/mongo-driver/mongo" "go.mongodb.org/mongo-driver/mongo/options" ) // MongoDB에 저장할 데이터 type Trainer struct { Name string Age int City string } func main() { // 접속할 MongoDB 주소 설정 clientOptions := options.Client().ApplyURI("mongodb://localhost:27017") // MongoDB 연결 client, err := mongo.Connect(context.TODO(), clientOptions) if err != nil { log.Fatal(err) } // 연결 확인 err = client.Ping(context.TODO(), nil) if err != nil { log.Fatal(err) } fmt.Println("Connected to MongoDB!") // "test" 데이터베이스 내 trainers라는 콜렉션과 연결 collection := client.Database("test").Collection("trainers") // MongoDB에서 조회할 데이터 조건 filter := bson.D{{"name", "Ash"}} // MongoDB에 데이터 조회 var result Trainer err = collection.FindOne(context.TODO(), filter).Decode(&result) if err != nil { log.Fatal(err) } fmt.Printf("Found a single document: %+v\n", result) // MongoDB 연결 종료 err = client.Disconnect(context.TODO()) if err != nil { log.Fatal(err) } fmt.Println("Connection to MongoDB closed.") }
FindOne함수에 조회 조건을 매개변수로 전달하면 일치하는 문서 중 처음 것을 반환하게 됩니다.
MongoDB에서 조회된 값이 decoding되어 trainer 구조체로 저장되게 됩니다. 작성한 Go 프로그램을 실행하면 위와 같이 MongoDB에서 앞서서 확인 것과 동일한 값을 출력하는 것을 볼 수 있습니다.
문서 삭제
MongoDB에서 문서를 삭제할 때는 DeleteOne 또는 DeleteMany 함수를 사용하면 됩니다.
이름 그대로 단일 문서를 삭제할 때 DeleteOne함수를 사용하고 다수의 문서를 삭제할 때 DeleteMany 함수를 사용하면 됩니다.
Delete 함수는 조회필터를 매개변수로 전달해주면 일치하는 문서를 삭제해줍니다.
package main import ( "context" "fmt" "log" // MongoDB driver import "go.mongodb.org/mongo-driver/bson" "go.mongodb.org/mongo-driver/mongo" "go.mongodb.org/mongo-driver/mongo/options" ) // MongoDB에 저장할 데이터 type Trainer struct { Name string Age int City string } func main() { // 접속할 MongoDB 주소 설정 clientOptions := options.Client().ApplyURI("mongodb://localhost:27017") // MongoDB 연결 client, err := mongo.Connect(context.TODO(), clientOptions) if err != nil { log.Fatal(err) } // 연결 확인 err = client.Ping(context.TODO(), nil) if err != nil { log.Fatal(err) } fmt.Println("Connected to MongoDB!") // "test" 데이터베이스 내 trainers라는 콜렉션과 연결 collection := client.Database("test").Collection("trainers") // MongoDB에 데이터 삭제 deleteResult, err := collection.DeleteMany(context.TODO(), bson.D{{}}) if err != nil { log.Fatal(err) } fmt.Printf("Deleted %v documents in the trainers collection\n", deleteResult.DeletedCount) // MongoDB 연결 종료 err = client.Disconnect(context.TODO()) if err != nil { log.Fatal(err) } fmt.Println("Connection to MongoDB closed.") }
위 예시에서는 삭제할 문서 조건에 {}를 전달하여 모든 문서를 삭제합니다.
작성한 Go 프로그램을 실행하면 이전에 생성하였던 "Ash" 트레이너 정보가 삭제되어 있는 것을 확인 할 수 있습니다.
이상으로 Go 프로그램에서 MongoDB driver를 사용하여 MongoDB에 연결하고 문서 (데이터)를 조작하는 방법에 대해서 알아보았습니다. 그럼 다음에도 도움이 될만한 Golang 글을 가져오도록 하겠습니다.
'IT 생활 > Go 프로그래밍' 카테고리의 다른 글
[vim-go] vim에 go 플러그인 설치하기 (0) 2021.12.12 Go 프레임워크 - echo 설치하기 (0) 2020.06.19 Go 개발환경 구축하기 - 우분투 Atom 설치 및 Go 플러그인 설치 (0) 2020.06.11 Golang 초보자를 위한 유용한 사이트 (0) 2020.06.10 GO 언어 시작하기 (0) 2020.04.01