서론
엔티티를 Dto로 리턴해야 하는 이유는 무엇일까?
하나의 엔티티에서 여러 개의 Dto를 만들면 이름 짓기도 애매해지고 Dto가 여러 개여서 유지보수도 힘들어 보일 수 있다.
하지만 왜 Dto를 만들어서 코드를 작성하는 것이 더 좋은 것일까? 에 대해
이번 포스팅에서 그 이유를 정리해 보도록 하자.
Entity
우선 Entity를 자세히 모르는 분은 JPA 도메인 설계, 엔티티에 관한 포스팅을 읽어보는 것을 추천드린다.
https://cobi-98.tistory.com/57
Entity 클래스는 데이터베이스의 테이블을 대표하는 클래스이며, 비즈니스 로직에 대한 처리를 포함하고 있을 수도 있다.
Entity 클래스를 그대로 리턴하거나 사용하는 것은 다음과 같은 문제점을 유발할 수 있으며, 이를 위해
비즈니스 로직을 처리하지 않고, 오로지 데이터 전송을 목적으로 하는 Dto 클래스를 사용하여 리턴하는 이유(장점)를 알아보자.
1. 불필요한 데이터 노출 ➡ 엔티티 내부 구현을 캡슐화
엔티티는 실제 DB의 테이블과 매칭되는 클래스이다.
그렇기 때문에 getter와 setter를 갖게 된다면, controller와 같은 비즈니스 로직과 크게 상관없는 곳에서 자원의 속성이 실수로라도 변경될 수 있다.
또한 엔티티를 UI계층에 노출하는 것은 테이블 설계를 화면에 공개하는 것이나 다름없기 때문에 보안상으로도 바람직하지 못한 구조가 된다.
따라서 엔티티의 내부 구현을 캡슐화하고 UI계층에 노출시키지 않아야 하는 것은 충분히 데이터 전달 역할로 Dto를 사용해야 할 이유로 볼 수 있다.
2. API 변경에 대한 유연성 부족 ➡ 화면에 필요한 데이터를 선별
Entity 클래스는 데이터베이스와 밀접한 관계가 있기 때문에, API 응답 형식 변경에 따라서 Entity 클래스를 수정하는 것은 매우 위험한 일이다. 또한 화면도 다양해지고, API 스펙도 더 많아질 것이다.
이때 요청과 응답으로 엔티티를 사용한다면, 요청하는 화면에 필요하지 않은 속성까지도 함께 보내지게 된다.
특히 같은 필드인데, 어떤 경우에는 null이고 어떤 경우에는 값이 있고 이렇게 모호하면 정말 유지보수가 어려워진다.
예를 들어 단순히 사용자의 이름만 보여주면 되는 상황에서 필요 이상으로 사용자가 가지고 있는 다른 속성들까지 항상 데이터 전송에 참여하게 되는 것이다.
이처럼 모든 API 요청과 응답에서 엔티티의 모든 속성이 함께 전송되기 때문에 당연히 속도도 느려질 수밖에 없다.
3. 데이터 변환 오류 ➡ 순환참조를 예방
Entity 클래스와 Dto 클래스가 1:1 매핑되는 경우, Entity 클래스를 그대로 사용하면 데이터 변환 오류가 발생할 수 있다.
예를 들어, Entity 클래스의 필드 이름과 Dto 클래스의 필드 이름이 다르면, 데이터 변환 시 필드 이름을 일일이 매핑해주어야 하므로 실수의 가능성이 있다.
JPA Entity로 개발을 할 때 양방향 참조를 사용했다면 순환참조를 조심해야 한다.
이 때, 양방향 참조된 엔티티를 컨트롤러에서 응답으로 return 하게 되면, 엔티티가 참조하고 있는 객체는 지연 로딩되고, 로딩된 객체는 또다시 본인이 참조하고 있는 객체를 호출하게 된다.
이렇게 서로 참조하는 객체를 계속 호출하면서 결국 무한 루프에 빠지게 되는 문제를 낳게 된다.
물론 이 순환참조의 근본적인 원인은 양방향 매핑 자체에 있다고도 할 수 있지만, 양방향 참조가 부득이한 상황이라면 순환참조가 일어나지 않도록 응답의 return으로 Dto로 두는 것이 더 안전하다고 할 수 있다.
결론
이와같이 Entity 클래스를 Dto 클래스로 변환하는 것이 API 응답 형식으로 사용하는 것이 좋고,
Dto 클래스는 필요한 필드만을 가지고 있으므로, 불필요한 데이터 노출이 없다.
또한, API 응답 형식 변경에 따른 수정도 용이하며, 데이터 변환 오류도 방지할 수 있다.
실무에서 API를 설계할 때는 생각보다 더 복잡한 구조로 되어있을 수 있다.
중요한 것은 Dto 클래스를 적절한 단위로 나누고 api를 구별해서 만드는 것이다.
여기서 Dto를 모든 API마다 구별해서 만들다 보면 너무 많은 Dto가 생겨서 관리하기 어렵다고 하기도 한다.
하지만 클래스를 여러개 만들더라도 결국 명확한 것이 훨씬 더 나은 설계일 수도 있다는 생각을 한다.
'Back-End > Spring' 카테고리의 다른 글
[JPA] QueryDSL을 RepositoryImpl로 관리해보자. (0) | 2023.08.05 |
---|---|
[MVC] DTO 역할 구분, 프로젝트 흐름도 분석 (0) | 2023.05.09 |
[JPA] 도메인 설계, 엔티티 매핑 (0) | 2023.04.19 |
[JPA] JPA를 사용하는 이유와 JPA에 대하여 (0) | 2023.04.18 |
[Spring] 테스트 코드 작성, Mock (0) | 2023.04.17 |