김동형수 개발기

클린 아키텍처 6부 - 세부사항 본문

책 스터디/[완료] 클린아키텍처

클린 아키텍처 6부 - 세부사항

김동형수 2023. 9. 11. 22:01

30장 데이터베이스는 세부사항이다.

아키텍처 관점에서 볼 때 데이터베이스는 엔티티가 아니다. 데이터베이스는 세부사항이라서 아키텍처의 구성요소 수준으로 끌어올릴 수 없다.

뛰어난 아키텍트라면 저수준의 메커니즘이 시스템 아키텍처를 오염시키는 일을 용납하지 않는다.

 

관계형 데이터베이스

데이터가 테이블 구조를 가진다는 사실은 오직 아키텍처의 외부 원에 위치한 최하위 수준의 유틸리티 함수만 알아야 한다.

 

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

우위를 차지할 수 있단 이유는 무엇일까? 한마디로 답하자면, 바로 '디스크'때문이다.

디스크 때문에 피해갈 수 없는 시간 지연이라는 점을 완화하기 위해, 색인, 캐시, 쿼리 계획 최적화가 필요해졌다.

하나는 파일 시스템이었고, 다른 하나는 관계형 데이터베이스 관리 시스셈이었다.

 

세부사항

데이터를 장기적으로 저장하는 공간에 지나지 않는다.

디스크 자체가 존재한다는 사실조차도 인식해서는 안 된다.

 

하지만 성능은?

성능은 시스템의 전반적인 아키텍처와는 아무런 관련이 없다.

 

결론

데이터는 중요하다. 데이터베이스는 세부사항이다.

 

31장 웹은 세부사항이다.

끝없이 반복하는 추

웹이 있기 전에는 클라인언트 서버 아키텍처가 있었다.

IT 역사 전체로 시야를 넓히면 웹은 아무것도 바꾸지 않았다.

업무 규칙을 UI로부터 분리했어야 한다.

 

요약

GUI는 세부사항이다. 웹은 GUI다.

아키텍트라면 이러한 세부사항은 핵심 업무 로직에서 분리된 경계 바깥에 두어야 한다.

하지만 UI와 애플리케이션 사이에는 추상화가 가능한 또 다른 경계가 존재한다.

 

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

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

 

프레임워크 제작자

물론 당신의 문제는 프레임워크가 풀려는 문제와 꽤 많이 겹칠 것이다.

겹치는 영역이 클수록 프레임워크는 실제로 더 유용해진다.

 

혼인 관계의 비대칭성

제작자는 프레임워크에 결합되기를 바란다.

한번 결합하면 그 관계를 깨기가 매우 어렵기 때문이다.

모든 위협과 부담은 오롯이 당신이 감수할 뿐, 제작자가 감수하는 건 아무것도 없다.

 

위험 요인

프레임워크는 의존성 규칙을 위반하는 경향이 있다.

제품이 성숙해지면 프레임워크가 제공하는 기능과 틀을 벗어나게 될 것이다.

프레임워크는 당신에게 도움되지 않는 방향으로 진화할 수도 있다.

새롭고 더 나은 프레임워크가 등장해서 갈아타고 싶을수도 있다.

 

해결책

당신은 스프링을 좋아할 것이다.

업무 객체보다는 메인 컴포넌트에서 스프링을 사용해서 의존성을 주입하는 편이 낫다.

 

결론

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

 

33장 사례 연구: 비디오 판매

제품

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

 

컴포넌트 아키텍처

정말로 시스템을 이러한 컴포넌트들로 모두 분할해서 여러 개의 .jar나 .dll파일로 전달해야 할까? 그럴 수도 있고 아닐 수도 있다.

서로 독립적으로 변경될 가능성이 큰 컴포넌트들을 독립적으로 배포할 수 있게 된다.

 

의존성 관리

의존성이 하나의 방향으로 향하는 이유 - 아키텍처가 의존성 규칙을 준수하기 때문이다. 모든 의존성은 경계선을 한 방향으로만 가로지르는데, 항상 더 높은 수준의 정책을 포함하는 컴포넌트를 향한다.

