루비 온 레일즈는 종종 새로운 프로젝트를 시작하기 위해 선택하는 프레임워크입니다. 개발 및 반복 작업의 속도는 여러 면에서 타의 추종을 불허합니다. 따라서 데이터에 많은 유연성이 필요하고 유동적인 구조를 가진 애플리케이션의 프레임워크로 Rails를 사용하고 싶을 수도 있습니다. 모든 종류의 데이터를 처리해야 하는 사물 인터넷 애플리케이션이나 콘텐츠 관리 시스템을 구축하고 있을 수도 있습니다. 기존 Rails용 데이터베이스 솔루션으로는 충분하지 않을 수 있습니다. 어떻게 해야 할까요?
이 가이드에서는 Rails 애플리케이션에 완전히 통합된 데이터베이스로 Couchbase를 활용하기 위한 고려 사항과 단계에 대해 설명합니다. Couchbase로 구축하기로 결정하면 기술 구현의 변화뿐만 아니라 데이터에 접근하는 방식에 대한 개념적 변화도 도입됩니다. 자세히 살펴보겠습니다.
요약 코드만 보고 싶으신가요? 다음에서 Ruby on Rails 및 Couchbase Ruby ORM으로 모든 CRUD 작업을 시연하는 실제 구축된 예제 앱을 확인하세요. GitHub.
문서 모델과 관계형 모델
Rails에서는 일반적으로 ActiveRecord를 사용하는 관계형 모델로 작업하는 데 익숙합니다. 데이터는 행과 열이 있는 테이블로 구성되며, 엔터티 간의 관계는 외래 키를 사용하여 정의됩니다. 반면에 Couchbase는 데이터가 JSON 문서에 저장되는 문서 모델을 사용합니다.
문서 모델은 데이터 구조에 더 많은 유연성을 제공합니다. 예를 들어, 이제 중첩된 데이터를 상위 데이터의 동일한 문서에 직접 저장할 수 있습니다. 즉, 블로그 플랫폼을 구축하는 경우 댓글 ID로 댓글을 기사에 연결하는 대신 각 기사의 JSON 문서에 직접 댓글을 추가할 수 있습니다. 이 기능을 사용할지 여부는 애플리케이션을 설계할 때 고려해야 하는 액세스 패턴과 성능 고려 사항에 따라 달라집니다.
데이터의 차이는 다음 예시와 같습니다.
임베드된 댓글:
1 2 3 4 5 6 7 8 |
{ "title": "내 기사", "content": "이것이 기사의 내용입니다...", "댓글": [ {"author": "User1", "text": "훌륭한 기사!"}, {"author": "User2", "text": "정보를 제공해 주셔서 감사합니다."} ] } |
반면, 대부분의 Rails 개발자에게 익숙한 기존 모델은 다음과 같습니다:
1 2 3 4 5 |
{ "title": "내 기사", "content": "이것이 기사의 내용입니다...", "comment_ids": ["comment1", "comment2"] } |
Couchbase에서 데이터를 모델링하는 방법을 결정할 때는 애플리케이션에서 데이터를 읽고 쓰는 방법을 고려해야 합니다. 문서 문서 내에 댓글을 포함하도록 선택하면 모든 데이터가 단일 문서에 포함되므로 읽기 작업을 더 빠르게 수행할 수 있습니다. 이 접근 방식은 모든 댓글과 함께 문서를 빠르게 검색해야 할 때 유용합니다. 하지만 문서나 댓글을 업데이트하려면 전체 문서를 다시 작성해야 한다는 단점이 있습니다. 이는 특히 문서가 크거나 업데이트가 자주 이루어지는 경우 비효율적일 수 있습니다. 따라서 댓글 임베딩은 댓글이 문서와 독립적으로 거의 업데이트되지 않고 읽기 성능이 중요한 시나리오에 적합합니다.
반면에 댓글을 ID로 참조하면 보다 세분화된 업데이트가 가능합니다. 각 댓글을 문서와 독립적으로 업데이트할 수 있으므로 쓰기 작업이 더 효율적입니다. 그러나 이 접근 방식은 모든 댓글이 있는 문서를 검색하려면 여러 문서를 가져와야 하므로 읽기 작업 속도가 느려질 수 있습니다. 이 패턴은 댓글이 자주 업데이트되거나 성능상의 이유로 전체 문서 크기를 작게 유지해야 하는 경우에 유리합니다.
이러한 장단점을 이해하면 애플리케이션에서 데이터를 구조화하는 방법에 대해 정보에 입각한 결정을 내리는 데 도움이 됩니다. 애플리케이션의 읽기 및 쓰기 패턴을 신중하게 고려하면 성능을 최적화하고 효율적인 데이터 관리를 보장할 수 있습니다.
레일즈 캐싱은 성능 절충점을 줄이는 데 도움이 됩니다.
Rails 애플리케이션에서 임베디드 문서 접근 방식과 참조 문서 접근 방식 간의 잠재적인 장단점을 고려할 필요성을 완화하기 위해 활용할 수 있는 한 가지 방법이 있습니다. 그 접근 방식은 캐싱 및 활용입니다. ActiveSupport::Cache
. 최소한의 추가 구성으로 Couchbase를 통해 그렇게 할 수 있다는 사실을 알고 계셨나요?
카우치베이스 루비 SDK 카우치베이스 데이터 전용 ActiveSupport 캐시 저장소 지원 포함. 이렇게 하면 JSON 문서 데이터에 대한 ActiveSupport의 모든 이점을 누릴 수 있습니다. 어떻게 작동하는지 간단히 살펴보겠습니다.
다음을 추가하여 Couchbase SDK를 설치한 후 보석 카우치베이스
를 보석 파일 및 실행 번들 설치
를 명령줄에서 실행하면 Rails 애플리케이션에 캐싱 지원을 통합할 준비가 된 것입니다.
먼저 Couchbase 스토어를 정의합니다. config.rb:
1 2 3 4 5 6 |
구성.캐시 저장소 = :couchbase_store, { 연결 문자열: # your_couchbase_capella_connection_string", 사용자 이름: your_couchbase_access_credentials_username, 비밀번호: YOUR_COUCHBASE_ACCESS_CREDIALS_비밀번호", 버킷: your_couchbase_버킷_이름 } |
그런 다음 애플리케이션에서 헬퍼 메서드를 생성하여 데이터를 가져와 캐시에 저장할 수 있습니다. 예를 들어 블로그 플랫폼을 만든다고 가정해 보겠습니다. 글은 일단 게시되면 오랫동안 동일하게 유지되는 경우가 많으므로 캐시에 보관하는 것이 안전합니다. 마찬가지로 Couchbase의 문서 JSON 문서에 댓글을 포함하도록 선택하면 새 댓글이 추가될 때마다 문서를 업데이트하고 캐시에서 새 사본을 가져오기만 하면 되므로 매번 요청할 때마다 문서를 가져오는 것보다 확실히 빈도가 적을 수 있습니다.
코드는 다음 예시와 같을 수 있습니다. 다음과 같은 메서드를 생성합니다.#fetch_article_with_caching
를 호출하여 카우치베이스에서 문서를 가져오고 결과를 구문 분석하여 문서 내용과 CAS 값을 얻습니다. CAS(비교 및 스왑) 값은 문서의 현재 상태를 나타내며, 모든 쓰기 작업에 대한 동시성 제어를 보장합니다. 로컬 캐시에 있는 데이터의 상태가 데이터베이스의 가장 최근 상태와 일치하는지 확인하는 데 도움이 됩니다. 이 방법은 CAS 값을 사용해 애플리케이션 캐시를 업데이트하거나 캐시에서 문서를 반환함으로써 Couchbase의 임베디드 데이터와 기존 관계형 데이터 모델 간의 절충점을 줄입니다.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 |
# 캐싱으로 기사 가져오기, 댓글 또는 기사 업데이트 확인 def FETCH_ARTICLE_WITH_CACHING(article_id) 캐시 키 = "article_#{article_id}" # 문서 메타데이터 가져오기(CAS 값 포함) # CAS 값은 동시성 제어를 위한 토큰으로, 문서 업데이트를 확인합니다. 결과 = 기사.버킷.기본_컬렉션.get(article_id, 카우치베이스::옵션::Get(with_expiry: true)) 기사 = 결과.콘텐츠 cas = 결과.메타.cas # 캐시된 글과 해당 CAS 값을 가져옵니다. 캐시된 기사, cached_cas = 레일.캐시.읽기(캐시 키) # 문서 또는 댓글이 변경된 경우 캐시 업데이트하기 만약 캐시된 기사.nil? || cached_cas != cas 레일.캐시.쓰기(캐시 키, [기사, cas], expires_in: 12.시간) else 기사 = 캐시_기사 끝 기사 끝 # 사용 예 기사 = FETCH_ARTICLE_WITH_CACHING("YOUR_ARTICLE_ID") |
액티브 레코드가 없나요... 아니면 있나요?
Couchbase로 전환하면 익숙한 ActiveRecord 라이브러리와 작별을 고해야 한다고 생각할 수도 있습니다. 하지만 새로운 카우치베이스 루비 ORM를 사용하면 Rails 애플리케이션에서 Couchbase로 작업할 때 ActiveRecord와 유사한 환경을 계속 즐길 수 있습니다.
Couchbase Ruby ORM은 ActiveRecord의 기능과 구문을 모방한 ORM 계층을 제공하여 Rails 개발자가 보다 원활하게 전환할 수 있도록 합니다. 이 라이브러리는 익숙한 관계형 모델과 Couchbase에서 사용하는 문서 모델 사이의 간극을 메워줍니다. Rails 개발자에게 익숙한 구문을 제공하므로 학습 곡선이 줄어듭니다. 모델을 정의하고, 속성을 설정하고, ActiveRecord와 유사한 방식으로 데이터베이스와 상호 작용할 수 있습니다.
예를 들어, 다음과 같이 정의해야 할 수 있습니다. 기사 클래스의 새 인스턴스를 생성합니다. 새 ORM을 사용하면 Couchbase에서 이 작업을 수행하는 것이 ActiveRecord에서 수행하는 것과 똑같아 보입니다.
1 2 3 4 5 6 7 |
클래스 기사 < 카우치베이스오름::기본 속성 :title, 유형: 문자열 속성 :콘텐츠, 유형: 문자열 속성 :댓글, 유형: 배열 끝 기사 = 기사.create(title: "내 기사", 콘텐츠: "이것이 기사의 내용입니다...") |
유효성 검사를 정의할 수도 있습니다. 기사 클래스처럼 사용할 수 있습니다.
1 2 3 4 5 6 7 8 9 10 |
클래스 기사 < 카우치베이스오름::기본 속성 :title, 유형: 문자열 속성 :콘텐츠, 유형: 문자열 속성 :댓글, 유형: 배열 끝 ## 모든 새 글에 제목이 있는지 확인합니다. 유효성 검사 :title, 존재감: true 기사 = 기사.create(title: "내 기사", 콘텐츠: "이것이 기사의 내용입니다...") |
서로 다른 모델 간에 연관을 만드는 것은 어떨까요? 문서에서 해당 댓글을 가져오기 위해 #댓글 메서드를 사용하여 has_many 매크로. 이것도 가능합니다.
1 2 3 4 5 6 7 8 9 10 11 12 13 |
클래스 기사 < 카우치베이스오름::기본 # 연결을 정의하고 파기하기 문서 삭제 시 # 종속성 has_many :댓글, 의존적: 파괴 속성 :title, 유형: 문자열 속성 :콘텐츠, 유형: 문자열 속성 :댓글, 유형: 배열 끝 유효성 검사 :title, 존재감: true 기사 = 기사.create(title: "내 기사", 콘텐츠: "이것이 기사의 내용입니다...") |
고유한 고려 사항
Rails 애플리케이션에서 데이터베이스로 Couchbase를 도입할 때, 일찍 도입하면 개발 작업이 더 원활하고 효율적으로 진행될 수 있다는 점을 고려해야 할 몇 가지 사항이 있습니다. 첫째, Ruby ORM은 매우 새롭기 때문에 테스트를 빌드할 때 모의, 스텁을 생성하고 일치자를 정의하기 위해 RSpec에 통합할 수 있는 테스트 라이브러리가 아직 없습니다.
즉, 모의 시험 및 기타 테스트 관련 항목을 직접 정의해야 합니다. 예를 들어 문서의 모의 문서를 만들고 그에 대한 기대치를 정의할 수 있습니다.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
RSpec.설명 기사, 유형: :모델 do let(:기사) do 기사.new(id: 'article-id', title: '테스트 제목', 설명: '테스트 설명', body: '테스트 바디', author_id: 작성자.id) 끝 컨텍스트 '기사를 저장할 때' do 설명 '#save' do it '데이터베이스에 새 문서 레코드를 생성합니다' do 허용(기사).에 받기(:new).and_return(기사) 허용(기사).에 받기(:저장).and_return(true) 기사.저장 기대(기사.id).에 eq('article-id') 끝 끝 끝 끝 |
기억해야 할 Couchbase 데이터의 또 다른 중요한 기능은 다음과 같은 역할입니다. 메타데이터 를 추가할 수 있습니다. 메타데이터에는 문서 ID, CAS 값, 만료 시간 등 문서에 대한 다양한 정보가 포함됩니다. 이 메타데이터는 데이터를 관리하고 데이터와 상호 작용하는 데 유용할 수 있습니다.
메타데이터의 핵심 구성 요소 중 하나는 문서 ID입니다. 문서 ID는 Couchbase의 각 문서에 대한 고유 식별자입니다. 이 ID를 기반으로 문서를 검색, 업데이트 및 삭제할 수 있습니다. 기본 키를 자주 사용하는 관계형 데이터베이스와 달리 Couchbase는 이러한 문서 ID를 사용하여 각 JSON 문서를 고유하게 식별합니다.
JSON 문서의 메타데이터에 액세스하려면 Ruby ORM을 사용하여 사용자 정의 쿼리를 만들 수 있습니다. 아래 예에서는 먼저 쿼리를 정의한 다음 이를 사용하는 메서드를 정의하여 문서 ID를 가져옵니다. 이 메서드는 문서 ID와 나머지 문서 데이터를 모두 반환합니다.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 |
클래스 기사 < 카우치베이스오름::기본 속성 :title, 유형: 문자열 속성 :콘텐츠, 유형: 문자열 속성 :댓글, 유형: 배열 # 문서 데이터와 함께 메타데이터 ID를 가져오는 사용자 지정 쿼리 n1ql :BY_ID_WITH_META, emit_key: [:id], 쿼리_fn: proc { |버킷, 값, 옵션| 클러스터.쿼리( "SELECT META(a).id AS meta_id, a.* FROM `#{버킷.이름}` AS a WHERE META(a).id = $1", 카우치베이스::옵션::쿼리(위치_파라미터: 값) ) } 끝 # 메타데이터 ID가 있는 문서를 가져와 표시합니다. def FETCH_ARTICLE_WITH_META_ID(article_id) 결과 = 기사.BY_ID_WITH_META(article_id) 결과.각 do |행| meta_id = 행["meta_id"] 기사_데이터 = 행.거부 { |키| 키 == "meta_id" } 풋 "메타 ID: #{meta_id}" 풋 "기사 데이터: #{article_data}" 끝 끝 # 사용 예 FETCH_ARTICLE_WITH_META_ID("YOUR_ARTICLE_ID") |
아직 Couchbase에 익숙하지 않다면 이 쿼리를 보고 SQL과 매우 비슷하다고 생각할 수 있으며, 맞을 것입니다! Couchbase의 가장 큰 장점 중 하나는 쿼리 언어를 도입했다는 점입니다. SQL++ - 를 사용하여 SQL 테이블에서와 동일한 상호 작용 환경을 제공합니다. SQL++를 사용하여 Couchbase에서 데이터 작업을 하면 모든 SQL 데이터베이스에서 익숙한 기능과 인체공학적 디자인을 그대로 사용할 수 있습니다. 작업에 추가적인 인지적 오버헤드를 도입할 필요가 없습니다. 우리 중 누구도 원치 않는 일이죠!
1 |
선택 메타(a).id AS meta_id, a.* FROM `#{버킷.이름}` WHERE META(a).id = $1 |
마무리
Rails의 동적 NoSQL 데이터에 ActiveRecord와 유사한 환경을 제공하는 ORM과 다른 사용 사례를 다루는 SQL과 유사한 쿼리 언어의 조합은 애플리케이션을 위한 완전한 다용도 데이터베이스 및 데이터 관리 시스템을 제공합니다. 완전한 기능을 갖춘 구현이 어떤 모습인지 살펴보고 싶다면 다음에서 Ruby ORM을 사용하여 모든 생성, 읽기, 업데이트 및 삭제 작업을 다루는 실제 예제 Rails 애플리케이션을 복제하여 살펴볼 수 있습니다. GitHub.
애플리케이션에 엄격한 스키마나 엄격하게 정의된 구조를 쉽게 따르지 않는 데이터가 필요하고 이를 수용하는 방법을 찾고 있다면 새로운 Ruby ORM이 포함된 Couchbase가 매력적인 솔루션을 제공합니다.