클린 아키텍처 스터디 6부 정리

Adam·2023년 2월 6일
0

클린 아키텍쳐

목록 보기
7/7
post-thumbnail

데이터베이스는 세부사항이다

데이터 베이스는 데이터에 접근할 방법을 제공하는 유틸리티(저수준 세부사항).

관계형 데이터 베이스

  • 관계형 테이블은 데이터 접근이 편리하지만, 아키텍처적으로 볼 때 중요하지 않다.
  • 데이터가 테이블 구조를 가진다는 사실은 오직 아키텍처의 외부 원에 위치한 최하위 수준의 유틸리티 함수만 알아야 한다.

데이터베이스 시스템은 왜 이렇게 널리 사용되는가?

  • 디스크는 느리다.
  • 데이터는 원형 트랙에 저장
  • 트랙은 섹터로 분할
  • 플래터는 수백개의 트랙으로 구성, 디스크는 십여 개의 플래터로 구성
  • 읽는 과정 : 헤드를 적절한 트랙으로 이동 -> 헤드 위치에 적절한 섹터에 올때까지 대기 -> 섹터의 4K를 RAM으로 읽어옴 -> RAM 버퍼의 색인을 찾아 필요한 바이트 가져옴
  • 데이터를 표현하는 일종의 표준적인 방식했고 파일 시스템과 RDBMS가 여기에서 나옴

파일 시스템

  • 문서 기반
  • 일련의 문서를 이름을 기준으로 저장하거나 조회할 때는 잘 동작하지만, 내용을 기준으로 검색할 때는 도움이 되지 않음

RDBMS

  • 내용 기반
  • 내용을 기반으로 레코드를 자연스럽고 편리하게 찾는 방법을 제공
  • 정형화되지 않은 문서를 저장하고 검색하는 데는 대체로 부적합하다.

두 시스템은 데이터를 디스크에 체계화해서, 효율적으로 데이터를 저장하고 검색할 수 있도록 해야 한다.

디스크가 없다면 어떻게 될까?

  • 디스크 역시 점차 RAM으로 대체될 것
  • 데이터를 파일이나 테이블 형태가 아닌 현재 RAM에 올리는 리스트, 트리와 같은 데이터 구조로 체계화할 것.

세부사항ㅊ

데이터베이스는 그저 메커니즘에 불과하며, 디스크 표면과 RAM 사이에서 데이터를 이리저리 옮길 때 사용하는 세부사항

하지만 성능은?

  • 데이터 저장소의 측면에서 성능은 완전히 캡슐화하여 업무 규칙과는 분리할 수 있는 관심사
  • 성능은 시스템 전반적인 아키텍처와는 아무런 관련이 없다.

결론

  • 체계화된 데이터 구조와 데이터 모델은 아키텍처적으로 중요
  • 데이터는 중요, 데이터베이스는 세부사항

웹은 세부사항이다

사실 웹이 바꾼 것은 아무것도 없었다.

끝없이 반복하는 추

  • 연산능력에는 차이가 있지만 결국 애플리케이션의 본질은 항상 같아 왔다.
  • 연산 능력을 중앙에 집중하는 방식과 분산하는 방식 사이에서 우리는 끊임없이 움직이는데, 업무규칙은 이에 영향을 받아서는 안된다.

요약

  • 웹은 GUI고 GUI는 세부사항이다.
  • 세부사항은 핵심 업무 로직에서 분리해야 한다.
  • 하지만 웹에서 장치 독립성은 비현실적이며 추상화 가능한 경계로 독립성을 유지하는 방향으로 가야됨

프레임워크는 세부사항이다

프레임워크는 아키텍처가 될 수 없다.

프레임워크 제작자

프레임워크 제작자는 당신을 알지 못하며 당신이 해결해야 할 문제도 알지 못한다.

혼인 관계의 비대칭성

  • 당신은 프레임워크를 위해 대단히 큰 헌신을 해야 하지만, 프레임워크 제작자는 당신을 위해 아무런 헌신도 하지 않는다.
  • 프레임워크에 한번 결합하면 떨어지기 힘들기 때문에 프레임워크에 의존적으로 설계를 하게 된다면 사용자는 프레임워크에 헌신하게 된다.

위험 요인

  • 프레임워크는 의존성 규칙을 위반하는 경향이 있다.
  • 프레임워크는 애플리케이션의 초기 기능을 만드는 데는 도움이 될 것이다. 하지만 제품이 성숙해지면서 프레임워크가 제공하는 기능과 틀을 벗어나게 될 것이다.
  • 프레임워크는 당신에게 도움되지 않는 방향으로 진화할 수도 있다.
  • 새롭고 더 나은 프레임워크가 등장해서 갈아타고 싶을 수도 있다.

