클린 아키텍처 - 계층 분리하기

이월(0216tw)·2024년 9월 4일

1. 사전 지식 : SOLID 5원칙

SRP (Single Responsibility Principle)

클래스는 하나의 기능만 있으며, 클래스를 변경할 이유는 오직 하나다.

예)
변경 전 : Robot 클래스에 청소하다() , 총을쏘다() , 배달하다() 메서드가 있음
변경 후 :
청소기로봇 - 청소하다()
전투용로봇 - 총을쏘다()
배달용로봇 - 배달하다()
등으로 하나의 클래스가 하나의 책임만 가지도록 한다.

OCP (Open - Closed Principle)

클래스는 확장에는 열려있고 변경에는 닫혀있다.
이는 추상화나 다형성(polym)을 통해서 구현이 가능하다.
즉, 특정 클래스에 종속하지 않고 독립적으로 끼워 넣을 수 있도록한다.
예) 탈것 클래스 <- 상속 ( 기차 , 자동차 , 버스 )
탈것 클래스에 각 기차, 자동차 , 버스를 업캐스팅해서 확장이 가능하다.
이 때 탈것 클래스 자체는 변동이 되지 않는다.

LSP (Liskov Substitution Principle)

서브 타입은 언제나 기반타입으로 대체 될 수 있어야 한다.
즉, 상속 관계에서 하위 클래스는 상위 클래스는 기능을 모두 갖춰야 하며,
상위 클래스에서 정의된 기능을 무시하거나 다른 방식으로 구현하면 안된다.

예)

class Bird {
	void fly() {
    	sout("날아요~"); 
    }
}

class 펭귄 extends Bird { 
	@Override //메서드 재정의를 해서 상위 클래스에 정의된 기능과 다른 형태로 구현 
    void fly() {
        throw new Exception("펭귄은 못 날죠"); 
    }
} 


## LSP 적용 방안 - 오버라이딩을 해도 상위 클래스가 기대하는 동작을 벗어나지 않게 한다. 

abstract class Bird { 
	abstract void move() ; 
}

class 펭귄 extends Bird {
	@Override 
    public void move() { //움직이는 행위 = 상위 클래스가 기대한 동작 (예외 말고) 
    	sout("헤엄쳐요"); 
    }
}

class 독수리 extends Bird {
	@Override
    public void move() { //움직이는 행위 = 상위 클래스가 기대한 동작 (예외 말고) 
    	sout("날아요~"); 
    }
}

ISP (Interface Separation Principle)

인터페이스에 너무 많은 기능이 들어가면 필요없는 메서드도 구현해야 한다.
그렇지 않게 나누자

DIP ( Dependency Inverseion Principle )

고수준 모듈이 저수준 모듈에 의존하지 않고, 추상화된 인터페이스 등에 의존해야한다.
예를 들어 컨트롤러가 서비스 구현체에 의존하지 않고 서비스 인터페이스에 의존해야한다는 것


2. 클린 아키텍쳐

[클린 아키텍처 구조도]

출처 : https://blog.cleancoder.com/uncle-bob/2012/08/13/the-clean-architecture.html


Entities Layer (=Domain Layer)

핵심 비즈니스 로직과 데이터 상태를 담당 , 외부 변화에 민감하지 않아야 함
외부 변화란 DB , UI , 프레임워크 와는 독립적으로 외부 시스템과 무관하게 독립 동작을 의미

  • 모델(model) : 비즈니스 개념을 나타내고 상태와 행동을 포함 , 가벼운 변경 메서드도 가능
    예) Order 의 상태와 행동 (필드 , 메서드)

  • 서비스(service) : 도메인 모델과 관련되며 도메인 객체가 표현하기 어려운 비즈니스 규칙 담당
    (실제 비즈니스 로직이 처리됨을 의미)


Use cases Layer (=Application Layer)

애플리케이션의 특정 기능을 구현하는 곳으로 엔터티를 활용해 비즈니스 로직을 구현함

비즈니스 규칙 자체 처리보다는 전체적인 흐름 및 트랜잭션 관리
, 하지만 트랜잭션은 가급적 service 레벨로 내리는 것이 좋음
(범위를 최소화 하면 좋겠다는 의미 , 너무 트랜잭션이 길어져도 좋지 않으니까 )

usecase 와 facade 의 차이점은 ??

예) usecase : 비즈니스 시나리오 별로 유즈케이스 처리

예) facade : 복잡한 비즈니스 로직을 단순화된 인터페이스로 제공함으로써

클라이언트가 여러 서비스와 상호작용하지 않도록 함

facade는 여러 서비스나 usecase를 조합해 단순한 인터페이스를 제공한다.
따라서 비즈니스 시나리오에 대해 더 추상화 할 수 있는 개념이며
usecase는 보통 하나의 특정 기능에 집중한다.


interface adapter Layer

  • 유즈케이스 계층과 외부 시스템을 연결하는 역할을 하며 데이터 변환UI상호작용 , DB 통신 등을 담당한다.

예) controller 는 사용자의 요청을 받는 역할
예) dto 는 사용자의 요청 및 반환할 응답 데이터를 처리하는 역할


Frameworks & Drivers Layer

기술적인 구현 세부사항을 처리
DB와의 상호작용 , 외부 API 호출 , 보안 설정 등 애플리케이션 동작에 필요한 기술적 부분을 처리
도메인계층과 독립적으로 동작


인터페이스 계층과 프레임워크 계층 둘다 외부시스템과 연결하는 거 아닌가?
무슨 차이가 있는거지?

  • 외부와 상호작용하는 부분의 책임과 범위, 방식 이 다름

인터페이스 어댑터 계층

  • use case 와 외부 시스템 간의 중재 역할
  • use case 계층과 직접 상호작용
  • DTO 변환 , Repository구현체 (인터페이스는 usecase 계층에 속함) , Controller (사용자 입출력 용도)

프레임워크 & 드라이버 계층

  • 외부 시스템과 상호작용하고 구체적인 프레임워크 및 라이브러리를 사용해 세부 사항 처리
  • use case 계층과 관계없이 인터페이스 어댑터 계층을 통해 상호작용
  • DB 드라이버 , third party , 웹 프레임워크 , Controller ( 실제 드라이버와 연결하는 용도 )
profile
#SQLD강사 #AI개발 #AI강사 #개발자 개발도 하고 강의도 하지만 고민을 제일 많이 합니다

0개의 댓글