spring boot/dto

dto(Data Transfer Object)를 사용하는 이유

junjunjun 2022. 11. 3. 15:02
반응형
해당 블로그는 초보 개발 지망생의 글로 정확하지 않을 수 있습니다. 

 

dto(Data Transfer Object)

계층 간 데이터 교환을 위한 객체라고 한다.

이렇게만 듣고 이해가 된다면 참 좋을 텐데... 

이런 그림으로 많이 설명한다.

 

나는 여태까지 DTO의 존재를 모르는 상태로 프로젝트를 진행했고, 딱히 dto의 필요성을 느끼지 못하였다.

그러다가 코드 리뷰를 하게 되면서 개인적으로 잘한다고 생각하는 분들이 공통적으로 dto를 사용한다는 것을 알게 되었고 나도 따라 쓰기로 결정하였다.

 

그저 dto클래스만 생성해주면 된다고 생각하였지만 그밖에 신경 써줘야 되는 부분이 많았다. 이때부터 굳이? 왜 만들어줘야 되는 거지... dto를 만들고 코드의 양은 더 늘었고 뭔가 의존성 관계도 뒤죽박죽 된 기분이었다.

 

역시 무작정 따라 하는 건 좋지 않다고 생각하여 왜 써야 되는지 이유를 찾아보게 되었다.

 

1. 다양한 비즈니스 로직과 요구사항에 유연하게 대응할 수 있다.

/* 어노테이션 생략*/
@Entity
class Member {
	private int id
	private String username; // 아이디
	private String password;
	private String email;
	private String name;
	private int age;	
	private String address;
	private String dateOfBirth // 생년월일
}

member 엔티티

 

상황 1. view 단에서 유저 아이디와 이메일 값만 필요한 경우 (dto가 없다면)

 

  • Member엔티티 자체를 view에 전달하게 될 경우, 필요하지 않은 필드까지 전달되기 때문에 데이터 낭비가 있을 수 있다.
  • password와 같은 민감한 정보를 가진 필드도 전달되기 때문에 보안에 문제가 생길 수 있다.
/* 어노테이션 생략*/
class MemberDto {
	private String username; // 아이디
	private String email;
}
// 필요한 필드만 넣어줄 수 있다.

 

상황 2. Member 엔티티에서 age 필드가 삭제된 경우

            더 이상 db에서는 age가 필요 없고 생년월일을 이용하여 동적으로 age를 구한다.

 

  • dto를 사용하지 않았을 경우 Member.age와 관련된 로직을 모두 수정해줘야 한다.
  • dto를 사용한 경우 dateOfBirth 필드를 가공시켜 age를 구해주는 로직만 추가해주면 된다.
/* 어노테이션 생략*/
class MemberDto {
	private int id
	private String username; // 아이디
	private String email;
	private String name;
	private int age;	
	private String address;
	private String dateOfBirth // 생년월일
	
	public MemberDto from(Member member) {
		this.username = member.username;
		this.age = (가공 member.dateOfBirth) // 여기만 수정시켜주면 된다.
        
        	... 생략
	}
}

 

2. dto를 사용하면 순환 참조를 막아준다. [rest api]

jpa에서 발생하는 순환 참조는 양방향으로 연결된 두 개의 엔티티가 서로를 무한으로 참조하면서 발생하는 문제를 말한다.

 

양방향 연결이 순환 참조의 원인이지만 실제로 순환 참조가 발생하는 부분은 controller 단에서 객체를 리턴해주는 부분이다.

이때 Jackson 라이브러리에 의해 객체가 JSON 형태로 변화되며 이 과정에서 엔티티의 getter가 양방향으로 연결된 엔티티를 계속해서 참조하게 되면서 발생한다.

https://dev-coco.tistory.com/133

 

순환 참조를 해결하는 방법은 다양하지만 그중 하나가 dto를 사용하는 것이다.

순환 참조가 일어나지 않도록, 필요로 하는 엔티티의 필드만 담은 dto를 return 해주면 된다.

 

 

3. 유효성 검사 분리

클라이언트로부터 들어오는 form 데이터의 유효성 체크를 위해 요청에 맞는 dto를 생성해서 사용해준다. 

유효성 검사를 위해 존재하는 dto의 경우 클래스명 뒤에 form을 붙인다.

@Data
public class MemberBeAuthorForm {
    @NotBlank(message = "작가명을 입력해주세요.")
    private String nickname;
}

유효성 검사만을 위한 클래스로 엔티티와 분리시켜 사용할 수 있다.

유효성만을 다루기 때문에 가독성에 좋고 유지 보수하기 좋다.

 

4. 엔티티 캡슐화

엔티티는 비즈니즈의 핵심 부분이며 데이터베이스와도 연결되어 있는 중요한 역할을 가진 클래스이다.

 

만약 비즈니스 로직과 거리가 먼 controller에서 부분별 하게 엔티티 사용할 경우 엔티티의 일관성이 깨지는 문제가 발생할 수 있다.

 

 

결론

이 밖에도 다양한 이점이 존재하였지만, 현재 나의 레벨로는 이해하기 힘들었다.

 

이렇게 다양한 장점이 존재하지만 dto도 결국에는 프로그래밍 패턴의 일종으로 dto를 사용하지 않고도 딱히 문제가 발생하지 않았다면 굳이 사용하지 않아도 된다.

많은 글에서도 dto는 선택사항으로 필요할 경우 사용할 것을 권장한다.

 

dto를 적용하는 방법과 적용한 다음 생각해봐야 될 문제점

"의존성" , "매핑", "dto범위"

에 대해서는 다음 글에서 작성할 예정이다.

 

참고 자료
https://studyandwrite.tistory.com/402
https://velog.io/@aidenshin/DTO%EC%97%90-%EA%B4%80%ED%95%9C-%EA%B3%A0%EC%B0%B0
https://wildeveloperetrain.tistory.com/101
https://softwareengineering.stackexchange.com/questions/373284/what-is-the-use-of-dto-instead-of-entity
https://tecoble.techcourse.co.kr/post/2020-08-31-dto-vs-entity/

 

반응형