해결책

  • 프레임워크를 아키텍처 바깥쪽 원에 속하는 세부사항으로 취급
  • 업무 객체를 프레임워크 기반의 클래스로 부터 파생하기를 요구한다면 프락시를 만들고 업무규칙에 플러그인할 수 있는 컴포넌틍에 프락시를 위치 시켜야 한다.
  • 스프링의 경우 DI할때 업무객체에 @Autowired가 산재해서는 안된다.
  • 메인컴포넌트는 최저 수준의 컴포넌트이기 떄문에 메인 컴포넌트에서 스프링을 사용해 의존성 주입하는게 낫다

이제 선언합니다.

  • 자바 표준 라이브러리와 같이 반드시 결혼해야 할 프레임워크도 존재
  • 애플리케이션이 프레임워크와 결혼하고자 한다면 애플리케이션의 남은 생애 동안 그 프레임워크와 항상 함께 해야 한다는 사실을 반드시 명심

결론

가급적이면 프레임워크를 가능한 한 오랫동안 아키텍처 경계 너머에 두자

사례 연구: 비디오 판매

시스템의 초기 아키텍처를 결정하는 첫 단계는 액터와 유스케이스를 식별하는 일

유스케이스 분석

  • 시스템을 분할하여 특정 액터를 위한 변경이 나머지 액터에게 전혀 영향을 미치지 않게 만들어야 한다.
  • 추상 유스케이스는 범용적인 정책을 담고 있으며, 다른 유스케이스에서 이를 더 구체화

컴포넌트 아키텍처

  • 뷰, 프레젠터, 인터랙터, 컨트롤러로 분리된 전형적인 분할 방법
  • 대응하는 액터에 따라 카테고리를 분리
  • 컴포넌트를 독립적으로 컴파일하고 빌드할 수 있는 환경을 구성하면 변경에 맞춰 배포 방식을 조정할 수 있다

의존성 관리

  • 모든 의존성은 경계성을 한 방향으로만 가로지르는데, 항상 더 높은 수준의 정책을 포함하는 컴포넌트를 향한다.
  • 사용 관계는 제어흐름과 같은 방향을 가리키며, 상속 관계는 제어흐름과는 반대 방향인데 개방 폐쇄 원칙을 적용한 것.
  • 수준의 세부사항에서 발생한 변경이 상위로 파급되어서 상위 수준의 정책에 영향을 미치지는 않음을 보장

빠져 있는 장

계층 기반 패키지

  • 전형적인 계층형 아키텍처는 웹, 업무규칙, 영속성 코드를 위해 수평으로 계층을 나눈다.
  • 엄격한 계층형 아키텍처라면 계층은 반드시 아래 게층에만 의존해야 한다.
  • 처음 시작 프로젝트를 시작히기엔 큰 문제가 없지만 시간이 지나면서 업무 도메인에 대해 알수 없다는 문제점이 드러나게 된다

기능 기반 패키지

  • 서로 연관된 기능, 도메인 개념, 또는 Aggregate Root에 기반하여 수직의 얇은 조각으로 코드를 나누는 방식.
  • 계층 기반 패키지와 달리 단 하나의 패키지로 묶여 있다. → 주문과 관련된 도메인이라는 점을 쉽게 파악할 수 있고 수정이 쉬워진다.
  • 서비스가 복잡해질수록 계층기반 패키지에서 기능기반 패키지로 리팩토링 하는 경향이 많지만 이는 좋은 코드 조직화 관점에서 보자면 차선책에 불과하다.

포트와 어댑터

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

컴포넌트 기반 패키지

  • 계층형 아키텍처의 문제 : 비순환 의존성 그래프가 생기기 쉽다.
  • 패키지에서도 사용자 인터페이스를 큰 단위의 컴포넌트로부터 분리해서 유지
  • 업무 로직과 영속성 관련 코드를 하나로 묶는다.

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

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

조직화 vs 캡슐화

  • 모든 타입을 public으로 지정한다면 패키지는 단순히 조직화를 위한 메커니즘으로 전락하여 캡슐화를 위한 메커니즘이 될 수 없다.
  1. 계층형: OrderServiceImpl은 구현체인데 아무도 의존하지 않게 protected을 써서 의존성을 강제할 수 있다.
  2. 기능기반: 외부에 노출되는 부분이 OrderController하나이기 떄문에 나머지를 protected으로 지정 가능
  3. 포트 어댑터 : 엔티티와 유즈케이스인 Orders와 OrderService는 public하게 하고 나머지 구현체는 런타임에 의존성 주입
  4. 컴포넌트 기반 패키지 : 의존성이 OrdersComponent로 향하며 이 컴포넌트만 public 나머지 구현체는 protected

결론

  • 최적의 설계를 꾀했더라도, 구현 전력을 고려하지 않으면 설계가 쉽게 망가진다.
profile
Keep going하는 개발자

0개의 댓글