개발을 하다 보면 소프트웨어 아키텍처라는 용어를 필수적으로 접하게 된다.
그렇다면 소프트웨어 아키텍처란 무엇을 의미하고 왜 등장했을까?
그리고 좋은 아키텍처란 무엇이며, 효과적으로 활용할 수 있는 방법은 무엇일까?

이 글에서는 소프트웨어 아키텍처의 개념과 역사, 그리고 그것이 왜 중요한지에 대해 정리 보려고 한다.
 
공부 목적으로 작성된 게시글이니, 본문 내용에 대한 피드백이나 수정이 필요한 부분이 있다면 댓글 부탁드립니다.


1. 아키텍처 란?

1.1 소프트웨어 아키텍처 등장 배경 🏛

소프트웨어 설계와 개념은 1960년대 후반부터 시작했으며, 소프트웨어 아키텍처라는 용어는 1990년대에 본격적으로 사용되었다.
 
당시 소프트웨어의 복잡성을 해결하기 위해 데이터 구조, 알고리즘, 관심사 분리 등의 방법이 주로 활용되었으며,
시스템 설계 역시 단순한 상자-선 다이어그램(box-and-line diagrams) 방식이 일반적이었다.
 
그러나 시간이 흐르면서 소프트웨어 시스템이 점점 더 복잡해졌고, 체계적인 아키텍처 설계의 필요성이 커졌다.
이에 따라 1990년대에는 아키텍처 스타일, ADL, 문서화, 형식적 방법 등이 활발히 연구되었고,
그 결과 소프트웨어 아키텍처 개념이 정립되고 궁극적으로 표준화로 이어졌다.

  • IEEE 1471-2000: 최초의 소프트웨어 아키텍처 표준
  • ISO/IEC 42010:2007 → ISO/IEC/IEEE 42010:2011: 국제 표준으로 발전

 

1.2 소프트웨어 아키텍처 정의

소프트웨어 아키텍처는 소프트웨어의 골격을 이루는 기본 구조이자, 구성 요소 간의 관계를 정의하는 체계이다.
이는 단순한 코드의 집합이 아니라, 시스템의 동작 방식과 상호작용을 결정하는 설계도의 역할을 한다.
 

💡 소프트웨어 아키텍처와 건축을 함께 비교해보자!

소프트웨어 아키텍처는 시스템의 뼈대와 같다.

건물을 지을 때 설계도 사용 없이 무작정 벽돌을 쌓는다면 건물 자체가 취약해질 확률이 높다.
마찬가지로, 소프트웨어를 아키텍처 없이 개발하는 것은 유지보수나 확장성이 떨어져 비효율적인 시스템이 될 가능성이 높다.
건축에서 구조, 재료 선택, 배관, 전기설비 등이 중요하듯이 소프트웨어에서도 모듈 구성, 데이터 흐름, 성능 최적화 등이 중요하다.


1.2 아키텍처가 필요한 이유

  • 유지보수성: 코드가 복잡해질수록 유지보수가 어려워지므로, 체계적인 구조가 필요하다.
  • 확장성: 새로운 기능을 추가하거나 변경할 때, 전체 시스템을 다시 만들 필요 없이 확장할 수 있어야 한다.
  • 재사용성: 동일한 아키텍처를 여러 프로젝트에서 활용할 수 있어 생산성이 향상된다.
  • 성능 및 안정성: 구조적인 설계를 통해 성능 최적화와 에러 관리가 용이하다.

 

2. 소프트웨어 아키텍처 원칙

1. 모듈화
시스템의 기능들을 모듈 단위로 나누는 것 _ 이때 모듈 개수는 적당히. 너무 많을 경우 통합 비용이, 너무 적을 경우 모듈 하나의 개발 비용이 많이 들게 됨.
2. 추상화
전체적이고 포괄적인 개념 설계 -> 차례로 세분화 / 구체화
3. 단계적 분해
문제를 상위의 중요 개념으로부터 하위의 개념으로 구체화시키며 분할
4. 정보 은닉
한 모듈 내부에 포함된 절차와 자료를 숨기며 독립적 수행을 가능캐 해, 다른 모듈이 접근하거나 변경하지 못하게 하기

2.1 SOLID 원칙

