❑ Service 계층
➤ DI를 통한 서비스 계층과 API 계층 연동
✔️ API 계층과 서비스 계층을 연동한다?
API 계층에서 구현한 Controller 클래스가 서비스 계층의 Service 클래스와 메서드 호출을 통해 서로 상호작용한다.
▶️ Service의 의미
애플리케이션에서 Service는 도메인 업무 영역을 구현하는 비즈니스 로직과 관련이 있다.
Serivce는 쉽게 말해 비즈니스 로직을 처리하기 위한 Service 클래스이다.
애플리케이션의 서비스 계층은 대부분 도메인 모델을 포함하고 있다.
도메인 모델은 빈약한 모델(anemic domain model)과 풍부한 도메인 모델(rich domain model)로 구분할 수 있다.
이러한 도메인 모델은 DDD(Domain Driven Design, 도메인 주도 설계)와 관련있다.
(DDD는 현업에서 클래스 설계 경험이 풍부해야 제대로 사용할 수 있다.)
➤ 도메인 엔티티(Domain Entity) 클래스
서비스 계층에서 데이터 엑세스 계층과 연동하면서 비즈니스 로직을 처리하기 위해 필요한 데이터를 담는 클래스
보통 리소스 이름으로 만든다. ex) Member, Coffee, Order
➤ 도메인 엔티티 클래스에 붙는 애너테이션
lombok 라이브러리에서 제공한다.
@Getter / @Setter
- getter/setter 메서드를 일일이 작성할 필요 없도록 추가해준다.
@AllArgsConstructor
- 클래스에 존재하는 모든 필드를 매개변수로 갖는 생성자를 자동으로 생성해준다.
- 만약에 필드 중에 @NotNull 애너테이션이 붙어 있다면 해당 부분은 생성자 내에서 null-check로직을 자동으로 생성한다.
@NoArgsConstructor
- 매개변수가 없는 생성자를 생성한다.
- 필드에 final 키워드가 있을 경우 초기화 할 수 없기 때문에 에러가 발생한다.
- 필드에 @NotNull 같은 제약조건이 설정되어 있을 경우, 생성자 내 null-check 로직이 생성되지 않는다.
@RequiredArgsConstructor
- 초기화 되지 않은 모든 final 필드, @NotNull이 설정되 있는 필드들에 대한 생성자를 자동으로 생성해준다.
※ lombok 라이브러리의 더 많은 애너테이션
https://projectlombok.org/features/all
➤ DI 주입
Service 클래스에 @Service 애너테이션 추가해서 Spring Bean으로 등록해주고
Controller 클래스와 Service 클래스간에 느슨한 결합(Losse Coupling)을 위해 DI를 주입해준다.
(Controller는 @RestController 로 이미 Spring Container에 등록되어 있다.)
※ 일반적으로 생성자가 하나일 경우에는 @Autowired 를 붙이지 않아도 Spring이 알아서 DI를 적용한다.
하지만 생성자가 하나 이상일 경우, DI를 적용하기 위해선 반드시 @Autowired를 붙여야 한다!
❑ Mapper(매퍼)
➤ Mapper를 이용한 DTO 클래스와 Entity(엔티티) 클래스 매핑
▶️ Mapper를 사용하지 않을 경우
- Controller의 핸들러 메서드가 DTO 클래스를 엔티티 클래스로 변환 하는 작업까지 하게 되어 여러 역할을 가지게 된다.
- 서비스 계층인 엔티티(Entity) 클래스 객체를 클라이언트의 응답으로 전송(API 계층의 역할)해서 계층 간의 역할 분리가 이루어지지 않는다.
▶️ Mapper 사용법
- 클래스를 Spring Bean으로 등록하기 위해 @Component 애너테이션을 추가한다.
- 등록된 빈은 Controller에서 사용된다.
➤ MapStruct를 이용한 Mapper 자동 생성
Mapper를 수작업으로 작성하는 것은 비효율 적이다.
Mapper를 자동으로 만들 수 있는 MapStruct을 이용하면 편리하다.
DTO클래스 처럼 Java Bean 규약을 지키는 객체들 간의 변환 기능을 제공하는 매퍼(Mapper) 구현 클래스를 자동으로 생성해주는 코드 자동 생성기이다.
MapStruct를 사용하려면 먼저 의존 라이브러리를 추가 해주어야 한다.
Gradle
build.gradle파일 dependencies에 아래 코드 추가한다.
dependencies {
implementation 'org.mapstruct:mapstruct:1.4.2.Final'
annotationProcessor 'org.mapstruct:mapstruct-processor:1.4.2.Final'
}
Mapper 인터페이스 추가하고 인터페이스에 @Mapper 애너테이션 추가한다.
-> 인터페이스가 MapStruct의 매퍼 인터페이스로 정의된 것임을 알려준다.
attribute로 componentModel = “spring” 지정해서 Spring Bean으로 등록한다.
MapStruct가 Mapper 인터페이스를 기반으로 매퍼(Mapper) 구현 클래스를 자동으로 생성해준다!
Gradle에 build task를 실행하면 자동으로 생성된다.
intelliJ에서 build task 실행하기
Gradle 탭 -> 해당 프로젝트 명 -> Tasks 디렉토리 -> build 디렉토리 -> build 더블클릭
읽어주셔서 감사합니다.
오개념에 대한 지적은 늘 환영입니다. 😆
'TIL(Today I Learned)' 카테고리의 다른 글
6/29 (수) [Spring MVC] 예외 처리 2️⃣ - 비즈니스 로직에 대한 예외 처리 (0) | 2022.07.04 |
---|---|
6/28 (화) [Spring MVC] 예외 처리1️⃣ (0) | 2022.07.04 |
6/24 (금) [Spring MVC] API 계층 - DTO(Data Transfer Object) (0) | 2022.06.27 |
6/23 (목) [Spring MVC] API 계층 - 1️⃣ Spring MVC Architecture & Controller (0) | 2022.06.26 |
6/21 (화) Spring Framework - AOP 2️⃣ (0) | 2022.06.21 |