Posts [클린아키텍처] 15장 아키텍처란?
Post
Cancel

[클린아키텍처] 15장 아키텍처란?

clean-architecture-book

‘클린 아키텍처’ 기술 서적에 대해 학습했던 내용을 정리하기 위한 목적의 TIL 포스팅입니다.🙆‍♂️

5부 - 아키텍처

15장 - 아키텍처란?

  • 소프트웨어 시스템의 아키텍처란 시스템을 구축했던 사람들이 만들어낸 시스템의 형태이다.
  • 그 형태는 아키텍처 안에 담긴 소프트웨어 시스템이 쉽게 개발, 배포, 운영, 유지보수되도록 만들어진다.

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

  • 형편없는 아키텍처를 갖춘 시스템도 그런대로 작동은 잘 한다.
  • 하지만 운영보단 배포, 유지보스, 개발 과정에서 어려움을 겪는다.
  • 아키텍처의 주된 목적은 시스템의 생명주기를 지원하는 것이다. 좋은 아키텍처는 시스템을 쉽게 이해하고, 쉽게 개발하며, 쉽게 유지보수하고, 또 쉽게 배포하게 해준다. 아키텍처의 궁극적인 목표는 시스템의 수명과 관련된 비용은 최소화하고, 프로그래머의 생산성은 최대화하는데 있다.

🙌나의 생각

  • 현재 개발하고 있는 제품은 MSA로 구성되어 있으며, 최근 제품의 스케줄링 아키텍처를 설계했다.

스크린샷 2023-08-06 오후 10 21 32

  • 위 아키텍처에 대해 간략하게 설명하면 다음과 같다.
    • AWS EventBridge(혹은 CloudWatch) 에서 일단위 이벤트를 람다함수로 발생시킨다.
    • 스케줄링 람다함수는 등록된 payload 에 기반하여 해당되는 마이크로서비스로 http 요청을 대신 호출해준다.
    • 만약 스케줄링이 실패하게 될 경우 별도 람다함수 트리거로 개발자들에게 팀즈 및 메일 알림을 전송한다.

시스템을 쉽게 이해할 수 있는가?

  • 내부적으로 등록된 시간에 http 요청을 대신 호출해주며 동작이 실행되기에 쉽게 이해된다고 볼 수 있다.

쉽게 개발할 수 있는가?

  • 1)위 아키텍처에 대한 노하우를 가지고 있기에(AWS 스케줄링의 가장 기반적인 아키텍처인거 같기도 하다..ㅎㅎ) 빠르게 구축 가능하다.
  • 2)도메인 내부에 구현된 로직들을 재사용 가능하다.
  • 3)JPA & QueryDSL 을 활용하여 빠르게 internal-api 만 구현해서 스케줄링만 등록하면 된다.

쉽게 유지보수 가능한가?

  • 오류 발생시 해당 internal-api 만 직접 http 요청을 보내서 빠르게 복구가능할 것이라 예상한다.

쉽게 배포 가능한가?

  • 기존 서버 배포 파이프라인을 그대로 재사용하여 배포 가능하다.
  • 별도 마이크로서비스별로 별도 스케줄링 서버를 두고 구축하는 것보다 다음과 같은 장점이 있다.
    • 1)마이크로서비스 마다 별도 스케줄링 프로젝트를 일일이 관리하지 않아도 된다.
    • 2)배포 파이프라인을 일일이 만들지 않아도 된다.
    • 3)새로운 마이크로서비스에 대한 스케줄링 요구사항을 쉽게 해결 가능하다.

아직 개발은 안된 상태이기에 추후 운영하며 겪는 이슈들은 따로 정리 예정입니다.

개발

  • 개발하기 힘든 시스템이라면 수명이 길지도 않고, 건강하지도 않을 것이다.
    • 시스템 아키텍처라면 개발팀들이 시스템을 쉽게 개발할 수 있도록 뒷밤침해야만 한다.
  • 팀 구조가 다르면 아키텍처 관련 결정에서도 차이가 난다.
    • 개발자5명 정도의 작은 팀은, 잘 정의된 컴포넌트나 인터페이스가 없더라도 서로 효율적으로 협력하여 모놀리틱 시스템을 개발할 수 있다. -> 아키텍처 관련 제약들이 오히려 방해가 된다 생각할 가능성이 높은데, 좋은 아키텍처가 결여되게 된다.
    • 개발자7명씩으로 구성된 다섯 팀이 시스템을 개발한다면, 시스템을 신뢰할 수 있고, 안정된 인터페이스를 갖춘, 잘 설계된 컴포넌트 단위로 분리하지 않으면 개발이 진척되지 않는다.
  • 이러한 ‘팀별 단일 컴포넌트’ 아키텍처가 시스템을 배포, 운영, 유지;보수하는데 최적일 가능성은 거의 없다.
    • 순정히 일정에만 쫓겨서 일한다면, 결국 이 아키텍처로 귀착될 것이다..

