3 분 소요

만들면서 배우는 클린 아키텍쳐 2장 정리

의존성 역전하기

단일 책임 원칙

단일 책임 원칙의 일반적인 해석은 다음과 같습니다.

하나의 컴포넌트는 오로지 한 가지 일만 해야 하고, 그것을 올바르게 수행해야 한다.

그러나 이는 단일 책임 원칙의 실제 의도는 아닙니다.

단일 책임 원칙의 실제 정의는 다음과 같습니다.

컴포넌트를 변경하는 이유는 오직 하나뿐이어야 한다.

그래서 단일 책임 원칙을 ‘단일 변경 이유 원칙’으로 바꾸는 게 더 자연스러울 수 있습니다.

단일 변경 이유 원칙이 지켜진다면 어떤 다른 이유로 소프트웨어를 변경하더라도 이 컴포넌트에 대해서는 전혀 신경 쓸 필요가 없습니다.

왜냐하면 소프트웨어가 변경되더라도 컴포넌트는 변경이 없기 때문에 여전히 그대로 작동하기 때문입니다.

그러나 변경할 이유라는 것은 컴포넌트 간의 의존성을 통해 너무나도 쉽게 전파됩니다.

그래서 단일 변경 이유 원칙을 어기면 시간이 갈수록 변경 비용이 증가하여 변경하는 것이 어려워집니다.

이렇게 되면 한 컴포넌트를 바꿨을 때 변경 전에는 정상적으로 동작하던 다른 컴포넌트에 에러가 발생할 수 있습니다.

책을 읽으면서 느낀 점

예전에 메모장 프로그램을 구현하면서 항상 겪은 경험인데 정상적으로 작동하던 기능이 새로운 기능을 추가하면 더이상 정상적으로 작동하지 않는 경우를 많이 경험하였습니다.

그 때를 생각해보면 기능을 구현하기 위해 객체를 생성하면서 서로 의존관계를 맺는 것에 크게 고민하지 않고, 그 때 그 때마다 편한 방식대로 객체들의 의존관계를 맺었습니다.

그러나 돌이켜보면 이 것이 화근이 되어 결국에 새로운 기능을 추가하면 문제가 되어 코드 전체를 수정하는 일이 빈번하였습니다.

이러한 경험을 통해 애초에 단일 책임 원칙을 지키는 것이 당장에는 시간이 걸리고 힘들지만 결국에 시간이 지나서 보면 유지보수 및 변경을 할 때 훨씬 더 좋다는 것을 알 수 있었습니다.

의존성 역전 원칙

도메인 계층이 영속성 계층에 의존하게 되면 영속성 계층을 변경할 때마다 비지니스에서 가장 중요한 코드인 도메인 코드도 변경을 해야합니다.

이를 막기 위한 방법이 바로 의존성 역전 원칙입니다.

즉, 코드 상의 어떤 의존성이든 그 방향을 바꿀 수 있습니다.

이 의존성 역전 원칙을 활용하여 도메인 계층이 영속성 계층의 의존하던 방향성을 바꿉니다.

서비스만 있던 기존의 도메인에 엔티티를 추가하고, 영속성 계층에 있는 레포지토리를 인터페이스화하여 도메인 계층에 위치시킵니다.

그리고 레포지토리의 구현체를 영속성 계층에 위치시킴으로써 이제 의존 관계가 역전이 됩니다.(영속성 계층이 도메인 계층에 의존하게 됩니다.)

책을 읽으면서 느낀 점

이렇게 레포지토리를 인터페이스 해 놓으면 더이상 리포지토리가 바뀐다고 해서, 즉, 영속성 계층이 변경된다고 해서 도메인 계층의 로직에는 손댈 필요가 없다는 점입니다.

예를 들어 영속성 계층의 리포지토리 구현체가 현재 메모리에 저장하는 방식인데 이를 데이터베이스에 저장하는 방식의 리포지토리 구현체로 바꾸더라고 도메인의 로직은 손댈 필요가 없습니다.

이 것이 가능한 이유는 다형성으로 인해 도메인 로직은 리포지토리의 인터페이스만 가지고 있으면 그 구현체가 누구든지간에 상관없이 동작을 하기 때문입니다.

클린 아키텍처

도메인 코드는 바깥으로 향하는 어떤 의존성도 없어야 합니다.

대신 의존성 역전 원칙의 도움으로 모든 의존성이 도메인 코드를 향해야 합니다.

이렇게 되면 도메인 코드에서는 어떤 영속성 프레임워크나 UI 프레임워크가 사용되는지 알 수 없기 때문에 특정 프레임워크에 특화된 코드를 가질 수 없고, 비즈니스 규칙에만 집중하여 코드를 설계할 수 있습니다.

즉, 도메인 주도 설계를 하기 수월해집니다.

하지만 클린 아키텍처에도 대가가 따릅니다.

예를 들어 영속성 계층에서 ORM 프레임워크를 사용하는데, 도메인 계층에서는 영속성 계층을 모르기 때문에 도메인 계층에서 사용하는 엔티티 클래스를 영속성 계층에서 재사용할 수 없스빈다.

그래서 도메인 계층과 영속성 계층이 데이터를 주고 받기 위해서는 도메인 계층의 엔티티와 별개로 영속성 계층을 위한 엔티티 클래스를 생성해야 합니다.

하지만 이는 바람직한 일인데, 왜냐하면 예를 들어 JPA에서는 엔티티에 인자가 없는 기본 생성자 추가를 강제하지만 도메인 계층의 엔티티에서는 이것이 필요없기 때문에 도메인 계층의 엔티티와 영속성 계층의 엔티티를 별개로 두어야 도메인 계층에서 불필요한 코드가 발생하지 않습니다.

책을 읽으면서 느낀 점

아직 정확하게는 모르겠지만 영속성 계층의 엔티티가 DTO를 말하는 것인가라는 생각이 듭니다.

즉, 예를 들어, 도메인의 엔티티에 Member 클래스라고 있으면, 영속성 계층의 엔티티에는 MemberDto 클래스를 두는 것이라고 이해를 하고 있습니다.

육각형 아키텍처(헥사고날 아키텍처)

육각형의 바깥에는 애플리케이션과 상호작용하는 다양한 어댑터들이 있고, 이 어댑터들은 각각의 포트와 연결되 어 있습니다.

입력 포트와 연결된 어댑터들은 애플리케이견 코어를 호출하기 때문에, 애플리케이션을 주도하는 어댑터들입니다.

출력 포드와 연결된 어댑터들은 애플리케이견 코어에 의해 호출되기 때문에 애플리케이션의 의해 주도되는 어댑터들입니다.

이러한 개념으로 인해 육각형 아키텍처는 ‘포트와 어댑터’ 아키텍처로 불리기도 합니다.

유지보수 가능한 소프트웨어를 만드는 데 어떻게 도움이 될까?

의존성 역전을 통해 도메인 코드가 다른 바깥쪽 코드에 의존하지 않게 함으로써 도메인에서는 영속성과 UI에 특화된 모든 문제를 없애고, 오로지 비지니스 로직에 집중하여 코드를 설계할 수 있습니다.

이렇게 되면 도메인 코드를 변경해야할 이유가 줄어들기 때문에 유지보수하기 좋아집니다.

댓글남기기