엔티티는 DB에 직접적으로 매핑되는 클래스이다. 데이터베이스에 실제로 쓰일 필드를 정의하고 엔티티끼리 연관관계를 맺어주는 역할을 한다.
스프링을 처음 다뤄볼 때는 그냥 이 엔티티 클래스로 Request, Response 요청을 다 처리해주었다. 전에 축제 사이트를 개발할 때에도 이렇게 했다.
하지만 나중에 가서 보니 이렇게 엔티티로 처리하는 것은 매우 위험한 방식이며, 무조건 DTO를 사용해야 됐었다.
왜 엔티티 클래스로 처리하지 않고 굳이 귀찮게 DTO를 또 만들어서 처리하는 걸까?
DTO란 Data Transfer Object의 약자이며, 클라이언트의 요청을 담아 전달하거나 서버의 응답을 담아 전달하는 역할을 한다.
엔티티 클래스로 요청, 응답을 처리하면 안되고 이 DTO로 처리해야 한다.
그렇다면 왜 이 DTO를 사용해야 하는 것일까?
엔티티 클래스는 DB와 직접적으로 맞닿아 있는 클래스이다. 때문에 매우 조심히 다루어야 한다.
엔티티 클래스가 요청/응답 객체와 항상 같지 않다.
예를 들어 회원 엔티티 클래스가 있다고 가정해 보자.
@Entity
public class Member {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@Column(unique = true)
private String username;
private String password;
@Column(unique = true)
private String email;
}
@RequestParam
을 사용하면 필드 하나하나 입력 받을 수 있지만 그냥 객체 하나로 요청받는 것이 더 깔끔하다.
이럴 때는 다음과 같은 DTO를 사용해 데이터를 받아야 한다.
@Getter
@Setter
public class MemberRequest {
private String username;
private String password;
}
스프링 시큐리티를 사용하면 데이터를 받을 클래스가 따로 필요 없이 편리하게 처리가 가능하다.
DB에 값을 반영하려면 요청 받은 DTO를 Entity로 변환해 주어야 하고 반대로 응답을 할 때 Entity를 DTO로 변환해 보내야 한다.
그럼 이 단계는 어디서 이루어지는 것이 좋을까?
여러 가지 방식이 있지만 다음 두 가지 방식을 보자.
컨트롤러 계층에서 처리
컨트롤러에서 DTO로 요청받아 Entity로 변환하고 서비스에 넘겨준다.
서비스단에서는 특정 작업을 진행 한 후 다시 컨트롤러에 넘겨준다.
넘겨받은 Entity를 다시 DTO로 변환해 응답한다.
서비스 계층에서 처리
컨트롤러에서 DTO로 요청받아 그대로 서비스에 넘겨준다.
서비스단에서 특정 작업을 진행한 후 다시 DTO로 변환해 컨트롤러로 넘겨준다.
넘겨받은 DTO로 응답한다.