소프트웨어 아키텍트란?
- 프로그래머이며, 앞으로도 계속 프로그래머로 남는다.
- 최고의 프로그래머이며, 앞으로도 계속 프로그래밍 작업을 맡을 뿐만 아니라 동시에 나머지 팀원들의 생산성을 극대화할 수 있는 설계를 하도록 방향을 이끌어 준다.
- 프로그래밍 작업을 계속하는 이유는, 발생하는 문제를 경험해보지 않는다면 다른 프로그래머를 지원하는 작업을 제대로 수행할 수 없기 때문이다.
아키텍처의 목적
- 시스템 아키텍처는 시스템의 동작 여부와는 거의 관련이 없다. 형편없는 아키텍처를 갖춘 시스템도 수없이 많지만, 그런대로 잘 동작한다. (이러한 시스템들은 대체로 운영에서는 문제를 겪지 않는다. 운영보다는 배포, 유지보수, 계속되는 개발 과정에서 어려움을 겪는다)
시스템의 생명주기를 지원하는 것
이다. 좋은 아키텍처는 시스템을 쉽게 이해하고, 쉽게 개발하며, 쉽게 유지보수하고, 또 쉽게 배포하게 해준다.- 아키텍처의 궁극적인 목표는 시스템의 수명과 관련된 비용은 최소화하고, 프로그래머의 생산성은 최대화 하는 데 있다.
개발
- 개발하기 힘든 시스템이라면 수명이 길지도 않고 건강하지도 않을 것이다. 따라서
시스템 아키텍처는 개발팀(들)이 시스템을 쉽게 개발할 수 있도록 뒷받침 해야만 한다
배포
- 소프트웨어 시스템이 사용될 수 있으려면 반드시 배포할 수 있어야 하고, 배포 비용이 높을수록 시스템의 유용성은 떨어진다.
- 따라서
소프트웨어 아키텍처는 시스템을 단 한번에 쉽게 배포할 수 있도록 만드는 데 그 목표를 두어야 한다
. - 예를 들어 개발 초기 단계에 개발자가 ‘마이크로서비스 아키텍처’를 사용하자고 결정했다면 배포할 시기가 되어 위협적일 만큼 늘어난 수많은 마이크로서비스를 발견하게 될지도 모른다.
- 만약 아키텍트가 배포 문제를 초기에 고려했다면 더 적은 서비스를 사용하고, 서비스 컴포넌트와 프로세스 수준의 컴포넌트를 하이브리드 형태로 융합하며 좀 더 통합된 도구를 사용하여 상호 연결을 관리했을 것이다.
운영
- 아키텍처가 시스템 운영에 미치는 영향은 개발, 배포, 유지보수에 미치는 영향보다는 덜 극적이다. 운영에서 겪는 대다수의 어려움은 소프트웨어 아키텍처에는 극적인 영향을 주지 않고도 단순히 하드웨어를 더 투입해서 해결할 수 있다.(비용 공식 관점에서 운영보다는 개발, 배포, 유지보수를 개선하기 위한 아키텍처에 더 힘이 기울게 됨)
- 시스템을 운영할 때 아키텍처가 맡는 또 다른 역할 ⇒
좋은 소프트웨어 아키텍처는 시스템을 운영하는 데 필요한 요구도 알려준다
- ↔ 시스템 아키텍처가 개발자에게 시스템의 운영 방식을 잘 드러내 준다고 할 수 있다.
- 시스템 아키텍처는 유스케이스, 기능, 시스템의 필수 행위를 일급(first-class) 엔티티로 격상시키고, 이들 요소가 개발자에게 주요 목표로 인식되도록 해야 한다.
유지보수
- 유지보수는 모든 측면에서 봤을 때 소프트웨어 시스템에서 비용이 가장 많이 든다. 새로운 기능은 끝도 없이 행진하듯 발생하고, 뒤따라서 발생하는 결함은 피할 수 없으며, 결함을 수정하는 데도 엄청난 인적자원이 소모된다.
- 유지보수의 가장 큰 비용은 탐사와 이로인한 위험부담에 있다. 탐사란 기존 소프트웨어에 새로운 기능을 추가하거나 결함을 수정할 때, 소프트웨어를 파헤쳐서 어디를 고치는 게 최선인지, 그리고 어떤 전략을 쓰는게 최적일지를 결정할 때 드는 비용이다.
- 주의를 기울여 신중하게 아키텍처를 만들면 이 비용을 크게 줄일 수 있다.
시스템을 컴포넌트로 분리하고, 안정된 인터페이스를 두어 서로 격리한다
선택사항 열어두기
- 소프트웨어는 두 종류의 가치(행위적 가치, 구조적 가치)를 지니는데 이 중 두번째 가치가 더 중요하다. 소프트웨어를 부드럽게(soft) 만드는 것은 바로 이 구조적 가치이기 때문임
- 소프트웨어를 부드럽게 유지하는 방법은 선택사항을 가능한 한 많이 그리고 가능한 한 오랫동안 열어 두는 것이다. 열어둬야 할 선택사항은 무엇일까? 그것은 바로
중요치 않은 세부사항
이다.
- 모든 소프트웨어 시스템은 주요한 두가지 구성요소로 분해할 수 있다. 바로
정책
과세부사항
- 정책 요소는 모든 업무 규칙과 업무 절차를 구체화한다. 정책이란 시스템의 진정한 가치가 살아 있는 곳이다.
- 세부사항은 사람, 외부 시스템, 프로그래머가 정책과 소통할 때 필요한 요소지만, 정책이 가진 행위에는 조금도 영향을 미치지 않는다.
- 이러한 세부사항에는 입출력 장치, 데이터베이스, 웹 시스템, 서버, 프레임워크, 통신 프로토콜 등이 있다.
아키텍트의 목표는 시스템에서 정책을 가장 핵심적인 요소로 식별하고, 동시에 세부사항은 정책에 무관하게 만들 수 있는 형태의 시스템을 구축하는 데 있다. 이를 통해 세부사항을 결정하는 일은 미루거나 연기할 수 있게 된다. (인터페이스를 통해 중간에 의존성을 끊어준다면, 세부사항을 정책에 무관하게 만들 수 있는 형태의 시스템을 구축할 수 있다)
- 예시
- 개발 초기에는 데이터베이스 시스템을 선택할 필요가 없다. 고수준의 정책은 어떤 종류의 데이터베이스를 사용하는 지 신경 써서는 안 된다.
- 개발 초기에는 웹 서버를 선택할 필요가 없다. 고수준의 정책은 자신이 웹을 통해 전달된다는 사실을 알아서는 안 된다.
- 개발 초기에는 REST를 적용할 필요가 없다. 고수준의 정책은 외부 세계로의 인터페이스에 대해 독립적이어야 하기 때문이다. 마이크로서비스 프레임워크 or SOA 프레임워크도 적용할 필요가 없다.
- 개발 초기에는 의존성 주입 프레임워크를 적용할 필요가 없다. 고수준의 정책은 의존성을 해석하는 방식에 대해 신경 써서는 안 된다.
- 이러한 세부사항에 대한 결정을 오래 참을 수 있다면, 더 많은 정보를 얻을 수 있고, 이를 기초로 제대로 된 결정을 내릴 수 있다.
- 다른 누군가가 이미 그러한 결정을 내렸다면, 또는 회사에서 특정 데이터베이스, 특정 웹 서버, 또는 특정 프레임워크에 기여해왔다면, 뛰어난 아키텍트라면 이러한 결정이 아직 내려지지 않은 것처럼 행동하며, 여전히 결정을 가능한 한 오랫동안 연기하거나 변경할 수 있는 형태로 시스템을 만든다.
예1) 장치 독립성
정책을 세부사항으로부터 분리함. 어떤 장치를 사용해서 프린터를 하는지가 세부사항
- 프린터로 인쇄할 일이 있다면, 해당 프린터를 제어하는 입출력 명령어를 직접 사용해서 코드를 작성했다. 이러한 코드는 장치 종속적(device dependent)이었다. ⇒ 다른 장치를 이용해 인쇄를 하기 위해서는 코드를 다시 작성해야 함!!
- 오늘날의 운영체제는 입출력 장치를 소프트웨어 함수로 추상화했고, 해당 함수는 추상화된 단위 레코드 장치를 처리함
예2) 물리적 주소 할당
- 25MB 크기의 디스크 드라이브에 여러 Agent(중개인), Employer(고용주), Member(회원)의 레코드를 저장했고, 레코드마다 크기도 제각각이었음. 그래서 디스크에서 처음 몇 개 실린더를 포맷하여 각 섹터가 단일 Agent 레코드와 크기가 똑같도록 만들고, 다음 실린더 몇개도 포맷하여 각 섹터가 단일 Employer 레코드와 크기가 일치하도록 만들었음 ⇒ 소프트웨어가 디스크의 상세 구조를 알도록 만듦
- 소프트웨어가 디스크의 상세구조를 알고 데이터를 저장하면, 구조가 다른 디스크 드라이브로 업그레이드 해야 한다면 소프트웨어 코드를 다 뜯어고쳐야 함
- 모든 업무규칙(
정책
)이 실린더/헤드/섹터 체계(세부사항
)을 세세하게 알고 있었음
⇒ 주소 할당 체계를 구조를 세세하게 다 알고 하는 것이 아닌 구조를 추상화하여(디스크를 섹터로 구성된 하나의 거대한 선형배열로 취급) 변환 루틴을 작성하고 이 루틴만이 세부사항을 알고 있음
이렇게 함으로 고수준의 정책(
데이터를 저장한다
)이 세부사항(디스크의 어느 위치에 저장한다
)으로부터 분리할 수 있게 됨