본문 바로가기

SearchDeveloper/클린 아키텍처

[5] 15~16 아키텍처와 독립성

2023.09.15

아키텍처란?

소프트웨어 아키텍트가 하는 일

  • 프로그래머이다. 설계만 하는 사람이 아니라 계속 개발하면서 팀원들이 좋은 방향으로 설계할 수 있도록 이끌어준다.
  • 그 모양은 컴포넌트를 어떻게 분할하고 배치하고 서로 의사소통하는 방식에 의해 결정된다.
  • 시스템의 동작 여부와는 관련없다. 좋지 않은 아키텍처로도 돌아가게 만들 수는 있기 때문이다.
  • 좋은 아키텍처를 만드려는 궁극적인 목표는 시스템 수명과 관련된 비용은 최소화하고, 프로그래머의 생산성은 최대화하기 위함이다.
  • 그러려면 시스템을 쉽게 이해하고 개발하고 유지보수하고 배포할 수 있어햐한다.

이런 일을 용이하게 만들기 위해서는 가능한 많은 선택지를 오래 남겨두는 전략을 따라야 한다.

개발

팀 규모에 따라 아키텍팅도 다르다.

팀이 5명 정도로 작으면 모노리틱이 용이할 수도 있지만 팀 단위로 더 커진다면 잘 분리된 아키텍팅을 해야 개발이 용이하다.

배포

초기 개발 단계는 배포 전략을 잘 생각하지 않지만 배포하기 쉽도록 설계해야 한다.

운영

운영은 개발, 배포, 유지보수보다는 덜 극적이다. 운영상 문제는 대부분 스펙 늘리면 해결되는데, 장비 비용이 개발, 배포, 유지보수 하는 인력 비용보다는 저렴하기 때문이다.

유지보수

비용이 가장 많이 드는 측면이다. 기능은 끝도 없이 변경되고 변경될 때마다 생길 수 있는 결함 가능성도 항상 뒤따르기 때문이다. 유지보수가 인적 자원이 크게 들어가는 이유는 탐사를 해야 하기 때문이다.

새 기능 추가하거나 결함 수정해야 할 때 코드를 파헤쳐서 어디를 어떻게 수정해야 최선인지 파악해야한다.(공감하는 부분.. 코드 분석과 설계할 때 시간이 가장 많이 소요된다.)

세부사항에 대한 결정은 최대한 나중에 할 수 있게 만들자!

소프트웨어는 행위적 가치구조적 가치로 구분된다. 구조를 빠르고 쉽게 변경할 수 있는 구조적 가치가 더 중요시 되는데, 이를 유지하는 방법은

① 정책과 세부사항으로 분리하고, ② 세부사항은 최대한 나중에 결정할 수 있는 구조로 만드는 것이다.

정책과 세부사항

  • 정책: 모든 업무 규칙과 업무 정책을 구체화한다.
  • 세부사항: 정책에는 영향을 미치지 않는 입출력 장치, DB, 웹, 서버, 프레임워크, 통신 프로토콜 등이다.

세부사항(어떤 DB 를 쓸지, 어떤 웹 서버를 쓸 지)에 상관없이 고수준 정책을 구현할 수 있을 경우 장점

  • 다양항 세부사항 선택지 중 어떤 걸 선택할지 실험해볼 수 있는 시간이 확보되고, 더 나은 결정을 할 수 있다.

좋은 아키텍트는 결정되지 않은 사항의 수를 최대화한다.

사례 ①

  • 정책: 프린터로 인쇄한다.
  • 세부사항: 천공카드를 쓴다.

처음엔 천공카드에 종속적으로 프린터 인쇄하는 명령어를 짰는데, 후에 더 좋은 자기 테이프로 이관하려면 명령어를 다시 짜야 했는데 리소스가 너무 많이 들었다.

→ 정책과 세부사항을 결합해버려서 확장에 닫혀버린 사례

사례 ②

  • 정책: 고객의 이름과 주소가 들어간 수천개의 광고 우편을 만든다.
  • 세부사항: 라인프린터를 사용하거나, 자기테이프를 사용하거나

처음에 출력으로 라인 프린터 하나만 이용했는데 임대료가 너무 비쌌다. 이후에 자기 테이프로 출력해 5대의 오프라인 프린터로 빠르게 끝냈다.

→ 정책과 세부사항을 분리해 어떤 장치를 사용할지에 대한 결정을 연기

