Rev Notebook

[Spring Boot] SpringBoot의 MVC 패턴

by Rev_

MVC 패턴이란?

모델-뷰-컨트롤러(Model-View-Controller)의 약자가 MVC이며, 소프트웨어 디자인 패턴의 한 종류이다.

사용자 인터페이스로부터 비즈니스 로직을 분리하여 애플리케이션의 시각적 요소나 그 이면에서 실행되는 비즈니스 로직을 서로 영향 없이 쉽게 고칠 수 있다.

MVC는 응용 프로그램을 3가지의 구성요소로 나눈다.

  • Controller : 모델에 명령을 보냄으로써 모델의 상태를 변경하거나, 컨트롤러가 관련된 뷰에 명령을 보냄으로써 모델에 표시 방법을 바꿀 수 있다.
  • Model : 모델의 상태에 변화가 있을 때 컨트롤러와 뷰에 이를 통보한다.
  • View : 사용자가 볼 결과물을 생성하기 위해 모델로부터 정보를 얻어온다.

 

나는 현재 Spring Boot를 사용하여 웹 애플리케이션을 개발하며, 공부하고 있다.

따라서 Controller, Service, DTO, Repository, Domain의 5가지 요소에 대하여 설명해보고자 한다.

  • Controller : 웹 계층에 속하는 대표적인 요소이다. 외부 요청과 응답에 대한 전반적인 영역을 의미한다.
  • Service : 비즈니스 로직을 구현하며, 일반적으로 controller와 repository의 중간에 위치한다.
  • Repository : DB와 같은 데이터 저장소에 접근하는 역할을 한다.
  • DTO : 계층 간의 데이터 교환을 위한 객체이다.
  • Domain : 개발 대상, 즉 도메인을 모든 사람이 동일한 관점에서 이해할 수 있고 공유할 수 있도록 단순화한 것이다. JPA를 사용한다면, @Entity의 영역이 도메인 영역이라고 할 수 있다.

내가 이해한 바로는 대충 이러한 구조라고 할 수 있겠다...

 

Entity와 DTO의 차이점

DTO(Data Transfer Object)의 약자로, 계층간 데이터 교환을 위한 Java Beans이다.

* Java Beans : 자바로 작성된 소프트웨어 컴포넌트

일반적으로 DTO순수한 데이터 객체이며, 객체의 속성과 그 속성의 접근을 위한 getter, setter 메소드만을 가지고 있다.

데이터베이스에서 데이터를 얻어 Service나 Controller 등으로 보낼 때 사용하는 객체이다.

 

데이터를 담고 있다는 점에서 Entity와의 차이점이 무엇인가? 라고 생각해볼수 있겠다.

Entity의 개념과 역할, DTO와 차이점에 대해서 알아보자.

 

Entity는 DB와 직접적으로 연관되어 있다. DB에 있는 컬럼들을 필드로 가지는 객체이다.

데이터베이스의 영속성 목적으로 사용되는 객체이기 때문에 Request, Response 값을 전달하는 클래스로 사용하는 것은 옳지 않다. (이 역할을 DTO 클래스에서 한다. request와 response 사용이 가능하며 자주 변경 가능)

특히 JPA를 사용하게 되면 Entity 객체는 단순히 데이터를 담는 객체가 아니라 실제 데이터베이스와 관련된 중요한 역할을 하며, 내부적으로 EM(EntityManager)에 의해 관리된다.

 

따라서 읽고, 쓰는 것이 모두 가능하고 일회성의 성격을 지닌 DTO와는 확실히 다르다.

Entity와 DTO가 분리되어 있지 않다면, 테이블에 매핑 되는 정보와 실제 View에서 보여줘야 하는 정보가 다를 경우 이를 필요한 정보에 맞게 데이터를 변환하는 로직이 필요할텐데, 이것이 Entity에 들어가는 것은 옳지 않다.

결론적으로 Entity와 DTO를 분리하는 이유는 DB와 View 사이의 역할 분리를 위함이다.

 

  • Builder 패턴

Domain(Entity)와 DTO에서는 Builder 패턴을 사용했다. 이는 왜 쓰는 것일까?

아마 정보처리기사를 공부해며 배웠을 디자인 패턴의 종류 중 하나이다. 빌더 패턴객체를 생성하는 클래스표현하는 클래스를 분리하여 동일한 절차에서도 서로 다른 표현을 생성하는 방법을 제공한다.

 

Lombok을 사용하면 getter/setter, constructor를 직접 작성해주지 않아도 어노테이션을 활용하여 손쉽게 작성해줄 수 있다. 마찬가지로 빌더 패턴도 @Builder를 사용할 수 있다. 

 

