Architecture 썸네일형 리스트형 Architecture Patterns with Python(13장) 의존성 주입(그리고 부트스트래핑) 의존성 주입(dependency injection; DI) 을 위해 bootstrap.py 라는 새로운 컴포넌트를 추가한다. 아래는 부트스트랩이 없는 경우를 보여준다. 엔드포인트에서 수많은 초기화를 수행하고 주 의존성인 UoW를 여기저기 전달해야 한다. 아래는 부트스트래퍼가 이러한 책임을 맡은 모습을 보여준다. (src/allocation/bootstrap.py) import inspect from typing import Callable from allocation.adapters import orm, redis_eventpublisher from allocation.adapters.notifications import ( AbstractNotifications, Em.. 더보기 Architecture Patterns with Python(12장) 명령-질의 책임 분리(CQRS) 읽기와 쓰기는 다르고, 또 다르게 취급해야 한다는 의견은 논란의 여지가 없다. 12.1 쓰기 위해 존재하는 도메인 모델 지금까지 비즈니스 상황에 부합하는 도메인 규칙을 만족시키는 소프트웨어를 만드는 방법들에 대한 설명을 이어왔다. '현재 사용 가능한 재고보다 더 많은 재고를 할당할 수 없다' 와 같은 명시적인 제약과 '각 주문 라인은 한 배치에만 할당된다' 와 같은 암시적인 제약을 설정하였다. 위의 규칙을 일관성 있게 지키기 위해 작은 작업 덩이리로 쪼개고 이를 커밋할 때 도움이 되는 작업 단위(UoW)나 애그리게이트 패턴을 도입했다. 이런 작은 작업 덩어리 사이에서 변경된 내용을 통신하기 위해 도메인 이벤트 패턴을 도입하여 '재고가 손상되거나 분실될 경우 배치의 사용 가.. 더보기 Architecture Patterns with Python(11장) 이벤트 기반 아키텍처 : 이벤트를 사용한 마이크로서비스 통합 앞선 장에서 커맨드와 이벤트를 분리하여 시스템 내부적으로 어떻게 이벤트를 구분하고 이를 처리할 것인지를 정의하였다. 이번 장에서는 레디스와 같은 외부 메시지 버스(혹으 메시지 브로커) 를 통해 이벤트를 주고 받는 구조에 대해 알아본다. 11.1 분산된 진흙 공, 명사로 생각하기 보통 시스템의 이벤트를 명사로 나눈다. 재고 배치, 주문, 상품, 고객 등이다. 행위가 아닌 말그대로 명사 기준이다. 할당보다는 배치로 표현한 것이 이에 해당한다. 정상 경로를 예시로 들어보면 아래와 같이 진행된다. 사용자가 웹 사이트에 방문해 재고가 있는 상품을 선택한다.(주문) 상품을 장바구니에 담고 재고를 예약한다.(배치) 주문이 완료되면 예약을 확정하고 창고에 출.. 더보기 Architecture Patterns with Python(10장) 커맨드와 커맨드 핸들러 지난 9장에서 모든 유스 케이스 함수를 이벤트 핸들러로 변경했다. API 는 새 배치를 만드는 POST 를 받으면 새로운 BatchCreated 이벤트를 만들어서 내부 이벤트처럼 처리한다. 위의 workflow 는 직관적으로 봤을 때 조금 어색함이 느껴진다. 배치가 생성되지 않은 상태에서 먼저 BatchCreated 라는 이벤트가 생성되고, 그 후에 배치가 진짜로 생성된다. 그렇다면 이름을 단순히 CreateBatch 로 바꾸면 될까? 여기서 사용되는 개념이 바로 커맨드(command) 라는 개념이다. 이번 챕터에서는 메시지를 다루는 방법 중, 커맨드와 이벤트를 활용하여 기존 코드를 리팩토링 해본다. 10.1 커맨드와 이벤트 이벤트와 마찬가지로 커맨드도 메시지의 일종이다. 시스템의.. 더보기 Architecture Patterns with Python(9장) 메시지 버스를 타고 시내로 나가기 8장에서 만든 메시지 버스를 보다 근본적인 요소로 만들어본다. 메시지 버스가 서비스 계층의 주 진입 지점으로 만든다. 9.1 새로운 아키텍처가 필요한 새로운 요구 사항 다음의 예기치 못한 상황이 발생했다고 가정해본다. 재고 조사를 하는 동안 지붕에 물이 새서 SPRINGY-MATTRESS 3개가 손상된 것을 발견했다. RELIABLE-FORK 배송에서 필요한 문서가 빠져서 몇 주 동안 세관에 머물러야 했다. 이후 RELIABLE-FORK 3개가 안전 검사에서 실패해 폐기했다. 세계적으로 반짝이는 금속이 부족해져서 다음 SPARKLY-BOOKCASE 배치를 생산할 수 없게 됐다. 이런 유형의 상황을 통해 시스템에 있는 배치 수량을 변경해야 한다는 사실을 알게 됐다. 시스.. 더보기 Architecture Patterns with Python(8장) 이벤트와 메시지 버스 비즈니스 로직을 만족하는 요소가 구현된 이후에, 무언가를 끼워 넣어야 하는 경우에는 아키텍처를 어떻게 유지할 수 있을까 도메인 이벤트 패턴과 이벤트에 대한 메시지 버스 패턴을 활용하는 방법을 예시로 알아본다. 앞서 계속해서 예제로 사용했던 주문과 배치 코드에서 재고가 없는 경우, 구매팀에 이메일로 통지하는 로직을 추가하려고 한다. 일반적으로 이러한 요구 사항이 생기면, 별 생각 없이 웹 컨트롤러에 넣기 쉽다. 8.1 지저분해지는 일 막기 8.1.1 웹 컨트롤러가 지저분해지는 일을 막자 @app.route("/allocate", methods=["POST"]) def allocate_endpoint(): line = model.OrderLine( request.json["orderid.. 더보기 Architecture Patterns with Python(6장) 작업 단위 패턴(Unit of Work) 이번 장에서 작업 단위 패턴을 이용해 서비스 계층과 데이터 계층을 완전히 분리해본다. 기존에는 플라스크 앱이 직접 데이터베이스에 요청해 세션을 시작하고, 저장소 계층과 대화하여 SQLAlchemyRepository 를 초기화하며 서비스 계층에 할당을 요청한다. UoW 가 있는 경우 플라스크 API 는 작업 단위를 초기화하고, 서비스를 호출하는 일만 하게 된다. 파이썬에서 콘텍스트 관리자로 UoW 를 구현하여 이러한 것들이 가능하도록 한다. UoW 가 동작하는 모습을 미리 보면 아래와 같다. def add_batch( ref: str, sku: str, qty: int, eta: Optional[date], uow: unit_of_work.AbstractUnitOf.. 더보기 Architecture Patterns with Python(5장) 높은 기어비와 낮은 기어비 TDD 지금까지 했던 단위 테스트는 저수준에서 작동하며, 모델에 직접 작용한다. 이런 테스트를 상위 계층으로 끌어올리면 발생하는 트레이드오프와 더 많은 일반적인 테스트 지침에 대해 알아본다. 지난 서비스 계층 챕터에서 플라스크 앱에 있던 서비스 로직을 따로 분리하는 작업을 했다. 이를 통해 API 엔드포인트 부분이 http request /response 관련 부분만 신경쓸 수 있도록 가벼워졌고, 주요 서비스 관련 기능을 오케스트레이션 하는 서비스 계층과 저장소 패턴을 통한 가짜 저장소를 조합해 높은 수준의 테스트까지 가능해졌다. 여기서 한 단계 더 나아가보자. 서비스 계층은 서비스 로직를 테스트하기 때문에 더는 도메인 모델 테스트가 필요없다. 대신 앞선 1장에서 작성했던 도메.. 더보기 이전 1 2 다음