본문 바로가기

Spring

Layered Architecture

 


 

 

Layered Architecture 계층 구조

일반적으로 Layered Architecture는 다음과 같은 계층으로 구성됩니다:

  • Presentation Layer (프레젠테이션 계층):
    • 사용자 인터페이스와 관련
    • 사용자가 시스템과 상호작용하는 인터페이스 제공
    • 예시: Controller 클래스
@Controller
public class UserController {

    private final UserService userService;

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

    @GetMapping("/users/{id}")
    public String getUser(@PathVariable Long id, Model model) {
        UserResponse user = userService.getUserById(id);
        model.addAttribute("user", user);
        return "userDetail";
    }

    @PostMapping("/users")
    public String createUser(@ModelAttribute UserRequest userRequest) {
        userService.createUser(userRequest);
        return "redirect:/users";
    }
}

 

 

 

  • Application Layer (응용 계층):
    • 비즈니스 로직을 처리
    • 사용자의 요청을 받아 처리
    • 데이터를 조작
    • 다른 계층과 상호작용
    • 예시: Service 클래스
@Service
public class UserService {

    private final UserRepository userRepository;
    private final UserMapper userMapper;

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

    public UserResponse getUserById(Long id) {
        User user = userRepository.findById(id)
                .orElseThrow(() -> new UserNotFoundException(id));
        return userMapper.toResponse(user);
    }

    public void createUser(UserRequest userRequest) {
        User user = userMapper.toEntity(userRequest);
        userRepository.save(user);
    }
}

 

 

 

  • Domain Layer (도메인 계층):
    • 핵심 비즈니스 로직과 규칙을 처리
    • 도메인 객체와 이들 간의 관계를 정의
    • 비즈니스 규칙과 정책이 포함
    • 시스템의 핵심 기능을 담당
    • 예시: domain, Entity
public class User {// 시스템의 도메인 엔티티

//속성들
    private Long id;
    private String name;
    private String email;
    private String password;

    public User(String name, String email, String password) {
        this.name = name;
        this.email = email;
        this.password = password;
    }

    public void changeEmail(String newEmail) {
        // 이메일 변경과 관련된 --> 비즈니스 규칙
        if (!newEmail.contains("@")) {
            throw new IllegalArgumentException("Invalid email address");
        }
        this.email = newEmail;
    }

    // Getter 및 Setter 메서드
}

 

 

 

 

 

 

  • Infrastructure Layer (인프라스트럭처 계층):
    • 데이터베이스 접근, 외부 시스템 통신, 파일 입출력 등 기술적인 세부 사항을 처리
    • 예시: Spring Data JPA 리포지토리

 

public interface UserRepository extends JpaRepository<User, Long> {
}

 

고수준 모듈, 저수준 모듈

  • 고수준 모듈 (High-Level Module):
    • 비즈니스 로직이나 도메인 계층에 가까운 계층
    • 시스템의 중요한 비즈니스 규칙과 기능을 포함
    • Application Layer, Domain Layer
  • 저수준 모듈 (Low-Level Module):
    • 기술적인 세부 사항이나 외부 시스템과의 상호작용을 담당하는 계층
    • Infrastructure Layer

 

고수준 모듈 보호의 의미

  • 저수준 모듈에 대한 의존성을 최소화하고,
  • 저수준 모듈이 고수준 모듈의 구현에 영향을 주지 않도록
  • 시스템의 설계가 변경될 때 고수준 모듈이 쉽게 영향을 받지 않도록 함
  • 시스템의 유지보수성과 확장성을 높임

 

예시

  1. 의존성 역전 원칙 (Dependency Inversion Principle, DIP):
    • 저수준 모듈이 고수준 모듈에 의존하지 않도록
    • 인터페이스나 추상 클래스에 의존하게 하는 원칙
    • 이를 통해 고수준 모듈이 구체적인 구현이 아닌
    • 추상화된 인터페이스에 의존하게 되어
    • 저수준 모듈이 변경되더라도 고수준 모듈이 쉽게 영향을 받지 않음
    • 인터페이스나 추상화를 사용하여 의존성을 제어
// 고수준 모듈 (Application Layer)
public class OrderService {
    private final PaymentProcessor paymentProcessor;

    public OrderService(PaymentProcessor paymentProcessor) {
        this.paymentProcessor = paymentProcessor;
    }

    public void processOrder(Order order) {
        paymentProcessor.process(order);
    }
}
/*
 OrderService는 
 구체적인 결제 처리 구현(PaypalPaymentProcessor)이 아닌 
 PaymentProcessor 인터페이스에 의존하
 결제 처리 방법이 변경되더라도 
 OrderService는 수정할 필요가 없다
 */

// 저수준 모듈 (Infrastructure Layer)
public class PaypalPaymentProcessor implements PaymentProcessor {
    public void process(Order order) {
        // PayPal을 통한 결제 처리 변경될 예정
    }
}

 


 

Layered Architecture에 따라 고수준 모듈을 보호하는 구성?

  • 시스템의 핵심 비즈니스 로직변경에 덜 영향을 받도록 설계하는 것
  • 저수준 모듈은 고수준 모듈에 직접 의존하지 않고
  • 인터페이스와 같은 추상화를 통해 간접적으로 의존
  • 시스템의 유연성과 유지보수성을 높임