[Spring] Web Application Layer

JE·2023년 9월 26일

SPRING

목록 보기
4/4
post-thumbnail

웹 애플리케이션을 개발할 때, 웹 애플리케이션에는 다음과 같은 책임 사항이 존재한다는 것을 알 수 있습니다.

  • 사용자의 입력을 처리하고 사용자에게 올바른 응답을 반환해야 한다.
  • 사용자에게 합리적인 오류 메시지를 제공하는 예외 처리 메커니즘이 필요하다.
  • 애플리케이션의 비즈니스 로직을 구현해야 한다.
  • 사용된 데이터 저장소 및 기타 외부 리소스와 통신해야 한다.

이러한 책임 사항들은 세개의 스프링 웹 애플리케이션 레이어를 통해 해결할 수 있습니다.


Dtos: 계층 간에 데이터 교환을 위한 객체를 Dto 라고 하며 Dtos 는 이들의 영역입니다.
Domain Model: 도메인(택시 앱이라면 배차, 탑승, 요금 등)이라 불리는 개발대상을 모든 사람이 동일한 관점에서 이해할 수 있고 공유할 수 있도록 단순화 시킨 것입니다. @Entity 역시 도메인 모델입니다.

DtosDomain Model 은 각 계층에서 역할을 수행하며, 데이터의 효율적인 전달과 비즈니스 로직 처리를 돕는 중요한 요소입니다.


Web Layer

controllers, exception handlers, filters, view templates, etc.

@Controller 를 사용하여 작성된 Controller 클래스가 웹 계층에 속합니다.

웹 계층은 웹 애플리케이션의 최상위 계층입니다. 사용자의 입력을 처리하고 사용자에게 올바른 응답을 반환하는 역할을 담당합니다. 그리고 다른 계층에서 발생한 예외도 처리합니다. 웹 계층은 애플리케이션의 진입점으로 사용자의 요청에 따라 어떤 처리를 할지 Controller 를 통해 결정을 Service 에 넘겨줍니다. 그리고 적절한 응답을 선택하여 클라이언트에게 응답을 제공합니다.

Controller

기본적으로 Controller를 사용하기 위한 두 가지 어노테이션이 있습니다.

  • @Controller
  • @RestController

@Controller 어노테이션은 전통적인 Spirng MVC에서 사용할 때 사용됩니다. 주로 View를 반환할 때 사용되며, @RestControllerRESTFul API 서버를 만들 때 사용됩니다.

  • 두 어노테이션의 차이 : @ResponseBody
    @RestController 는 @Controller 에 @ResponseBody가 추가된 것입니다. 그렇기 때문에 @Controller 에 @ReponseBody를 붙이게 되면 @RestController 와 동일하게 Json 형태로 객체 데이터를 반환할 수 있게 됩니다.
@Controller
public class HomeController {
    @GetMapping("/home") //home으로 Get요청이들어오면
        return "home"; //home.html 반환
}
@RestController // JSON으로 데이터를 주고받음을 선언합니다.
public class ProductRestController {

    private final ProductService productService;
    private final ProductRepository productRepository;

    // 등록된 전체 상품 목록 조회
    @GetMapping("/api/products")
    public List<Product> getProducts() {
        return productRepository.findAll();
    }
}

Service Layer

application service and infrastructure service

애플리케이션 비즈니스 로직 처리와 비즈니스와 관련된 도메인 모델의 적합성 검증을 하고 트랜잭션에 대한 경계 역할을 담당합니다.

@Service 를 사용하여 작성된 Service 클래스가 서비스 계층에 속하고, @Transactional 이 사용되어야 하는 영역이기도 합니다.

  • @Transactional
    @Transactional 은 Spring Framework에서 트랜잭션 관리를 담당하는 어노테이션입니다. 서비스 계층에서 해당 어노테이션이 사용된다는 것은 해당 서비스 메서드가 트랜잭션 범위 내에서 실행된다는 의미를 가집니다.
    • 트랜잭션 범위 내에서 실행되는 메서드는 데이터베이스 작업을 안전하게 수행할 수 있습니다. 즉, 메서드 내의 모든 데이터베이스 작업은 하나의 트랜잭션으로 묶여서 처리됩니다.
    • 만약 메서드 실행 중에 예외가 발생하면, 트랜잭션은 롤백되어 이전 상태로 복구됩니다. 이렇게 하면 데이터베이스 일관성이 유지됩니다.

