파이썬(Python)

[파이썬으로 살펴보는 아키텍처 패턴] 00. 도입

leebaro 2021. 10. 21.
728x90

이 글은 "파이썬으로 살펴보는 아키텍처 패턴" 책을 보며 정리한 내용입니다. 자세한 내용은 책을 통해서 확인 가능합니다.

 

파이썬으로 살펴보는 아키텍처 패턴: TDD, DDD, EDM 적용하기 - 교보문고

고수준 아키텍처 패턴을 적절한 위치에서 활용하는 능력을 키워보자 이 책은 파이썬을 활용한 실전 예제를 통해 도메인 주도 개발을 설명한다. 설명하는 과정에서 이론이나 실무에 지나치게 치

www.kyobobook.co.kr


0.1 설계가 왜 잘못되는가?

소프트웨어 시스템도 혼돈 상태로 향하려는 경향이 있다. 시스템을 처음구축할 때는 코드를 깔끔하게 질서 잡힌 상태로 유지하기 위해 원대한 계획을 세운다. 하지만 시간이 지남에 따라 잘못 구현한 부분이라 에지 케이스(잘 일어나지 않는 드문 경우)를 처리하기 위한 코드가 점점 늘어나고 결국에는 관리자 클래스와 유틸리티 모듈로 이루어진 혼란스러운 늪에 빠지게 된다.

이런 일이 흔히 발생해서 소프트웨어 엔지니어들은 이런 혼돈 상태를 부르는 용어를 만들었다. 큰 진흙 공(big ball of mud) 안티패턴이다.

0.2 캡슐화와 추상화

캡슐화(encapsulation) : 행동의 단순화와 데이터 은닉이라는 두 가지 단어가 밀접하게 연관된 아이디어. 코드에서 수행할 작업을 식별하고 이 작업에 잘 정의된 객체나 함수를 부여함으로써 행동을 캡슐화 한다. 이렇게 (행동을 캡슐화해주는) 객체나 함수를 추상화(abstraction)라고 한다.

p.27의 캡슐화 설명 코드 참고

행동을 추상화로 캡슐화하는 것은 코드의 표현력ㅇ르 더 높이고 테스트와 유지보수를 더 쉽게 만드는 강력한 도구다.

 

객체 지향 세계의 문헌을 보면 고전적인 접근 방식으로 책임 주도 설계(responsibility-driven design)가 있다. 이 설계 기법은 작업이 아니라 역할과 책임이라는 단어를 사용한다. 여기서 핵심은 코드를 데이터나 알고리즘이 아니라 행동을 중심으로 생각하자는 것이다. 책임에 대해 생각하면 어떻겍 각 부분을 나눌지 결정할 때 도움이 된다.

 

추상화와 ABC
전통적인 OO 언어에서는 추상 기반 클래스(abstract base class)나 인터페이스를 사용해 추상화를 정의한다. 파이썬에서도 ABC를 사용할 수 있지만, 주로 덕 타이핑에 의존한다.



추상화는 단지 '여러분이 사용하는 대상이 공개한 API'를 뜻한다. 예를 들면 함수 이름과 파라미터들이 바로 추상화이다.

참고 덕 타이핑 덕 타이핑은 특정 타입에 얽매이지 않고, 원하는 행동을 할 수 있는 여부로 판단한다. 그래서 타입에 제약없이 사용하여 보다 유연하게 코드를 작성할 수 있다.

출처: https://mygumi.tistory.com/367 [마이구미의 HelloWorld] https://nesoy.github.io/articles/2018-02/Duck-Typing https://mygumi.tistory.com/367

0.3 계층화

캡슐화와 추상화를 하면 세부 사항을 감추고 데이터의 일관성을 보호할 수 있다. 하지만 객체와 함수들의 상호작용에도 주의를 기울여야 한다. 어떤 함수나 모듈, 객체인 A가 다른 함수나 모듈, 객체인 B를 사용할 때 이를 A가 B에 의존한다.(A depends on B)라고 한다. 이런 의존성은 네트워크나 그래프를 이룬다.

큰 진흙 공에서는 의존성이 제어할 수 없을 정도로 복잡하다. 시스템의 여러 부분에 영향을 줄 가능성이 있기 때문에 그래프에서 어느 한 노드를 변경하기가 어렵다. 계층화한 아키텍처는 이 문제를 해결하는 방법 중 하나다. 계층화한 아키텍처에서는 코드를 서로 구분하는 범주나 역할로 분할하고, 어떤 코드 범주가 어떤 범주를 호출할 수 있는지에 대한 규칙을 도입한다.