배포

  • 배포 비용이 높을수록 시스템의 유용성은 떨어진다.(배포와 유용성(제품을 사용하기 쉬운 정도)은 어떤 관계가 있을까..?)
  • 따라서 아키텍트는 시스템을 단 한 번에 쉽게 배포할 수 있도록 그 목표를 둬야한다.
  • 예를 들어, 개발 초기 다계에 개발자가 ‘마이크로서비스 아키텍처’를 사용하자고 결정할 수도 있다.
    • 시슽엠을 매우 쉽게 개발할 수 있다고 판단했을텐데 배포할 시기가 되면 위협적일 만큼 늘어난 수많은 마이크로서비스를 발견하게 될지도 모른다. 이는 오작동이 발생할 원천이 스며들 수도 있기 떄문이다.
  • 만약 아키텍트가 배포 문제를 초기에 고려했다면 다른 결정을 내렸을 것이다. 더 적은 서비스를 사용하고, 서비스 컴포넌트와 프로세스 수준의 컴포넌트를 하이브리드 형태로 융합하며, 좀 더 통합된 도구를 사용하여 상호 연결을 관리했을 것이다.

운영

  • 운영에 미치는 영향은 개발, 배포, 유지보수에 미치는 영향보단 덜 극적이다.
    • 운영에서 겪는 대다수의 어려움은 단순히 하드웨어를 더 투입해서 해결 가능하기 때문이다.
  • 좋은 소프트웨어 아키텍처는 시스템을 운영하는데 필요한 요구도 알려준다.
    • 달리 표현하면, 시스템 아키텍처가 개발자에게 시스템의 운영 방식을 잘 드러내 준다고 할 수 있다.
  • 시스템 아키텍처는 유스케이스, 기능, 시스템의 필수 행위를 일급 엔티티로 격상시키고, 이들 요소가 개발자에게 주요 목표로 인식되도록 해야 한다.
  • 이를 통해, 시스템을 이해하기 쉬워지며, 따라서 개발과 유지보수에 큰 도움이 된다.

유지보수

  • 비용이 가장 많이 든다.
  • 유지보수의 가장 큰 비용은 탐사와 이로 인한 위험부담에 있다.
    • 탐사란 기존 소프트웨어에 새로운 기능을 추가하거나 결함을 수정할 때, 소프트웨어를 파헤쳐서 어디를 고치는게 최선인지, 그리고 어떤 전략을 쓰는게 최적일지 결정할 때 드는 비용이다.
    • 이러한 과정 중에 의도치 않은 결함이 발생할 가능성은 항상 존재하며, 이로 인한 위험부담 비용이 추가된다.
  • 주의를 기울여 신중하게 아키텍처를 만들면 이 비용을 크게 줄일수도 있다.
    • 시스템을 컴포넌트로 분리하고, 안정된 인터페이스를 두어 서로 격리한다.
    • 이를 통해 미래에 추가될 기능에 대한 길을 밝혀 둘 수 있을 뿐만 아니라 의도치 않은 장애가 발생할 위험을 크게 줄일 수 있다.

