architecture

클린 아키텍쳐 파이썬- django

코드모헨 2024. 4. 25. 18:38
Clean- Architecture란 무엇일까?

 

 

clean- architecture가 2021년 유럽 장고콘에서 다뤼졌다.

기존의 django 구조에는 어떤 문제가 있었길래 이런 clean architecture가 소개 된걸까?

 

기존 Django Architecture의 문제점은?

※ 비즈니스 로직을 어디에 두어야 할까?

  • Views → 읽기 힘들다, 다시쓰기 힘들다
  • Models → 모델의 dependency를 너무 복잡하게 생성한다. (즉, 수정하기 힘들다 능동적 db대응 힘듬)
  • Forms 이건 UI에 묶여있는 로직이라 불가하다

- 위의 모든 파트는 unit test하기 힘들고 share하기도 힘들다.

 

해결책은 무엇일까?

  • 특정한 layer에 고립된 비즈니스 로직을 만들자
  • 이런 layer들을 use cases layer에서 접근하게 하자
  • adapter layer를 만들어 외부에서 접근하게 하자(ex: model)
  • interface layer(ex:view)를 통해 adapter안에 있는 use case에 접근하자  

이 해결책을 바탕으로 다시금 만든 architecture구조가 바로 소개할 clean architecture다


Clean Architecture

clean architecture구조 /출처 https://www.youtube.com/watch?v=l5AtMQbAsAk

 

Clean architecture란 무엇인가?
  • 프레임워크에 독립적
  • 유닛테스트에 용이 → ui, DB, web server 그 외 모든 외부요소와 관련없이 비즈니스 로직만 테스트가능
  • UI에 독립적 UI는 언제나 쉽게 변한다 특히 front는 back보다 기술변화가 빠른데 여기에 독립적인것은
    큰 이득이다.
  • DB에 독립적 → django프로젝트를 하면서 db를 스키마를 orm을 통해 잘못 구축했을 때 변경해본 고역을 겪어본사람이라면 이게 얼마나 큰 것인지 잘 알것이다. 언제든 DB를 바꿀 수 있다. 
  • 모든 외부적 요소 3rd party든 혹은 다른것이든 이 모든것에 독립적이다.

글보단 코드가 익숙할것이다. 

다음은 clean architecture와 기존 구조와의 비교다.

 

1. 기본 구조

 

책들의 값의 평균을 구하는 로직으로 간단한 비즈니스 로직이다.

def books_average_price(request):
    price_data = Book.objects.all().aggregate(Avg('price')))
    return JsonResponse({"price":float(price_data["price__avg"])})

 

작동도 잘 되는 django의 기본 구조다. view를 통해 orm에 접근한다.

django 기본 구조 / 출처 https://www.youtube.com/watch?v=l5AtMQbAsAk

 


2. 비즈니스 로직을 통해 orm에 접근한 구조

class PriceEngine:
    def get_average_price(self):
        price_data = Book.objects.all().aggregate(Avg('price'))
        return float(price_data["price__avg"])

def books_average_price(request):
    price_engine = PriceEngine()
    price = price_engine.get_average_price()
    return JsonResponse({"price":price})

 

비즈니스 로직 모듈을 불러 orm에 접근한다.

view 함수가 직접적으로 orm에 접근하지 않는다.

변경된 비즈니스 로직 구조 / 출처 https://www.youtube.com/watch?v=l5AtMQbAsAk


3. Clean Architecture

def is_summer():
    return datatime.datatime.now().month in (6,7,8)


class PriceEngine(ABC):
    @abstractmethod
    def get_average_price(self):
        pass

class PriceEngineGeneral(PriceEngine):
    def get_average_price(self):
        price_data = Book.objects.all().aggregate(Avg('price'))
        return float(price_data["price__avg"])

class PriceEngineDiscount(PriceEngine):
    def __init__(self,discount):
        self.discount = discount or 08
    def get_average_price(self):
        price_data = Book.objects.all().aggregate(Avg('price'))
        return float(price_data["price__avg"]) * self.discount

def price_engine_factory(discount=None)->PriceEngine:
    if is_summer():
        return PriceEngineDiscount(discount)
    return PriceEngineGeneral()

def books_average_price(request):
    price_engine = price_engine_factory()
    price = price_engine.get_average_price()
    return JsonResponse({"price":price})

이제 clean architecture를 이용해서 로직을 나누었다.

 

클린 아키텍쳐 / 출처 https://www.youtube.com/watch?v=l5AtMQbAsAk

 

view는 factory를 통해 비즈니스 로직에 접근한다. 그 후 비즈니스 로직은 orm에 접근한다.

이를 통해 외부 interface가 변하여도 비즈니스 로직은 어떠한 영향을 받지 않게 되었다.