빠져 있는 장

Gooreum·2021년 11월 5일
0

클린아키텍처

목록 보기
33/33
  • 이 장은 시몬 브라운이 기고한 것으로, 클린 아키텍처를 실전에 도입시(코드화) 맞딱뜨릴 문제점과 해결책에 대해 설명한다.
  • 따라서 클린 아키텍처는 잠시 한쪽으로 제쳐 놓고, 설계나 코드 조직화와 관련된 몇 가지 접근법을 살펴보자.

계층 기반 패키지

  • 전형적인 계층형 아키텍처는 웹, 업무규칙, 영속성 코드를 위해 수평으로 계층을 나눈다.
  • 엄격한 계층형 아키텍처라면 계층은 반드시 아래 게층에만 의존해야 한다.
  • 자바의 경우 계층은 주로 패키지로 구현된다.

  • 계층형 아키텍처는 처음 시작 프로젝트를 시작히기엔 큰 문제가 없지만 시간이 지나면서 업무 도메인에 대해 알수 없다는 문제점이 드러나게 된다. (단순히 웹 - 업무규칙 - 영속성 코드로만 패키지화 되어 있기 때문, 만약 새로운 유스케이스를 추가하거나 기존의 것을 수정해야 될 때 어디서 시작해야할지 찾기 어려워짐.)

기능 기반 패키지

  • 서로 연관된 기능, 도메인 개념, 또는 Aggregate Root에 기반하여 수직의 얇은 조각으로 코드를 나누는 방식.
  • 자바로 구현시 모든 타입이 하나의 자바 패키지에 속하며, 패키지 이름은 그 안에 담긴 개념을 반영해 지음.

  • 계층 기반 패키지와 달리 단 하나의 패키지로 묶여 있다. → 주문과 관련된 도메인이라는 점을 쉽게 파악할 수 있다. 또한 '주문 조회하기' 유스케이스가 변경될 경우 변경해야 할 코드를 모두 찾는 작업이 더 쉬워짐.
  • 서비스가 복잡해질수록 계층기반 패키지에서 기능기반 패키지로 리팩토링 하는 경향이 많지만 이는 좋은 코드 조직화 관점에서 보자면 차선책에 불과하다.

포트와 어댑터

  • 엉클밥이 얘기하는 업무/도메인에 초점을 둔 코드가 프레임워크나 데이터베이스 같은 기술적인 세부 구현과 독립적이며 분리된 아키텍처를 코드 베이스는 '내부'(도메인)와 '외부'(인프라)로 구성된다는 점을 말함.

  • 여기서 중요한 것은 외부가 내부에 의존하며, 절대 그 반대로는 안된다.
  • 이 방식에 따라 주문 조회하기 유스케이스를 구현한 모습을 보자.

  • com.mycompany.myapp.domain 패키지가 '내부' 도메인 이며 나머지 패키지는 '외부'임.
  • 추가로 Orders는 OrdersRepository라는 이름에서 바뀐 이름인데, DDD에서는 유비쿼터스 도메인 언어를 관점으로 기술하라고 했기때문에 반영된것임.

→ 예를들면 도메인에 대해 논의할 때 '주문'에 대해 말하는것이지 '주문 레파지토리'에 대해 말하는것이 아니기 때문임.

컴포넌트 기반 패키지

  • SOLID, REP, CCP, CRP에 대해 동감하지만, 코드를 조직화하는 방법에 대해 다른 결론에 이름. 그래서 또 다른 선택지를 제시하려고 하는데 이를 '컴포넌트 기반 패키지'라고 부름.

  • 컴포넌트 기반 패키지를 살펴보기 앞서 계층형 아키텍처 문제점을 살펴보자.

  • 계층형 아키텍처

    • 계층형아키텍처는 의존성 화살표가 항상 아래로 향해야하고 각 계층은 반드시 바로 아래 계층에만 의존해야 함.
    • 이런 방식으로 깔끔한 비순환 의존성 그래프를 만들 수 있지만 코드베이스의 요소들이 서로 의존할 때는 몇가지 규칙을 반드시 지켜야함.
    • 계층형 아키텍처를 비순환 의존성 그래프 형식으로 만들 수 있지만 문제는 속임수를 써서 몇몇 의존성을 의도치 않은 방식으로 추가하더라도 보기에는 여전히 좋은 비순환 의존성 그래프가 생긴다.
      • 신입사원의 완화된 계층형 아키텍처 예시.
        • OrdersController가 OrdersRepository로 아래로 의존하기 때문에 비순환 원칙을 어기진 않는다. 그렇지만 이는 원하는 흐름이 아니다. 웹은 반드시 업무규칙와 분리되어야 하는데, 그러지 못하고 있기 때문에 잘못된 것이며 반드시 강제하는 규칙을 팀 내에서 정해야 한다. 하지만 이는 사람에게 강제하는 규칙이기 때문에 상황에 따라 위반되는 경우들이 많이 발생한다..
  • 포트 어댑터에서 웹을 그저 또 다른 전달 메커니즘으로 취급하는 것과 마찬가지로, 컴포넌트 기반 패키지에서도 사용자 인터페이스를 큰 단위의 컴포넌트로부터 분리해서 유지한다.

  • 이 접근법은 '업무 로직'과 영속성 관련 코드를 하나로 묶는다.
  • 컴포넌트 기반 패키지 접근법의 주된 이점은 주문과 관련된 무언가를 코딩해야 할 때 오직 OrdersComponent만 둘러보면 된다.
    • 이 컴포넌트 내부에서 관심사의 분리는 여전히 유효하며 따라서 업무 로직은 데이터 영속성과 분리되어 있다.

구현 세부사항엔 항상 문제가 있다

  • 살펴본 네 가지 아키텍처를 구현시 public 지시자를 과용한다면 설계 의도에 부합하는 아키텍처 스타일을 만들 수 없다.

조직화 vs. 캡슐화

  • 모든 타입을 public으로 지정한다면 패키지는 단순히 조직화를 위한 메커니즘(폴더와 같이 무언가를 묶는 방식)으로 전락하여 캡슐화를 위한 메커니즘이 될 수 없다.
  • public 지시자를 과용하면 네 가지 아키텍처 접근법은 본질적으로 같아진다.

  • 채택하려는 아키텍처 접근법과 관계 없이 화살표들이 모두 동일한 방향을 가리키고 있다.

  • 모든 타입을 public으로 선언한다면 수평적 계층형 아키텍처를 표방하는 네 가지 방식에 지나지 않는다.

  • 자바에서 접근 지시자를 적절하게 사용하면, 타입을 패키지로 배치하는 방식에 따라서 각 타입에 접근할 수 있는 정도가 실제로 크게 달라질 수 있다.

  • 계층기반 패키지 접근법
    • OrdersServiced와 OrdersRepository 인터페이스는 외부 패키지의 클래스로부터 자신이 속한 패키지 내부로 들어오는 의존성이 존재하므로 public으로 선언되어야 한다.
    • 반면 구현체 클래스(ordersServiceImpl과 JdbcOrdersRepository)는 더 제한적으로 선언할 수 있다(패키지 protected). 이들 클래스는 누구도 알 필요가 없는 구현 세부사항이다.
    • 나머지 아키텍처 패키지 접근법도 마찬가지이다.
profile
하루하루 꾸준히

0개의 댓글