객체 지향 설계에서 중요한 5가지 원칙으로, 유지보수성과 확장성을 높이는 데 도움을 준다.
단일 책임 원칙 (Single Responsibility Principle, SRP)

  • 하나의 클래스(모듈, 함수)는 단 하나의 책임만 가져야 한다.
  • 여러 기능을 한 클래스나 함수에 몰아넣으면 유지보수가 어려워지므로, 책임을 분리해야 한다.

개방-폐쇄 원칙 (Open-Closed Principle, OCP)

  • 기능 확장은 가능해야 하지만, 기존 코드 변경은 최소화해야 한다.
  • 인터페이스나 추상 클래스를 활용하여 새로운 기능을 추가할 수 있도록 설계해야 한다.

리스코프 치환 원칙 (Liskov Substitution Principle, LSP)

  • 상위 타입의 객체를 하위 타입으로 교체하더라도 프로그램이 정상적으로 동작해야 한다.
  • 즉, 서브클래스는 부모 클래스의 기능을 해치지 않고 확장해야 한다.

인터페이스 분리 원칙 (Interface Segregation Principle, ISP)

  • 클라이언트가 자신이 사용하지 않는 기능에 의존하지 않아야 한다.
  • 하나의 큰 인터페이스보다는 여러 개의 작은 인터페이스로 나누는 것이 좋다.

의존성 역전 원칙 (Dependency Inversion Principle, DIP)

  • 구체적인 구현이 아닌 **추상화(인터페이스, 프로토콜)**에 의존해야 한다.
  • 상위 모듈이 하위 모듈의 구체적인 구현을 직접 참조하는 것이 아니라, 추상화 계층을 두어 의존성을 줄인다.

 

3. 아키텍처 스타일 (Architectural Style)

3.1 아키텍처 스타일의 개념

아키텍처 스타일은 시스템의 구성 요소와 그 상호작용 방식을 정의하는 공통된 패턴이나 접근 방식을 의미한다.
즉, 시스템의 구성 요소, 데이터 흐름, 상호작용 방식을 정하는 큰 틀이다.

3.2 대표적인 아키텍처 스타일 종류

3.2.1 클라이언트-서버 아키텍처 (Client-Server Architecture)
클라이언트-서버 아키텍처는 네트워크를 통해 클라이언트와 서버가 상호 작용하는 분산 애플리케이션 구조이다. 클라이언트는 사용자 인터페이스를 제공하고 서버에 서비스를 요청하며, 서버는 이러한 요청을 처리하고 데이터를 제공한다.

특징:

  • 클라이언트와 서버는 별도의 하드웨어에서 실행되며, 네트워크를 통해 통신한다.
  • 서버는 여러 클라이언트의 요청을 동시에 처리할 수 있다.

장점:

  • 중앙 집중식 관리로 데이터와 리소스를 효율적으로 관리할 수 있다.
  • 서버의 성능을 향상시켜 전체 시스템의 성능을 개선할 수 있다.

단점:

  • 서버에 부하가 집중되면 성능 저하가 발생할 수 있다.
  • 서버 장애 시 전체 시스템이 영향을 받을 수 있다.

예시:
웹 브라우저와 웹 서버, 이메일 클라이언트와 메일 서버 등.


 

3.2.2 모놀리식 아키텍처 (Monolithic Architecture)
모놀리식 아키텍처는 애플리케이션의 모든 기능이 단일 코드베이스와 실행 환경에서 동작하는 전통적인 소프트웨어 개발 모델이다.

특징:

  • 애플리케이션의 모든 구성 요소가 하나의 코드베이스에 포함되어 있다.
  • 단일 단위로 배포 및 실행된다.

장점:

  • 개발 및 배포가 단순하며, 초기 개발 속도가 빠르다.
  • 통합된 환경에서 성능 최적화가 용이하다.

단점:

  • 애플리케이션이 커질수록 유지보수와 확장이 어려워진다.
  • 부분적인 기능 업데이트 시 전체 시스템을 재배포해야 한다.

예시:
전통적인 엔터프라이즈 애플리케이션, 초기 전자상거래 플랫폼 등.


3.2.3 레이어드 아키텍처 (Layered Architecture, N-Tier)
레이어드 아키텍처는 애플리케이션을 기능별로 계층화하여 각 계층이 특정 역할을 담당하도록 설계하는 방식이다. 일반적으로 프레젠테이션, 비즈니스 로직, 데이터 접근 계층으로 구성된다.

