3.2 DTO와 Mapper

yeonseong Jo·2023년 6월 13일
0

SEB_BE_45

목록 보기
33/47
post-thumbnail

Controller를 자세히 배우기 이전에
나는 오늘 알게 된 DTO나 Mapper 빼고는

(django에서 model이나 dto,
serializer가 mapper라 생각하기 때문에..)

모든 구현 사항을 Controller에 다 구현했었다.
그래서 내 django 프로젝트를 보면
모든 기능별로 views.py가 엄청 길다..


DTO

DTO는
Data Transfer Object로
직역하자면 데이터 전송 객체이다.

DTO 적용

@RestController
@RequestMapping("/test")
class Controller{
	@PostMapping
    public ResponseEntity post(@RequestParam("email") String email,
    						   @RequestParam("name") String name
                               ...
}

DTO 적용 이전

@RestController
@RequestMapping("/test")
class Controller{
	@PostMapping
    public ResponseEntity post(@RequestBody PostDto postDto)
                               ...
}

DTO 적용 이후

DTO를 통하면
파라미터들을 RequestParam annotation없이
DTO 객체 하나에 다 전달되기 때문에
코드가 간결해지고 유지보수성이 늘어난다.

Validator

import javax.validation.constraints.*;

class PostDto {
	@Email
	private String email;
    @NotBlank
    private String name;
    @Pattern("^010-\\d{4}-\\d{4}$")
    private String phone;
    ...
    // getter / setter
}

또한,
DTO에서 검증절차를 적용시켜
전달받은 데이터에 유효성 검사를 할 수 있다.

Custom Validator

javax라이브러리에 있는 validator 외에도
직접 validator를 작성할 수 있다.

@Target(ElementType.Field)
@Retention(RetentionPolicyt.Runtime)
@Contstraint(validatedBy = {CustomValidator.class})
public @interface CustomValid {
	String message() default "오류 메세지";
    Class<?>[] groups() default {};
    Class<? extends Payload>[] payload() default {};
    boolean value() default false;
}

위와 같이 Custom annotation을 정의하고,

Target

  • custom annotaion이 어디에 선언 할 수 있는지를 의미

Retention

  • 어느 시점 까지 annotaion의 메모리를 가져갈지 설정

Constraint

  • 무슨 validator를 사용할 지 설정

value

  • validator에 파라미터(?)를 전달하기 위해 사용
    validator에서 CustomAnnotation 객체에
    .value()를 통해 가져올 수 있음
public class CustomValidator implements ConstraintValidator<CustomValid, 검사할 필드의 타입> {
	private boolean param;
    
    @Override
    public void initialize(CustomValid constraintAnnotation){
    	// custom annotation을 통해 파라미터를 받음
    	this.param = constraintAnnotation.value();
        ContstraintValidator.super.initialize(constraintAnnotation);
    }
    
    @Override
    public boolean isValid(검사할 필드의 타입 value, ConstraintValidatorContext context){
    	유효성 검사...
    	return 유효성검사 결과;
    }
}

validator class를 구현하면 된다.


Mapper

Controller에서 mapper는 DTO와 Entity를
상호 변환 해주는 역할을 한다.

Mapper Object

public class Mapper{
	public Entity postDtoToEntity(PostDto postDto){
    	...
        return entity
    }
    public Entity patchDtoToEntity...
    
    ...
    
    public ResponseDto entityToResponseDto(Entity entity){
    	...
        return responseDto;
    }
}

그냥 클래식하게
하나의 클래스에서 여러 메서드로
각 DTO를 Entity로 바꾸는 방법도 있고,

MapStruct

import org.mapstruct.Mapper;

@Mapper(compoentModel="spring")
public interface Mapper{
	Entity PostDtoToEntity(PostDto postDto);
    ...
    ResponseDto entityToResponseDto(Entity entity);
}

mapstruct 라이브러리를 추가하여
mapper 구현 크랠스를 자동으로 생성해줄 수도 있다.

Mapper annotation

  • componentModel에 "spring"을 넣어 Bean으로 등록된다

Gradle에서 build를 하면, Mapperlmpl 클래스가 생성된다.

적용

Controller의 생성자에서
Mapper객체를 Service객체와 함께 주입받고,
Mapper의 각 기능을 HTTP 메서드에 맞게 호출하여 사용하면 된다.

profile
뒤(back)끝(end)있는 개발자

0개의 댓글