클린 아키텍처 (2) - 클린 아키텍처란?

itbuddy·2024년 9월 4일

클린아키텍처란?

Robert C. Martin (Uncle Bob)이 이상적이라고 생각하는 당대의 아키텍처들을 모아서 공통점과 규칙을 기술한것으로 유지보수하는데 투입되는 비용을 최소화하여 소프트웨어의 수명을 늘리고, 추후 개발 속도가 느려지지 않도록 하기 위해 고안된 아키텍처 입니다.

클린아키텍처를 기술할 때 사용한 아키텍처들

  • Hexagonal Architecture (a.k.a. Ports and Adapters) by Alistair Cockburn and adopted by Steve Freeman, and Nat Pryce in their wonderful book Growing Object Oriented Software
  • Onion Architecture by Jeffrey Palermo
  • Screaming Architecture from a blog of mine last year
  • DCI from James Coplien, and Trygve Reenskaug.
  • BCE by Ivar Jacobson from his book Object Oriented Software Engineering: A Use-Case Driven Approach

위 아키텍처들의 공통점

  1. 프레임워크에 독립적입니다. 아키텍처는 기능이 가득한 소프트웨어 라이브러리의 존재에 의존하지 않습니다. 이를 통해 시스템을 제한된 제약에 집어넣지 않고도 이러한 프레임워크를 도구로 사용할 수 있습니다.
  2. 테스트 가능. 비즈니스 규칙은 UI, 데이터베이스, 웹 서버 또는 기타 외부 요소 없이 테스트할 수 있습니다.
  3. UI와 무관합니다. UI는 시스템의 나머지 부분을 변경하지 않고도 쉽게 변경할 수 있습니다. 예를 들어, 웹 UI는 비즈니스 규칙을 변경하지 않고도 콘솔 UI로 대체될 수 있습니다.
  4. 데이터베이스와 무관합니다. Oracle이나 SQL Server를 Mongo, BigTable, CouchDB 또는 다른 것으로 바꿀 수 있습니다. 비즈니스 규칙은 데이터베이스에 구속되지 않습니다.
  5. 외부 기관과 무관합니다. 사실, 귀사의 비즈니스 규칙은 외부 세계에 대해 전혀 알지 못합니다.

클린 아키텍처에서 가장 중요한 규칙은 종속성 규칙입니다.
각 종속성은 내부만을 가리킬 수 있습니다.
내부 원은 외부 원에 대해 전혀 아는것이 없어야 하며 외부 원에 선언 된것은 내부원에서 언급되어서는 안됩니다.

위는 보통의 레이어드 아키텍처입니다. 레이어드 아키텍처는 위와 같은 종속성을 가지는데 이를 클린 아키텍처에 맞게 바꾼다면 다음과 같이 Interface를 통아혀 의존성을 역전시킴으로서 완성할수 있습니다.

클린 아키텍처의 종속성 규칙을 간단하게 생각하면
핵심 비즈니스 로직 레이어는 외부 환경에 의해 변경이 되는 레이어에 종속되면 안된다는 것입니다.
종속성 규칙을 지키지 못하는 예를 들자면 다음과 같은 코드입니다.

@Service
class ...

public void createUser(CreateUserCommand command){
...
	// DB의 변화에 민감한 Entity를 핵심 비즈니스 로직에서 직접 생성하여 사용하여 Bussiness Layer가 Persistence layer를 import 해서 써야합니다. 즉 종속성을 가지게 됩니다.
   UserEntity user = UserEntity.builder()
   								.id(command.getId())
                                .name(command.getName())
                                .birth(command.getBirth())
   								.build();
  userRepository.save(user);
  ...
}

이를 클린 아키텍처에 맞게 수정 한다면
아래와 같이 UserEntity에서 of 메서드를 통해서 UserEntity를 Service 대신 생성하면 되겠습니다.

@Service
class ...

public void createUser(CreateUserCommand command){
...
  final UserEntity user = UserEntity.of(command);
  userRepository.save(user);
  ...
}

또는 다음과 같이 관심사를 분리하기 위해 변환 레이어를 추가하면 됩니다.

@Service
class ...

public void createUser(CreateUserCommand command){
...
  final UserEntity user = UserMapper.toEntity(command);
  userRepository.save(user);
  ...
}

다음 시간에는 실제 구현한 프로젝트를 바탕으로 추가적인 설명을 하겠습니다.


Ref
The Clean Code Blog - The Clean Architecture

profile
프론트도 조금 아는 짱구 같은 서버 프로그래머

0개의 댓글