독서(Reading)/클린아키텍처(Clean Architecture)

5부 아키텍처 16장 독립성

Chaany 2022. 12. 29.
728x90

1. 유스케이스

  • 시스템의 아키텍처는 시스템의 의도를 지원해야 함
  • 아키텍트의 최우선 관심사는 유스케이스이며, 아키텍처에서도 유스케이스가 최우선, 아키텍처는 반드시 유스케이스를 지원해야 함
  • 시스템의 유스케이스는 시스템 구조 자체에서 한눈에 드러나야 함 
  • 행위는 일급 요소이며 시스템의 최상위 수준에서 알아볼 수 있으므로 개발자가 일일이 찾아 헤매지 않아도 됨
  • 클래스, 함수 또는 모듈로서 아키텍처 내에서 핵심적인 자리를 차지할 뿐만 아니라, 자신의 기능을 분명하게 설명하는 이름을 가짐
  • 참고
    • 21 소리치는 아키텍처 

2. 운영

  • 요구와 관련된 각 유스케이스에 걸맞은 처리량과 응답시간을 보장해야하며 운영 작업을 허용할 수 있는 형태로 아키텍처를 구조화 해야함
  • 아키텍처에서 각 컴포넌트를 적절히 격리하여 유지하고 컴포넌트 간 통신 방식을 특정 형태로 제한하지 않는다면, 시간이 지나 운영에 필요한 요구사항이 바뀌더라도 스레드, 프로세스, 서비스로 구성된 기술 스펙트럼 사이를 전환하는 일이 훨씬 쉬워짐

3. 개발

  • 콘웨이의 법칙
  • 시스템을 설계하는 조직이라면 어디든지 그 조직의 의사소통 구조와 동일한 구조의 설계를 만들어 낼 것이다
  • 잘 격리되어 독립적으로 개발 가능한 컴포넌트 단위로 시스템을 분할하여 독립적으로 행동하기 편한 아키텍처를 확보하여 개발하여야 한다.
  • 컴포넌트를 독립적으로 작업할 수 있는 팀에 할당할 수 있어야 한다.

4. 배포

  • 아키텍처는 배포 용이성을 결정하는 데 중요한 역할을 하며, 목표는 즉각적인 배포.
  • 좋은 아키텍처는 수십 개의 작은 설정 스크립트나 속성 파일을 약간씩 수정하는 방식을 사용하지 않음
  • 시스템이 빌드된 후 즉각 배포할 수 있도록 지원해야 함
  • 시스템을 컴포넌트 단위로 적절하게 분할하고 격리시켜야 함
  • 마스터 컴포넌트는 시스템 전체를 하나로 묶고 각 컴포넌트를 올바르게 구동하고 통합하고 관리해야 함
  • 참고
    • 26 메인 컴포넌트 <- 마스터 컴포넌트에 대한 내용

5. 선택사항 열어놓기

  • 컴포넌트 구조와 관련된 관심사들 사이에서 균형을 맞추고 각 관심사를 모두 만족시켜야 함
  • 몇몇 아키텍처 원칙의 구현 비용은 비교적 비싸지 않으며, 관심사들 사이에서 균형을 잡는데 도움이 됨
  • 선택사항을 열어 둠으로써, 향후 시스템에 변경이 필요할 때 어떤 방향으로든 쉽게 변경할 수 있도록 함

6. 계층 결합 분리

  • 아키텍트는 유스케이스 전부를 알지 못하지만 시스템의 기본적인 의도는 분명히 알고 있음
  • 단일 책임 원칙과 공통 폐쇄 원칙을 적용하여, 의도의 맥락에 따라서 다른 이유로 변경되는 것들은 분리하고, 동일한 이유로 변경되는 것들은 묶음
  • 사용자 인터페이스가 변경되는 이유는 업무 규칙과 아무런 관련이 없음
  • 업무 규칙은 그 자체가 애플리케이션과 밀접한 관련이 있거나, 혹은 더 범용적일 수 있음
    • 입력 필드 유효성 검사는 애플리케이션 자체와 밀접하게 관련된 업무 규칙
    • 계좌의 이자 계산, 재고품 집계는 업무 도메인에 더 밀접하게 연관된 업무 규칙
  • 데이터베이스, 쿼리 언어, 심지어 스키마조차도 기술적인 세부사항이며, 업무 규칙이나 UI와는 아무런 관련이 없음
  • 시스템을 서로 결합되지 않은 계층으로 분리한 사례
    • UI
    • 애플리케이션에 특화된 업무 규칙
    • 애플리케이션과는 독립적인 업무 규칙
    • 데이터 베이스

7. 유스케이스 결합 분리

  • 유스케이스
    • 시스템을 분할하는 매우 자연스러운 방법
    • 시스템의 수평적인 계층을 가로지르도록 자른 수직으로 좁다란 조각
    • UI의 일부, 애플리케이션 특화 업무 규칙의 일부, 애플리케이션 독립적 업무 규칙의 일부, 데이터베이스 기능의 일부를 사용
  • 시스템에서 서로 다른 이유로 변경되는 요소들의 결합을 분리하면 기존 요소에 지장을 주지 않고도 새로운 유스케이스를 계속해서 추가할 수 있게 됨
  • 유스케이스를 뒷받침하는 UI와 데이터베이스의 서로 다른 관점을 사용하게 되면, 새로운 유스케이스를 추가하더라도 기존 유스케이스에 영향을 주는 일은 거의 없음
  • 참고
    • 27 크고 작은 모든 서비스들 <- 횡단 관심사 분리에 대한 내용