제어흐름과 같은 방향을 가리키며, 상속 관계는 제어 흐름과는 반대 방향을 가르킴에 주목하자.

 

결론

코드를 한 번 구조화하고 나면 시스템을 실제로 배포하는 방식은 다양하게 선택할 수 있게 된다.

 

34장 빠져 있는 장

계층 기반 패키지

전통적인 수평 계층형 아키텍처

기술적인 관정메서 해당 코드가 하는 일에 기반해 그 코드를 분할한다.

엄청난 복잡함을 격지 않고도 무언가를 작동시켜 주는 아주 빠른 방법이다.

규모가 커질 경우 계층에 대한 고민을 한다.

 

기능 기반  패키지

애그리거트 루트에 기반하여 수직의 얇은 조각으로 코드를 나누는 방식이다.

코드 찾는 작업이 쉬워질 수 있다. 변경해야 할 코드가 여러 군데 퍼져 있지 않고 모두 한 패키지에 담겨 있기 때문이다.

 

컴포넌트 기반 패키지

컴퍼일러를 사용해서 아키텍처를 강제하는 방식을 선호한다.

컴포넌트 기반 패키지를 도입해야 하는 이유는 바로 이 때문이다. 이 접근법은 지금까지 우리가 본 모든 것들을 혼합한 것으로 큰 단위의 단일 컴포넌트와 관련된 모든 책임을 하나의 자바 패키지로 묶는데 주안점을 둔다.

업무 로직과 영속성에 관련 코드를 하나로 묶는 묶음을 컴포넌트라고 부른다.

컴포넌트는 배포 단위다. 컴포넌트는 시스템의 구성 요소로, 배포할 수 있는 가장 작은 단위다. 자바의 경우 jar 파일이 컴포넌트다.

컴포넌트를 잘 정의하면 마이크로서비스 아키텍처로 가기 위한 발판을 삼을 수 있다.

 

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

모든 타입에서 public 지시자를 사용한다는 건 사요하는 프로그래밍 언어가 제공하는 캡슐화 관련 이점을 활용하지 않겠다는 뜻이다.

 

조직화 vs. 캡슐화

public 타입을 코드 베이스 어디에서도 사용할 수 있다면 패키지를 사용하는 데 따른 이점이 거의 없다.

분명하게 해두고 싶은 점은 모놀리식 애플리에션에서 모든 코드가 단 하나의 소스 코드 트리에 존재하는 경우다.

아키텍처 원칙을 강제할 때 자기 규율이나 컴파일 후처리 도구를 이용하지 말고, 반드시 컴파일러에 의지할 것을 권장한다.

 

다른 결합 분리 모드

모듈 시스템을 제대로 사용하면 public 타입과 외부에 공표할 타입을 분리할 수 있다. 예를 들어 Orders 모듈을 생성할 때 모든 타입을 public으로 지정하더라도 그 중 일부 타입만을 외부에서 사용할 수 있도록 공표할 수 있다.

빌드 도구를 사용해서 모든 컴포넌트 각각을 개별적인 소스코드 트리로 구성해야 한다.

현실에서 소스 코드를 이 처럼 나누다 보면 성능, 복잡성, 유지보수 문제가 생기기 때문이다.

잠재적으로 절충해야 할 부분이 있음을 알고 있어야만 한다.

 

결론

설계를 어떻게 해야만 원하는 코드 구조로 매핑할 수 있을지, 그 코드를 어떻게 조직화 할지, 런타임과 컴파일러 타임에 어떤 결합 분리 모드를 적용할지를 고민하라.

팀의규모, 기술 수준, 해결책의 복잡성을 일정과 예산이라는 제약과 동시에 고려하라. 또한 선택된 아키텍처 스타일을 강제하는데 컴파일러의 도움을 받을 수 있을지를 고민하며, 데이터 모델과 같은 다른 영역에 결합되지 않도록 주의하라. 구현 세부사항에는 항상 문제가 있는 법이다.

Comments