가장 일반적인 예는 3층 아키텍처이다. 표현계층 --> 비즈니스 로직 --> 데이터베이스 계층

비즈니스 소프트웨어를 구축할 때 아마도 계층화한 아키텍처가 가장 흔한 패턴일 것이다. 이 모델에는 사용자 인터페이스 컴포넌트가 있다. 이 컴포넌트는 웹 페이지나 API거나 명령줄 일 수 있다. 이런 사용자 인터페이스 컴포넌트는 비즈니스 규칙과 워크플로를 담은 비즈니스 로직 계층과 의사소통한다. 마지막으로 데이터를 읽고 쓰는 역할을 하는 데이터베이스 계층이 있다.

0.4 의존성 역전 원칙

캡슐화를 설명할 때처럼 3가지 짧은 코드 조각을 가지고 DIP을 설명할 수는 없다.(SOLID의 D인 의존성 역전 원칙(dependency inversion principle)) DIP의 엄밀한 정의는 다음과 같다.

  1. 고수준 모듈은 저수준 모듈에 의존해서는 안 된다. 두 모듈 모두 추상화에 의존해야 한다.
  2. 추상화는 세부 사항에 의존해서는 안 된다. 반대로 세부 사항은 추상화에 의존해야 한다.

고수준 모듈(high-level module)은 여러분의 조직에서 정말 중요하게 여기는 코드다. 제약 회사에 근무 한다면 고수준 모듈은 환자와 임상시험을 관리한다. 은행에서 근무한다면 고수준 모듈은 거래나 외환을 관리한다. 고수준 모듈은 실세계의 개념을 처리하는 함수, 클래스, 패키지를 말한다. 저수준 모듈은 조직에서 신경쓰지 않는 코드다. HR 부서가 파일 시스템이나 네트워크 소켓에 관심을 갖을 가능성이 낮다. 기술적이지 않은 관련자들에게 이런 저수순 개념은 흥미롱누 대상이거나 중요하지 않다.

의존성은 꼭 임포트나 호출만을 뜻하지 않는다. 대신 한 모듈이 다른 모듈을 필요로 하거나, 안다는 좀 더 일반적인 생각이 의존성이다.

추상화는 duckduckgo모듈이 검색 엔진 API를 캡슐화해준 것처럼 행동을 캡슐화하는 단순화한 인터페이스이다.

DIP의 첫 부분은 비즈시느 코드가 기술적인 세부 사항에 의존해서는 안 된다는 의미다. 대신 양 쪽 모두 추상화를 사용해야 한다. 서로를 독립적으로 변경하길 원하기 때문이다. 고수준 모듈은 비즈니스의 필요에 따라 쉽게 변경이 가능해야 한다. 저수준 모듈은(또는 그 세부 사항은) 실제로 변경하기가 어렵다. 함수 이름을 바꾸는 것와 열 이름을 바꾸기 위해 데이터베이스 마이그레이션을 정의하고, 테스트하고, 배치(deploy)하는 것을 비교해보자. 비즈니스 로직이 저수준 인프라의 세부 사항과 밀접하게 연결돼서 변경이 어려워지는 일이 없기를 바란다. 하지만 인프라 세부 사항을 변경할 필요가 있을 때(예를 들어 데이터베이스 샤딩을 변경하는 경우) 비즈니스 계층을 변경하지 않고도 인프라 세부 사항을 바꿀 수 있어야 한다. 추가로 둘 사이의 추상화(유명한 추가 간접 계층)을 사용하면 두 계층이 서로 (더 많이) 독립적으로 변경될 수 있다.

두 번째 부분은 더 어렵다. "추상화는 세부 사항에 의존해서는 안 된다."라는 말은 충분히 명확해 보이지만, "세부 사항은 추상화에 의존해야 한다."는 상상하기 어렵다. 어떻게 자신이 추상화하는 세부 사항에 의존하지 않는 추상화가 가능할까? 뒤에서 구체적인 예제를 다룬다.

0.5 모든 비즈니스 로직을 위한 장소 : 도메인 모델

3계층 아키텍처의 내부를 뒤집어 밖으로 보내기 전에 중간 계층인 고수준 모듈이나 비즈니스 로직에 대해 좀 더 이야기할 필요가 있다. 필자가 만든 설계가 잘못되는 가장 일반적인 경우는 비즈니스 로직이 애플리케이션의 전 계층에 퍼지기 때문이다. 이렇게 되면 비즈니스 로직은 식별하고, 이해하고, 변경하기가 어려워진다.

728x90