본문 바로가기

DEV/Application Architecture

[Architecture] 3-tier 레이어드 아키텍처의 한계를 마주하다

728x90
반응형

3-tier 아키텍처 시스템에서 데이터베이스가 변경되거나 다른 저장소를 추가해야 한다면?

DB와 비즈니스 로직의 강결합으로 인한 문제가 발생한다.

추상화 된 인터페이스가 없이 비즈니스 로직에서 직접적으로 MySQL 구현체를 사용한다.

DIP 위반 - 고수준 모듈(Service)에서 저수준 모듈(Repository)에 의존한다.

OCP 위반 - 확장에 열려있지 않으며, 저수준 모듈에서 수정 시 의존하는 고수준 모듈 역시 수정해야 하므로 수정에 닫혀있지도 않다. 

 

MySQL DB에서 MongoDB로 변경

  1. 비즈니스(서비스) 로직의 구현체를 MongoDB 구현체로 수정해야 한다.
  2. 새로 MongoDB의 구현체로 만든 Repository에서 MongoDB에 맞는 데이터 처리 로직을 새로 구현해야 한다.
public class UserService {

    private UserRepository userRepository;

    public UserService() {
        this.userRepository = new UserRepository();  // DIP 위반
    }

    public List<User> getUser(Long id) {
        return userRepository.findById(id);  // DB 구현에 의존
    }
}
//기존 코드 (MySQL)
public class UserService {
    private UserRepository userRepository;

    public UserService() {
        this.userRepository = new UserRepository();
    }

    public User getUser(Long id) {
        return userRepository.findById(id);
    }
}

public interface UserRepository extends JpaRepository<User, Long> {
    public User findById(Long id);
}

//변경 코드 (MongoDB)
public class UserService {
    private MongoUserRepository userRepository;

    public UserService() {
        this.userRepository = new MongoUserRepository();
    }

    public User getUser(Long id) {
        return userRepository.findById(id);
    }
}
public class MongoUserRepository extends MongoRepository<User, Long>{
    public User findById(Long id);
}

 

레이어드 아키텍처에 클린 아키텍처 적용

4-tier Layer + 클린 아키텍처 개념 => DIP + OCP 만족하는 구조 완성

Presentation Layer -> Application Layer -> Domain Layer <- Infra Layer 구조로 4-tier Architecture

 

MySQL DB에서 MongoDB로 변경

MongoDB Repository 구현체를 만들어 갈아끼운다. ( MySQL Repository 구현체 -> Mongo Repository 구현체)

public interface UserRepository {
	...
}
//JpaRepository를 사용하는 MySQL Repository 구현체
class UserRepositoryImpl implements UserRepository {
	private final UserJpaRepository userJpaRepository;

}

class UserJpaRepository extends JpaRepository<UserEntity, Long> {

}
//MongoRepository를 사용하는 Mongo DB Repository 구현체
class UserRepositoryImpl implements UserRepository {
	private final UserMongoRepository userMongoRepository;

}

class UserMongoRepository extends MongoRepository<UserEntity, Long> {

}

 

 

레이어드 아키텍처란?

  • Layered Architecture(계층 구조)는 소프트웨어를 여러 개의 계층으로 나누어 설계하는 구조.
  • 각 계층은 특정한 역할과 책임을 가지며, 바로 아래 계층과만 상호작용한다.
  • 일반적으로 사용하는 구조는 소프트웨어 애플리케이션을 3가지 계층으로 분리한 3-tier Architecture이다.
    • Presentation Layer
    • Business Layer(Domain Layer)
    • Data Layer
  • 3-tier에서 추가된 Persistence Layer에 인터페이스로 통신해 DIP를 적용한 4-tier Architecture
    • Presentation Layer
    • Business Layer
    • Persistence Layer
    • Data Layer

 

기존 레이어드 아키텍처의 문제

  • 비즈니스(도메인) 로직이 핵심이 아니며, 보호받지 못한다.
  • 상위 계층이 필요한 기능을 하위 계층에서 구현해서 전달하므로 하위 계층의 변경이 상위 계층에 영향을 줄 수 있다.

=> OCP 원칙에 위반하는 문제

 

 

OCP 원칙
(개방 폐쇄의 원칙)

소프트웨어 개체(클래스, 모듈, 함수 등등)는 확장에 대해 열려 있어야 하고, 수정에 대해서는 닫혀 있어야 한다.

확장에 대해 열려있다 => 모듈의 동작을 확장할 수 있어야 한다. 애플리케이션의 요구사항에 맞게 새로운 동작이나 수정을 할 수 있어야 한다.

수정에 대해 닫혀있다 => 모듈의 소스코드를 수정하지 않아도, 모듈의 기능을 확장하거나 변경할 수 있어야 한다.

예시) JPA의 Repository Interface

  • Spring Data JPA는 Repository Interface를 제공해 JpaRepository를 추상화한 인터페이스를 구현하여 OCP를 지킬 수 있다.
  • 기본적으로 CRUD는 JpaRepository에서 제공해주기 때문에, 기존 코드 수정 없이 인터페이스에 선언만 해주면 된다.
  • CRUD 외의 쿼리는 직접 쿼리로 만들어 확장할 수 있다.

 

클린 아키텍처란?

  • 애플리케이션의 핵심은 비즈니스(도메인) 로직에 집중되어 있다.
  • Interface Adapters에는 Controller 와 Use Case가 의존하는 추상화 된 Port 역할의 Repository Interface가 위치하고, 실제 Repository 구현체는  가장 바깥 원인 Frameworks&Drivers에 위치해 분리된다. => DIP 만족
  • 새로운 Repository 구현체가 필요하면, 기존 코드는 수정하지 않고 인터페이스 구현체만 추가한다. => OCP 만족

 

 


ref.
https://en.wikipedia.org/wiki/Multitier_architecture

728x90
반응형