호돌맨의 요절복통 개발쇼 (SpringBoot, Vue.JS, AWS) 를 보며 학습한 내용을 정리하기 위해서 포스팅을 진행합니다. 이번 포스팅에서는 CRUD에서 수정을 의미하는 UPDATE 기능에 대해 서술해보도록 하겠습니다.
첫번째 안좋은 예시
// Post.java
@Setter
...
public class Post {
private String title;
private String content;
}
// PostService.java
public void Edit(Long id, PostEdit postEdit){
Post post = postRepository.findById(id)
.orElseThrow(() -> new IllegalArgumentStatement("존재하지 않는 아이디"));
post.setTitle(postEdit.getTitle());
post.setContent(postEdit.getContent());
...
}
Post
도메인 클래스에 @Setter 어노테이션을 추가하여 Setter 메소드를 통해 내용을 수정하는 코드입니다.
개발에서 @Setter를 사용하는 것을 지양하는데 이유는 다음과 같습니다.
쉽게 설명하자면 악의적인 사용자가 Setter 메소드를 이용해 자신이 원하는 값으로 데이터를 수정할 수 있으며 이는 굉장히 큰 문제를 야기할 수 있습니다. 따라서 위와 같은 코드를 사용해서는 안됩니다.
두번째 안좋은 예시
// Post.java
public class Post {
...
public void change(String title, String content) {
this.title = title;
this.content = content;
}
}
// PostService.java
public void Edit(Long id, PostEdit postEdit){
Post post = postRepository.findById(id)
.orElseThrow(() -> new IllegalArgumentStatement("존재하지 않는 아이디"));
post.change(postEdit.getTitle(), postEdit.getContent());
...
}
위 예제에서는 change()
로 넘겨주는 매개변수의 순서가 정해져있습니다. 두 개의 필드라 단순해 보이지만, 만약 10개가 넘는 필드가 있다면 어떨까요? 필드의 순서에 맞춰 값을 넘기다보면 실수가 발생할 수 있습니다. 그리고 해당 실수는 컴파일에 아무런 문제가 없기 때문에 문제를 발견하기 더 힘들어집니다.
좋은 예시
// Post.java
public PostEditor.PostEditorBuilder toEditor() {
return PostEditor.builder()
.title(title)
.content(content);
}
public void edit(PostEditor postEditor){
this.title = postEditor.getTitle();
this.content = postEditor.getContent();
}
// PostEditor.java
public class PostEditor {
private final String title;
private final String content;
@Builder
public PostEditor(String title, String content){
this.title = title;
this.content = content;
}
// PostService.java
...
public void edit(Long id, PostEdit postEdit) {
Post post = postRepository.findById(id)
.orElseThrow(() -> new IllegalArgumentStatement());
PostEditor.PostEditorBuilder editorBuilder = post.toEditor();
PostEditor postEditor = editorBuilder.title(postEdit.getTitle())
.content(postEdit.getContent())
.build();
post.edit(postEditor)
하지만 여전히 문제점이 존재합니다. 예를 들어, 사용자는 title
만 수정하였으므로 프론트 단에서 수정된 title
값만 넘겨주었다고 가정해봅시다. content
에는 null
이 들어갑니다. 따라서 이는 수정할 데이터만 보낼 것인지, 수정할 데이터를 포함한 모든 데이터를 보낼 것인지에 따라 로직이 변경될 수 있습니다.
대처 방안
if(postEdit.getTitle()!= null){
editorBuilder.title(postEdit.getTitle());
}
if(postEdit.getContent()!= null) {
editorBuilder.content(postEdit.getContent());
}
post.edit(editorBuilder.build());
만약 수정된 값만 넘어온다고 가정하면 위와 같이 null
여부를 확인하고 변경된 값에 대해서만 값을 넘겨주면 됩니다.
글 잘 봤습니다, 감사합니다.