특징:

  • 각 계층은 독립적으로 개발 및 수정이 가능하며, 다른 계층과 명확한 인터페이스를 가진다.
  • 계층 간의 의존성을 최소화하여 모듈성을 향상시킨다.

장점:

  • 코드의 재사용성과 유지보수성이 높아진다.
  • 각 계층의 역할이 명확하여 개발 및 테스트가 용이하다.

단점:

  • 계층 간의 호출이 많아질 경우 성능 저하가 발생할 수 있다.
  • 단순한 애플리케이션에는 과도한 설계가 될 수 있다.

예시:
전통적인 엔터프라이즈 애플리케이션, MVC(Model-View-Controller) 패턴을 적용한 시스템 등.

 

3.2.4 이벤트 기반 아키텍처 (Event-Driven Architecture)
이벤트 기반 아키텍처는 시스템 구성 요소들이 이벤트를 통해 비동기적으로 상호 작용하는 방식이다. 이벤트는 상태의 변화나 특정 작업의 완료 등을 나타내며, 이를 기반으로 다른 구성 요소들이 반응한다.

특징:

  • 구성 요소 간의 결합도가 낮아 유연하고 확장성이 높다.
  • 실시간 데이터 처리와 반응형 시스템 구축에 적합하다.

장점:

  • 시스템의 확장성과 유연성이 향상된다.
  • 실시간 처리와 모니터링이 가능하다.

단점:

  • 이벤트 흐름을 추적하고 디버깅하기 어려울 수 있다.
  • 데이터 일관성 유지에 대한 추가적인 고려가 필요하다.

예시:
IoT 시스템, 실시간 알림 시스템, 금융 거래 시스템 등.


3.2.5 마이크로서비스 아키텍처 (Microservices Architecture)
마이크로서비스 아키텍처는 애플리케이션을 작은 독립적인 서비스들의 모음으로 구성하는 방식이다. 각 서비스는 특정 비즈니스 기능을 담당하며, 독립적으로 배포 및 운영될 수 있다.

특징:

  • 각 서비스는 독립적인 코드베이스와 데이터 저장소를 가질 수 있다.
  • 서비스 간 통신은 일반적으로 HTTP API, gRPC, 메시지 큐 등을 사용한다.
  • 개별 서비스는 별도로 개발, 테스트, 배포, 확장할 수 있다.

장점:

  • 특정 서비스에 대한 변경 및 배포가 독립적으로 이루어져, 개발 및 운영 효율성이 높아진다.
  • 서비스 장애가 전체 시스템에 미치는 영향을 최소화할 수 있다.
  • 각 서비스가 서로 다른 기술 스택을 사용할 수 있어 유연성이 향상된다.

단점:

  • 서비스 간 통합이 필요하므로 네트워크 통신 오버헤드가 발생할 수 있다.
  • 분산 시스템으로 인해 모니터링과 디버깅이 어려울 수 있다.
  • 데이터 일관성을 유지하기 위한 추가적인 고려(예: 분산 트랜잭션 관리)가 필요하다.

예시:
Netflix, Amazon, Uber와 같은 대규모 분산 시스템
Kubernetes 기반 클라우드 네이티브 애플리케이션
금융 서비스(예: 개별 결제 및 인증 시스템 분리)

 

4. 아키텍처 패턴 (Architectural Pattern)

4.1 아키텍처 패턴의 개념

아키텍처 패턴이란 특정 소프트웨어 설계 문제를 해결하기 위해 반복적으로 사용되는 구조적인 해결책이다.

4.2 대표적인 아키텍처 패턴 종류

4.2.1 MVC (Model-View-Controller)
특징:

  • Model, View, Controller로 역할을 분리한다.
  • View와 Model 간 직접적인 연결을 피하고, Controller를 통해 상호작용한다.

장점:

  • 개발 및 유지보수가 쉽다.
  • 구조가 단순하여 빠르게 개발 가능하다.

약점:

  • View와 Controller 간 결합도가 높아 코드가 복잡해질 수 있다.
  • 대규모 애플리케이션에서는 확장성이 떨어질 수 있다.

