프로젝트/개인

여러 개의 DTO, 여러 개의 @RequestBody

menuhwang 2022. 9. 24. 11:43

여러 개의 DTO, 여러 개의 @RequestBody를 사용할 수 없을까?


 프로젝트 진행 중 한 번의 클라이언트 요청으로 유저 정보와 프로필 정보를 받아와 유저 서비스, 프로필 서비스 각각 DTO를 넘겨 처리하고 싶었다.

 

 그래서 단순하게 @RequestBody DTO를 컨트롤러 파라미터에 추가해보았고 역시 생각대로 되지 않았다.

 

 이 질문은 스택오버플로우에도 이미 올라와 있었다. 결론부터 말하자면 두 개 이상의 @RequestBody를 사용하여 값을 받아올 수 없다.

 

Multiple @RequestBody

 

Multiple @RequestBody values in one controller method

I'm receiving error 400 when I send PATCH request to my endpoint that looks like this @RequestMapping(value = "...", method = RequestMethod.PATCH, consumes = "application/json", produc...

stackoverflow.com

 

 

방법


 그럼 어떻게 하면 유저 정보, 프로필 정보 두 개의 DTO를 각각의 서비스로 전달해줄 수 있을까?

 

방법 1

 두 DTO의 필드를 하나로 통합한 DTO를 새로 만들어 사용하는 방법.

 

 기타 어노테이션은 생략하였습니다.

 

MemberRequestDTO.java

public class MemberRequestDTO {
    private String email;
    private String password;
}

 

ProfileRequestDTO.java

public class ProfileRequestDTO {
    private String name;
    private int age;
}

 

SignInDTO.java

public class SignInDTO {
    private String email;
    private String password;
    private String name;
    private int age;
}

 

 이 방법을 사용하면 단순히 필요한 필드를 넣어주면 된다. 하지만 필드가 많아지거나 Member, Profile DTO에 변동이 생겼을 때 따로 수정해줘야 하는 유지보수 측면에서의 문제가 있다.

 

 또한 SignInDTO에서 Member, Profile 정보를 각각의 DTO로 나눠주는 과정이 필요하다.

 

 

방법 2

 하나의 DTO안에 두 개의 DTO를 필드로 받는 방법.

 

MemberRequestDTO.java

public class MemberRequestDTO {
    private String email;
    private String password;
}

 

ProfileRequestDTO.java

public class ProfileRequestDTO {
    private String name;
    private int age;
}

 

SignInDTO.java

public class SignInDTO {
    private MemberRequestDTO member;
    private ProfileRequestDTO profile;
}

 

 방법 1과 다르게 각각의 DTO를 수정했을 때 따로 SignInDTO를 수정해 줄 필요가 없다. 큰 문제는 아니지만 json(body, form) 작성에 주의할 필요가 있다.

 

방법 1 Request Body

{
    "email" : "email@email.com",
    "password" : "passw0rd",
    "name" : "menu",
    "age" : 5
}

 

방법 2 Request Body

{
    "member" : {
                   "email" : "email@email.com",
                   "password" : "passw0rd",
               },
    "profile" : {
                    "name" : "menu",
                    "age" : 5
                }
}

 

나는 유지보수의 장점이 있는 방법 2를 적용하기로 했다.