GridFS 가이드 : https://www.mongodb.com/ko-kr/docs/drivers/node/current/fundamentals/gridfs/
구조화되지 않은 데이터의 큰 부분은 비디오, 대용량 텍스트, 파일, 오디오 및 이미지에서 나옵니다. 이것들은 모두 크기가 매우 크고 저장을 위해 더 많은 공간이 필요합니다. 이 글에서는 MongoDB가 GridFS라는 중요한 기능을 사용하여 이처럼 큰 크기의 데이터를 저장하고 검색하는 방법을 알아보겠습니다.
* BSON 문서 및 크기 제한
알다시피 MongoDB는 BSON 형식으로 데이터를 저장하는데, 이는 최대 16MB의 데이터만 저장할 수 있는 제한이 있습니다. 그 이유는 단일 문서가 너무 많은 RAM을 차지하거나 트랜잭션 중에 대역폭을 과도하게 사용하는 것을 방지하기 위한 것입니다. 바로 이 점 때문에 GridFS가 필요합니다. 16MB 이상의 데이터를 저장하기 위해 GridFS API는 데이터를 청크(chunk)라는 더 작은 크기로 나눕니다. 검색하는 동안 데이터 청크를 결합하여 동일한 데이터를 얻을 수 있습니다. 각 청크는 데이터 파일의 해당 부분을 이진으로 표현한 것입니다.
* GridFS 버킷
MongoDB는 GridFS 버킷 fs를 사용하여 파일, 즉 파일과 청크를 저장하기 위한 두 개의 컬렉션을 저장합니다. 컬렉션은 기본적으로 fs.chunks 및 fs.files로 식별되지만 이름을 변경하고 더 많은 버킷을 만들 수도 있습니다.
청크 컬렉션
각 데이터 청크는 'chunks'라는 컬렉션에 별도의 문서로 저장됩니다. MongoDB는 각 문서에 기본 고유 식별자와 기타 필드를 제공합니다. 이는 전체 데이터 대신 원하는 경우 데이터의 일부를 검색할 수 있으므로 매우 중요한 기능입니다. 그런 다음 원하는 데이터 부분만 메모리에 로드되므로 시스템의 성능과 효율성이 향상됩니다. 그런 경우 GridFS를 사용하여 파일을 저장할 수도 있는데, 16MB보다 작을 수 있지만 여전히 데이터를 분할하고 필요에 따라 일부만 검색하여 메모리를 절약하려고 합니다.
마지막 청크를 제외하고 각 데이터 청크의 크기는 최대 255kb여야 합니다.
몽고DB 드라이버
애플리케이션이 큰 파일을 직접 삽입, 업데이트 및 읽을 수 있도록 MongoDB는 다양한 언어에 대한 드라이버를 제공합니다. 검색하는 동안 모든 청크를 저장하고 결합하는 동안 데이터 파일을 청크로 크기를 줄이는 전체 작업은 GridFS API에서 수행되며 개발자는 새 GridFS 버킷을 열고 upload_from_stream()(또는 언어에 따라 유사한 메서드)을 사용하여 저장하고 open_download_stream()(또는 언어에 따라 유사한 메서드)을 사용하여 파일을 검색하는 메타데이터를 포함한 필수 매개변수와 함께 파일을 전달하는 코드만 작성하면 됩니다. delete() 메서드를 사용하고 _id 필드를 전달하여 특정 항목을 제거할 수도 있습니다. 버킷 자체, 즉 청크와 파일 컬렉션을 삭제하려면 drop() 메서드를 사용합니다.
오늘날의 디지털 세계에서 우리는 많은 데이터를 소비하고 생성하며, MongoDB가 GridFS 형태로 제공하는 효율적인 메커니즘이 없다면 데이터를 저장하고 검색할 수 있는 것이 빠르게 병목 현상이 될 수 있습니다. 그러나 이런 방식으로 매우 큰 파일(몇 기가바이트)을 저장하는 경우 애플리케이션의 스토리지 요구 사항이 증가하고 성능 오버헤드가 발생할 수 있습니다. GridFS에 파일을 저장하기 전에 의미를 신중하게 고려해야 합니다. 예를 들어, 전체 파일을 로드하지 않고 큰 파일의 일부에 액세스하려는 경우 GridFS를 사용하는 것이 합리적입니다. 마찬가지로 파일과 메타데이터를 여러 시스템과 시설에서 자동으로 동기화하고 배포하려는 경우 GridFS를 사용할 수 있습니다.
참조 : https://www.geopits.com/blog/mongodb-gridfs.html
GridFSBucket 클래스
GridFSBucket은 MongoDB에서 대용량 파일을 업로드하고 관리하기 위한 도구입니다. GridFS를 사용하면 큰 파일을 여러 청크로 나누어 MongoDB에 저장할 수 있으며, GridFSBucket을 통해 파일을 쉽게 업로드하고 다운로드할 수 있습니다.
GridFSBucket은 MongoDB에서 제공하는 GridFS의 기능을 관리하기 위한 클래스입니다. GridFS는 MongoDB에서 대용량 파일을 저장하고 관리하기 위한 파일 시스템입니다. 언급한대로 MongoDB는 하나의 문서(document)에 16MB까지의 크기 제한이 있습니다. 하지만 GridFS를 사용하면 이 제한을 우회하고 대용량 파일을 여러 개의 청크(chunk)로 나누어 저장할 수 있습니다.
GridFSBucket은 이러한 대용량 파일을 관리할 수 있도록 파일을 업로드, 다운로드, 찾기, 삭제하는 메소드를 제공합니다.
주요 특징:
- 대용량 파일 관리: GridFS는 파일을 여러 개의 작은 청크로 나누어 저장합니다. GridFSBucket을 사용하면 이러한 파일을 쉽게 관리할 수 있습니다.
- 청크 단위 저장: 대용량 파일을 청크 단위로 나누어 저장하고, 파일을 요청할 때 이를 조합하여 제공할 수 있습니다.
- 파일 시스템 기능: MongoDB 안에 파일을 저장하고 관리하는 파일 시스템 역할을 합니다. 주로 이미지, 동영상, 백업 파일 등 대용량 데이터를 저장할 때 유용합니다.
GridFSBucket의 사용 사례:
1) 대용량 파일 저장: 동영상, 이미지, PDF 등의 대용량 파일을 MongoDB에 저장할 때 사용됩니다.
2) 파일 백업: 대량의 백업 데이터를 효율적으로 저장하고 관리할 수 있습니다.
3) 청크 기반 스트리밍: 대용량 파일을 청크로 나누어 전송 및 다운로드하여 스트리밍 형태로 데이터를 처리할 수 있습니다.
GridFSBucket에서 자주 사용하는 메소드:
1) uploadFromStream: 파일을 MongoDB에 업로드할 때 사용됩니다. 파일을 청크 단위로 나누어 저장하고, 업로드가 완료되면 그 파일의 고유한 ObjectId를 반환합니다.
ex) ObjectId fileId = gridFSBucket.uploadFromStream("filename", inputStream);
2) downloadToStream: 파일을 MongoDB에서 다운로드할 때 사용됩니다. 지정한 ObjectId나 파일 이름으로 저장된 파일을 다운로드하고, 이를 OutputStream에 저장합니다.
ex) gridFSBucket.downloadToStream(fileId, outputStream);
3) find: 저장된 파일을 검색할 때 사용됩니다. 특정 조건을 만족하는 파일을 찾거나, 모든 파일 목록을 가져옵니다.
ex) gridFSBucket.find();
4) delete: 파일을 MongoDB에서 삭제할 때 사용됩니다. 특정 ObjectId를 사용하여 저장된 파일을 삭제합니다.
ex) gridFSBucket.delete(fileId);
java 코드예 : GridFSBucket을 사용한 파일 업로드와 다운로드 -----------------------
// MongoDB에 연결
MongoClient mongoClient = MongoClients.create("mongodb://localhost:27017");
MongoDatabase database = mongoClient.getDatabase("mydatabase");
// GridFSBucket 생성
GridFSBucket gridFSBucket = GridFSBuckets.create(database);
// 파일 업로드
try (InputStream streamToUploadFrom = new FileInputStream("/path/to/file")) {
ObjectId fileId = gridFSBucket.uploadFromStream("myFile", streamToUploadFrom);
System.out.println("File uploaded with ObjectId: " + fileId);
}
// 파일 다운로드
try (ByteArrayOutputStream outputStream = new ByteArrayOutputStream()) {
gridFSBucket.downloadToStream(fileId, outputStream);
System.out.println("File downloaded: " + new String(outputStream.toByteArray()));
}
------------------------------------------------------------------------------------------