๋ฌธ์ ํ โ ์ ํ๋ฆฌ์ผ์ด์ ๊ฐ๋ฐ โ MongoDB ๋๋ผ์ด๋ฒ โ Go ๋๋ผ์ด๋ฒ
GridFS.
์ด ํ์ด์ง์ ๋ด์ฉ
๊ฐ์
์ด ๊ฐ์ด๋์์๋ GridFS ์ฌ์์ ์ฌ์ฉํ์ฌ MongoDB์ ๋์ฉ๋ ํ์ผ์ ์ ์ฅํ๊ณ ์กฐํํ๋ ๋ฐฉ๋ฒ์ ๋ํด ์ค๋ช ํฉ๋๋ค. GridFS๋ ๋์ฉ๋ ํ์ผ์ ์ฒญํฌ๋ก ๋ถํ ํ๊ณ ๊ฐ ์ฒญํฌ๋ฅผ ๋ณ๋์ ๋ฌธ์๋ก ์ ์ฅํฉ๋๋ค. GridFS์ ํ์ผ์ ์ฟผ๋ฆฌํ๋ฉด ๋๋ผ์ด๋ฒ๊ฐ ํ์์ ๋ฐ๋ผ ์ฒญํฌ๋ฅผ ์กฐ๋ฆฝํฉ๋๋ค. GridFS์ ๋๋ผ์ด๋ฒ ๊ตฌํ์ ํ์ผ ์คํ ๋ฆฌ์ง์ ์ด์๊ณผ ๊ตฌ์ฑ์ ๊ด๋ฆฌํ๋ ์ถ์ํ์ ๋๋ค.
ํ์ผ ํฌ๊ธฐ๊ฐ BSON ๋ฌธ์ ํฌ๊ธฐ ์ ํ์ธ 16 MB๋ฅผ ์ด๊ณผํ๋ ๊ฒฝ์ฐ GridFS๋ฅผ ์ฌ์ฉํ์ธ์. ๋ํ GridFS๋ฅผ ์ฌ์ฉํ๋ฉด ์ ์ฒด ํ์ผ์ ๋ฉ๋ชจ๋ฆฌ์ ๋ก๋ํ์ง ์๊ณ ๋ ํ์ผ์ ์ก์ธ์คํ ์ ์์ต๋๋ค. GridFS๊ฐ ์ฌ์ฉ ์ฌ๋ก์ ์ ํฉํ์ง ์ฌ๋ถ์ ๋ํ ์์ธํ ๋ด์ฉ์ GridFS ์๋ฒ ๋งค๋ด์ผ ํ์ด์ง๋ฅผ ์ฐธ์กฐํ์ธ์.
GridFS ์๋ ๋ฐฉ์
GridFS๋ ํ์ผ ์ฒญํฌ์ ํ์ผ์ ์ค๋ช ํ๋ ์ ๋ณด๊ฐ ๋ค์ด ์๋ MongoDB ์ปฌ๋ ์ ๊ทธ๋ฃน์ธ ๋ฒํท์ ํ์ผ์ ๊ตฌ์ฑํฉ๋๋ค. ๋ฒํท์๋ ๋ค์๊ณผ ๊ฐ์ ์ปฌ๋ ์ ์ด ํฌํจ๋์ด ์์ต๋๋ค.
๋ฐ์ด๋๋ฆฌ ํ์ผ ์ฒญํฌ๋ฅผ ์ ์ฅํ๋
chunks
์ปฌ๋ ์ .ํ์ผ ๋ฉํ๋ฐ์ดํฐ๋ฅผ ์ ์ฅํ๋
files
์ปฌ๋ ์ .
์ GridFS ๋ฒํท์ ์์ฑํ๋ฉด ๋๋ผ์ด๋ฒ๋ ์์ ์ค๋ช
ํ ์ปฌ๋ ์
์ ์์ฑํฉ๋๋ค. ๋ค๋ฅธ ๋ฒํท ์ด๋ฆ์ ์ง์ ํ์ง ์๋ ํ ๊ธฐ๋ณธ ๋ฒํท ์ด๋ฆ์ธ fs
๊ฐ ์ปฌ๋ ์
์ด๋ฆ ์์ ๋ถ์ต๋๋ค. ๋๋ผ์ด๋ฒ๋ ์ฒซ ๋ฒ์งธ ์ฐ๊ธฐ ์์
์ค์ ์ GridFS ๋ฒํท์ ์์ฑํฉ๋๋ค.
๋ํ ๋๋ผ์ด๋ฒ๋ ํ์ผ ๋ฐ ๊ด๋ จ ๋ฉํ๋ฐ์ดํฐ๋ฅผ ํจ์จ์ ์ผ๋ก ๊ฒ์ํ ์ ์๋๋ก ๊ฐ ์ปฌ๋ ์ ์ ์ธ๋ฑ์ค๋ฅผ ์์ฑํฉ๋๋ค. ์ธ๋ฑ์ค๊ฐ ์์ง ์กด์ฌํ์ง ์๊ฑฐ๋ ๋ฒํท์ด ๋น์ด ์๋ ๊ฒฝ์ฐ ๋๋ผ์ด๋ฒ๊ฐ ์ธ๋ฑ์ค๋ฅผ ์์ฑํฉ๋๋ค. GridFS ์ธ๋ฑ์ค์ ๋ํ ์์ธํ ๋ด์ฉ์ GridFS ์ธ๋ฑ์ค์ ๋ํ ์๋ฒ ๋งค๋ด์ผ ํ์ด์ง๋ฅผ ์ฐธ์กฐ ํ์ธ์.
GridFS๋ก ํ์ผ์ ์ ์ฅํ ๋ ๋๋ผ์ด๋ฒ๋ ํ์ผ์ ์์ ์ฒญํฌ๋ก ๋ถํ ํ๋ฉฐ, ๊ฐ๊ฐ์ ์ฒญํฌ๋ chunks
์ปฌ๋ ์
์์ ๋ณ๋์ ๋ฌธ์๋ก ํ์๋ฉ๋๋ค. ๋ํ files
์ปฌ๋ ์
์ ํ์ผ ID, ํ์ผ ์ด๋ฆ ๋ฐ ๊ธฐํ ํ์ผ ๋ฉํ๋ฐ์ดํฐ๊ฐ ํฌํจ๋ ๋ฌธ์๋ฅผ ๋ง๋ญ๋๋ค. ๋ค์ ๋ค์ด์ด๊ทธ๋จ์ GridFS๊ฐ ์
๋ก๋๋ ํ์ผ์ ๋ถํ ํ๋ ๋ฐฉ๋ฒ์ ๋ณด์ฌ์ค๋๋ค.
GridFS๋ ํ์ผ์ ์กฐํํ ๋ ์ง์ ๋ ๋ฒํท์ files
์ปฌ๋ ์
์์ ๋ฉํ๋ฐ์ดํฐ๋ฅผ ๊ฐ์ ธ์จ ๋ค์, ํด๋น ์ ๋ณด๋ฅผ ์ฌ์ฉํ์ฌ chunks
์ปฌ๋ ์
์ ๋ฌธ์์์ ํ์ผ์ ์ฌ๊ตฌ์ฑํฉ๋๋ค. ํ์ผ์ ๋ฉ๋ชจ๋ฆฌ์ ์
๋ ฅํ๊ฑฐ๋ ์คํธ๋ฆผ์ ์ถ๋ ฅํ ์ ์์ต๋๋ค.
GridFS ์ฌ์ฉ
GridFS ์์ ๊ณผ ์ด๋ฅผ ์ํํ๋ ๋ฐฉ๋ฒ์ ์์๋ณด๋ ค๋ฉด ๋ค์ ์น์ ์ผ๋ก ์ด๋ํ์ธ์.
GridFS ๋ฒํท ๋ง๋ค๊ธฐ
GridFS์์ ํ์ผ์ ์ ์ฅํ๊ฑฐ๋ ์กฐํํ๋ ค๋ฉด ๋ฒํท์ ๋ง๋ค๊ฑฐ๋ MongoDB ๋ฐ์ดํฐ๋ฒ ์ด์ค์์ ๊ธฐ์กด ๋ฒํท์ ๋ํ ์ฐธ์กฐ๋ฅผ ๊ฐ์ ธ์ค๋ฉด ๋ฉ๋๋ค. GridFSBucket
์ธ์คํด์ค๋ฅผ ๋ง๋ค๋ ค๋ฉด ๋ฐ์ดํฐ๋ฒ ์ด์ค ๋งค๊ฐ ๋ณ์๋ฅผ ์ฌ์ฉํ์ฌ NewBucket()
๋ฉ์๋๋ฅผ ํธ์ถํฉ๋๋ค.
db := client.Database("db") bucket, err := gridfs.NewBucket(db) if err != nil { panic(err) }
์ฐธ๊ณ
GridFS ๋ฒํท์ด ์ด๋ฏธ ์๋ ๊ฒฝ์ฐ NewBucket()
๋ฉ์๋๋ ์ ๋ฒํท์ ์ธ์คํด์คํํ๋ ๋์ ๋ฒํท์ ๋ํ ์ฐธ์กฐ๋ฅผ ๋ฐํํฉ๋๋ค.
๊ธฐ๋ณธ์ ์ผ๋ก ์ ๋ฒํท์ ์ด๋ฆ์ fs
์
๋๋ค. ์ฌ์ฉ์ ์ง์ ์ด๋ฆ์ผ๋ก ๋ฒํท์ ์ธ์คํด์คํํ๋ ค๋ฉด ๋ค์๊ณผ ๊ฐ์ด BucketOptions
์ธ์คํด์ค์์ SetName()
๋ฉ์๋๋ฅผ ํธ์ถํฉ๋๋ค.
db := client.Database("db") opts := options.GridFSBucket().SetName("custom name") bucket, err := gridfs.NewBucket(db, opts) if err != nil { panic(err) }
ํ์ผ ์ ๋ก๋
๋ค์ ๋ฐฉ๋ฒ ์ค ํ๋๋ฅผ ์ฌ์ฉํ์ฌ GridFS ๋ฒํท์ ํ์ผ์ ์ ๋ก๋ํ ์ ์์ต๋๋ค.
์ ๋ ฅ ์คํธ๋ฆผ์์ ์ฝ๋
UploadFromStream()
๋ฉ์๋๋ฅผ ์ฌ์ฉํฉ๋๋ค.์ถ๋ ฅ ์คํธ๋ฆผ์ ์ฐ๋
OpenUploadStream()
๋ฉ์๋๋ฅผ ์ฌ์ฉํฉ๋๋ค.
๋ ์
๋ก๋ ํ๋ก์ธ์ค์์ ์ธ์คํด์ค์ ๋ํ ๊ตฌ์ฑ ์ ๋ณด๋ฅผ ์ง์ ํ ์ UploadOptions
์์ต๋๋ค.UploadOptions
ํ๋์ ์ ์ฒด ๋ชฉ๋ก์ API ์ค๋ช
์๋ฅผ ์ฐธ์กฐํ์ธ์.
์ ๋ ฅ ์คํธ๋ฆผ์ ์ฌ์ฉํ์ฌ ์ ๋ก๋
์
๋ ฅ ์คํธ๋ฆผ์ ์ฌ์ฉํ์ฌ ํ์ผ์ ์
๋ก๋ํ๋ ค๋ฉด ๋ค์ ๋งค๊ฐ ๋ณ์์ ํจ๊ป UploadFromStream()
๋ฉ์๋๋ฅผ ์ฌ์ฉํฉ๋๋ค.
ํ์ผ ์ด๋ฆ
์ด๋ฆฐ ํ์ผ์ ๋งค๊ฐ ๋ณ์๋ก ์ฌ์ฉํ๋
io.Reader
UploadFromStream()
์ ๋์์ ์์ ํ๋ ์ ํ์ opts
๋งค๊ฐ ๋ณ์
๋ค์ ์ฝ๋ ์์์์๋ file.txt
๋ผ๋ ํ์ผ์์ ์ฝ๊ณ ์ฝํ
์ธ ๋ฅผ GridFS ๋ฒํท์ ์
๋ก๋ํฉ๋๋ค. opts
๋งค๊ฐ ๋ณ์๋ฅผ ์ฌ์ฉํ์ฌ ํ์ผ ๋ฉํ๋ฐ์ดํฐ๋ฅผ ์ค์ ํฉ๋๋ค.
file, err := os.Open("path/to/file.txt") uploadOpts := options.GridFSUpload().SetMetadata(bson.D{{"metadata tag", "first"}}) objectID, err := bucket.UploadFromStream("file.txt", io.Reader(file), uploadOpts) if err != nil { panic(err) } fmt.Printf("New file uploaded with ID %s", objectID)
์ถ๋ ฅ ์คํธ๋ฆผ์ ์ฌ์ฉํ์ฌ ์ ๋ก๋
์ถ๋ ฅ ์คํธ๋ฆผ์ ์ฌ์ฉํ์ฌ ํ์ผ์ ์
๋ก๋ํ๋ ค๋ฉด ๋ค์ ๋งค๊ฐ ๋ณ์์ ํจ๊ป OpenUploadStream()
๋ฉ์๋๋ฅผ ์ฌ์ฉํฉ๋๋ค.
ํ์ผ ์ด๋ฆ
OpenUploadStream()
์ ๋์์ ์์ ํ๋ ์ ํ์ opts
๋งค๊ฐ ๋ณ์
๋ค์ ์ฝ๋ ์์์์๋ GridFS ๋ฒํท์์ ์
๋ก๋ ์คํธ๋ฆผ์ ์ด๊ณ opts
๋งค๊ฐ ๋ณ์๋ฅผ ์ฌ์ฉํ์ฌ ๊ฐ ์ฒญํฌ์ ๋ฐ์ดํธ ์๋ฅผ ์ค์ ํฉ๋๋ค. ๊ทธ๋ฌ๋ฉด file.txt
์ ์ฝํ
์ธ ์ Write()
๋ฉ์๋๊ฐ ํธ์ถ๋์ด ํด๋น ์ฝํ
์ธ ๊ฐ ์คํธ๋ฆผ์ ๊ธฐ๋ก๋ฉ๋๋ค.
file, err := os.Open("path/to/file.txt") if err != nil { panic(err) } // Defines options that specify configuration information for files // uploaded to the bucket uploadOpts := options.GridFSUpload().SetChunkSizeBytes(200000) // Writes a file to an output stream uploadStream, err := bucket.OpenUploadStream("file.txt", uploadOpts) if err != nil { panic(err) } fileContent, err := io.ReadAll(file) if err != nil { panic(err) } var bytes int if bytes, err = uploadStream.Write(fileContent); err != nil { panic(err) } fmt.Printf("New file uploaded with %d bytes written", bytes)
ํ์ผ ์ ๋ณด ๊ฒ์
GridFS ๋ฒํท์ files
์ปฌ๋ ์
์ ์ ์ฅ๋ ํ์ผ ๋ฉํ๋ฐ์ดํฐ๋ฅผ ์กฐํํ ์ ์์ต๋๋ค. files
์ปฌ๋ ์
์ ๊ฐ ๋ฌธ์์๋ ๋ค์ ์ ๋ณด๊ฐ ํฌํจ๋์ด ์์ต๋๋ค.
ํ์ผ ID
ํ์ผ ๊ธธ์ด
์ต๋ ์ฒญํฌ ํฌ๊ธฐ
์ ๋ก๋ ๋ ์ง ๋ฐ ์๊ฐ
ํ์ผ ์ด๋ฆ
๋ค๋ฅธ ์ ๋ณด๋ฅผ ์ ์ฅํ ์ ์๋
metadata
๋ฌธ์์ ๋๋ค.
ํ์ผ ๋ฐ์ดํฐ๋ฅผ ์กฐํํ๋ ค๋ฉด GridFSBucket
์ธ์คํด์ค์์ Find()
๋ฉ์๋๋ฅผ ํธ์ถํฉ๋๋ค. ํน์ ํ์ผ ๋ฌธ์๋ง ์ผ์น์ํค๋ ค๋ฉด ์ฟผ๋ฆฌ ํํฐ๋ฅผ Find()
์ ์ธ์๋ก ์ ๋ฌํ๋ฉด ๋ฉ๋๋ค.
์ฐธ๊ณ
Find()
๋ฉ์๋์์๋ ์ฟผ๋ฆฌ ํํฐ๋ฅผ ๋งค๊ฐ ๋ณ์๋ก ์ฌ์ฉํด์ผ ํฉ๋๋ค. files
์ปฌ๋ ์
์ ๋ชจ๋ ๋ฌธ์๋ฅผ ์ผ์น์ํค๋ ค๋ฉด ๋น ์ฟผ๋ฆฌ ํํฐ๋ฅผ Find()
์ ์ ๋ฌํฉ๋๋ค.
๋ค์ ์์์๋ files
์ปฌ๋ ์
์์ length
๊ฐ์ด 1500
๋ณด๋ค ํฐ ๋ฌธ์์ ํ์ผ ์ด๋ฆ๊ณผ ๊ธธ์ด๋ฅผ ์กฐํํฉ๋๋ค.
filter := bson.D{{"length", bson.D{{"$gt", 1500}}}} cursor, err := bucket.Find(filter) if err != nil { panic(err) } type gridfsFile struct { Name string `bson:"filename"` Length int64 `bson:"length"` } var foundFiles []gridfsFile if err = cursor.All(context.TODO(), &foundFiles); err != nil { panic(err) } for _, file := range foundFiles { fmt.Printf("filename: %s, length: %d\n", file.Name, file.Length) }
ํ์ผ ๋ค์ด๋ก๋
๋ค์ ๋ฐฉ๋ฒ ์ค ํ๋๋ฅผ ์ฌ์ฉํ์ฌ GridFS ํ์ผ์ ๋ค์ด๋ก๋ํ ์ ์์ต๋๋ค.
DownloadToStream()
๋ฉ์๋๋ฅผ ์ฌ์ฉํ์ฌ ํ์ผ์ ์ถ๋ ฅ ์คํธ๋ฆผ์ ๋ค์ด๋ก๋ํฉ๋๋ค.OpenDownloadStream()
๋ฉ์๋๋ฅผ ์ฌ์ฉํ์ฌ ์ ๋ ฅ ์คํธ๋ฆผ์ ์ฝ๋๋ค.
์ถ๋ ฅ ์คํธ๋ฆผ์ ํ์ผ ๋ค์ด๋ก๋
DownloadToStream()
๋ฉ์๋๋ฅผ ์ฌ์ฉํ์ฌ GridFS ๋ฒํท์ ํ์ผ์ ์ถ๋ ฅ ์คํธ๋ฆผ์ ์ง์ ๋ค์ด๋ก๋ํ ์ ์์ต๋๋ค. DownloadToStream()
์ ํ์ผ ID์ ํจ๊ป io.Writer
๋ฅผ ๋งค๊ฐ ๋ณ์๋ก ์ฌ์ฉํฉ๋๋ค. ์ด ๋ฉ์๋๋ ์ง์ ๋ ํ์ผ ID๋ฅผ ๊ฐ์ง ํ์ผ์ ๋ค์ด๋ก๋ํ์ฌ io.Writer
์ ๊ธฐ๋กํฉ๋๋ค.
๋ค์์ ํ์ผ์ ๋ค์ด๋ก๋ํ์ฌ ํ์ผ ๋ฒํผ์ ๊ธฐ๋กํ๋ ์์ ๋๋ค.
id, err := primitive.ObjectIDFromHex("62f7bd54a6e4452da13b3e88") fileBuffer := bytes.NewBuffer(nil) if _, err := bucket.DownloadToStream(id, fileBuffer); err != nil { panic(err) }
์ ๋ ฅ ์คํธ๋ฆผ์ ํ์ผ ๋ค์ด๋ก๋
OpenDownloadStream()
๋ฉ์๋๋ฅผ ์ฌ์ฉํ์ฌ ์
๋ ฅ ์คํธ๋ฆผ์ ํตํด GridFS ๋ฒํท์ ํ์ผ์ ๋ฉ๋ชจ๋ฆฌ์ ๋ค์ด๋ก๋ํ ์ ์์ต๋๋ค. OpenDownloadStream()
์ ํ์ผ ID๋ฅผ ๋งค๊ฐ ๋ณ์๋ก ์ฌ์ฉํ๊ณ ํ์ผ์ ์ฝ์ ์ ์๋ ์
๋ ฅ ์คํธ๋ฆผ์ ๋ฐํํฉ๋๋ค.
๋ค์ ์์์๋ ํ์ผ์ ๋ฉ๋ชจ๋ฆฌ์ ๋ค์ด๋ก๋ํ๊ณ ํด๋น ์ฝํ ์ธ ๋ฅผ ์ฝ์ต๋๋ค.
id, err := primitive.ObjectIDFromHex("62f7bd54a6e4452da13b3e88") downloadStream, err := bucket.OpenDownloadStream(id) if err != nil { panic(err) } fileBytes := make([]byte, 1024) if _, err := downloadStream.Read(fileBytes); err != nil { panic(err) }
ํ์ผ ์ด๋ฆ ๋ฐ๊พธ๊ธฐ
Rename()
๋ฉ์๋๋ฅผ ์ฌ์ฉํ์ฌ ๋ฒํท์ ์๋ GridFS ํ์ผ์ ์ด๋ฆ์ ์
๋ฐ์ดํธํ ์ ์์ต๋๋ค. ํ์ผ ID ๊ฐ๊ณผ ์ filename
๊ฐ์ ์ธ์๋ก Rename()
์ ์ ๋ฌํฉ๋๋ค.
๋ค์ ์์์๋ ํ์ผ ์ด๋ฆ์ "mongodbTutorial.zip"
์ผ๋ก ๋ณ๊ฒฝํฉ๋๋ค.
id, err := primitive.ObjectIDFromHex("62f7bd54a6e4452da13b3e88") if err := bucket.Rename(id, "mongodbTutorial.zip"); err != nil { panic(err) }
ํ์ผ ์ญ์
Delete()
๋ฉ์๋๋ฅผ ์ฌ์ฉํ์ฌ GridFS ๋ฒํท์์ ํ์ผ์ ์ ๊ฑฐํ ์ ์์ต๋๋ค. ํ์ผ ID ๊ฐ์ ์ธ์๋ก Delete()
์ ์ ๋ฌํฉ๋๋ค.
๋ค์์ ํ์ผ์ ์ญ์ ํ๋ ์์ ๋๋ค.
id, err := primitive.ObjectIDFromHex("62f7bd54a6e4452da13b3e88") if err := bucket.Delete(id); err != nil { panic(err) }
GridFS ๋ฒํท ์ญ์
Drop()
๋ฉ์๋๋ฅผ ์ฌ์ฉํ์ฌ GridFS ๋ฒํท์ ์ญ์ ํ ์ ์์ต๋๋ค.
๋ค์ ์ฝ๋ ์์์์๋ GridFS ๋ฒํท์ ์ญ์ ํฉ๋๋ค.
if err := bucket.Drop(); err != nil { panic(err) }
์ถ๊ฐ ๋ฆฌ์์ค
GridFS์ ๊ทธ ์ด์์ ๋ํด ์์ธํ ์์๋ณด๋ ค๋ฉด GridFS ๋งค๋ด์ผ ํ์ด์ง๋ฅผ ๋ฐฉ๋ฌธํ์ธ์.
API ๋ฌธ์
์ด ๊ฐ์ด๋์ ์ค๋ช ๋ ๋ฉ์๋ ๋๋ ์ ํ์ ๋ํด ์์ธํ ์์๋ณด๋ ค๋ฉด ๋ค์ API ์ค๋ช ์๋ฅผ ์ฐธ์กฐํ์ธ์.