소프트웨어 아키텍처
📌 시스템을 효율적이고 안정적으로 만들기 위해, 각 구성 요소를 큰 그림으로 설계하는 설계도이다.
- 아래의 가치 중 구조적 가치를 제공한다.
왜 아키텍처를 고민을 해야할까?
- 확장성(Scalability) 확보
- 사용자 수가 늘어날 때, 시스템이 문제 없이 확장 가능
- 유지보수(Maintainability) 용이
- 아키텍처가 잘 정리되어 있으면, 버그 수정이나 새로운 기능 추가 시 어떤 부분을 건드려야 할지 명확
- 모듈별 역할과 의존성을 분리하면, 유지보수 비용과 시간이 크게 감소
아키텍처 구현을 위한 주요 패턴
1. 레이어드 아키텍처 (Layered Architecture)
특징
- 전통적인 계층 기반의 구조로, 애플리케이션을 역할별로 구분(예: 프레젠테이션, 비즈니스 로직, 데이터 접근 등).
- 계층 간 호출 순서가 정해져 있어, 각 계층은 바로 아래 계층만 호출.
장점
- 역할 분리: 각 계층의 역할이 명확하여 코드 가독성과 유지보수가 용이.
- 구조화된 설계: 초기에 아키텍처를 설계하기 쉬움.
- 범용성: 대부분의 애플리케이션에 적용 가능.
단점
- 계층 간 의존성: 변화가 많은 프로젝트에서 수정 비용 증가.
- 성능 문제: 계층이 많아질수록 호출 스택이 깊어져 성능 저하 가능.
- 유연성 부족: 비즈니스 로직과 인프라 간 결합도가 높음.
2. 헥사고날 아키텍처 (Hexagonal Architecture)
특징
- 코어 도메인 중심 설계: 핵심 비즈니스 로직을 중심에 두고, 외부 인터페이스(데이터베이스, UI, 외부 API 등)는 어댑터로 연결.
- 포트와 어댑터: 도메인은 포트를 통해 어댑터와 상호작용하며, 어댑터는 실제 구현체.
장점
- 의존성 분리: 도메인과 외부 시스템 간 결합도를 낮춤.
- 테스트 용이: 외부 의존성을 Mock으로 대체해 테스트 가능.
- 유연성 증가: 데이터베이스 교체나 외부 인터페이스 변경이 용이.
단점
- 진입 장벽: 설계와 구현의 복잡성으로 인해 초기 이해가 어려울 수 있음.
- 설계 비용: 소규모 프로젝트에서는 과도한 설계가 될 가능성.
3. 클린 아키텍처 (Clean Architecture)
특징
- 의존성 역전 원칙(DIP)을 적용하여, 핵심 비즈니스 로직이 외부 프레임워크에 의존하지 않도록 설계.
- 로버트 C.마틴(Robert C. Martin, Uncle Bob)의 제안
- 계층 구분:
- 가장 안쪽: 엔티티(핵심 비즈니스 로직).
- 중간: Use Case(앱의 동작 정의).
- 바깥쪽: 프레젠테이션, 프레임워크(UI, 데이터베이스 등).
장점
- 변경 용이성: 외부 기술 스택에 구애받지 않음.
- 유지보수성: 비즈니스 로직과 구현체를 분리.
- 테스트 가능: 핵심 로직은 외부 종속 없이 독립적으로 테스트 가능.
단점
- 복잡성: 계층 간 명확한 설계가 필요하며, 과도하게 적용 시 개발 속도 저하.
- 학습 비용: 팀 내 이해와 합의 필요.
클린 아키텍처 필수 요건
- 의존성 규칙(Dependency Rule)
- 의존성은 바깥 레이어에서 안쪽 레이어로만 흐릅니다.
- 핵심 비즈니스 로직(도메인)은 프레임워크, UI, DB를 전혀 몰라야 합니다.
- 도메인 로직(핵심 비즈니스 로직)의 독립성
- 도메인 모델(Entity 등)은 순수 자바 코드로 작성해, 프레임워크나 DB 관련 코드를 넣지 않습니다.
- 도메인 정책(Validation, Calculation 등)은 도메인 레벨에서 처리하고, 바깥 레이어(프레임워크/인프라) 의존 로직을 섞지 않습니다.
- 인터페이스를 통한 의존 역전(DIP)
- 도메인이나 Use Case 측에서 필요한 기능(DB 저장, 메시지 전송 등)은 인터페이스로 정의합니다.
- 실제 구현은 Adapter(구현체) 가 담당하고, 도메인/Use Case는 구현체를 몰라야 합니다.
- 테스트 용이성
- 도메인/Use Case가 외부 환경(DB, 네트워크 등)에 의존하지 않도록 설계합니다.
- Mock/Stub을 이용해 유닛 테스트가 쉽도록 구조를 마련합니다.
4. 마이크로서비스 아키텍처 (Microservices Architecture)
특징
- 시스템을 독립된 작은 서비스로 분리하여, 각각의 서비스가 독립적으로 배포 및 확장 가능.
- 각 서비스는 독립적인 데이터베이스를 가질 수 있음.
장점
- 확장성: 서비스별로 독립적인 스케일링 가능.
- 유연성: 각 서비스마다 적합한 기술 스택 선택 가능.
- 장애 격리: 특정 서비스 장애가 전체 시스템에 영향을 덜 미침.
단점
- 운영 복잡성: 서비스 간 통신, 배포 관리, 모니터링 등 관리 부담 증가.
- 데이터 일관성: 트랜잭션 관리가 복잡해질 수 있음.
- 개발 비용: 초기 설계와 개발 단계에서 시간과 리소스 투자 필요.
5. 이벤트 드리븐 아키텍처 (Event-Driven Architecture)
특징
- 컴포넌트 간 통신을 이벤트로 처리하여, 비동기 메시징 기반으로 동작.
- 프로듀서와 컨슈머가 느슨하게 결합.
장점
- 확장성: 비동기 처리로 높은 트래픽 처리 가능.
- 유연성: 각 컴포넌트가 독립적으로 동작하며, 쉽게 추가 및 제거 가능.
- 실시간 처리: 이벤트 기반으로 즉각적인 응답 처리.
단점
- 복잡성: 이벤트 흐름 관리 및 디버깅이 어려움.
- 데이터 정합성: 이벤트 중복 처리 및 트랜잭션 관리 필요.
6. 주요 아키텍처 비교
아키텍처 | 주요 특징 | 장점 | 단점 | 적용 사례 |
레이어드 아키텍처 | 계층별 역할 분리 | 구조화 쉬움, 가독성 높음 | 계층 간 의존성, 성능 저하 가능 | 전통적 웹 애플리케이션 |
헥사고날 아키텍처 | 도메인 중심, 외부는 어댑터로 연결 | 도메인 독립성, 테스트 용이 | 초기 설계 복잡 | 대규모 엔터프라이즈 시스템 |
클린 아키텍처 | 의존성 역전 원칙 적용, 계층 간 분리 | 유지보수 용이, 테스트 가능 | 복잡한 설계, 높은 학습 비용 | 비즈니스 로직이 복잡한 시스템 |
마이크로서비스 | 작은 서비스로 독립 배포 | 장애 격리, 서비스별 스케일링, 다양한 기술 스택 | 운영 및 데이터 관리 복잡 | 대규모 분산 시스템, 클라우드 네이티브 앱 |
이벤트 드리븐 | 이벤트 기반 비동기 처리 | 확장성, 높은 성능 | 디버깅 어려움, 데이터 정합성 문제 | 실시간 데이터 처리, IoT, 메시징 시스템 |
학습하면 좋은 추가 주제
- 각 아키텍처의 실제 적용 사례
- 각 패턴을 기반으로 설계된 오픈소스 프로젝트 분석.
- 아키텍처 설계와 테스트 전략
- 아키텍처별 단위 테스트, 통합 테스트, E2E 테스트 적용 방법.
- 도메인 중심 설계(DDD)
- 헥사고날 및 클린 아키텍처와 결합해 효과적으로 도메인 로직 설계.
- 아키텍처 선택 기준
- 프로젝트 규모, 팀 역량, 요구사항에 따라 아키텍처를 선택하는 전략.