주제
Http method 중 PUT 과 PATCH 의 차이가 뭘까
Http method 중 자원의 수정을 의미하는 메서드로는 PUT 과 PATCH 가 있다. 한 개만 있어도 될 것 같은데 왜 2개지?? 하는 의문으로 알아보았다.
RFC 문서를 직접 찾아봤다.
PUT은 자원을 대체(replace) 한다. 즉, 없으면 생성하고 있으면 기존 값을 버리고 요청값으로 바꾼다.
(튜터님은 보통 프로젝트에선 성공 응답은 전부 200 OK 로 통일한다고 하고, 나도 이 방법이 더 좋다고 생각하지만 일단의 표준은)
PUT 요청시 자원이 없다면 POST와 같이 새로 생성 후, 201 Created 를 응답한다.
자원이 있다면, 기존 자원을 대체 후 200 OK 나 204 NO CONTENT 를 응답한다.
PUT 메서드를 사용하는 클라이언트는 (자원을 전부 대체해버리므로) 해당 자원의 상태를 모두 알고 있다고 가정되어야 한다. 그렇지 않고 빼먹은 상태가 있다면 그 값은 null로 대체가 되어 버린다.
PATCH는 자원을 부분적 수정(partial modifications)한다. 기존 값을 두고 새로운 요청 값만 바꾼다.
멱등성 (Idempotent)
같은 연산을 여러번 실행한다고 해도 그 결과가 달라지지 않는 성질을 의미한다.
f(f(x)) = f(x)
PUT은 자원을 완전히 대체해버리기 때문에, 일단 한번 요청이 되면 그 뒤로 몇 번이고 같은 요청을 해도 동일한 결과를 가진다.
하지만 PATCH는 부분적인 수정을 하므로, 멱등성을 항상 보장한다고 볼 순 없다. 이 부분 이라는게 애매해서, 설계에 따라 완전히 대체 버릴 수도, 아니면 정말 부분만 수정할 수도 있기 때문이다.
프로젝트 활용
이번에 진행했던 스프링 개인 프로젝트로 익명 게시판 만들기가 있었는데, 게시글 수정에 나는 PATCH 가 쓰였다.
/**
* 게시글 엔티티.
*/
@Getter
@Entity
@Table(name = "post") // 테이블명을 명시적으로 알림
@NoArgsConstructor(access = AccessLevel.PROTECTED) // JPA는 기본 생성자를 필요하므로 최소의 접근제어자로 생성
public class Post extends BaseEntity {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@Column(nullable = false, length = 30) // 제목은 1이상 30 글자 이하
private String title;
@Column(nullable = false, length = 20) // 작성자명은 2이상 20 글자 이하
private String author;
@Column(nullable = false, length = 128) // 비밀번호는 4이상 50이하 이나, 암호화로 128자 까지 저장
private String password;
@Column(nullable = false, columnDefinition = "text") // 글내용은 1이상 65,535 byte 이하
private String contents;
private Post(String title, String author, String password, String contents) { // private 로 선언
this.title = title;
this.author = author;
this.password = password;
this.contents = contents;
}
public static Post create(PostCreateRequestDto request) { // 특정 DTO로 생성을 제한함
return new Post(request.getTitle(), request.getAuthor(), request.getPassword(), request.getContents());
}
public void edit(PostEditRequestDto request) { // 특정 DTO로 수정을 제한함
this.title = request.getTitle();
this.author = request.getAuthor();
this.contents = request.getContents();
}
}
일단 게시글 엔티티는 다음과 같다. 필드로는 id, 제목, 작성자, 비밀번호, 글내용이 있다.
/**
* 게시글 수정
* @param postId URL로부터 게시글 id 받아옴
* @param request JSON 으로 수정 정보를 받아오며 검증되지 않으면 예외 발생
* @param password 보안상 중요한 비밀번호는 Header 에 담아서 받아옴
* @return 수정된 게시글 세부 정보를 반환함.
*/
@PatchMapping("/{postId}")
public ResponseEntity<PostDetailResponseDto> editPost(
@PathVariable Long postId,
@Valid @RequestBody PostEditRequestDto request,
@RequestHeader String password) {
PostDetailResponseDto editedPostDetail = postService.editPost(postId, request, password);
return ResponseEntity.ok(editedPostDetail);
}
/**
* 게시글 수정 요청 DTO
*/
@Getter
public class PostEditRequestDto {
@NotBlank
@Length(min = 1, max = 30)
private String title;
@NotBlank
@Length(min = 2, max = 20)
private String author;
@NotBlank
private String contents;
}
그리고 게시글을 수정하는 컨트롤러 메서드와 수정 요청 DTO는 위와 같다.
수정 요청 Http Method 는 Patch로 정했는데, 우선 요구사항이 DTO에 나온 대로 제목, 작성자명, 글내용 3개로 제한되었기 때문이다. 만약 PUT으로 했더라면 게시글id와 비밀번호는 null 값이 되어버려야 한다.
'TIL ✍️' 카테고리의 다른 글
23년 11월 9일(목요일) - 29번째 TIL (0) | 2023.11.09 |
---|---|
23년 11월 8일(수요일) - 28번째 TIL (0) | 2023.11.08 |
23년 11월 6일(월요일) - 26번째 TIL (0) | 2023.11.06 |
23년 11월 3일(금요일) - 25번째 TIL (0) | 2023.11.03 |
23년 11월 2일(목요일) - 24번째 TIL (0) | 2023.11.02 |