Software Architecture Pattern
- 좋은 아키텍처 패턴이란
- 지속적으로 성장가능한 안정적인 소프트웨어를 잡기위한 최고의 가이드라인
- 지켜야 할 기본적인 개발 가이드라인을 잡아주는 틀
- 참고
- DIP(의존역전 원칙) - 인터페이스로 통신
- OCP(개방-폐쇄 원칙 - 확장에는 Open, 수정에는 Close, ex. Repository Interface)
1. Layered Architecture
- 상위 계층에서 하위 계층을 호출하는 단방향 흐름을 유지
- 상위 계층이 필요한 기능을 하위 계층 구현으로 전달
- 비즈니스 로직이 핵심이 아니며 보호받지 못함
- DIP 준수
- OCP 원칙이 지켜지지 않는다. DB에 수정이 생기면 위층 레이어로 상방전파된다.
2. Hexagonal 아키텍처
- 애플리케이션 핵심은 비즈니스 로직
- 데이터 계층 및 API계층이 비즈니스 로직에 의존 (Adaptor & Port 패턴)
- 다양한 외부 인터페이스(API, MessageQueue, WebSocket 등)에 동일한 비즈니스 로직을 전
- 도메인을 중점으로 바라보는 아키텍처
- MSA에 효율적인, 모든 비즈니스 로직이 작은 단위로 구성되고 바라보는 관점
3. Clean Architecture
- 애플리케이션 핵심은 비즈니스 로직
- 데이터 계층 및 API 계층이 비즈니스 로직 의존(UseCase & Port 패턴)
- 도메인 주심적인 고수준의 관심사 분리
- DIP, OCP 준수
4. Clean + Layered Architecture
- 애플리케이션 핵심은 비즈니스 로직
- 데이터 계층 및 API 계층이 비즈니스 로직 의존 (비즈니스 Interface 활용)
- 도메인 중심적인 계층 아키텍처
- Presentation은 도메인을 API로 서빙, Datasource는 도메인이 필요로하는 기능을 서빙
- DIP, OCP 준수
- 인터페이스로 의존성을 역전하면 인터페이스 명세 먼저 작성하고 구현체는 나중에 작성. 유연함
Clean Code
- 읽기 쉽고 단순한 코드 : 누구나 쉽게 읽을 수 있어야 하며, 너무 많은 책임을 가지고 있지 않을
- 의존성 격리 : 모듈 간 미치는 영향을 최소화하기 위해 골
- 추상화 : 명세와 구현을 적절히 분리할 것
- 중복 최소화
더보기
class OrderService(
private val orderRepository: JpaRepository<OrderEntity, Long>,
private val userService: UserService,
private val couponService: CouponService,
) {
fun placeOrder() { orderRepository.save(OrderEntity) }
}
class OrderController(private val service: OrderService) {
fun placeOrder()
}
--- 위는 우리가 평소에 하던 Layered Architecture
--- 아래는 제가 Clean + Layered 짬뽕한 Architecture
--- 멀티모듈의 도움을 받아 아예 도메인 로직을 격리 시킴.
( 얘는 순수 Java/Kotlin/TS 코드만 존재 )
class OrderCoreRepository : OrderRepository // 프레임워크 도움을 받아 DI
interface OrderRepository { } // 한번 끊어주기
class OrderService(private val orderRepository: OrderRepository) { } // 요거로는 좀 밋밋함.
// 그래서 아래와 같이 작성하곤 한다.
class OrderAppender(private val orderRepository: OrderRepository)
class OrderFinder(private val orderRepository: OrderRepository)
--> 실제 작은 단위의 비즈니스 로직을 가진 구현체들 ( 책임의 분리를 명확히 )
interface OrderInterface // 외부에 열어줄 명세 : 알아서 갖다 쓰쇼가 이유지만 선호하지 않음.
interface OrderMessageInterface
// 외부에서 접근가능한건 XXXService 뿐이다.
class OrderService(
private val userReader: UserReader,
private val orderFinder: OrderFinder,
private val productFinder: ProductFinder,
private val orderAppender: OrderAppender,
) : OrderInterface
-- 외부 계층
class OrderController(private val orderInterface: OrderInterface)
class OrderMessageBroker(private val orderInterface: OrderMessageInterface)
```
'항해플러스' 카테고리의 다른 글
[항해+] 1주차 TDD (0) | 2024.03.22 |
---|---|
[항해+] 시작하는 마음 (0) | 2024.03.16 |