개발자
백엔드를 공부중인 학생입니다. 최근 NEST와 SPRING으로 공부중입니다. DB에서 데이터를 받아올때 프런트엔드에 전송하는데 테이블에 있는 모든 데이터를 보내는 것이 아닌 특정 속성만 뽑아서 보내주기 위해 DTO를 사용하고 있습니다. 이때 하나의 API당 하나의 DTO를 만드는게 일반적인가요? 연관관계가 성립된 Entity는 어떻게 Entity에 변환하는지도 궁금합니다. dto.dto_id = entity.entity_id 이런식으로 변환을 하나요? 아니면 다른 방법이 있나요? 현업에서는 어떻게 하는지 궁금합니다. 감사합니다!
답변 1
인기 답변
1. @Entity 클래스를 특정 DTO 등으로 매핑하는 것은 말씀하신대로 변환을 하면 됩니다. 멤버 필드의 변수명은 의미에 맞게 변환하셔도 되고요. 해당 변환을 처리하는 메서드를 빌더 패턴 등을 활용하여 @Entity 클래스에 포함시키는 방식으로 처리할 수 있어요. (참조 코드를 하단에 작성했어요.) 2. 아키텍쳐의 구성에 따라 다를 수가 있지만 하나의 DTO만 생성해서 로직을 처리하기는 어려울 것 같아요. DTO의 갯 수라는 접근은 저의 경우에 결국 DDD building block으로 연결되는 고민이었던 것 같은데요. 일단 질문자 분의 가정을 따라가 봅시다. 하나의 API 요청에 대한 DTO가 하나라고 해보죠. 통상적인 레이어드 아키텍쳐임임을 가정할 때 그 DTO가 하는 역할은 이하 정도가 있을 것 같습니다. - 클라이언트의 요청을 역직렬화 후 클래스로 매핑 - 클래스로 매핑된 DTO가 @Controller의 로직을 추가적으로 처리(인증 정보, 요청 정보)하고 @Service를 호출 - @Service 로 넘겨진 DTO가 비즈니스 로직을 처리하고 @Repository를 호출 - @Repository로 넘겨진 DTO가 DB I/O를 수행하고 결과물이 새로운 DTO로 생성됨(JPA의 경우 Entity로 매핑) - 이 후 후처리되는 로직을 통해 DTO의 필드가 추가적으로 수정 여지가 생김 - 최종적으로 직렬화되어 응답 값으로 변환 하나의 DTO가 이것들을 다 수행하려면 각 단계에서만 필요한 필드 혹은 메서드를 포함하고 있다는 이야기 인데, 이것을 로직을 직접 따라가지 않는 이상 파악하기 어렵죠. 테스트를 만드려는 관점에 있어서도 레이어의 계층에 따라 DTO가 특정 상태를 갖게 끔 만들어야 하기 때문에 추가적인 정보가 많이 필요하게 될 것 같아요. '그래서 그럼 한 개가 아니면 몇 개를 만들어야 하는데?'라는 생각이 드실 수 있을 것 같은데, 이 부분은 설계 상 선택의 문제가 됩니다. API가 많은 로직에 얽혀 있다면 그만큼 세세한 구분이 있어야 후에 수정에 용이하게 될 것이고, 아주 간단한 로직만 수행하고 수정도 예상되지 않는데 계층별로 전환을 전부 처리하게끔 하면 개발이 너무 오래 걸리겠죠. 물론 아무리 단순한 상황에도 JPA의 Entity 클래스 자체를 API 응답으로 던지지는 않을 것 같습니다. 다양한 의견이 있을 수 있는 질문인 것 같으니, 적합한 해결책을 찾으시길 바래요!
1@Entity
2@Table(name = "members")
3public class MemberEntity {
4
5 @Id
6 @GeneratedValue(strategy = GenerationType.IDENTITY)
7 private Long id;
8
9 ... 생략
10
11 public Member toModel() {
12 return Member.builder()
13 .id(id)
14 .email(email)
15 .status(status)
16 .lastLoginAt(lastLoginAt)
17 .build();
18 }
19}
익명
작성자
2024년 02월 07일
답변 너무 감사드립니다. 확실히 서비스가 어떻게 되는지에 따라 답이 달라졌을거 같습니다. 공통되는 DTO를 만들어서 다양한 로직에 활용하고 싶었는데 그렇게 쉽게 되지 않네요 한개의 로직을 만들때마다 그에 해당하는 DTO를 만들고 있기 때문에 너무 비효율적인 방식인가? 고민하고 있었습니다. 좀 더 공부해보겠습니다. 감사합니다
지금 가입하면 모든 질문의 답변을 볼 수 있어요!
현직자들의 명쾌한 답변을 얻을 수 있어요.
이미 회원이신가요?
커리어리 AI 봇
GPT가 달아주는 답변입니다.
2024년 02월 05일
일반적으로 하나의 API에 대해 하나의 DTO를 만드는 것은 아닙니다. DTO는 'Data Transfer Object'로, 계층간 데이터 교환을 위한 객체입니다. 그러므로 어떤 특정 API에 종속되기 보다는 데이터 구조와 사용처에 따라 설계됩니다. 예를 들면, 회원가입과 회원정보 수정 API가 있을 때 두 API 모두 사용자 이름, 이메일 등 비슷한 정보를 받아야 한다면 같은 DTO를 사용할 수 있습니다. 하지만 만약 회원 가입시에 비밀번호 확인 필드가 필요하고, 사용자 정보 수정시에는 필요하지 않다면 두 개의 다른 DTOs를 생성할 수도 있습니다. 연관관계가 성립된 Entity 변환을 위해서는 여러 방법이 있습니다. 1) 직접 setter 혹은 builder 패턴을 이용하여 변환하는 방법 2) ModelMapper 라이브러리 활용: 이 라이브러리는 자동으로 도메인 모델 및 DTO간에 매핑을 해줍니다. 그러나 중첩된 속성들은 이상하게 작동하기 때문에 주의해야 합니다. 3) MapStruct 라이브러리 활용: 이것도 ModelMapper와 유사하지만 컴파일 시점에서 매핑 코드를 생성해 성능이 더 좋습니다. 현업에서는 상황에 따라 다르게 사용합니다. 복잡도, 성능 요구사항 등을 고려하여 가장 적합한 방법을 선택합니다.
지금 가입하면 모든 질문의 답변을 볼 수 있어요!