이미지 저장에 가장 적합한 데이터베이스는 무엇인가요? 이미지, 문서, PDF 또는 기타 바이너리 객체를 Couchbase에 저장하는 것에 대한 질문을 자주 받습니다. 아니면 이미지 저장에 가장 적합한 데이터베이스는 Couchbase일까요?
서비스 및 데이터베이스 설계자로서 저는 보통 같은 대답을 합니다. 이러한 종류의 객체의 경우 파일을 데이터베이스에 저장하는 것은 평범한 생각입니다. 제가 이렇게 말하는 것은 오랜 기간 동안 많은 관계형 데이터베이스와 NoSQL 데이터베이스를 사용해 온 개인적인 경험에서 나온 말입니다.
개발자 입장에서는 데이터베이스에 파일을 저장하는 것이 쉽고 편리하다는 것을 알고 있습니다. 논리적으로도 그렇게 하는 것이 합리적입니다. 데이터가 있으니 저장해야 합니다. 그 데이터를 조회하고 사용자에게 데이터를 제공할 수 있도록 해당 데이터에 대한 정보를 갖고 싶습니다. 이 모든 것이 저에게도 이해가 됩니다.
이러한 유형의 객체를 데이터베이스(Couchbase 또는 기타)에 저장하는 것이 왜 평범한 아이디어인지에 대한 두 가지 논거가 있습니다. 또한 효율적이고 최종 사용자에게 가장 적합한 비용으로 Couchbase 이미지 스토리지 데이터베이스를 가장 잘 사용하는 방법에 대한 솔루션을 제안할 것입니다. 이것이 결국 우리 모두가 진정으로 여기 있는 이유겠죠?
운영 비용 및 성과
대용량 개체를 데이터베이스에 영구적으로 저장하면 대부분의 사용 사례에서 일반적으로 정적이고 자주 변경되지 않는 개체에 대해 가장 비싸고 가장 성능이 좋은 레이어를 사용하게 됩니다. 해당 오브젝트를 S3에 저장하는 것과 비교하여 AWS의 EC2 인스턴스에 저장하는 GB당 비용을 생각해 보세요. 이 글을 쓰는 시점에 AWS 계산기를 사용했을 때, S3 스토리지는 가장 저렴한 EC2 스토리지 비용의 1/5에 불과했습니다.
이 설정은 실제로 다른 용도로 사용되기 때문에 1:1로 비교할 수 있는 것이 아니기 때문입니다. S3는 특히 매우 합리적인 비용으로 매우 높은 내구성의 많은 정적 개체를 보관하기 위한 것이고, EC2는 운영용 스토리지를 위한 것입니다.
이제 대상 이미지를 데이터베이스에 저장한 다음 몇 달 또는 몇 년 동안 복제하고 백업하는 데 드는 물리적 비용을 생각해 보세요. 그 많은 양의 데이터를 옮기는 데 드는 비용과 운영 시간이 얼마나 큰지 알 수 있습니다. 시간이 지남에 따라 이러한 개체들은 운영팀의 목을 조이는 골칫거리가 됩니다. 또한 올바르게 관리하지 않으면 2년 후에도 1.5년 전에 서비스 사용을 중단한 사용자의 이미지를 저장, 백업, 복제하는 데이터베이스가 남아 있을 수 있으며, 여러 번 사용한 모든 KB에 대해 여전히 비용을 지불하고 있을 수도 있습니다.
이 모든 오버헤드는 단순히 개발 편의를 위한 것입니다. 장기적으로 볼 때 그만한 가치가 있거나 효율적이지 않습니다. 다시 한 번 말씀드리지만, 이것은 결코 Couchbase만의 문제는 아닙니다.
각 도구를 가장 잘 활용할 수 있는 용도로 사용하세요.
객체 ID를 통해 액세스하거나 쿼리에서 원하는 객체를 식별한 경우 Couchbase는 RAM의 관리되는 캐시에서 바로 뛰어난 성능으로 객체를 제공할 수 있습니다. Couchbase는 이미지나 더 큰 바이너리도 RAM에서 매우 빠르게 저장하고 제공할 수 있나요? 물론 가능하지만 이러한 성능을 얻으려면 스토리지뿐만 아니라 고가의 서버 리소스를 소비하게 됩니다. 또한 Couchbase에는 20MB의 개체 크기 제한이 있습니다. 개체가 그 크기에 근접하지 않더라도 이러한 유형의 개체를 데이터베이스에 영구적으로 저장하는 것은 좋지 않을 수 있습니다. 앞서 언급했듯이 Amazon S3와 HDFS는 이와 같은 정적 콘텐츠를 저장하고 제공하는 데 탁월합니다. 이것이 바로 이러한 용도로 설계된 것입니다. 이러한 유형의 워크로드에 적합한 비용으로 뛰어난 성능을 제공합니다. 올바른 작업에 적합한 도구를 사용하는 것이 가장 좋습니다. 정적 객체뿐만 아니라 대용량 이미지도 데이터베이스에 저장할 수 있지만, 이는 데이터베이스가 가장 잘하는 일은 아닙니다.
그렇다면 데이터베이스에 대용량 데이터를 저장하려면 이 문제를 어떻게 해결해야 할까요? 저장할 자료가 너무 많아요!
이 예제에서는 이미지 저장소에 대해 이야기하겠습니다. 가장 일반적인 사용 사례이기 때문이지만 모든 종류의 큰 정적 객체가 될 수 있습니다. 이 사용 사례의 높은 수준에서는 사용자가 이미지를 찾을 때 애플리케이션에 필요한 데이터만 Couchbase에 저장하는 것을 고려해야 합니다. 데이터 액세스 패턴과 그에 따른 데이터베이스 개체 모델을 계획할 때는 몇 가지 질문을 해보세요.
- 앱이 각 이미지에 대해 사용자에게 표시해야 하는 데이터는 언제, 어떤 흐름에서 제공해야 하나요?
- 이미지에 대해 어떤 검색이 수행되며 결과는 어떻게 표시되나요? (키워드, 제목, 작성자, 작성일 등) 사용 사례에 맞는 경우 빠른 전송 옵션을 위해 스토리지 데이터베이스에 작은 이미지 썸네일을 저장할 수도 있습니다.
- 애플리케이션 흐름에서 각 데이터가 필요한 시점은 언제인가요?
- 각 이미지의 메타데이터 객체에 대한 객체 ID 패턴은 무엇인가요? Couchbase 객체 모델링 및 객체 ID 예제에 대한 자세한 내용은 다음 블로그 게시물을 참조하세요. 여기 그리고 여기 를 클릭해 아이디어를 얻으세요.
이제 카우치베이스에서 사용자 대면 데이터를 확보했으므로 빠른 키 조회, 맵 축소 보기 또는 보조 인덱스에 대한 전체 N1QL 쿼리를 수행하여 데이터를 얻을 수 있습니다. 대용량 이미지는 사용 사례와 예산에 따라 AWS S3, HDFS, CDN(콘텐츠 전송 네트워크), 웹 서버, 파일 서버 또는 그 외 대용량 정적 객체를 제공하는 데 적합한 곳에 저장해야 합니다.
이제 좀 더 자세히 살펴보고 이를 설계하는 방법에 대해 더 자세히 이야기해 보겠습니다.
개체 모델 예시
애플리케이션의 각 실제 이미지에 대해 Couchbase에서 두 개의 객체를 제안합니다:
- 이미지에 대한 메타데이터가 포함된 JSON 객체입니다. JSON으로 되어 있으므로 애플리케이션에 필요한 모든 것을 인덱싱하고 N1QL 또는 보기로 쿼리할 수 있습니다. 이 객체에는 다른 시스템의 기본 이미지에 대한 포인터도 포함됩니다.
- 메인 이미지의 썸네일 이미지에 대한 데이터를 포함하는 키/값 객체로, 별도의 Couchbase 버킷에 저장됩니다. 사용자에게 빠르게 보여주기 위해 썸네일을 Couchbase에 보관하고 있습니다. 이론적으로는 메타데이터와 함께 JSON 문서에 값으로 저장할 수도 있지만, 특히 데이터 변이율이 높을 것으로 예상되는 경우 인덱싱과 Couchbase 리소스 활용 측면에서 분리하는 것이 이점을 상쇄할 수 있습니다.
Couchbase의 모든 개체에는 고유한 개체 ID(버킷 내)가 있어야 하고 해당 ID에 250바이트를 사용할 수 있으므로 이를 활용하여 쉽고 빠른 개체 검색을 위해 표준화된 개체 ID 패턴을 만들어 보겠습니다. 표준화된 개체 ID를 사용하면 Couchbase 데이터 서비스에서 이미지와 관련 콘텐츠를 쉽게 검색하거나 N1QL을 사용할 때 쿼리할 때 빠르게 검색할 수 있습니다.
각 문서의 개체 ID 패턴은 다음과 같습니다:
- 메타데이터 객체입니다: 메타데이터:: 에서 고유 식별자가 애플리케이션에 의해 해당 이미지에 할당됩니다. N1QL로 쿼리하여 이미지를 찾을 예정이므로 좀 더 설명적인 객체 ID를 사용하지 않겠습니다.
- 썸네일 개체: 썸네일:: 여기서 이름은 메타데이터 객체에 사용한 이름입니다. 이렇게 하면 개체 간에 비공식적인 관계를 설정할 수 있습니다. 각각의 메타데이터 객체에는 해당 썸네일 객체입니다. 따라서 두 개를 모두 가져와야 한다면 가능합니다. UUID를 알면 썸네일을 매우 빠르게 가져올 수 있고 그 반대의 경우도 마찬가지입니다.
객체 자체의 경우:
- 메타데이터 객체는 JSON 문서이며 다음과 같이 보일 수 있습니다:
{ "title" : "귀여운 키티와 강아지",
"파일 위치" : "https://s3.amazonaws.com/kittypics/cutekittyanddoggy.jpg",
"thumbnail1" : "thumbnail::
“,
"dimensions-px" : "50×50"
}
썸네일에서 라고 표시된 부분
는 당연히 해당 객체의 ID로 대체됩니다. 이렇게 하면 메타데이터 객체를 가져올 때 썸네일 객체의 ID를 알 수 있고 이를 빠르게 가져올 수 있습니다. 이것은 한 번의 호출로 처리하는 것이 더 나은 다른 데이터베이스에서와 같이 Couchbase를 여러 번 호출하는 것이 더 나은 경우 중 하나입니다.
- 썸네일 객체는 단순히 키/값이며 값은 2진수입니다.
카우치베이스 관련 설정
버킷
저는 두 개의 카우치베이스 버킷을 제안합니다. 하나는 각 이미지에 대한 메타데이터가 포함된 JSON 문서용이고 다른 하나는 썸네일용입니다. 그 구체적인 이유는 두 가지입니다:
- 별도의 버킷을 사용하면 오브젝트의 필요에 따라 관리되는 캐시를 조정할 수 있습니다. 예를 들어, 각 이미지의 메타데이터를 항상 최대한 빨리 사용할 수 있기를 원한다고 가정해 보겠습니다. 최상의 성능을 위해 '메타데이터' 버킷의 RAM 할당량을 관리형 캐시에 모든 개체가 포함되도록 조정합니다. 썸네일용 키 값 데이터 스토리지의 경우, 몇 초 후에 표시되더라도 큰 문제가 되지 않으므로 인스턴스 크기를 조금 줄이고 캐시에 많은 인스턴스를 보관하지 않으려는 경우가 있습니다. 메타데이터 버킷의 RAM 할당량을 클러스터 전체에 걸쳐 300GB로 설정하고 썸네일은 디스크에 더 큰 데이터 세트일지라도 클러스터 전체에 걸쳐 50GB로 설정할 수 있습니다.
- 썸네일 오브젝트를 색인하거나 쿼리할 필요가 없습니다. 메타데이터 JSON 문서에서 가져온 객체 ID나 이를 생성하는 애플리케이션을 통해 언제든지 가져올 수 있습니다. 이러한 객체를 두 개의 개별 버킷에 넣는 이유에 대해 한 단계 더 자세히 설명하자면, Couchbase에서 색인을 수행할 때 버킷의 모든 객체가 색인에 포함되어야 하는지 여부를 확인하기 위해 어느 시점에서 조사됩니다. 이 작업은 뷰를 사용하는 경우 뷰 인덱서에서, GSI(글로벌 보조 인덱싱)를 사용하는 경우 프로젝터에서 수행합니다. 이 두 가지 데이터 유형을 별도의 버킷, 즉 인덱서와 프로젝터에 가지고 있으면, 인덱스가 버킷에 따라 달라지기 때문에 JSON 문서를 쿼리하는 데 필요한 썸네일 객체를 신경 쓸 필요가 없고 주기나 리소스를 낭비할 필요가 없습니다. 또 다른 장점은 데이터와 함께 저장되는 카우치베이스 뷰를 사용하는 경우, 뷰 인덱서가 데이터가 이동할 때 썸네일을 조사할 필요가 없기 때문에 클러스터 재조정 시간을 줄일 수 있다는 것입니다. 전반적으로 더 적은 서버 리소스가 필요하므로 더 비용 효율적입니다.
이 예제에서는 두 버킷을 '메타데이터'와 '썸네일'과 같은 암호화된 이름으로 부르겠습니다.
가치 퇴거(기본값) 또는 완전 퇴거
이 특정 사용 사례에서는 Couchbase의 전체 퇴거 기능을 사용하지 않을 가능성이 높습니다. 이 기능은 훌륭한 기능이지만 이러한 이미지 메타데이터 객체를 Couchbase에 저장하는 이유 중 하나는 기능뿐만 아니라 관리형 캐시에서 얻을 수 있는 성능 때문이기도 합니다. 사용 사례에서 애플리케이션 흐름의 어느 시점에서 객체의 존재 여부를 확인해야 할 가능성이 높습니다. 이 경우 전체 퇴거를 사용하면 이를 확인하기 위해 디스크로 이동해야 하므로 좋지 않습니다. 기본 "값 퇴거"를 사용하면 모든 개체에 대한 카우치베이스 데이터가 항상 관리되는 캐시에 있기 때문에 개체의 존재 여부를 매우 빠르게 알 수 있습니다. 따라서 이 기능을 현명하게 사용하고 애플리케이션에 어떤 영향을 미칠지, 왜 그런지 정확히 알고 있는 경우에만 전체 퇴거를 사용하도록 설정하세요.
규칙의 예외
항상 그렇듯이 규칙에 어긋나는 예외가 있습니다. 제가 아는 한 Couchbase 고객은 바이너리 객체(구체적으로 오디오 파일)를 Couchbase Server에 삽입하여 놀라운 성공을 거두고 있습니다. 하지만 이 고객은 Couchbase를 유리하게 활용하는 매우 특별한 이유가 있습니다. 오디오 녹음을 Couchbase에 삽입하지만, 핵심은 애플리케이션이 오디오 파일을 작은 덩어리로 나누고 해당 녹음에 대한 메타데이터 문서와 함께 들어올 때 각각을 Couchbase로 스트리밍한다는 것입니다. 흥미로운 점은 영구적으로 이 문서에서 이미 설명한 이유로 오디오 파일을 데이터베이스에 저장합니다. 몇 분 후 오디오 파일에 액세스하지 않으면 백그라운드 프로세스가 각 파일을 재구성하여 장기 저장을 위해 Amazon S3로 이동합니다. 그런 다음 S3의 파일에 대한 포인터로 오디오 파일의 메타데이터 JSON 문서를 업데이트합니다. Couchbase를 통해 매우 빠른 속도로 수집하고 S3를 통해 장기 정적 객체를 저장합니다. 가장 잘할 수 있는 일에 가장 적합한 도구를 사용한 좋은 예입니다.
요약
엉뚱한 질문을 하지 마세요. 이미지에 가장 적합한 데이터베이스는 무엇인가요? 파일 저장에 가장 적합한 데이터베이스는 무엇인가요? 어떤 데이터베이스 플랫폼을 사용하든 데이터베이스에 큰 개체를 영구적으로 저장하는 것은 기껏해야 평범한 아이디어일 뿐입니다. 데이터베이스에 대용량 바이너리 파일을 작은 파일로 분할하여 데이터베이스에 저장하고 자동으로 재조립하는 특수한 모의 파일 시스템이 있다고 해도 마찬가지입니다. 동일한 개념이 적용됩니다. 개발의 용이성과 비용이 많이 들고 운영이 더 어려워지는 것을 맞바꾸는 것입니다. 이는 나중에 당신을 괴롭힐 것입니다.
최상의 솔루션을 얻으려면 각 도구의 장점을 최대한 활용하세요. 각 개체에 대한 메타데이터 JSON 문서(기껏해야 작은 썸네일 이미지 정도)를 Couchbase에 저장하세요. 이 문서에는 애플리케이션에서 해당 개체에 대해 신속하게 필요한 데이터뿐만 아니라 S3, 파일 시스템 또는 HDFS와 같은 특수 목적의 개체 저장소에 대한 포인터도 포함되어 있습니다. 두 마리 토끼를 모두 잡을 수 있습니다. 추가 작업 없이도 성능, 운영 편의성, 비용 효율성이라는 세 마리 토끼를 모두 잡을 수 있습니다.
동의하지 않으시나요? 규칙에 대한 또 다른 예외가 있나요? 댓글에 추가하여 이야기해 주세요.