이는 객체를 생성할 때 생성자만 사용할 때 발생할 수 있는 문제를 개선하기 위해 고안되었다.

생성해야하는 클래스에 대한 속성 값이 많을 때 다음과 같은 문제점들이 있다.

  1. 클래스에 대한 속성값이 많을 땐 타입과 순서에 대한 관리가 어려워져 에러 발생 확률이 높아짐
  2. 경우에 따라 필요 없는 파라미터들에 대해서 팩토리 클래스에 일일히 NULL 값을 넘겨줘야 함
  3. 생성해야 하는 서브 클래스가 무거워지고 복잡해짐에 따라 팩토리 클래스 또한 복잡해진다.

이러한 문제들을 해결하기 위해 별도의 Builder 클래스를 만들어서 필수값에 대해서는 생성자를 통해, 선택적인 값들에 대해서는 메소드를 통해 build() 메서드를 거쳐 최종적으로 하나의 인스턴스를 return 하는 방식이다.

 

Controller

컨트롤러는 웹 브라우저와 연결되어 있다.

요청된 url에 따라 적절한 view와 mapping을 처리한다. 적절한 ResponseEntity(DTO)를 body에 담아 웹 브라우저에 반환한다.

그리고 목적에 따라 Controller나 RestController 어노테이션의 사용이 필요하다.

  • @Controller : API와 view를 동시에 사용하는 경우
  • @RestController : view가 필요없는 API만 지원하는 서비스에서 사용

 

Service

사실 컨트롤러와 엔터티, 레포지토리의 역할은 어느정도 알겠는데 서비스는 정확히 어떤건지 잘 가늠이 안됐다..

데이터를 얻어와서 가공하는 역할을 하여 데이터베이스로 전달하거나, 데이터베이스에서 데이터를 전달 받아 가공하여 유저에게 전달하는 역할을 한다.

딱 Controller와 Respository의 중간에서 데이터를 주고 받으며 가공하여 전달하는 역할이라고 이해된다. 공장에 들어가서 제품을 만드는 과정에 속한다고 이해하면 되려나?

 

  • @Transactional

트랜잭션이란, 흔히 데이터베이스의 상태를 변화시킬 때 수행하는 작업의 단위를 뜻한다.

Spring에서 사용하는 개념도 동일하다. 한 가지 기능을 하는 일련의 코드들을 한 단위로 묶어서 작업을 처리하는 방법이며, 중간에 오류가 생겼을 때 작업 이전으로 되돌려주는 역할을 한다.

Service 클래스를 작성할 때 기능을 구현하는 개별 메소드마다 이 어노테이션이 붙어 있는 것을 볼 수 있다.

 

Spring에서 @Transactional를 클래스나 메서드에 붙여주면 트랜잭션 기능이 적용된 프록시 객체가 생성된다.

그 다음으로 PlatformTransactionManager를 사용하여 트랜잭션을 시작하고, 동작여부에 따라 commit이나 rollback을 결정한다.

 

@Transactional은 클래스단보다는 CUD 메서드 단에 붙여주는 것이 좋다. DB 외에 다른 외부 자원을 사용하는 경우에 지연이 발생하면 DB까지 영향이 갈 수도 있고, 각 메서드마다 상황에 따라 트랜잭션을 어떻게 처리할지 달라질 수도 있기 때문이다.

 

만약 R(Read)에 대해서도 필요하다면, 이 어노테이션을 붙여줄 수 있지만 이때는 readOnly 옵션을 준다. 그렇지만 이때는 다른 이슈가 없는지 판단해보고 결정해야 한다.

@Transactional(readOnly = true)
public Station findById(Long id) {
    // ...
}

나중에 JPA를 쓰거나 하면 CrudRepository 자체적으로 @Transactional를 가지고 있다.

 

@Transcational이 작동하지 않는 경우도 있다. 메서드 접근 제한자가 public이 아닌 경우에는 동작하지 않는다.

 

Repository

DB를 관리하는 객체이며, DB에 CRUD의 명령을 실행하게 만드는 인터페이스 객체이다.

JPA에서 JPARepository<Entity, 기본키 타입>을 상속받으면 기본적인 CRUD가 자동으로 생성된다.

 

사실 백날 이론 뚜드려봤자 실제로 코드 보면서 이해하는게 더 빠를거 같다!

실습하면서 중간중간에 개념들에 대해서 열심히 정리해보자😋

 

[Reference]

https://wildeveloperetrain.tistory.com/101

https://velog.io/@dasole1234/dTo-Controller-Service-Repository-%EB%9E%80

블로그의 정보

Hi Rev

Rev_

활동하기