Client가 요청을 보내면 Controller는 넘어온 요청을 처리하기 위해 Service를 호출합니다. Service는 알맞은 정보를 가공하여 Controller에게 데이터를 넘깁니다. 여기서 Service가 알맞은 정보를 가공하는 과정을 '비즈니스 로직을 수행한다.' 라고 합니다. 주문 처리, 사용자 인증, 결제 처리, 재고 관리 등의 기능은 모두 비즈니스 로직에 해당합니다.


비즈니스 로직은 Service에서 처리하는게 맞을까?

앞선 설명처럼 서비스에서 모든 비즈니스 로직을 처리하는 것을 트랜잭션 스크립트 패턴 이라고 합니다. 이 패턴의 단점은 프로젝트가 커지면 하나의 서비스에서 더욱 많은 모델을 읽어 로직이 구성될 수록 서비스의 복잡도가 매우 높아진다는 것입니다. 복잡도가 높아지면 결국 테스트와 유지보수가 힘들어지게 되는것이고 유연하지 못한 소프트웨어가 됩니다. 이러한 이유 때문에 Service에서는 트랜잭션, 도메인 간 순서 보장의 역할만 하는 것이 좋습니다.

그렇다면 기존에 Service에서 처리하던 비즈니스 로직은 어디서 구현되어야 할까?

도메인(Entity) 또한 비즈니스 로직을 가지고 이를 처리할 수 있습니다. 엔티티 자체에서 해결할 수 있는 로직들은 엔티티 안에 넣으면이 더 객체 지향적인 설계가 됩니다. 도메인이 비즈니스 로직을 가지고 객체 지향의 특성을 적극적으로 활용하는 것을 도메인 모델 패턴이라고 합니다. 이 방식은 도메인 주도 설계(Domain-Driven Design, DDD) 원칙을 따르는 것으로, 엔티티가 자체적으로 자신의 상태와 규칙을 관리하도록 하는 것을 강조합니다. 비즈니스 로직이 도메인에 가까울 수록 서비스 단의 복잡도를 낮추는 효과를 얻을 수 있습니다. 하지만 엔티티에서 처리가 가능하다고 해서 모든 로직을 엔티티에 다 넣게 되면 엔티티 자체가 복잡해질 수 있습니다. 엔티티 하나에서 처리할 수 있는 범위를 넘어가면 서비스에서 협업이 필요하기때문에 이런 경우에는 Service에 비즈니스 로직을 작성해줍니다.

애플리케이션의 구조 및 설계, 상황에 맞는 적절한 방법을 선택하는 것이 중요합니다.

Repository Layer

repository interfaces and thier implementaions

사용된 데이터 저장소와의 통신을 담당하여 데이터베이스에 접근하는 영역입니다.

Repository 인터페이스와 @Repository 를 사용하여 작성된 Repository 의 구현 클래스가 서비스 계층에 속합니다. 데이터베이스 구조가 만들어지면 Repository는 이 Databases 의 CRUD 와 같은 부분을 담당합니다.

Repository Layer 가 데이터베이스에 접근하기 위한 다양한 기술들이 존재합니다.
Spring에서 사용할 수 있는 대표적인 데이터 액세스 기술

  • mybatis
  • Spring JDBC
  • Spring Data JDBC
  • JPA
  • Spring Data JPA

이러한 기술들은 SQL 중심 기술객체 중심 기술 로 분류할 수 있습니다.

SQL 중심 기술
데이터베이스에 접근하기 위해 SQL 쿼리문을 애플리케이션 내부에 직접적으로 작성하는 것이 중심이 되는 기술로 Mybatis와 Spring JDBC가 대표적인 SQL 중심 기술에 해당됩니다.

객체 중심 기술
객체 중심 기술은 데이터를 SQL 쿼리문 위주로 생각하는 것이 아닌 모든 데이터를 객체 관점으로 바라보는 기술로 SQL 쿼리문을 직접적으로 작성하지 않고 Java 객체를 이용하여 애플리케이션 내부에서 SQL 쿼리문으로 자동 변환된 후에 데이터베이스 테이블에 접근합니다.

이러한 객체 중심의 데이터 액세스 기술을 ORM(Object-Relational Mapping)이라고 합니다. Java 에서는 대표적인 ORM 기술로는 Hibernate 가 있습니다.





참고
https://www.petrikainulainen.net/software-development/design/understanding-spring-web-application-architecture-the-classic-way/
https://wonyong-jang.github.io/spring/2020/06/14/Spring-Web-Layer.html
https://ittrue.tistory.com/251#google_vignette

0개의 댓글