선택사항 열어두기

  • 시스템 유연성은 시스템의 형태, 컴포넌트의 배치 방식, 컴포넌트가 상호 연결되는 방식에 상당히 크게 의존한다.
  • 소프트에어를 부드럽게 유지하는 방법은 선택사항을 가능한 많이, 그리고 가능한 오랫동안 열어두는 것이다.
    • 그렇다면 열어둬야할 선택사항이란 무엇일까? 바로 중요치 않은 세부사항이다.
  • 모든 소프트웨어 시스템은 주요한 두 가지 구성요소로 분해 가능하다.
    • 정책과 세부사항이다.
    • 정책 요소는 모든 업무 규칙과 업무 절차를 구체화한다. 정책이란 시스템의 진정한 가치가 살아 있는 곳이다.
    • 세부사항은 사람, 외부 시스템, 프로그래머가 정책과 소통할 때 필요한 요소지만, 정책이 가진 행위에는 조금도 영향을 미치지 않는다.
    • 이러한 세부사항엔 입출력 장치, 데이터베이스, 웹 시스템, 서버, 프레임워크, 통신 프로토콜 등이 있다.
  • 아키텍트의 목표는 시스템에서 정책을 가장 핵심적인 요소로 식별하고, 동시에 세부사항은 정책과 무관하게 만들 수 있는 형태의 시스템을 구축하는데 있다.
  • 이를 통해 세부사항을 결정하는 일은 미루거나 연기할 수 있게 된다. 예를 들어보자.
    • 1)개발 초기엔 어떤 DB(관계형, 분산형, 계층형, 평범한 플랫 파일)인지 선택할 필요가 없다. 고수준의 정책은 어떤 종류의 DB를 사용하는지 신경써선 안된다.
    • 2)개발 초기엔 웹 서버(HTML, AJAX, JSF)를 선택할 필요가 없다. 고수준 정책은 자신이 웹을 통해 전달된다는 사실을 알아선 안된다.
    • 3)개발 초기엔 REST 를 적용할 필요가 없다. 고수준 정책은 외부 세계로의 인터페이스에 대해 독립적이어야 하기 때문이다.
    • 4)개발 초기엔 의존성 주입 프레임워크(ex. 스프링)를 적용할 필요가 없다. 고수준 정책은 의존성을 해석하는 방식에 대해 신경써선 안된다.
  • 결정을 더 오래 참을 수 있다면, 더 많은 정보를 얻어 이를 기초로 제대로된 결정을 내릴 수 있다.
  • 이를 통해 다양한 실험을 시도해볼 수 있는 선택지도 열어 둘 수있다.
  • 현재 동작하고 있는 일부 고수준 정책이 있고, 이들 정책이 데이터베이스에 독립적이라면 다양한 데이터베이스를 후보로 두고 그 적용 가능성과 성능을 검토해볼 수 있다.
  • 선택사항을 더 오랫동안 열어둘 수 있다면 더 많은 실험이 가능하다.
    • 결정을 더 이상 연기할 수 없는 순간이 이러한 실험 덕분에 더 많은 정보를 획득한 상태일 것이다.(에센셜 스크럼에서 말하는 ‘결정을 내리지 못함으로써 손실이 발생할때가 가장 이익이 높은 결정’ 이라는 얘기가 연상된다..)
    • 뛰어난 아키텍트라면 위에서 설명한 세부사항이 아직 내려지지 않은 것처럼 행동하며, 여전히 결정을 가능한 오랫동안 연기하거나 변경할 수 있는 형태로 시스템을 만든다.

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

장치 독립성

  • 동일한 소프트웨어를 아무 변경 없이 다양한 장치에서 읽고 쓸 수 있도록 설계하는 것이 중요하다.

광고 우편

  • 광고 우편을 찍어내는데 프로그램을 장치 독립적으로 만들었더니 새로운 장치를 연결하여 엄청난 생산성을 만들어낼 수 있었다.
    • 운영체제의 입출력 추상화를 사용해서 작성되었기 때문에
  • 어떤 장치를 사용할지 전혀 모른채, 그리고 고려하지 않고도 프로그램 작성이 가능했다.
  • 이런 프로그램은 정책을 세부사항으로부터 분리한 형태를 가지고 있었다.
    • 예제의 경우엔 이름과 주소 레코드에 대한 서식이었다.
    • 세부사항은 장치였다.
    • 저자는 어떤 장치를 사용할지에 대한 결정을 연기시켰다.

물리적 주소 할당

  • 주소 할당 체계를 직접 프로그램이 알도록 개발하다보니, 다른 디스크로 마이그레이션시 너무 큰 고통을 안게되었다.(프로그램이 디스크의 주소 체계를 직접적으로 전부 아는 구조다보니 일일이 대응을해줘야해서..)
  • 새로운 동료의 조언으로 주소 할당 체계를 상대 주소를 사용하도록 바꾸었더니 위와 같은 문제를 해결할 수 있었다.
    • 시스템에서 고수준의 정책이 디스크의 물리적 구조로부터 독립되도록 수정했고, 덕분에 디스크 드라이브 구조에 대한 결정사항을 애플리케이션으로부터 분리할 수 있게 되었다.

결론

  • 좋은 아키텍트는 세부사항을 정책으로부터 신중하게 가려내고, 정책이 세부사항과 결합되지 않도록 엄격하게 분리한다.
  • 이를 통해 정책은 세부사항에 관한 어떠한 지식도 갖지 못하게 되며, 어떤 경우에도 세부사항에 의존하지 않게 된다.
  • 좋은 아키텍트는 세부사항에 대한 결정을 가능한 오랫동안 미룰 수 있는 방향으로 정책을 설계한다.

Reference

This post is licensed under CC BY 4.0 by the author.

[클린아키텍처] 12 ~ 14장

[클린아키텍처] 16장 독립성