Coding/Back - Spring Framework

Spring Business(Service) Layer #Day6

꿀딴지- 2023. 8. 23. 18:09

Spring MVC의 Layered Architecture

  1. API(Presentation) Layer @Controller : DTO 사용
    • 전달받은 요청 데이터를 Service 클래스로 전달하고, 응답 데이터를 클라이언트로 다시 전송해 주는 단순한 역할
  2. Business(Service) Layer @Service : Entity 사용
    • 도메인 업무 영역을 구현하는 비즈니스 로직 구현영역
    • Entity : 서비스 계층에서 데이터 엑세스 계층과 연동하면서 비즈니스 로직을 처리하기 위해 필요한 데이터를 담는 역할 (controller의 dto와 동일)
  3. Persistance(Data access) Layer @Repository : Entity 사용

 

API Layer ↔ Business Layer 연동

  1. 객체 간 의존관계 생성:
    • Controller에서 new Service를 해서 객체를 생성할 수도 있지만, Spring DI(Loose Coupling) 생성자 주입 기능을 활용하여 연결 @Service @Component
  2. 데이터 전환 : DTO ↔ Entity간 전환하는 걸 mapper라고 함
    • DTO, Entity 를 매핑해서 변환하는 이유
      • 계층별 관심사의 분리(DTO : 데이터를 주고받음, Entity : 데이터 조작)
      • 코드구성 단순화(유효성 검사 등)
      • REST API 스펙의 독립성 확보 : 데이터 엑세스 계층에서 전달받은 데이터(패스워드) 등이 클라이언트에게 전송되면 안됨 → 원하는 정보만 제공
      • 들어오는 req 데이터와 서비스 로직에서 처리하는 데이터를 완전 분리하여, 개발자가 의도치 않은 상황에 데이터가 변조될 우려를 원천 차단하기 위함.
    • 구현방법
      • mapper class 직접 구현
      • MapStruct : spring mapping 라이브러리 사용
@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