Work & Programming/System Design

[Architecting] Why would we need this?

자전거통학 2024. 4. 6. 05:56

 

 

 

아키텍팅, 즉 시스템 디자인이 왜 필요한가 에 대해서 먼저 생각해 본다. 

 

프로그래머는 코드 생성, 즉 프로그래밍을 통해 전반적으로 2개의 의무를 수행한다. 

 

첫째는 기능 구현으로서의 의무다. 프로그램을 통해서 사람은 컴퓨터에게 필요한 기능을 위임한다. 계산기 같은 것이 쉬운 예이다. 입력을 받으면, 그 입력을 기반으로 컴퓨터가 프로그램에 가이드 된 내용을 토대로 결과를 돌려준다.

심플하다. 

 

둘째로 전체 디자인을 효율적으로 유지해야 할 의무를 가진다. 

그렇다면 여기서 몇 가지 파생 질문이 나온다. 

효율적이라는 것을 무엇을 말하는 것인가?

왜 그래야 하는가? - 비 효율적이어도 프로그램은 여전히 잘 기능할 수 있다. 

그렇다면, 어떻게 이 과정에 실제적으로 도달하는가?

등을 고민해 볼 수 있다. 

 

첫번째 질문부터 생각해 보자. 

무엇이 효율적인 것인가? 

 결과적으로 프로그래밍에서 효율적인 구조라함은 한마디로 '변화 당 파급 범위를 최소한으로 유지하는 것'을 의미한다.

 프로그램 개발이라는 것은 개발 과정과 지난한 서비스 과정을 합한 총체적인 것을 말한다. 예를들어 윈도우 OS를 만든 시간과 판매 후 서비스를 통해 유지하면서 각종 업데이트를 한 시간을 비교해 보면 어떤 말인지 이해가 될 것이다. 

 윈도우의 마우스 드라이버를 고치는데, 키보드 입력이 영향을 받는다면, 이것은 우리가 원하는 것이 아니다. 멀티 스크린 기능을 지원하려고 하는데, 특정 프로그램이 열리지 않는다던가 하는 문제가 생기는 것은 역시 원하는 바가 아니다. 

 이처럼 무언가 추가하거나, 고치거나, 변화를 만들 때, 이것으로 인한 영향이 최소화 되기를 바라는 것이 시스템 디자인의 목표이며 이를 효율적이다 라고 말할 수 있겠다. 

 즉, 변화 당 관련 비용을 최소한으로 유지하고자 하는 노력이라 할 수 있으며, 이는 당연하게도 프로그램 개발 사이클당 매우 큰 차이를 보인다. 개발 후기에는 프로그램이 커지고 그 복잡도와 규모가 필연적으로 커지므로, 이를 궁극적으로 개발 초기 시점과 같이 유지하고자 노력하는 것이 아키텍팅의 목표라 할 수 있겠다. 

즉, 이것은 결국 비용의 문제인 것이다. ( 아름답게 보이기 위함이 절대 아니며, 이것은 조직의 존속에 대한 문제에 가깝다. )

 

그렇다면 어떻게 이 과정으로 도달 할 수 있는가. 

 전반적으로 우선 구현하고자 하는 프로그램에 걸맞는 자원과 해당 자원 provider에 대해 잘 알고 있어야 한다.

 많이 알 수 있을 수록 더 많은 옵션을 고려할 수 있으니 말이다. (cloud service, database, app release tool, monitoring tool etc.)

 프로그램안으로는 우선 단단한 모듈을 만들고 모듈간 관계에서 검증된, 효율적인 구조를 가지려고 애쓴다. 

 여기가 각 모듈 구성 모델과, 원칙들, OOP 개념들, 디자인 패턴 등 관련 지식이 필요되는 지점이다.

 

 어떻게 스스로 단단한 모듈을 만드는가. 

 어떻게 모듈간 구조를 간결하면서 변화에 유기적으로 구성하는가 등이다. 

 

모듈은 그 자체로 깔끔한 구성을 가져야 한다. 

의도는 명료하며, 버그가 최소화 되어 있고, 중복코드가 적어야 한다. (Encapsulation)

따라서 중복 없이 모듈을 명료하게 사용하기 위해서 상속개념이 필요하다. (Inheritance)

상속해서 중복코는 재사용하고 싶지만, 구현은 종종 다르게 하고 싶다, 여기에 가상함수 개념, 즉 폴리모피즘이 들어온다. 

모듈의 의도가 정확해야 하므로, interface 구성 시 해당 의도를 명료하게 한다, 즉 single responsibility 해야 하고 interface segregation, 리스코프 substitute 해야 한다. 

한번 배포한 모듈은 바꾸지 않고, 코드는 재사용하면서 추가 구현을 해야 하므로, Open/Close 원칙이 필요하며, 

마지막으로, 구현을 외부에서 통제하여 내부 코드 수정을 최대한으로 억제 하고자 하므로, dependency inversion 이 필요하다.

 

따라서 interface, abstract class 등이 이러한 목적으로 존재한다는 것을 알아야 한다.

다시 말하지만, 이들을 안 써도 프로그램은 작동할 것이다. 그렇지만, 프로그램 수정 시 많은 대가를 치뤄야 할 것이며, 그 값은 점점 더 커질 것이다.

 

추후 포스트에서는 이에 조금 더 나아가서 각종 모델 및 디자인 패턴과 그 실례에 대해 알아보기로 하자.