[MSA] 레이어드 아키텍처란? :: 매운코딩
728x90
300x250

소프트웨어 아키텍처인 레이어드와 헥사고날에 대해 공부한다.

ChatGPT를 활용하였습니다.

 

1. 레이어드 아키텍처 (계층화 아키텍처)

계층별로 하는일을 한정시키고 계층별로 독립적으로 개발,배포,확장

  1. 프레젠테이션 계층 (Presentation Layer): 사용자 인터페이스와 상호작용하는 부분.
  2. 애플리케이션 계층 (Application Layer): 애플리케이션의 기능을 정의하고, 비즈니스 로직을 실행하는 부분.
  3. 도메인 계층 (Domain Layer): 핵심 비즈니스 로직과 도메인 객체를 포함하는 부분.
  4. 인프라스트럭처 계층 (Infrastructure Layer): 데이터베이스, 파일 시스템, 네트워크 등의 기술적인 세부 사항을 처리하는 부분.

역방향 의존성이란?

역방향 의존성이란 상위 계층이 아닌 하위 계층이 상위 계층에 의존하는 상황을 말합니다. 예를 들어, 인프라스트럭처 계층이 도메인 계층이나 애플리케이션 계층에 의존하는 경우입니다.

하위 계층을 수정하니 다른 상위계층의 일부 메소드들에도 영향이 가서 고쳐야하는 경우, 하위 계층이 상위 계층을 호출하는 경우 등등이 .. 역방향의존성이다.

interface를 의존하는 경우  App. Layer에서 영향을 끼칠수있다.

역방향 의존성이 문제인 이유

  1. 책임 분리가 깨짐: 각 계층은 특정한 책임을 가지고 있으며, 그 책임은 명확하게 분리되어야 합니다. 역방향 의존성이 발생하면 하위 계층이 상위 계층의 책임을 알게 되고, 이는 책임 분리 원칙을 깨뜨리게 됩니다.
  2. 코드 복잡성 증가: 하위 계층이 상위 계층에 의존하면, 두 계층 간의 상호작용이 복잡해져 코드의 가독성과 유지보수성이 떨어집니다.
  3. 변경의 어려움: 상위 계층의 변경이 하위 계층에 영향을 미치게 되므로, 시스템의 한 부분을 변경할 때 다른 부분까지 수정해야 할 수 있습니다. 이는 시스템의 확장성과 유연성을 저해합니다.
  4. 테스트의 어려움: 하위 계층이 상위 계층에 의존하면, 독립적으로 테스트하기가 어려워집니다. 이는 단위 테스트와 통합 테스트를 복잡하게 만들어, 버그를 발견하고 수정하는 데 시간이 더 걸릴 수 있습니다.

 

<올바른 의존성 예제>

// 도메인 계층
public class User {
    private Long id;
    private String name;
    // getters and setters
}

// 인프라스트럭처 계층
public interface UserRepository {
    User findById(Long id);
}

public class UserRepositoryImpl implements UserRepository {
    @Override
    public User findById(Long id) {
        // 데이터베이스 조회 로직
        return new User(id, "John Doe");
    }
}

// 애플리케이션 계층
public class UserService {
    private UserRepository userRepository;

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

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

// 프레젠테이션 계층
public class UserController {
    private UserService userService;

    public UserController(UserService userService) {
        this.userService = userService;
    }

    public void displayUser(Long id) {
        User user = userService.getUserById(id);
        System.out.println("User: " + user.getName());
    }
}

 

 

<잘못된 의존성 예제>

// 애플리케이션 계층 (잘못된 의존성)
public class UserService {
    private UserController userController; // 역방향 의존성

    public UserService(UserController userController) {
        this.userController = userController;
    }

    public void updateUser(User user) {
        // 비즈니스 로직
        userController.displayUser(user.getId()); // 상위 계층 호출
    }
}

// 프레젠테이션 계층
public class UserController {
    public void displayUser(Long id) {
        // 사용자에게 결과 표시
        System.out.println("User ID: " + id);
    }
}

 

사용 기준:

  • 명확한 책임 분리가 필요한 경우: 애플리케이션의 기능이 명확히 구분되고, 계층별로 책임이 분명한 경우.
  • 일관된 개발 패턴이 필요한 경우: 팀 내의 개발 표준을 유지하고, 새로운 팀원이 쉽게 시스템을 이해하고 개발할 수 있도록 하는 경우.
  • 재사용성과 유지보수성을 중요시하는 경우: 시스템이 장기간 유지보수되어야 하며, 특정 계층의 기능을 재사용할 필요가 있는 경우.

모놀리식 구조나 일반적인 프로젝트 구조에 최적화

728x90

+ Recent posts