[Spring] MVC Layer 책임소재

유아 Yooa·2023년 7월 20일
3

Spring

목록 보기
13/18
post-thumbnail

Overview

클라이언트 요청 파라미터 중 null 값을 validate하고 이에 따라 다른 값(e.g. null -> "" 빈문자열로)을 처리해주는 작업을 서비스단에서 처리했다.

필자는 이것도 비즈니스 로직에 포함된다고 단단히 잘못 판단하였고 서비스단에서 처리해주었다.

객체지향적인 개발을 위하여 컨트롤러와 서비스의 책임 분리를 명확하게 해주면 좋을 것 같다는 리뷰를 받았고, 오늘은 Springboot flow architecture를 살펴보며 레이어별 역할을 살펴보자.


Springboot flow architecture

  • 스프링부트에서는 Controller - Service - Repository의 3가지 레이어를 두고 서버 로직을 수행하는 Layered Architecture 방식을 사용한다.

책임이란 외부 객체의 요청에 대한 응답이다. 이러한 책임이 모여 역할이 되며 역할은 대체 가능성을 의미한다. 그걸기 때문에 대체가 가능할 정도의 적절한 크기를 가져야 한다.

layer를 분리한다는 것

  • layer를 분리한다는 것은 다른 layer를 추상화한다는 것이다.
    • 추상화를 잘 했다면, 관심 분리를 통해 현재 작업중인 layer에 집중할 수 있다.
    • 다른 layer의 모듈을 부품 갈아끼우듯 변경할 수 있다. 세부사항을 몰라도 추상화해서 제공해야 한다.
  • 컴포넌트 간의 의존 계층 관계를 깔끔하게 유지할 수 있다.
    • 각 layer들이 스파게티처럼 꼬여 있는 관계가 아니라, 위에서 아래로 떨어지는 간단한 구조 혹은 복잡한 참조는 같은 계층 내에서 끝내는 등 상대적으로 깔끔한 구조로 만들 수 있다.

Controller

  • 실질적인 Spring MVC 객체로, 클라이언트의 요청을 직접 가공하여 Service Layer로 전달하는 역할을 수행한다.
  • 클라이언트의 request 정보는 일반적인 parameter 형식이거나 json 형식의 데이터일 수 있다.
  • 해당 요청 정보가 서비스에서 요구하는 형식과 일치하는지 검증하고, 일치하다면 가공하여 다음 layer에 전달한다.

Service

  • Domain Model을 묶어서 이 소프트웨어에서 사용 가능한 핵심 작업 집합을 설정하는 계층

    • 이 소프트웨어가 수행해야 하는 작업은 무엇인가?
    • 이 소프트웨어에 내릴 수 있는 명령은 무엇인가?
  • 보통 도메인 모델의 비즈니스 로직 하나를 호출하는 것 만으로는 복잡한 작업을 처리할 수 없다.

    • 도메인 모델 여러개를 불러와 요청을 가공하고, 비즈니스 로직을 호출하고, 응답을 조정해서 또 다른 비즈니스 로직을 호출해주는 상위 layer가 있어야 한다.
    • 여러 비즈니스 로직을 의미있는 수준으로 묶어 제공하는 것이 Service Layer의 역할이다.
  • 도메인의 핵심 비즈니스 로직을 구현하는 영역이 아니라 인프라 스트럭쳐 (데이터베이스) 영역과 도메인 영열을 연결해주는 매개체 역할이다.

  • 비즈니스 로직을 수행하고, 하나의 로직인 하나의 transaction으로 이루어져 있다.

  • 비즈니스 로직 수행 간 DB에 접근해야 한다면 다음 layer를 호출하여 수행한다.

  • 요청 정보가 유효한지 (Validation) 체크하고, 비즈니스 로직 접근 권한(authorization)을 관리한다.

  • 서비스는 불필요하게 HTTP 통신을 위한 HttpServlet을 상속 받을 필요가 없는 순수한 자바 객체로 구성되어야 한다.

  • service에서 request나 response와 같은 객체를 매개 변수로 받아선 안된다. 그걸 사용하는 작업은 컨트롤러에서 해주어야 한다. 그렇기에 자신을 어떤 컨트롤러가 호출하든 상관없이 필요한 매개변수만 준다면 자신의 로직을 처리하게 된다.

    모듈화를 통해 어디서든 재사용 가능한 클래스 파일이라는 것.

Repository

  • 직접 DB에 쿼리를 생성하고 전송하는 layer이다.
  • domain 객체를 영속화하고, 전송된 쿼리 결과를 통해 얻은 영속화 객체를 바탕으로 서비스 레이어에 필요로 하는 데이터를 반환한다.

의존의 단방향성

  • 기본적으로 각 layer는 하위 layer에 의존할 수 있으나, 같은 layer 혹은 상위 layer는 의존하지 않음으로써 순환 참조를 방지한다.

결론

객체지향적인 개발을 위하여 컨트롤러와 서비스의 책임 분리를 명확하게 해주면 좋을 것 같다.

Controller Layer 역할 중 하나인 '클라이언트의 요청을 직접 가공'과 Service Layer가 소프트트웨어 필요한 핵심 기능을 구현한다는 것을 중점으로 살펴보았다.

기존 서비스단에서 null 값을 체크하고 이에 따라 빈 문자열을 처리해준 코드를 Controller 단에서 수행하도록 변경해야할 것 같다. 서비스의 핵심 기능이기보다는 사용자의 요청 값을 가공하는 것에 해당되기 떄문이다.

각 레이어의 책임을 명확히 인지하고 뚱뚱한 서비스 코드를 작성하지 않도록 유의하며 작성해야겠다.


ref

profile
기록이 주는 즐거움

1개의 댓글

comment-user-thumbnail
2023년 7월 20일

좋은 글 감사합니다!

답글 달기