# Layered Architecture

## 레이어드 아키텍처

* 응용 프로그램을 독립적인 레이어로 구성
* 각각의 특정 책임을 부여하는 소프트웨어 디자인 패턴
* 느슨한 결합, 모듈성 및 관심사의 분리를 촉진

### 주요 레이어

> 레이어드 아키텍처를 가져갔을 때 어떤것들을 레이러드로 나눌것인지 정의하는것이 필요

* 프레젠테이션
* 비즈니스 로직
* 데이터 엑세스(퍼시스턴스)
* 데이터베이스

### 프레젠테이션 레이어

* 사용자 **상호작용**을 처리
* 사용자 인터페이스를 표시하는 역할
* 사용자 인터페이스, 컨트롤러 및 뷰와 같은 구성요소가 포함됨

### 비즈니스 로직 레이어

> 상호작용 요청이 들어왔을 때 처리하는 레이어

* 응용 프로그램의 핵심 기능이 포함됨
* 비즈니스 규칙을 구현하고 데이터를 처리
* "서비스 레이어"
* 응용 프로그램이 의도한 대로 작동하고 필요한 작업을 수행하는지 보장

### 데이터 액세스 레이어

> 비즈니스 레이어에서 핵심 로직을 처리하기 위해서는 데이터가 필요하다.
>
> 데이터를 저장하고 조회하고 조작하는 레이어가 필요

* 데이터베이스나 외부 API와 같은 데이터 저장 시스템과 상호 작용 담당
* 데이터 액세스 및 조작 로직을 캡슐화
* 기반 데이터 저장소에 대한 추상화를 제공
* 유연성과 유지 보수성을 높힘

### 레이어 아키텍처의 장점

* 각 레이어를 독립적으로 개발, 테스트 및 유지관리
* 코드의 재사용성, 확장성 및 유지 보수의 용이성을 촉진
* 레이어 간의 인터페이스 일관성을 유지하면 변경된 내용이 다른 레이어에 영향을 주지 않게됨
* 소프트웨어 개발에 구조적이고 조직적인 접근 방식을 제공
* 코드 구조화, 관심사의 분리 및 유지보수성을 개선

### Sample

```java
// Presentation Layer
class UserController {
  private UserService userService;
  
  public UserController(UserService userService) {
    this.userService = userService;
  }
  
  public void registerUser(String username, String password) {
    // Presentation Layer에서 받은 요청을 비즈니스 로직 레이어로 전달
    userService.registerUser(username, password);
  }
}

// Business Logic Layer
class UserService {
  private UserRepository userRepository;
  
  public UserService(UserRepository userRepository){
    this.userRepository = userRepository;
  }
  
  public void registerUser(String username, String password) {
    // 비즈니스 로직 수행
    if (isValidUser(username)) {
      userRepository.saveUser(username, password)
    } else {
      System.out.println('invalid username');
    }
  }
  
  private boolean isValidUser(String username) {
    // 실제 유효성 검사 로직은 여기 구현
    return username !== null && !username.isEmpty()
  }
}

// Data Access Layer
class UserRepository {
  public void saveUser(String username, String password) {
    // 데이터베이스에 사용자 정보 저장
    System.out.println('saving user to the db');
  }
}

// client code
public class LayeredArchitectureExample {
  public static void main(String[] args) {
    // 각 레이어의 인스턴스 생성
    UserRepository userRepository = new UserRepository();
    UserService userService = new UserService(userRepository);
    UserController userController = new UserController(userService);
    
    // 사용자 등록 요청
    userController.registerUser("john_doe", "password");
  }
}
```
