아키텍처는 구조적 해결책이다¶
HJ, Ph.D. / Software Architect (js.seth.h@gmail.com) 초안: 2018년 06월 / 개정: 2025년 12월
Abstract¶
- 소프트웨어 시스템에서의 아키텍처는 애플리케이션, 혹은 작은 모듈이라도 체계화된 처리의 구조를 정의한다.
- 아키텍처는 규모에 대한 얘기가 아니다.
- 아키텍처는 모방을 위한 기준점이 아니다.
- 아키텍처는 단순히 설명을 위한 다이어그램도 아니다.
- 아키텍처는 애플리케이션/시스템의 공통적인 문제에 대하여 보편적 해결 방법을 제시하는 것이다.
- 이러한 방법은 코드/기능에서 기능/성능 목표를 달성하는 것과는 관점이 다르다.
- 문제 해결의 보편적 기본 구조는 '문제 정의', '원인 분석', '해결안 도출', '실행', '평가' 정도로 나뉜다.
- 일반적인 업무, 즉 기능 구현, 매뉴얼 작성 등은 문제 및 목표가 1개로 정해진다.
- 소프트웨어 아키텍처의 경우는 그렇지 않고, 애플리케이션/시스템의 공통적 문제의 보편적 해결이라는 집합적인 성질을 가진다.
- 가령 애플리케이션/시스템의 70% 문제에 대하여 80% 보편성의 해결방식과 같은 접근이 된다.
- 때문에 소프트웨어 아키텍처는 처음부터 규격 이외의 상황을 다룰 수 있어야 한다. (건축과는 매우 다르다)
- 따라서 소프트웨어 아키텍처가 제공하는 해결책은 상당히 추상적이고, 체계적이며, 구조적이다.
- 추상성: 구체성이 없다. 구체성은 개별 구현에서 부여되므로 아키텍처는 대략의 절차만 논한다.
- 체계성: 결과물이 하나의 완결된 시스템(System)으로 동작하므로 일정한 질서가 아키텍처 내부에 흐른다.
- 구조성: 해결책 내의 구성요소 간의 관계와 역학이 부여되어 있으며, 이에 따라 움직이는 경우에 동작하는 상위 개념의 방식이다. (사회 구조와 유사)
- 이 중 가장 어려운 것은 구조적인 측면이다.
- 아키텍처는 매우 요약된 형태이며, 본래부터 구체성을 가지기 어렵고, 결과물로 인해 체계성이 없기도 어렵다.
- 그래서 추상성과 체계성은 자연스럽게 획득된다.
- 하지만 구조적 해결책, 즉 단순히 기능을 구현하는 것이 아니라 시스템 공통의 문제를 개별 기능에서 분리하여 기반구조(Infrastructure)에서 해결하는 것은 자연스럽게 나오는 결론이 아니다.
- 적절하게 선택된 아키텍처에서는 파레토의 법칙(80/20 법칙)이 발견된다. 20%에 해당하는 인프라스트럭처가 전체 작업의 80%를 처리한다.
- 이를 Non-Infrastructure 상황과 비교하면, 작업 규모(=노동시간)가 수분의 일에서 십수분의 일로 줄어든다는 의미이다.
- 야근이 싫다면, 구조적 해결책이 답이다.
아키텍처의 본질: 구조적 해결책¶
대부분의 개발자들은 아키텍처를 거대한 어떤 구조로서 취사선택의 대상으로 여기며, 어떤 구조를 모방하면 여러 문제가 해결될 것처럼 생각한다. 그러나 아키텍처 자체도 상위, 중위, 하위의 층위가 있으며, 특정한 목적의 서비스만 제공하는 DLL을 제작함에 있어서도 고유 아키텍처가 들어갈 수 있다. 이는 마치 법령이 효력 순서로 헌법, 법률, 명령, 조례, 규칙, 행정규칙으로 위계가 분류되는 것과 비슷하다. 즉, 아키텍처는 규모로 결정되는 것이 아니다.
한편, MSA, Restful, Flux와 같은 이름이 유행을 타면서 무분별하게 모방하는 경향이 짙다. 그러나 아키텍처는 단순 모방을 통해 그 아키텍처의 장점을 취하기 어렵다. 이는 아키텍처 자체가 추상적 문제에 대한 추상적 해답이기 때문에 구체적 문제를 해결하지 못하기 때문이다. 각 프로젝트별 구체적 정보처리의 흐름과 상이한 아키텍처를 선택하거나, 조직 구성 등 외부적 지원에 대한 요구를 충족하지 못한다면, 아키텍처는 오히려 없었던 문제를 가져올 수도 있다.
때론 아키텍처의 도식을 아키텍처 그 자체로 이해하는 경우도 있는데, 도식은 추상적 질서라는 아키텍처의 특성이 반영된 전달 방법일 뿐이다. 아키텍처를 도식으로 이해하는 것은 달을 가리키는 손을 보고, 손가락 끝만 보는 것과 같다.
아키텍처의 본질은 단순히 컴포넌트를 나열하거나 기술 스택을 정하는 데 있지 않다. 아키텍처는 시스템이 직면한 반복적이고 공통적인 문제들을 한데 모아, 그 문제들이 일관된 처리를 하도록 일정한 패턴과 규칙을 정의하는 것이다. 공통적인 문제라는 특성 때문에 대규모화되는 경향이 있는 것도 사실이다. 하지만 반대로 높은 변칙성으로 인해, 개별 소프트웨어는 소수의 형태만 다루나, 라이브러리의 범용성 문제로 유연한 아키텍처를 구성하는 경우도 있다.
규모와 관계없이 아키텍처는 문제를 보편화시키고, 그에 대한 보편적 해답을 낸다는 특징을 가진다.
문제 해결의 기본 구조와 아키텍처¶
일반적인 문제 해결은 공통된 골격을 가진다.
- 문제 정의
무엇이 문제인지, 증상과 범위를 명확히 규정한다. 목표와 성공 기준을 함께 설정한다. - 원인 분석
표면적 현상이 아니라 근본 원인을 식별한다. 가설을 세우고 근거로 검증한다. - 해결안 도출
가능한 대안을 나열하고 효과·비용·리스크를 비교하여 최적안을 선택한다. - 실행
계획을 수립하고 역할·일정·자원을 배분하여 실행한다. - 평가
결과를 측정하여 성공 기준 충족 여부를 확인하고, 필요 시 보완·재시도한다.
아키텍처 관점에서도 이 기본 구조는 동일하지만, 범위와 관점이 확장된다.
아키텍처는 개별 문제가 아니라 공통의 문제, 즉 보편화된 문제를 다루며, 이로 인해 확장이 발생한다. 문제의 정의부터가 시스템이 겪는 문제의 전체가 아니라 일정한 비율의 공통화된 문제를 설정하게 된다. 그리고 각 해결책이 모든 경우에 최적화되긴 어려우므로 대략 70~80% 정도의 보편적 해결책을 추구하게 된다. 때문에 일반적 문제 해결에서는 '실패'로 여겨질 수 있는 정해진 규격 이외의 사항의 처리를 해결안 내부에 포함해야 한다. 실행 또한 구체적 문제들에 적용을 모두 해보는 과정이 필요하며, 평가 역시 집합적 결과에 대한 통계적 평가는 물론이고, 희소 사례에 대한 대응이 가능했는지, 그 비용이 어느 정도였는가도 감안되어야 한다.
아키텍처가 일반적 해결안 도출과 다른점¶
일반적인 문제 해결은 보통 단기적·국소적 관점에서 접근한다. 개발 분야가 아니라도 대부분의 문제는 거시적이지 않다.
그러나 아키텍처적 문제 해결은 장기적이고 전체론적 관점에서 접근한다. 의사결정은 구현만이 아니라 장래의 유지보수 비용, 팀의 작업 패턴, 확장 가능한 한계 등을 고려한다.
아키텍처적 접근 중 하나는 구조적 제약을 도입함으로써 미래의 실수를 방지하는 것이다. 예컨대 엄격한 인터페이스 계약을 도입하면 초기 개발 속도는 느려질 수 있으나, 실수로 인한 무의미한 손실을 방지할 수 있다.
다른 방식으로는 추상화 계층과 경계를 명시함으로써 복잡도를 통제한다. 복잡도의 원천을 바꾸거나 재분배하여 문제 자체의 재발을 줄인다. 이는 소프트웨어가 성장해도 예측 가능한 행동을 유지하게 한다.
핵심적인 차이는 의사결정의 대상을 '구성요소'에서 '관계'로 이동시킨다는 점이다. 개별 함수나 클래스의 최적화가 아니라 모듈 간 데이터 흐름, 경계, 정보 흐름의 방향을 설계하는 것이 아키텍처의 주된 관심사다. 이로 인해 해결 효과가 단일 요소에 있는 것이 아니라 시스템 전반으로 확산된다.
추상성¶
아키텍처는 본질적으로 추상성을 갖게 된다. 이는 초기 문제 정의 자체가 집합적 성격을 가지기 때문에 자명한 결론이다.
그러나 아키텍처 선택이 적절했는가는 구체적 사안에서 판가름난다. 아키텍처에 담긴 구성요소, 역학관계, 처리의 흐름, 정보의 흐름은 구체성을 가지고 있지 않다. 아키텍처는 실제 구체적인 행위를 규정하는 것이 아니라, 그것을 둘러싼 환경을 규정하기 때문이다. 하지만 환경적 제한은 구체적 금지사항 몇 가지보다 더 강력하기 마련이다.
비유하자면, 민주주의와 공산주의의 체제 경쟁을 예시로 들 수 있다. 전산학적으로 풀이하자면, 각각 '민주주의'라는 아키텍처와 '공산주의'라는 아키텍처를 선택한 시스템이 별도로 있는 것이다. 시스템의 특성은 물리적인 모듈의 존재로 결정되는 것이 아니다. 어떤 정치 체계이든 그 속의 인간의 욕망을 거세할 수 없듯이, 서비스는 결국 목적 기능을 작성해야 한다. 그러나 이때 아키텍처는 환경적 제약으로 작용한다. 물론 어떤 구성을 가지든 환경에 적응하여 목적 서비스를 구현하는 것이 가능은 할 것이다. 그러나 그 노력이 같지는 않다.
아키텍처는 개별 사례에 작동하는 제약사항이나 지침을 하나하나 서술하는 방식으로 정의되지 않는다. 아키텍처는 거시적인 관점에서 구성요소와 관계, 그 역할과 책임과 권한, 처리와 정보의 흐름으로 정의된다.
집합적 성격의 문제에 대해, 집합의 구성원을 다루는 해답을 제시하기 때문이다.
추상성은 문제의 속성에 기인한다.
체계성¶
아키텍처는 본질적으로 체계성(systematicity)을 가지게 된다. 이는 구현의 결과인 소프트웨어를 하드코딩된 기능의 단순 목록으로 구성하는 것이 경제성의 측면에서 도저히 맞지 않기 때문이다. 아키텍처는 소프트웨어의 효과적인 제작 및 유지보수를 목표로 함으로써, 체계성을 직접 구축하게 된다.
이러한 체계성은 단순 목록과는 큰 차이가 있다. 우선 설계 결정들이 서로 모순되지 않도록 통합적 관점을 유지한다. 모든 의사 결정은 불가분의 관계를 가진 다양한 측면을 동시에 결정하게 된다. 예를 들어 웹 서버를 물리적으로 분산하는 결정은 서버 간에 세션 상태를 공유하는 메커니즘을 구성하거나, 순수한 무상태(Stateless)로 개발해야 한다는 불가분의 조건을 가져온다. 서비스가 Stateless도 아니면서 서버 간의 상태 공유 메커니즘도 없는 분산 웹 서버는 물리적으로 존재하기 어렵다. 이처럼 하나의 결정은 다른 결정을 요구하거나, 제약한다.
물론, 단순히 모순만 없으면 되는 상태 또한 아니다. 애초에 서비스는 각자 고유의 비즈니스 목적이 있고, 그것을 달성하기 위해 설계 및 구현을 한다. 즉, 아키텍처의 결정은 분명한 목적성 하에 진행되는 것이다. 그러니, 특정 목적을 달성하기 위한 통합된 설계 결정이 모여서 아키텍처를 이루게 된다. 각 요소가 목적을 위해 무엇을 제공하며, 대략적으로 어떻게 그것을 달성할지까지 규정됨으로 아키텍처는 세부사항이 생략되었을 뿐 충분한 체계성을 가진다.
따라서 소프트웨어 아키텍처는 모든 결정사항이 서로를 요구하거나 지지하면서 동일한 목적을 위해 긴밀하게 연결된 안정된 역학관계를 가진 상태를 유지해야만 한다. 그리고 체계성을 가진 추상적 밑그림에 따라 구체적 구현을 진행하면, 체계성을 가진 소프트웨어가 작성되는 것은 당연한 인과관계이다. 또한 그 역으로, 체계적인 비즈니스를 실현하기 위해 준비하는 아키텍처가 체계성을 가져야만 하는 것도 마땅한 일이다.
체계성은 결과의 속성에 기인한다.
구조성¶
아키텍처의 해결책은 개별 사안도 지시도 아니며, 추상적인 뜬구름도 아니다. 추상성을 가질 수밖에 없는 문제와 실행 가능한 구현체라는 결과 사이에 존재하기에, 정확히 그 매개가 되는 성격을 갖는다. 적당히 구체적이면서 적당히 추상적인 해법은 실체(Concrete)를 생략하고 역할과 책임과 권한, 처리와 정보의 흐름으로 정의한 구조적 해법(Structural Solution)이다.
설계 및 디자인 패턴에서 구조적 해법이라는 언급을 자주 접하더라도 그 의미를 정확히 이해하지 못하는 경우가 많다. 이는 표현하는 단어의 혼용에서 기인하는 문제로 보이는데, 개발자가 처음 생각하는 구조는 대개 자료구조(Data Structure), C언어 등에서 사용자 형식(Custom Type) 정의에 쓰는 키워드 'struct' 등이기 때문이다. 그러나 이 맥락에서 구조의 개념은 사회과학이 말하는 구조(structure)이거나, 국가 개발 수준에서 말하는 인프라스트럭처(Infrastructure)에 가깝다.
사회과학이 말하는 구조(structure)
용례: 권력 구조, 노동 구조, 자본 구조, 물류 구조
- 기본 정의
개인이나 단일 사건을 넘어, 사회 현상이 지속적으로 반복·재생산되도록 만드는 안정된 관계망과 제도적 틀을 의미한다. 사회를 구성하는 제도·규범·역할·권력·자원 분배가 일정한 패턴으로 조직된 상태로서, 개인의 선택은 이 구조 안에서 제약·유인을 받는다. - 핵심 구성 요소
- 제도(Institution): 법, 시장, 가족, 교육, 국가 등 공식·비공식 규칙 체계
- 규범·가치(Norm/Value): 무엇이 바람직한지에 대한 사회적 기대
- 역할(Role): 지위에 따라 기대되는 행동 양식
- 권력·자원(Power/Resource): 누가 무엇을 통제·분배하는가
- 관계망(Relations): 계층, 조직, 네트워크 간 상호작용
- 개인과 구조의 관계
- 구조적 제약: 선택 가능한 행동의 범위를 제한
- 구조적 기회: 특정 행동을 유리하게 만듦
- 개인의 행위는 구조를 재생산하거나 변형할 수 있음
기술적으로 디자인 패턴이 다양한 상황에 맞춰 각기 다른 구조를 제시한다는 점에서 이해하기 좋은 샘플이 된다.
디자인 패턴의 경우 구체적인 구현 객체는 알려주지 않고 실현 클래스(Concrete Class)라고 익명으로 처리한다. 즉, 실행 시의 구체적인 개체(Instance)는 생략하고 역할과 책임과 권한, 처리와 정보의 흐름을 통해 해결하는 방법을 모형적으로 제시하고 있다.
구조성은 해결안 도출 방법에서 온다.
구조적 해결책의 실질적 효과¶
사회 과학적 정의를 차용하면, 아키텍처 안에서 개별 모듈과 클래스는 제약과 유인을 받는다. 즉 A 방향의 구현은 더 어렵고, B 방향의 구현은 더 쉽다. 그러면, 개별 구현은 전반적으로 B 방향으로 쏠리게 된다. 그렇게 함으로 아키텍처는 전체 시스템의 코드 품질, 안정성, 유지보수 비용, 확장성 등을 아키텍트가 원하는 방향으로 모은다.
이러한 유인과 제약은 각 비즈니스의 목적, 성격, 비용 구조, 인력 구조 등 여러 맥락에 맞게 결정되어야 한다. 적절한 아키텍처가 적용될 때, 즉 타당한 유인과 제약이라는 대가를 토대로 구조적 이점을 충분히 얻어낼 수 있을 때, 작업 효율이 향상되고 필요한 노력이 줄어든다.
이와 관련하여 직관적인 세 가지 상태가 있다. 이 세 가지 상태는 아키텍처의 유인과 개별 구현의 요구가 충돌하는지, 시너지를 내는지 느낄 수 있는 기준으로 볼 수 있다.
- Worst - 간단한 기능 구현이 번거롭고, 어려운 기능은 너무 어렵거나 불가능하다.
- Normal - 간단한 기능 구현은 무난하고, 어려운 기능 구현은 어렵다.
- Best - 간단한 기능 구현은 간단하고, 어려운 기능 구현도 상대적으로 쉽다.
구조적 해결책은 Worst를 피하고, 적어도 Normal, 가능하다면 Best를 목표로 한다. 이는 문제의 공통적인 성질과 비즈니스 목적, 성능 목적 등을 정확히 파악하여, 적절한 역할 분배와 처리 흐름을 결정함으로써, 공용 인프라에서 가능한 많은 일을 정형화(Normalize/Standardize)하여 처리하도록 디자인함으로써 실현이 가능하다. 기능이 정형화되어 공통 함수의 사용 비율이 높아지면 자연스럽게 개별 기능 구현에서 위탁/위임 분량이 많아짐으로써 달성된다. 그러나 이것은 공통 모듈 구현의 양을 늘리는 것이나, 공통 모듈 내부의 분기를 복잡하게 하는 것이 아니다. 양이나 분기가 많다면, 리스크의 위치가 옮겨졌을 뿐, 정형화를 기반으로 일정한 질서를 부여하여 체계화(Systemize)를 달성했다고 볼 수 없으며, 실제 개발에서 오류의 위치만 달라지는 결과로 나타난다.
엄격히 말해 아키텍처 자체가 완벽한 밀봉 용기는 아니기 때문에, 이처럼 아키텍처를 지키지 않는 개발이 얼마든지 가능하다. 이런 경우에는 이점보다 손실이 더 클 수밖에 없다. 때문에 아키텍처는 아키텍트의 전유물이 아니라, 프로젝트의 모든 개발자가 알고 있어야 한다.
결론¶
구조적 해결책은 단순히 기능을 개발하거나 서비스를 잘 구현하자고 말하는 것이 아니다. 그것은 오랜 시간 열심히 하드코딩하는 것으로도 충분히 달성할 수 있다.
개발자에게 구조적 해결책의 궁극적 목적은 파레토의 법칙의 실현이다.
20%의 코드가 80%의 일을 해결한다는 것은 단순히 재사용을 통해 코드의 작성 분량이 줄었다는 것 이상의 의미이다. 현실적으로는 코드의 양이 많고 각 요소가 개성을 가지고 있다면 가독성의 하락, 일관성의 상실, 복잡성으로 인한 커뮤니케이션 비용 등 개발/디버깅에 승수 효과가 발생하기 때문에 몇 배의 노동력을 필요로 하게 된다.
야근이 싫다면, 구조적 해결책이 구조적 해결책이다.
See Also¶
- 소프트웨어 아키텍처는 의사결정이지, 모방이 아니다 - 아키텍처의 본질과 모방의 한계, 의사결정의 중요성을 다룸
- 소프트웨어 아키텍처는 확장보다 불변에 의해 결정된다 - 아키텍처의 불변성과 구조적 관점 강조
- 디자인 패턴은 본래 고쳐 쓰는 것이다 - 구조적 해결책과 패턴의 실용적 적용에 대한 논의
- 불신의 코딩 vs 신뢰의 코딩 - 시스템 구조와 개발 문화, 구조적 제약의 의미
Author¶
HJ, Ph.D. / Software Architect
(js.seth.h@gmail.com)
https://js-seth-h.github.io/website/Biography/
Over 20 years in software development, focusing on design reasoning and system structure - as foundations for long-term productivity and structural clarity.
Researched semantic web and meta-browser architecture in graduate studies,
with an emphasis on structural separation between data and presentation.
Ph.D. in Software, Korea University
M.S. in Computer Science Education, Korea University
B.S. in Computer Science Education, Korea University
저작자표시-비영리-변경금지(CC BY-NC-ND 4.0)