항해플러스

[항해+] 2주차 클린아키텍처

idleday 2024. 3. 23. 23:10

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