Spring MVC의 Layered Architecture
- API(Presentation) Layer @Controller : DTO 사용
- 전달받은 요청 데이터를 Service 클래스로 전달하고, 응답 데이터를 클라이언트로 다시 전송해 주는 단순한 역할
- Business(Service) Layer @Service : Entity 사용
- 도메인 업무 영역을 구현하는 비즈니스 로직 구현영역
- Entity : 서비스 계층에서 데이터 엑세스 계층과 연동하면서 비즈니스 로직을 처리하기 위해 필요한 데이터를 담는 역할 (controller의 dto와 동일)
- Persistance(Data access) Layer @Repository : Entity 사용
API Layer ↔ Business Layer 연동
- 객체 간 의존관계 생성:
- Controller에서 new Service를 해서 객체를 생성할 수도 있지만, Spring DI(Loose Coupling) 생성자 주입 기능을 활용하여 연결 @Service @Component
- 데이터 전환 : DTO ↔ Entity간 전환하는 걸 mapper라고 함
- DTO, Entity 를 매핑해서 변환하는 이유
- 계층별 관심사의 분리(DTO : 데이터를 주고받음, Entity : 데이터 조작)
- 코드구성 단순화(유효성 검사 등)
- REST API 스펙의 독립성 확보 : 데이터 엑세스 계층에서 전달받은 데이터(패스워드) 등이 클라이언트에게 전송되면 안됨 → 원하는 정보만 제공
- 들어오는 req 데이터와 서비스 로직에서 처리하는 데이터를 완전 분리하여, 개발자가 의도치 않은 상황에 데이터가 변조될 우려를 원천 차단하기 위함.
- 구현방법
- mapper class 직접 구현
- MapStruct : spring mapping 라이브러리 사용
- DTO, Entity 를 매핑해서 변환하는 이유
@RestController
@RequestMapping("/v2/members")
@Validated
public class MemberController {
// (1) Controller - Serivice 의존관계 생성
private final MemberService memberService;
private final MemberMapper mapper; // maberMapper DI
public MemberController(MemberService memberService, MemberMapper mapper) {
// this.memberService = new MemberService(); // new를 통한 의존관계 생성
this.memberService = memberService; // Spring DI (생성자 주입)
this.mapper = mapper;
}
@PostMapping
public ResponseEntity postMember(@Valid @RequestBody MemberPostDto memberDto) {
// (2) DTO -> Entity 변환 (서비스레이어 처리용)
// Member member = new Member(); // 객체 생성해서 직접 하나씩 넣기
// member.setEmail(memberDto.getEmail());
Member member = mapper.memberPostDtoToMember(memberDto); // 매퍼를 이용
Member response = memberService.createMember(member);
// (3) Entity -> DTO 변환 (응답용)
// return new ResponseEntity<>(response, HttpStatus.CREATED);
return new ResponseEntity<>(mapper.memberToMemberResponseDto(response),
HttpStatus.CREATED); //매퍼 이용
}
}
<MapStruct>
1. 의존 라이브러리 설정(build.gradle)
dependencies {
...
implementation 'org.mapstruct:mapstruct:1.4.2.Final'
annotationProcessor 'org.mapstruct:mapstruct-processor:1.4.2.Final'
}
2. (MapStruct)기반 Mapper 인터페이스 정의
[Gradle] 탭 [프로젝트 명 > Tasks 디렉토리 > build 디렉토리 > build task]
→ MapperImpl 클래스를 자동으로 생성해줌
- @Mapper(componentModel="spring") : 매퍼 인터페이스로 정의하고 Spring의 bean으로 등록함
- @Mapping(source = "price", target = "price.value") : 변경할 entity와 dto의 데이터 타입이 불일치 할경우 명시
@Mapper(componentModel="spring")
public interface CoffeeMapper {
//dto -> entity
@Mapping(source = "price", target = "price.value")
public Coffee coffeePostDtotoCoffee(CoffeePostDto coffeePostDto);
@Mapping(source = "price", target = "price.value")
public Coffee coffeePatchDtotoCoffee(CoffeePatchDto coffeePatchDto);
//entity -> dto
@Mapping(source = "price.value", target = "price")
public CoffeeResponseDto coffeeToCoffeeResponseDto(Coffee coffee);
// entitys -> dtos
List<CoffeeResponseDto> coffeesToCoffeeResponseDtos(List<Coffee> coffees);
}
'Coding > Back - Spring Framework' 카테고리의 다른 글
(review) Spring 구성하기 #Day8 (0) | 2023.08.28 |
---|---|
Spring 예외처리 #Day7 (0) | 2023.08.24 |
Spring DTO, Validation #Day5 (0) | 2023.08.22 |
Spring Presentation(API) Layer #Day4 (0) | 2023.08.21 |
Spring MVC (0) | 2023.08.21 |