8. 결합 분리 모드

  • 결합을 분리할 때 적절한 모드를 선택해야 함
    • 분리된 컴포넌트를 서로 다른 서버에서 실행해야 하는 상황이라면, 이들 컴포넌트가 단일 프로세서의 동일한 주소 공간에 함께 상주하는 형태로 만들어져서는 안됨
    • 분리된 컴포넌트는 반드시 독립된 서비스가 되어야 하고, 일종의 네트워크를 통해 서로 통신해야 함
  • 때떄로 컴포넌트를 서비스 수준까지도 분리해야 함
  • 좋은 아키텍처는 선택권을 열어 둔다. 결합 분리 모드는 선택지 중 하나
  • 계층과 유스케이스의 결합 분리 방법
    • 소스 수준 분리 모드
      • 소스 코드 모듈 사이의 의존성 제어 가능
      • 하나의 모듈이 변하더라도 다른 모듈을 변경하거나 재컴파일하지 않도록 만들 수 있음
    • 배포 수준 분리 모드
      • jar파일, DLL, 공유 라이브러리와 같이 배포 가능한 단위들 사이의 의존성 제어 가능
      • 한 모듈의 소스 코드가 변하더라도 다른 모듈을 재빌드하거나 재배포하지 않도록 만들 수 있음
      • 결합이 분리된 컴포넌트가 jar 파일, Gem 파일, DLL과 같이 독립적으로 배포할 수 있는 단위로 분할되어 있음
    • 서비스 수준 분리 모드
    • 데이터 구조 단위까지 의존하는 수준을 낮출 수 있음
    • 네트워크 패킷을 통해서만 통신하도록 만들 수 있음
    • 모든 실행 가능한 단위는 소스와 바이너리 변경에 대해 서로 완전히 독립적(ex. 서비스 또는 마이크로 서비스)
    • 단점
      • 개발 시간 측면뿐 아니라 시스템 자원 측면에서도 비용이 많이 듦 = 필요치도 않은 서비스 경계를 처리하는 데 드는 작업은 노력(가장 비쌈), 메모리, 계산량 측면에서 모두 낭비
  • 프로젝트 초기 단계는 어떤 모드가 최선인지 알기 어려움
  • 단순히 서비스 수준에서의 분리를 기본 정책으로 삼는 것이 해결책 중 하나
    • 비용이 많이 들고, 결합이 큰 단위(coarse-grained)에서 분리됨
  • 필자의 방식
    • 컴포넌트 결합을 분리하되 서비스가 되기 직전에 멈추는 방식 선호
    • 컴포넌트들을 가능한 한 오랫동안 동일한 주소 공간에 남겨둠
    • 서비스에 대한 선택권 열어 둠
    • 초기에는 컴포넌트가 소스 코드 수준에서 분리됨
    • 배포나 개발에서 문제가 생기면 일부 결합을 배포 수준까지 분리해 대응
    • 개발, 배포, 운영적인 문제가 증가하면 서비스 수준으로 전환할 배포 단위들을신중하게 선택한 후 시스템 변경
  • 시간이 흐르면 시스템에서 운영 요구사항은 감소할 수 있으며, 서비스 수준까지 분리해야 했던 것들이 배포 수준, 소스 수준의 결합 분리만으로 충분할 수 있음
  • 좋은 아키텍처
    • 시스템이 모노리틱 구조로 태어나서 단일 파일로 배포되더라도, 이후에는 독립적으로 배포 가능한 단위들의 집합으로 성장하고, 또 독립적인 서비스나 마이크로서비스 수준까지 성장할 수 있도록 만들어져야 함
    • 상황이 바뀌었을 때 거꾸로 돌려 모놀리틱 구조로 되돌릴 수도 있어야 함
    • 변경으로부터 소스 코드 대부분을 보호함
    • 결합 분리 모드를 선택사항으로 남겨두어 배포 규모에 따라 가장 적합한 모드 선택해 사용할 수 있게 만들어 줌

9. 개발 독립성

  • 기능 팀, 컴포넌트 팀, 계층 팀, 혹은 또 다른 형태의 팀이라도, 계층과 유스케이스의 결합이 분리되는 한 시스템의 아키텍처는 그 팀 구조를 뒷받침해 줌

10. 배포 독립성

  • 유스케이스와 계층의 결합이 분리되면 배포 측면에서 고도의 유연성이 생김
    • 운영 중인 시스템에서도 계층과 유스케이스를 교체할 수 있음
    • 새로운 유스케이스를 추가하는 일은 새로운 jar파일이나 서비스 몇 개를 추가하는 단순한 일이 됨

11. 중복

  • 일반적으로 소프트웨어에서의 중복은 나쁜 것
  • 진짜 중복
    • 한 인스턴스가 변경되면, 동일한 변경을 그 인스턴스의 모든 복사본에 반드시 적용해야 하는 경우
  • 거짓된 또는 우발적 중복
    • 두 코드 영역이 각자의 경로로 발전한다면, 즉 서로 다른 속도와 다른 이유로 변경되는 경우
  • 유스케이스를 수직으로 분리할 때 중복 문제를 마주칠 테고, 유스케이스를 통합하고 싶다는 유혹을 받게 됨
  • 자동반사적으로 중복을 제거해버리는 잘못을 저지르는 유혹을 떨쳐내야함.
  • 중복이 진짜인지 가짜인지 확인해야 함
  • 특히 뷰 모델을 별도로 만드는 일은 그다지 많은 노력이 들지 않을 뿐 아니라, 계층 간 결합을 적절하게 분리하여 유지하는 데도 도움이 됨

결론

  • 시스템의 결합 분리 모드는 시간이 지나면서 바뀌기 쉬우며, 뛰어난 아키텍트라면 이러한 변경을 예측하여 큰 무리 없이 반영할 수 있도록 만들어야 함

 

728x90

댓글