Type hint 적용후 circular dependency 문제 해결법

장고(Django)에서 순환 종속성(circular dependency)은 서로가 서로를 의존하는 모듈 또는 패키지 간의 관계를 말합니다. 이는 코드 구조에서 일반적으로 문제가 될 수 있는 상황입니다.

장고 프로젝트는 여러 개의 앱으로 구성될 수 있습니다. 각 앱은 모델, 뷰, 템플릿 등의 구성 요소를 포함하고 있습니다. 종종, 한 앱이 다른 앱의 모델이나 뷰를 참조해야 할 때 순환 종속성 문제가 발생할 수 있습니다.

예를 들어, 앱 A가 앱 B의 모델을 참조하고 앱 B가 앱 A의 모델을 참조한다고 가정해 봅시다. 이 경우, 앱 A를 실행하려면 앱 B의 모델이 필요하고 앱 B를 실행하려면 앱 A의 모델이 필요합니다. 따라서 어느 앱을 먼저 로드해야 할지 결정할 수 없습니다. 이는 순환 종속성이 발생한 상황입니다.

순환 종속성은 일반적으로 장고에서 발생하는 문제 중 하나이며, 이를 해결하기 위해 몇 가지 방법을 사용할 수 있습니다.

  1. 모델 구조 변경: 순환 종속성이 발생하는 경우, 모델 간의 관계를 다시 설계하여 순환 종속성을 제거할 수 있습니다. 모델 간의 관계를 단방향으로 만들거나 중간에 다른 모델을 도입하여 종속성을 해결할 수 있습니다.
  2. 앱 분리: 순환 종속성 문제가 발생한 경우, 관련된 모델, 뷰, 템플릿 등을 다른 앱으로 분리할 수 있습니다. 이렇게 하면 각 앱은 독립적으로 로드될 수 있으며, 순환 종속성 문제가 발생하지 않습니다.
  3. 임시 해결책: 순환 종속성 문제를 일시적으로 해결하기 위해 임시로 lazy_import 등을 사용할 수도 있습니다. 이를 통해 모듈이 필요한 시점에 로드되도록 지연시킬 수 있습니다. 하지만 이 방법은 장기적인 해결책은 아니며, 코드 복잡성을 증가시킬 수 있습니다.

순환 종속성은 코드의 가독성과 유지보수에 문제를 일으킬 수 있으므로, 가능한 한 피하는 것이 좋습니다.

이러한 경우가 아니더라도 타입 힌트를 적용하다보면 순환 종속성 문제를 마주하기 쉽습니다.

예시 코드: company/models.py

from users.models import User, UserProfile

class Department(TimestampZone):
    # ... 생략

    def add_member(self, user: User):
        """부서원으로 user 추가"""
        user_profile: UserProfile = user.user_profile.first()
        user_profile.department = self
        user_profile.save()

company.models 모듈이 users.models를 가져오려고 하고, 동시에 users.modelscompany.models를 가져오려고 합니다. 이러한 상황은 파이썬이 모듈을 불러오는 방식 때문에 문제가 발생합니다.

타입 힌트(type hint)에서만 사용되는 import의 경우, 이 문제를 해결하는 데 좋은 방법은 TYPE_CHECKING 를 사용하는 것입니다. 이를 사용하면 타입 힌트를 위한 import를 실행 시간에 건너뛸 수 있습니다.

예를 들어, 다음과 같이 코드를 수정할 수 있습니다

from typing import TYPE_CHECKING
if TYPE_CHECKING:
    from users.models import User, UserProfile

class Department(TimestampZone):
    # ... 생략

    def add_member(self, user: 'User'):
        """부서원으로 user 추가"""
        user_profile: 'UserProfile' = user.user_profile.first()
        user_profile.department = self
        user_profile.save()

위의 코드에서, TYPE_CHECKING을 사용하여 타입 힌트에 대한 import를 정적 타입 검사기가 실행할 때만 수행하도록 했습니다. 또한 실제 클래스 대신 문자열로 타입 힌트를 제공하여 실행 시간에 해당 이름의 실제 클래스를 찾지 않도록 했습니다. 이러한 방법으로 순환 종속성 문제를 해결할 수 있습니다.

'Python > Django' 카테고리의 다른 글

django 템플릿 <script>태그  (0) 2023.07.08
Django ORM에서 던더(__)  (0) 2023.07.07
FK 관계를 설정하는 방법  (0) 2023.06.30
(Django) reverse와 reverse_lazy 차이  (0) 2023.06.23
Django로 비밀번호 유효성 검사 구현하기  (0) 2023.06.17