개발 환경 설정 변경
Mongoid 5로 업그레이드한 후 Rails 앱을 실행하면 가장 먼저 데이터베이스 설정이 올바르지 않다는 오류를 만나게 됩니다.
해결 방법은 간단합니다. 설정 파일에서 sessions를 clients로 변경하기만 하면 됩니다:
development:
clients:
default:
database: appsignal_development
hosts:
- localhost:27017드라이버 변경 사항
저희 코드베이스에서는 Mongoid 대신 moped/mongo-ruby-driver에 직접 쿼리를 실행하기 위해 "드라이버로 직접 내려가는" 경우가 많았습니다. 예를 들어 계정별로 컬렉션을 생성하는 작업 등이 그렇습니다. 이런 부분에서도 session을 client로 변경해야 합니다.
또 하나의 변화는 read 옵션이 값을 직접 받는 대신 :mode 키를 가진 해시를 기대한다는 점입니다:
def create_log_entry_collection
Mongoid
.client('default') # 기존에는 `.session('default')`
.with(:read => {:mode => :primary}) # 기존에는 `read: => :primary`
.database
.command(:create => 'foo')
endMoped에는 단일 문서 또는 문서 배열을 모두 받을 수 있는 insert 메서드가 있었습니다. 반면 새로운 mongo-ruby-driver는 두 개의 별도 메서드를 제공하며, 삽입하려는 문서의 수에 따라 적절한 메서드를 선택해야 합니다:
# 변경 전
Mongoid.client('default')['foo'].insert(document)
Mongoid.client('default')['foo'].insert([document, document])
# 변경 후
Mongoid.client('default')['foo'].insert_one(document)
Mongoid.client('default')['foo'].insert_many([document, document])정렬 보장의 부재
새 드라이버의 가장 큰 변화 중 하나는 문서가 더 이상 기본적으로 _id 기준으로 정렬되지 않는다는 점입니다.
정렬 옵션이 지정되지 않은 경우 first와 last가 더 이상
_id정렬을 자동으로 추가하지 않습니다. 특정 문서가 확실히 첫 번째 또는 마지막임을 보장하려면 이제 명시적인 정렬 조건이 필요합니다.
즉, 정렬 순서에 의존하는 모든 곳(.first, .last)에서는 쿼리에 _id 기준 정렬을 명시적으로 지정해야 합니다:
# 변경 전
expect( User.first.name ).to eq 'bob'
expect( User.last.name ).to eq 'kelso'
# 변경 후
expect( User.asc('_id').first.name ).to eq 'bob'
expect( User.asc('_id').last.name ).to eq 'kelso'기존과 동일하게 코드가 동작하도록 보장하기 위해, 저희는 _id 기준으로 정렬하는 기본 스코프(default scope)를 추가하는 concern을 만들어 사용했습니다:
# concerns/ordered_by_id_asc.rb
module OrderedByIdAsc
extend ActiveSupport::Concern
included do
default_scope -> { asc('_id') }
end
end# models/account.rb
class Account
include Mongoid::Document
include Mongoid::Timestamps
include OrderedByIdAsc
endFindAndModify
find_and_modify 메서드는 제거되었으며, 대신 다음 세 가지 메서드 중 하나를 선택해 사용할 수 있습니다:
find_one_and_updatefind_one_and_replace(편의 메서드로, 내부적으로find_one_and_update를 호출)find_one_and_delete
ExpireAfterSeconds
다소 생소한 변경 사항 중 하나는 TTL 인덱스 생성 방식입니다. 저희는 고객의 요금제에 따라 데이터를 자동으로 삭제하기 위해 TTL 인덱스를 사용합니다(예: 7일 후 또는 한 달 후 삭제).
인덱스 옵션 이름이 기존의 expire_after_seconds에서 expire_after로 변경되었습니다:
# 변경 전
collection.indexes.create_one(
{:time => 1},
{:expire_after_seconds => ttl}
)
# 변경 후:
collection.indexes.create_one(
{:time => 1},
{:expire_after => ttl}
)스테이징/프로덕션 설정 변경
개발 환경에서는 sessions를 clients로 바꾸는 것만으로 충분했지만, 스테이징/프로덕션 설정은 훨씬 더 많은 수정이 필요했습니다:
# 변경 전
staging:
sessions:
default:
database: appsignal_main
username: <%= ENV['MONGOID_USERNAME'] %>
password: <%= ENV['MONGOID_PASSWORD'] %>
hosts:
- mongo1.staging:27017
- mongo2.staging:27017
- mongo3.staging:27017
options:
read: :primary
pool_size: {{ mongoid_pool_size }}
ssl:
ca_file: /etc/ssl/certs/root_ca.crt
client_cert: /app/shared/config/mongodb_app.crt
client_key: /app/shared/config/mongodb_app.key
# 변경 후
staging:
clients:
default:
database: appsignal_main
hosts:
- mongo1.staging:27017
- mongo2.staging:27017
- mongo3.staging:27017
options:
user: <%= ENV['MONGOID_USERNAME'] %>
password: <%= ENV['MONGOID_PASSWORD'] %>
read:
mode: :primary
max_pool_size: {{ mongoid_pool_size }}
ssl: true
ssl_ca_cert: /etc/ssl/certs/root_ca.crt
ssl_cert: /app/shared/config/mongodb_app.crt
ssl_key: /app/shared/config/mongodb_app.key
replica_set: stagingusername은user로 이름이 변경되고options아래로 이동했습니다password도options아래로 이동했습니다read옵션은 이제mode라는 중첩 키를 요구합니다- SSL은 더 이상 중첩된 해시가 아니며
options아래에 설정됩니다 - 레플리카셋(replicaset) 구성을 사용하는 경우 설정에
replica_set키가 반드시 필요합니다
업그레이드 공식 문서에서는 MongoDB 2.4 및 2.6 버전이 :plain 인증 방식을 사용한다고 안내하지만, 실제로는 auth_mech 키를 완전히 제거해야만 정상적으로 동작했습니다.
결론
변경 목록이 상당히 길어 보이지만, 실제 업그레이드 과정은 비교적 수월했으며 새 드라이버가 기존 Moped 드라이버보다 훨씬 안정적으로 느껴졌습니다. Mongoid 5로의 전환을 고려하고 있다면 위의 변경 사항들을 미리 점검해 두면 마이그레이션 작업을 훨씬 원활하게 진행할 수 있을 것입니다.