Springboot Dto는 많이 만들어도 될까?
Dto란?
Dto는 Data Transfer Object의 약자입니다. 계층 간 데이터 교환 역할을 합니다. DB에 저장되는 Entity를 감싸 Wrapper라고 생각할 수 있습니다. Entity를 클라이언트단과 연결되는 Controller에 사용할 때 문제점이 있습니다.
1. Entity의 스펙 노출 -> Entity의 모든 값이 외부에 노출 될 수 있습니다.
2. 기능에 따라 요구하는 데이터가 다름 -> signup 기능: 이름, 아이디 등등 , login 기능: 아이디, 패스워드
이러한 문제를 해결하기 위해 Dto를 사용합니다. 예를 보겠습니다.
@RestController
@RequiredArgsConstructor
@Slf4j
public class UserController {
private final UserService userService;
@PostMapping("/signup")
@ResponseStatus(HttpStatus.OK)
public SignUpDto signup(@RequestBody UserDto userDto)throws UserDupulicatedException {
User user = userService.join(userDto);
return new SignUpDto(user.getId(), true);
}
@GetMapping("/duplicate")
@ResponseStatus(HttpStatus.OK)
public DuplicateDto checkEmail(@RequestParam String email) throws UserDupulicatedException {
return new DuplicateDto(userService.checkEmail(email));
}
@PostMapping("/login")
@ResponseStatus(HttpStatus.OK)
public ResponseEntity<String> login(@RequestBody UserDto userDto, HttpServletResponse response) throws UsernameNotFoundException, BadCredentialsException, Throwable {
String accessToken = userService.login(userDto);
response.setHeader("X-AUTH-TOKEN",accessToken);
return new ResponseEntity<String>("ok",HttpStatus.OK);
}
}
- 클라이언트에게 정보를 받는 UserDto가 있습니다.
@Data
@AllArgsConstructor
public class UserDto {
public String email;
public String password;
}
- 클라이언트에게 정보를 주는 SignupDto, DuplicateDto가 있습니다.
@AllArgsConstructor
@Data
public class DuplicateDto {
boolean success;
}
@AllArgsConstructor
@Data
public class SignUpDto {
Long userId;
boolean success;
}
Dto를 활용해서 위에서 언급되는 문제점들을 해결했습니다. 패키지를 한 번 보겠습니다.
데이터의 유형에 따라 Dto를 만드니 패키지가 더러워지는 것을 볼 수 있습니다.
Dto를 활용해서 해결하라며?? -> 맞습니다. 하지만 다른 사람들이 봤을 때 이해하기 쉬운 코드가 좋은 코드라고 생각합니다. 패키지 구성 요소가 많다면 코드를 이해하는데 오랜 시간이 걸릴 수 있습니다. 이 문제를 Inner Class로 해결해보겠습니다.
하나의 Dto Inner Class 활용
UserDto 수정
@Data
@AllArgsConstructor
public class UserDto {
@Data
@AllArgsConstructor
public static class SignupAndLoginDto{
public String email;
public String password;
}
@AllArgsConstructor
@Data
public static class ResponseSignupDto {
Long userId;
boolean success;
}
@AllArgsConstructor
@Data
public static class DuplicateDto {
boolean success;
}
}
- 하나의 클래스 안에 사용되는 목적이 명확한 이름을 가진 inner 클래스로 구성합니다.
Controller 수정
@RestController
@RequiredArgsConstructor
public class UserController {
private final UserService userService;
@PostMapping("/signup")
@ResponseStatus(HttpStatus.OK)
public UserDto.ResponseSignupDto signup(@RequestBody UserDto.SignupAndLoginDto userDto)throws UserDupulicatedException {
User user = userService.join(userDto);
return new UserDto.ResponseSignupDto(user.getId(), true);
}
@GetMapping("/duplicate")
@ResponseStatus(HttpStatus.OK)
public UserDto.DuplicateDto checkEmail(@RequestParam String email) throws UserDupulicatedException {
return new UserDto.DuplicateDto(userService.checkEmail(email));
}
@PostMapping("/login")
@ResponseStatus(HttpStatus.OK)
public ResponseEntity<String> login(@RequestBody UserDto.SignupAndLoginDto userDto, HttpServletResponse response) throws UsernameNotFoundException, BadCredentialsException, Throwable {
String accessToken = userService.login(userDto);
response.setHeader("X-AUTH-TOKEN",accessToken);
return new ResponseEntity<String>("ok",HttpStatus.OK);
}
}
- Dto의 이름은 길어졌지만 더 명확하게 어떤 곳에 사용되는지 알 수 있게됐습니다.
inner 클래스를 사용해서 패키지가 깔끔해졌습니다.
정리
Dto의 사용은 선택이 아닌 필수입니다. 하지만 깔끔한 코드를 작성하기 위해 inner 클래스를 활용하는 방법이 있습니다.
읽여주셔서 감사합니다.
'SpringBoot > 기타' 카테고리의 다른 글
테스트 코드를 위해 실제 코드에 영향이 가도 될까?? (0) | 2022.12.26 |
---|---|
Springboot Test 코드 작성 (2) | 2022.03.18 |
springboot [No Creators, like default construct, exist): cannot deserialize from Object value (no delegate- or property-based Creator.] 오류 (0) | 2022.01.10 |
댓글
이 글 공유하기
다른 글
-
테스트 코드를 위해 실제 코드에 영향이 가도 될까??
테스트 코드를 위해 실제 코드에 영향이 가도 될까??
2022.12.26 -
Springboot Test 코드 작성
Springboot Test 코드 작성
2022.03.18 -
springboot [No Creators, like default construct, exist): cannot deserialize from Object value (no delegate- or property-based Creator.] 오류
springboot [No Creators, like default construct, exist): cannot deserialize from Object value (no delegate- or property-based Creator.] 오류
2022.01.10