SpringMVC 🌱 Model의 이해
SpringMVC Model
이전 포스트로 Controller에 대해 알아보았다. 이번엔 Model에 대해 알아보자.
Model 이란
SpringMVC에서 사용되는 컴포넌트중 하나로 비즈니스 로직 및 도메인 객체, DB와 상호작용을 하는 객체를 의미한다. 정해진 역할에 따라 VO, DTO, DAO(Repository), Service, Entity으로 나뉜다.
1. VO (Value Object)
public class TestVO{ private int no; private String name; public TestVO(int no, String name){ this.no = no; this.name = name; } @Override public boolean equals(Object o) { if (this == o) return true; if (o == null || getClass() != o.getClass()) return false; User user = (User) o; return no == user.no && Objects.equals(name, user.name); } @Override public int hashCode() { return Objects.hash(userNo, userId, userPw); } ...getter }
값 객체 라는 의미를 가지고 있는 VO는 도메인의 값 비교 및 도메인 객체간의 상호작용을 위해 사용한다.
불변성 : VO는 생성 후 값을 변경할 수 없는 불변객체로 작성된다. 이는 생성자를 통해 객체를 생성하고 Setter를 구현하지 않음으로써 성립된다. 데이터 안정성과 신뢰성을 보장한다.
- 값 기반 비교 : 주로 값을 통한 비교를 수행한다. 이를 위해 hashCode, equals 함수를 Override하여 객체 내부 값을 기준으로 동등성을 판단한다.
- 데이터 캡슐화 : Setter가 없고 Getter만을 구현하기 때문에 내부 데이터 변경은 불가능하며, 읽기 전용 객체로 데이터의 캡슐화를 보장한다.
2. DTO (Data Transfer Object)
public class TestDTO{ private int no; private String name; ...getter, setter }
데이터 전송 객체라는 의미를 지니고 있다. 계층간 데이터를 전송하는 객체이며, VO와의 차이점은 DTO가 값 변경에 열려있는 가변 객체라는 점이다.
- 캡슐화 : 필드 인자를 private으로 선언하고 getter와 setter를 통해 간접적으로 데이터를 변경하기 때문에 캡슐화 원칙에 준수하여 설계한다.
데이터 직렬화 : DB 또는 View로 데이터를 전송하거나 받기위해 JSON 혹은 XML과 같은 형태로 변환하여 직렬화 또는 역직렬화를 한다.
- 계층간 데이터 전송 : View로 데이터를 보내거나 View에서 받은 데이터를 DB 또는 비즈니스 로직(Service)으로 전달하는 매개체로 사용된다.
3. Service
@Service public class TestService{ ... }
비즈니스 로직을 구현하는 Service 객체이다. @Service 어노테이션을 사용하여 DAO(Data Access Object)와 Controller 사이에서 비즈니스 로직을 구현하기 위해 사용한다. 비즈니스 로직을 하나의 클래스에 작성하여 유지보수, 재사용성, 테스트에 용이하다는 장점이 있다.
비즈니스 로직의 집중화 : 비즈니스 로직을 하나의 클래스에 구현함으로써 여러 컨트롤러에서 사용되거나 중복을 최소화하여 일관성을 유지하고 유지보수 및 재사용성에 이점을 가진다.
- 트랜잭션 관리 : Controller와 DAO 사이에 위치하여 트랜잭션의 시작과 끝을 관리하여 데이터 일관성과 무결성을 유지할 수 있다.
- 보안 : 접근 권한을 검사하는 등 트랜잭션을 시작하기 전 수행할 수 있어 보안에 이점이 있다.
- 테스트 : 다른 계층과 분리되어 있으므로 비즈니스 로직에 대한 단위 테스트 및 통합 테스트를 진행할 수 있다.
4. DAO (Data Access Object)
@Repository public class TestDAO(){ ... }
DB와의 트랜잭션을 수행하는 객체. @Repository 어노테이션을 사용하여 해당 클래스가 데이터 엑세스 계층의 클래스임을 나타내고 Bean 등록을 수행한다. DB Connection 객체를 구현하여 CRUD 작업을 수행한다. SQL을 수행시 Connection을 열고 닫음을 반복하지 않고, DAO 객체에서 관리하기 때문에 다량의 쿼리 작업시에 발생할 오버헤드를 줄일 수 있다.
- CRUD : Create, Read, Update, Delete를 의미하는 기본 작업이며, 해당 작업을 수행하고 데이터 로직을 단순하고 일관성있게 구현하고 수행한다.
- 트랜잭션 관리 : DB와의 연결을 관리하고 트랜잭션에 대한 일관성과 안정성을 유지한다.
- 쿼리 수행 : DB와 통신하며 쿼리를 수행하거나 관리한다.
- 예외처리 : DB Connection 오류, 쿼리 수행 오류등의 예외처리를 수행한다.
- 테스트 수행 : 비즈니스 로직과 분리하여 DB Connection 또는 데이터 엑세스 로직을 수월하게 테스트할 수 있다.
5. Entity (JPA)
@Entity public class TestEntity{ @Id @GeneratedValue(strategy = GenerationType.IDENTITY) privae int no; @Column(nullable = false) private String name; }
주로 JPA에서 사용되는 Model 객체. Entity는 테이블과 1:1로 매핑해 사용한다. 어노테이션을 사용하여 기본키 또는 컬럼과 필드인자를 매핑하여 사용한다.
- @Entity을 통해 Entity 객체임을 나타낸다.
@Id을 사용해 테이블의 primarty key와 매칭한다.
- @Column을 사용해 컬럼과 매칭한다.
Model을 구분하는 이유
View와 비즈니스, DB 로직을 나누고 주어진 객체의 역할에 일관성을 유지시켜 유지보수, 재사용성,
단위 또는 통합 테스트에 이점을 얻기 위함을 알 수 있다.