231127W
오늘도 Spring Boot와 함께하는 싱나는 코딩중, 수정에 관련된 API를 작성하려던 도중이었다.
수정에 관련해 @Put 과 @Patch 가 있는데, 둘은 같은 듯 비슷한 듯 다른 듯 한 녀석들이라고 들었는데 제대로 이해하진 못한 상태였다.
@Put은 전체수정, @Patch는 부분수정 이라는 정도?
이전까진 수정에 관한 API면 묻고 @Put으로 갔었는데, 이번엔 좀 더 이해를 하고 필요에 맞춰서 써보고 싶었다.
일단 당시의 생각대로 작성해봤던 코드다.
//프로필 수정
@PatchMapping("/profile/{userId}")
public ResponseEntity<UserResponseDto> updateProfile(@PathVariable Long userId,
@RequestBody UserUpdateProfileRequestDto requestDto,
@AuthenticationPrincipal UserDetailsImpl userDetails) {
UserResponseDto userResponseDto = userService.updateProfile(userId, requestDto,
userDetails.getUser());
return ResponseEntity.ok(userResponseDto);
}
//비밀번호 수정
@PutMapping("/password/{userId}")
public ResponseEntity<String> modifyPassword(@PathVariable Long userId,
@Valid @RequestBody UserModifyPasswordRequestDto requestDto,
@AuthenticationPrincipal UserDetailsImpl userDetails) {
userService.modifyPassword(userId, requestDto,
userDetails.getUser());
return ResponseEntity.ok(CommonCode.OK.getMessage());
}
나의 생각은 이러했다.
‘프로필은 일단 작성 해놓으면 나중에 수정하더라도 일부만 바꾸는 경우가 다반사이니 부분수정인 Patch를 이용해야겠지?’
‘그리고 비밀번호 수정은 아무래도 보안에 민감할 텐데 부분 수정인 Patch를 하면 수정이 안된 남은 부분이 생기면 문제가 생기지 않을까? 역시 한 번에 모두 갈아치우는 Put을 써야겠지!’ - 진지
참으로 귀엽고 가소롭지 않을 수 가 없다 ^^
후에 조금 더 알아보니, 차이점을 더 자세하게 알 수 있었다.
@Put 의 경우 존재하는 자원을 수정하거나, 자원이 없었던 경우 새로이 생성 할 수 있다.
그리고 @Patch 는 존재하던 자원의 일부를 수정한다.
…라는데, 여기에서 자원이라는 개념이 잘 와닿지 않았다.
그러다 같이 작업하던 팀원과의 얘기에서 자원이 곧 클래스의 필드에 선언된 변수들 이란 걸 알게 되었다.
여기까지 알고 예를 들어보자.
public class Post {
private String title; //제목
private String writer; //작성자
private String content; //내용
}
어떤 Class에 필드에 제목, 이름, 내용 이 필드에 각각 선언되어 있는데, 이들 모두가 변경이 되는 경우에 @Put을 사용하게 되고,
혹은 작성자, 내용은 같은데 제목만 변경을 하겠다 하면 @Patch를 사용하게 되는 거다.
그런데 그렇다면 ‘굳이 나눠서 사용할 거 없이 전체 수정인 @Put을 사용하는게 깔끔하고 편한거 아닌가?’ 라는 의문이 들었는데,
직접 요청을 하고 받게 될 결과 까지 고려를 해본다면 마냥 가벼운 문제는 아니었다.
위의 Entity를 사용, 게시글을 하나 POST 했다고 예시를 들어보자.
{
"title" : "아니 이게무슨;",
"writer" : "엘사",
"content" : "얼음성에서 안나가 춥다길레 모닥불 피웠더니 얼음바닥 녹음;"
}
이런식의 데이터가 저장되어 있는데, 내가 제목만 바꾸고 싶을 때 Put과 Patch의 사용을 보면 이렇다.
@Put을 사용할 경우 :
{
"title" : "아 내 얼음성;", //<-수정 할 부분
"writer" : "엘사", //같음
"content" : "얼음성에서 안나가 춥다길레 모닥불 피웠더니 얼음바닥 녹음;" //같음
}
요청할 body값으로 title, writer, content를 등록된 데이터에 맞춰 모두 써줘야 하고, 바뀔 부분을 수정해준다.
@Patch를 사용할 경우 :
{
"title" : "아 내 얼음성;" //<-수정 할 부분
}
수정할 필드값만 요청 body값으로 보내면 된다. ‘편안~’
만약 @Put을 사용하며 바로 위 처럼 요청을 보내게 되면,
{
"title" : "아 내 얼음성;",
"writer" : null,
"content" : null
}
아주 후NullNull하다.
위와 같이 What The Null 같은 상황이 발생하게 된다. 전체수정과 부분수정의 차이점에 대한 의미가 바로 저거였던 거다.
전체 자원값을 수정하게되는 @Put을 날렸는데 요청한 필드가 title밖에 없으니 나머지에 null이 박혀버린 것!
이렇게 알게 되니 상황에 맞춰 확실히 구분해서 사용해야겠다는 생각이 들었다.
사실, 지금 내가 작업했던 요청 Class는 API당 하나씩 밖에 없고, 그 안에 필요한 필드들을 다 사용하는, 한마디로 간단한 작업이기에 딱히 문제는 없다.
하지만 이번에 이에 대해 알아본게 아주 잘한 일이라고 생각된다.
그럴 법도 한게 null이 관련되어 있었으니; (실은 그 전날 `NullPointerException` 과 미친듯이 조우했던 터라 아직 혐오감이 가시지 않았던 터였다.)
아무튼 이번에도 거하게 한 수 배우고 간다.
가려운데 긁었는데 완전 스팟이라 엄청 시원해진 이 기분, 너무 달달하다.
p.s - Put, Patch의 차이점에 대해 알아볼 때 꼭 나오는게 ‘멱등성’ 이라는데, 이를 연결해서 공부하면 더 맛있다는 제보를 입수했다. ⇒ 떡밥
'코딩 > JAVA' 카테고리의 다른 글
Size is matters. (0) | 2023.11.26 |
---|---|
NoErrorMessege (1) | 2023.11.06 |
TPJ-호텔 예약 프로그램 (5) (1) | 2023.11.02 |
TPJ-호텔 예약 프로그램 (4) (1) | 2023.11.01 |
TPJ-호텔 예약 프로그램 (3) (1) | 2023.11.01 |