[아키텍처] 소프트웨어 아키텍처 요약
소프트웨어 아키텍처란?
소프트웨어 아키텍처는 시스템의 기본 구조이며, 시스템을 구성하는 요소와 각 요소 간의 관계를 정의하는 지도와 같다. 소프트웨어 아키텍처는 시스템의 주요 속성을 결정하고, 개발 과정의 중요한 설계 결정을 통제하는 역할을 한다.
그럼 왜 중요할까?
우리는 흔히 코드를 작성할 때 구조와 기능을 개발해야 한다. 흔한 개발자들은 기능이 중요하지! 하며 기능에 큰 투자를 한다. 이 경우 초기 동작은 빠르고 잘 작동할 수 있다.
시간이 지나 누군가 이 코드를 읽고 발전시켜야 한다면 어떨까?
- 어디에 어떤 코드가 있는지 도저히 모르겠어…
- 이 클래스는 어디에 추가해야 하지?
- 컨벤션이 뒤죽박죽이네
위와 같은 고민이 들 수 있다.
즉, 지금 당장은 편리할 수 있어도 언젠가 문제가 터지기 마련인 법이다.
아키텍처 vs 설계
아키텍처는 시스템의 전체적인 구조를 정의하고, 각 요소 간의 관계와 설계 지침을 세우는데 초점을 둔다.
설계는 개별 구성 요소의 세부 구현에 집중한다.
아키텍처의 원칙
- 관심사 분리와 모듈화
- 관심사분리(Separation of Concerns)는 소프트웨어 시스템을 독립된 부분으로 나누어 각 부분이 특정 관심사에만 집중하도록 하는 설계 원칙을 말한다.
- 이러한 관심사 분리를 효과적으로 구현하는 방법의 하나로 모듈화가 있다.
- 모듈화
- 모듈화(Modularity)는 시스템을 여러 모듈로 분할하고, 각 모듈이 특정 기능을 담당하도록 하는 방식이다.
- 각 모듈은 독립적으로 개발, 테스트, 배포될 수 있고, 시스템의 복잡성을 최소화할 수 있다.
- 모듈화가 효과적이려면 모듈 간의 결합도는 나주고, 각 모듈 내부의 응집도는 높여야 한다.
대표적인 아키텍처
대표적인 아키텍처라고 하면 일반적으로 Layered Architecture, Clean Architecture, Hexagonal Architecture
가 있다. 물론 독보적으로 좋은 것이 있는 게 아니라 상황에 따라 선택해야 하며 그에 따른 트레이드오프가 반드시 존재하게 된다.
Layered Architecture
Layer의 수와 역할이 정해져 있는 것은 아니지만 일반적으로 3 계층 혹은 4 계층을 구성한다.
- Presentation Layer : 사용자의 요청과 응답을 처리하는 계층
- 클라이언트의 요청을 변환
- 클라이언트의 요청 검증
- 클라이언트에 응답 반환
- 흔히 생각하는 컨트롤러가 대표적인 역할이다.
- Business Layer : 비즈니스 로직을 수행하는 계층
- 애플리케이션 요구 사항, 비즈니스 로직을 수행함
- 도메인을 담고 있는 것이 대표적이다.
- Persistence Layer & Database Layer
- infrastructure로 묶여 사용되는 경우도 있다.
- DB 혹은 외부와 상호작용하는 책임을 갖고 있다.
위의 과정을 보면 알겠지만 최종적으로 Database Layer으로 귀결된다.
→ 데이터베이스 주도 개발을 하게 된다. 도메인에 집중해 코드를 작성하는 것이 아닌, DB에 집중하게 되는 것이다.
→ DB의 변화가 생기면 위의 모든 계층이 영향을 받게 된다.
→ 각 계층에 대한 여러 개발자의 동시 개발이 힘들다.
Clean Architecture
엉클밥으로 불리는 Robert C. Martin의 클린 아키텍처라는 책에서 나온 아키텍처이다.
계층형 아키텍처와 다른 점은 화살표가 Entities로 향하고 있다는 것이다. 즉, Domain에 집중하는 개발이다.
핵심 규칙 또한 도메인 코드가 바깥으로 향하는 어떤 의존성도 없어야 한다는 것이다.
- 엔티티 (Entities)
- 의도에 따라 도메인 계층으로도 불리며, 엔티티 계층은 하나 이상의 프로그램 간에 공유될 수 있다는 가정하에 만드는 수명이 긴 객체이다.
- 재사용의 가능성이 높다는 것을 인지하고 외부에 의해 변경될 가능성을 낮추어야 한다.
- Enterprise 규모의 비즈니스 데이터를 포함하거나 핵심이 되는 비즈니스 규칙을 캡슐화한다.
- 유즈케이스 (Use cases)
- 애플리케이션 계층으로도 불리며, 애플리케이션 규모의 비즈니스 규칙을 포함한다.
- 이 레이어의 변경사항은 엔티티에 영향을 미쳐서는 안 되며, 인프라 단의 DB나 UI, 라이브러리와 같은 외부요소에 의해 영향을 받지 않는다는 것을 원칙으로 한다.
- 이는 즉 해당 계층의 수정은 응용 프로그램의 동작에 영향을 미친다는 의미입니다.
- 인터페이스 어뎁터 (Interface Adapter)
- 어뎁터 계층은 DB나 Web, UI와 같은 바깥 계층에서 사용하기 편리하도록, 유즈케이스 또는 엔티티 계층에서 데이터를 변환하는 어뎁터의 집합이다.
- 흔히 MVC, MVVM과 같은 아키텍처를 포함하는 것이 이 영역으로 컨트롤러, 프레젠터, 게이트웨이 등이 속합니다.
말만 들었을 때는 반드시 이것을 써야겠다!라는 생각이 들 수 있지만, 실제로 정확한 가이드라인이 없어 생각보다 작용하기 어려울 수 있다.
정형화된 아키텍처가 아닌 대략적인 길을 제시하며 이것에 대한 모든 팀원의 이해가 있어야 효율적으로 작동한다.
즉, 구현이 가능하다면 매우 좋지만 실제 사용에 있어서는 많은 시행착오가 있을 수 있다.
또한, 이 과정에서 지름길의 유혹과 싸우며 적당한 기술적 트레이드오프를 취하는 것이 매우 까다로운 부분이다.
Hexagonal Architecture
실제 구현과 개념 사이의 간극이 큰 클린 아키텍처보다 실제 구현에 있어 다양한 예제와 조건이 있어 많이 사용되는 헥사고널 아키텍처이다.
DIP를 통해 domain을 보호하며 외부와의 동작을 취하게 된다.
모든 의존성이 중심을 향하는 방향으로, Domain Driven Development를 달성하게 해 준다.
헥사고날 아키텍처는 애플리케이션의 비즈니스 로직을 설계의 중심에 두고, 입력과 출력 인터페이스(포트)를 육각형의 가장자리에 배치하는 구조이다.
도메인 엔티티와 이와 상호작용하는 유스케이스는 육각형 내부에 위치하며, 웹, 데이터베이스 등 외부 시스템과 상호작용하는 어댑터들은 육각형 외부에 위치한다.
→ 애플리케이션 코어는 어댑터에 종속되지 않고 독립적으로 작동할 수 있다.
포트와 어댑터 아키텍처라 불리는 이유
애플리케이션 코어는 각각의 포트를 제공하며, 이 포트를 통해 외부 어댑터들과 통신한다.
비즈니스 로직은 REST, GraphQL API나 데이터베이스, 마이크로서비스 API, CSV 파일 등 외부 데이터 소스에 의존하지 않는다.
→ 로직의 독립성과 모듈화를 보장하는 것이다.
헥사고널 아키텍처의 장점
- 유연성
- 포트와 어댑터를 사용함으로써 다양한 기술 변화에 쉽게 대응할 수 있다.
- 기술 환경이 빠르게 변화하는 상황에서 새로운 기술을 도입하는 것이 필수가 되며, 이러한 유연성은 소프트웨어의 변경에 용이하다.
- 유지보수성이다
- 각 컴포넌트의 책임이 분리되어 있으므로 코드의 이해와 수정이 용이하다.
- 기존 기능을 다른 기술로 변경할 때, 새로운 어댑터만 추가하면 되기 때문에 유지보수가 편리하다.
- 테스트 용이성
- 애플리케이션 코어와 어댑터가 분리되어 있어, 각 컴포넌트를 독립적으로 테스트할 수 있으며, 외부 의존성 없이도 테스트가 가능 → 전체 시스템의 품질과 개발 속도가 향상된다.
최종 정리
이렇게 살펴보면 어떤 아키텍처가 좋다는 것일까? 의문이 든다. 물론 가장 좋은 것은 클린 아키텍처 같다. 구현이 와닿는 것은 헥사고널이지만 포트와 어댑터 등으로 너무나도 구현해야 할 부분이 많다.
실제 예시를 보면 헥사고널의 경우 매우 많은 패키지의 증가가 발생했다.
그래서 뭐가 좋은 건데!!!
- 서비스의 규모, 변경 가능성, 개발 기간 등에 따라 결정된다.
- 서비스의 규모가 크다면 다양한 개발자가 협업하기에 일관된 아키텍처를 정한 뒤 개발하는 것이 효율적이다.
- 서비스 규모가 작다면 복잡한 아키텍처가 큰 비용이 될 수 있다.
- 변경이 일어날 일이 없다면 향후 코드 수정을 염두하는 아키텍처가 크게 중요하지 않을 수 있다. 당장의 기능이 더 우선될 수 있다.
- 개발 기간이 짧다면, 시간에 쫓겨 정확한 아키텍처를 고수하지 못하는 일이 발생할 수 있다. 편리함을 추구하며 하나의 패키지를 대충 배치해 가다가 스노우볼이 될 수 있다.
- 팀원의 숙련도와 이해도에 따라 결정된다.
- 좋은 아키텍처가 무엇인지는 정해져 있지 않지만 클린 아키텍처 같은 경우 모두 동일한 아키텍처에 대한 이해를 갖고 있어야 한다.
- 아키텍처에 대한 개념이 다르다면 최종적인 수정&유지 비용이 동일하게 발생할 수 있다.