Django에서 두 개의 데이터베이스 (SQLite와 PostgreSQL)를 연결하고 데이터베이스 라우터(MultiDBRouter)를 사용하여 데이터베이스 설정했다.
settings.py)Django의 설정 파일인 settings.py에서 여러 데이터베이스를 정의할 수 있다. 이번 예제에서는 기본 데이터베이스로 SQLite를 사용하고, 두 번째 데이터베이스로 PostgreSQL을 사용한다. PostgreSQL은 Docker를 통해 연결되어 있다고 가정한다.
# settings.py
import environ
import os
from pathlib import Path
env = environ.Env()
BASE_DIR = Path(__file__).resolve().parent.parent
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.sqlite3',
'NAME': os.path.join(BASE_DIR, "db.sqlite3"),
},
'postgres': {
'ENGINE': 'django.db.backends.postgresql',
'NAME': env('POSTGRES_DB'),
'USER': env('POSTGRES_USER'),
'PASSWORD': env('POSTGRES_PASSWORD'),
'HOST': env('POSTGRES_HOST'),
'PORT': env('POSTGRES_PORT'),
}
}
DATABASE_ROUTERS = ['config.database_routers.MultiDBRouter']
위 설정에서 두 개의 데이터베이스가 정의되어 있다:
default: SQLite 데이터베이스이다.postgres: PostgreSQL 데이터베이스로, 환경 변수를 통해 설정을 가져온다.MultiDBRouter)다음 단계는 데이터베이스 라우터(MultiDBRouter)를 구현하여 읽기/쓰기 작업을 어떤 데이터베이스에서 수행할지 결정하는 것이다. 이를 통해 특정 모델의 작업이 어느 데이터베이스에서 이루어질지 제어할 수 있다.
database_routers.py 파일을 생성하고 다음과 같이 작성한다.
# config/database_routers.py
class MultiDBRouter:
"""
다중 데이터베이스 작업을 제어하기 위한 라우터이다.
- 읽기는 기본적으로 SQLite에서 먼저 시도하고, 그 다음 PostgreSQL에서 시도한다.
- 쓰기는 기본적으로 SQLite에서 이루어진다.
"""
def db_for_read(self, model, **hints):
# 읽기 작업 시도 순서: 기본(default)에서 읽기를 시도한다.
return 'default'
def db_for_write(self, model, **hints):
# 쓰기 작업은 기본적으로 SQLite에서 진행한다.
return 'default'
def allow_relation(self, obj1, obj2, **hints):
# 두 객체가 같은 데이터베이스에 있다면 관계를 허용한다.
db_set = {'default', 'postgres'}
if obj1._state.db in db_set and obj2._state.db in db_set:
return True
return None
def allow_migrate(self, db, app_label, model_name=None, **hints):
# 마이그레이션을 두 데이터베이스에서 모두 허용한다.
return db in {'default', 'postgres'}
다음은 Post라는 모델을 사용하여 두 데이터베이스에서 데이터를 관리하는 예제이다. 이 모델은 기본적으로 SQLite에 저장되지만, 추가적으로 PostgreSQL에도 데이터를 저장한다.
from django.db import models, transaction
class Post(models.Model):
title = models.CharField(max_length=100)
description = models.TextField(null=True, blank=True)
created_at = models.DateTimeField(auto_now_add=True)
def save(self, *args, **kwargs):
# 기본 데이터베이스에 먼저 저장한다 (SQLite)
super().save(*args, **kwargs)
# 나머지 데이터베이스에도 동일하게 저장한다 (PostgreSQL)
for db in ['postgres']:
try:
db_kwargs = kwargs.copy()
db_kwargs['using'] = db
with transaction.atomic(using=db):
super(Post, self).save(*args, **db_kwargs)
except Exception as e:
# 오류 발생 시 로그 출력
print(f"Failed to save to database {db}: {e}")
def __str__(self):
return self.title
이 예제에서:
save() 메서드가 오버라이드되어 있다.transaction.atomic()을 사용하여 PostgreSQL에 저장할 때 데이터의 일관성을 보장한다.두 개의 데이터베이스에 대해 마이그레이션을 적용하려면 다음 단계를 거쳐야 한다.
마이그레이션 파일 생성:
python manage.py makemigrations gallery
gallery 앱에 대해 마이그레이션 파일을 생성한다.SQLite 데이터베이스에 마이그레이션 적용:
python manage.py migrate --database=default
PostgreSQL 데이터베이스에 마이그레이션 적용:
python manage.py migrate --database=postgres