Django에서 다중 데이터베이스 사용하기

찬민·2024년 10월 1일

TIL

목록 보기
62/62

Django에서 두 개의 데이터베이스 (SQLite와 PostgreSQL)를 연결하고 데이터베이스 라우터(MultiDBRouter)를 사용하여 데이터베이스 설정했다.

1. 데이터베이스 설정 (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 데이터베이스로, 환경 변수를 통해 설정을 가져온다.

2. 데이터베이스 라우터 구현 (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'}

3. 다중 데이터베이스에 대한 모델 설정

다음은 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() 메서드가 오버라이드되어 있다.
  • 데이터는 기본 데이터베이스 (SQLite)에 먼저 저장되고, 이후 PostgreSQL에도 동일하게 저장된다.
  • transaction.atomic()을 사용하여 PostgreSQL에 저장할 때 데이터의 일관성을 보장한다.

4. 데이터베이스 마이그레이션

두 개의 데이터베이스에 대해 마이그레이션을 적용하려면 다음 단계를 거쳐야 한다.

마이그레이션 생성 및 적용

  1. 마이그레이션 파일 생성:

    python manage.py makemigrations gallery
    • gallery 앱에 대해 마이그레이션 파일을 생성한다.
  2. SQLite 데이터베이스에 마이그레이션 적용:

    python manage.py migrate --database=default
    • 기본 데이터베이스인 SQLite에 대해 마이그레이션을 적용한다.
  3. PostgreSQL 데이터베이스에 마이그레이션 적용:

    python manage.py migrate --database=postgres
    • PostgreSQL에도 동일한 마이그레이션을 적용한다.

0개의 댓글