슬기로운 개발생활

DTO Inner Class로 한번에 관리하기

by coco3o
반응형

필자의 프로젝트엔 다음과 같이 패키지 안에 각 모듈별 패키지와 request, response dto 클래스들이 있다.

 

위 DTO 클래스들을 간결한 코드로 만들며 개선한 내용을 정리해보겠다.


DTO를 Inner Static Class로 관리

DTO 패키지 내 클래스 파일들을 깔끔하게 관리하기 위해 Inner Class(Nested Class)로 DTO를 관리하는 것이다.

 

/**
* request, response DTO 클래스를 하나로 묶어 InnerStaticClass로 한 번에 관리
*/
public class PostsDto {
@Data
@AllArgsConstructor
@NoArgsConstructor
@Builder
public static class Request {
private Long id;
private String title;
private String writer;
private String content;
private String createdDate, modifiedDate;
private int view;
private User user;
/* Dto -> Entity */
public Posts toEntity() {
Posts posts = Posts.builder()
.id(id)
.title(title)
.writer(writer)
.content(content)
.view(0)
.user(user)
.build();
return posts;
}
}
@Getter
public static class Response {
private Long id;
private String title;
private String writer;
private String content;
private String createdDate, modifiedDate;
private int view;
private Long userId;
private List<CommentDto.Response> comments;
/* Entity -> Dto*/
public Response(Posts posts) {
this.id = posts.getId();
this.title = posts.getTitle();
this.writer = posts.getWriter();
this.content = posts.getContent();
this.createdDate = posts.getCreatedDate();
this.modifiedDate = posts.getModifiedDate();
this.view = posts.getView();
this.userId = posts.getUser().getId();
this.comments = posts.getComments().stream().map(CommentDto.Response::new).collect(Collectors.toList());
}
}
}

 

 

Controller

@RequiredArgsConstructor
@RequestMapping("/api")
@RestController
public class PostsApiController {
private final PostsService postsService;
/* CREATE */
@PostMapping("/posts")
public ResponseEntity save(@RequestBody PostsDto.Request dto, @LoginUser UserDto.Response user) {
return ResponseEntity.ok(postsService.save(dto, user.getNickname()));
}
/* READ */
@GetMapping("/posts/{id}")
public ResponseEntity read(@PathVariable Long id) {
return ResponseEntity.ok(postsService.findById(id));
}
/* UPDATE */
@PutMapping("/posts/{id}")
public ResponseEntity update(@PathVariable Long id, @RequestBody PostsDto.Request dto) {
postsService.update(id, dto);
return ResponseEntity.ok(id);
}
/* DELETE */
@DeleteMapping("/posts/{id}")
public ResponseEntity delete(@PathVariable Long id) {
postsService.delete(id);
return ResponseEntity.ok(id);
}
}

 

Service

@RequiredArgsConstructor
@Service
public class PostsService {
private final PostsRepository postsRepository;
private final UserRepository userRepository;
@Transactional
public Long save(PostsDto.Request dto, String nickname) {
User user = userRepository.findByNickname(nickname);
dto.setUser(user);
Posts posts = dto.toEntity();
postsRepository.save(posts);
return posts.getId();
}
@Transactional(readOnly = true)
public PostsDto.Response findById(Long id) {
Posts posts = postsRepository.findById(id).orElseThrow(() ->
new IllegalArgumentException("해당 게시글이 존재하지 않습니다. id: " + id));
return new PostsDto.Response(posts);
}
@Transactional
public void update(Long id, PostsDto.Request dto) {
Posts posts = postsRepository.findById(id).orElseThrow(() ->
new IllegalArgumentException("해당 게시글이 존재하지 않습니다. id: " + id));
posts.update(dto.getTitle(), dto.getContent());
}
@Transactional
public void delete(Long id) {
Posts posts = postsRepository.findById(id).orElseThrow(() ->
new IllegalArgumentException("해당 게시글이 존재하지 않습니다. id: " + id));
postsRepository.delete(posts);
}
...
}

이렇게 1개의 Class 파일로 DTO를 Inner Class로 관리하면 조금 더 깔끔하게 패키지를 관리할 수 있고,

코드의 캡슐화를 증가시키며, 코드의 복잡성도 줄일 수 있다는 장점이 생긴다.

반응형
블로그의 프로필 사진

블로그의 정보

슬기로운 개발생활

coco3o

활동하기