사례 ③

데이터를 디스크에 기록해야하는데, 물리 주소가 아닌 상대 주소로 변경함으로써 디스크 드라이브 구조에 대한 결정사항을 미루게 된 얘기

독립성

좋은 아키텍처가 되기 위해 지원해야 하는 것

  • 유스케이스: 시스템의 의도(ex.장바구니)를 아키텍처 수준(ex. 장바구니 애플리케이션이구나) 에서 알아볼수 있게 만들어야한다.
  • 운영: 운영 중 트래픽과 처리량에 대응할 수 있어야 한다. 모노리틱 구조보다 컴포넌트를 적절이 격리하는게 다중 프로세스, 다중 스레드, MSA 구조로 개선하기 쉬울 것이다.
  • 개발: 각 팀이 독립적으로 행동하기 편하게 컴포넌트 단위로 시스템을 분할하여 서로 방해받지 않게 할 수 있어야 한다.
  • 배포: 즉각적인 배포가 가능하도록 분리해야한다.

→ 이를 지원하는 좋은 아키텍처 중 하나: 계층 결합 분리

결합 분리 아키텍처

[1차] 계층 결합 분리

: 수평 분리 - 동일한 이유로 분리되는 애들끼리 결합시켜서 각 계층을 분리한다.

  • UI 부분
  • 애플리케이션에 특화된 업무 규칙 (정책) ex. 필드 유효성 검사
  • 애플리케이션과 독립적인 정책 ex. 결제 같은 업무 도메인
  • DB 단 - 쿼리, 스키마 같은

[2차] 유즈케이스 결합 분리

: 수직 분리 - 유스케이스 단위로 분리한다

  • 주문 추가
  • 주문 삭제

유즈케이스 분리

 

이렇게 분리하면 장점

  • 유즈케이스 별로 서버 스펙을 다르게 구성할 수 있다.
  • 개발 독립성 - 팀 별로 간섭 없이 개발을 독립적으로 할 수 있다.
  • 배포 독립성 - 계층 별로, 유즈케이스 별로 분리해놓으면 수정한 부분만 배포해서 다른 부분에 영향도 적고 새 유즈케이스를 쉽게 추가할 수도 있다.

→ 이러한 선택권을 열어두기 때문에 결합 문리 모드는 좋은 아키텍처 중 하나라고 할 수 있다.

 

※ 진짜 중복인지 확인하라

  • 화면 구조가 비슷하다고 해서 중복되는 부분을 제거하면 나중에 화면이 달라졌을 때 다시 분리해야할 수도 있다.
  • DB 스키마와 화면 필드가 같다고 그대로 내보내면 나중에 달라질 때 변경하기 어렵다.

 

결합 분리 단위 3가지

① 소스 수준 분리 모드 (뭐가 있을까.. 멀티모듈?)

  • 하나 모듈 변경해도 다른 모듈 재컴파일 하지 않게 할 수 있다.
  • 모든 컴포넌트가 같은 주소 공간에서 실행, 함수 호출로 통신한다.
  • 컴퓨터 메모리에는 하나의 실행파일이 로드된다.
  • = 모노리틱 구조

② 배포 수준 분리 모드 (디펜던시 주입?)

  • jar, DLL, 공유 메모리 같이 독립적으로 배포 가능한 단위로 의존성을 제어할 수 있고 분할되어 있다.
  • 하나 모듈 변경해도 다른 모듈 재컴파일 하지 않게 할 수 있다.
  • 모든 컴포넌트가 같은 주소 공간에서 실행, 함수 호출로 통신한다.

③ 서비스 수준 분리모드 (타팀과 API 분리?)

  • 네트워크 패킷 통해서만 통신할 수 있는 분리
  • 모든 변경에 대해 완전히 독립적이다.
  • ex. MSA

셋 중 어떤게 좋을까?

개발 초기에 소스 코드 수준에서 컴포넌트 분리하고, 개발/배포/운영 문제 증가하면 서비스 수준으로 분리하는 거 추천.

서비스 수준은 개발 시간, 시스템 자원에서 비용이 많이 들기 때문.

첨엔 모노리틱 구조여도 나중에 MSA 수준까지 쉽게 확장하거나 그 반대로 쉽게 축소도 가능하게 설계해야 좋은 아키텍처다.

 

레퍼런스

클린아키텍처 15, 16장