4.2.2 MVP (Model-View-Presenter)
특징:

  • Presenter가 View와 Model 사이에서 중재 역할을 수행한다.
  • View는 Presenter에 의존하고, Model을 직접 참조하지 않는다.

장점:

  • View와 Model 간의 결합도를 낮출 수 있다.
  • 테스트가 용이하다 (Presenter를 단위 테스트 가능).

약점:

  • Presenter의 역할이 많아져 코드가 복잡해질 수 있다.
  • 유지보수가 어려워질 가능성이 있다.

4.2.3 MVVM (Model-View-ViewModel)
특징:

  • ViewModel을 통해 View와 Model 간 결합도를 낮춘다.
  • 데이터 바인딩을 적극 활용하여 UI 업데이트를 자동화한다.

장점:

  • UI 코드와 로직이 명확히 분리된다.
  • 테스트가 쉬워지고 유지보수성이 향상된다.
  • SwiftUI, Jetpack Compose 같은 선언형 UI와 잘 어울린다.

약점:

  • 데이터 바인딩이 복잡해질 수 있다.
  • 작은 프로젝트에서는 오히려 코드가 과도하게 많아질 수 있다.

4.2.4 MVI (Model-View-Intent)
특징:

  • 상태(State) 기반의 UI 업데이트 방식이다.
  • 사용자의 Intent(의도)가 명확하게 Model에 전달된다.

장점:

  • 상태 관리가 명확하여 예측 가능한 동작을 보장한다.
  • 멀티스레드 환경에서 동작이 안정적이다.

약점:

  • 상태(State) 관리가 복잡해질 수 있다.
  • 데이터 흐름이 많아지고 코드량이 증가할 가능성이 있다.

4.2.5 VIPER (View-Interactor-Presenter-Entity-Router)
특징:

  • 역할을 최대한 분리하여 책임을 최소화한다.
  • 화면 이동을 Router가 담당한다.

장점:

  • 모듈화가 잘 되어 유지보수성이 뛰어나다.
  • 테스트가 용이하다.

약점:

  • 구조가 복잡하여 학습 곡선이 높다.
  • 작은 프로젝트에서는 과도한 설계가 될 수 있다.

4.2.6 클린 아키텍처 (Clean Architecture)
특징:

  • 애플리케이션을 계층 구조(Layer)로 나누어 역할을 분리한다.
  • 비즈니스 로직을 UI와 독립적으로 설계한다.

장점:

  • 유지보수성과 확장성이 뛰어나다.
  • 다양한 UI 및 프레임워크와 독립적으로 설계 가능하다.

약점:

  • 초기 설계 비용이 크고 복잡하다.
  • 작은 프로젝트에서는 불필요하게 과한 설계가 될 수 있다.

 

5. 아키텍처 스타일 vs. 아키텍처 패턴 비교

아키텍처 스타일 아키텍처 패턴
시스템 전체적인 구조 및 데이터 흐름을 정의 특정 문제를 해결하기 위한 구조적 설계 방식
예제: 레이어드, 마이크로서비스 예제: MVC, MVVM
적용 범위: 시스템 전체 적용 범위: 개별 모듈 또는 애플리케이션 내부

 

6. 마치며

이번 글에서는 아키텍처의 개념과 아키텍처 스타일 및 패턴의 차이를 비교하며 다양한 종류를 살펴보았다.

이 글에 말하고자 하는 점은, 소프트웨어 아키텍처와 스타일, 패턴이 모두 프로젝트의 요구사항과 목적에 맞는 시스템 구조를 설계하는 데 중요한 역할을 한다는 것이다.

글을 작성하는 과정에서 아키텍처 스타일과 패턴이 일부 겹치는 부분이 있어 자료를 찾을 때 혼동이 있었지만, 새로운 정보를 발견하면 학습하여 현 게시물에 반영해 나갈 계획이다.

다음 게시글에서는 각 스타일과 패턴에 대해 더 깊이 있게 다뤄 보겠다.


 
📌 참고 자료

• Software Architecture Patterns – Martin Fowler
• 클린 아키텍처 개념 – Uncle Bob
https://youtu.be/I-yBv72RCeA?feature=shared


https://youtu.be/4E1BHTvhB7Y?feature=shared


 

+ Recent posts