PUT과 PATCH 너네 둘이 궁금하다
오늘 팀 프로젝트를 하던 중, 프로필 수정에서 PUT방식을 써야할 까 PATCH 방식을 써야할까 많은 고민을 했다.
PUT vs PATCH
대충
PUT은 전부 변경
PATCH는 일부만 변경하는 것으로 알고 있을 것이다.
여기서 차이가 생긴다
PUT은 전부 변경하기 위해 사전에 해당 객체의 모든 정보를 알고 있어야 한다.
PATCH는 변경하기 위해 변경해야할 부분의 정보만 알고 있으면 된다.
PUT
PUT은 전부 변경하기 위해 사전에 해당 객체의 모든 정보를 알고 있어야 한다고 했다.
예를 들어 게시글 수정을 해야한다고 하자
게시글에는 제목, 작성자, 내용과 같은 정보가 들어있다.
{
"title" : "title"
"author" : "author"
"content" : "content"
}
JSON으로 수정을 하고 싶을 때 이렇게 보내면 된다.
네이버 블로그 수정 할 때를 보자
제목과 내용이 기본으로 이렇게 들어가 있다.
블로그 글을 작성 완료하면 위에 봤던 JSON 처럼 요청이 보내질 것이다.
사전에 해당 정보를 모두 알고 있어야하는 것을 이렇게 해소하는 것이다.
PATCH
PATCH는 변경하기 위해 변경해야할 부분의 정보만 알고 있으면 된다.
무슨 소리냐
만약에 네이버 메인 홈페이지에서 PATCH 메소드로 저기 웹툰 부분의 이름을 변경할 수 있는 메소드가 있다고 가정하자
저기에 있는 정보가 뭐가 있을까?
위의 아이콘과 아이콘 밑에 있는 웹툰이라는 글씨다.
나는 아이콘말고 웹툰이라는 글씨만 바꾸고 싶다.
기존의 PUT 방식이라면
{
"icon" : "https://iconsite.com/icon_naver_webtoon.png"
"title" : "만화"
}
위 처럼 icon 정보를 알고 있어야한다.
근데 PATCH는
{
"title" : "만화"
}
이렇게만 보내도 수정이 되는 것이다.
DB에서 딱 원하는 한 부분만 수정이 가능 한 것이다.
PUT과 PATCH를 왜 고민했어?
회원 정보 수정(회원 닉네임, 회원 소개, 회원 비밀번호)에 대해 얘기를 나눌 때 처음 얘기 나온 메소드는 PUT인데
곰곰이 생각해보니까
unique값 중복에 대한 예외 처리를 어떻게 해야하나? (회원 닉네임)
비밀번호를 변경할 때마다 회원 닉네임을 계속 검증하고, 회원 소개까지 보내줘야 하나? (회원 비밀번호, 회원 소개 동일)
회원정보 수정에 비밀번호 수정까지 작성하라고 하면 설명하나 바꾸고 싶을 뿐인데, 비밀번호 까지 다 입력해서 보내야 되나????
기존 사이트들의 방법은 어떨까? 에서 시작한 고민이다.
기존 사이트들은 어떨까?
네이버
구글
깃허브
흠... 개발에는 정답이 없다는데.. 그냥 PUT으로 하면 안 되나? (청개구리 심보)
갑자기 청개구리 심보가 발동했다.
개발에는 정답이 없다는데 !!!
근데 나는 이미 이 고민을 하는 순간부터 효율에 대해 고민을 하고 있었다는 것이다.
아... 나는 이미 정답을 얼추 알면서 고민하는 것이었다... ㅋㅋ
가정
이런 인터페이스가 있다고 가정하자
이 인터페이스는 개발 초기에 대충 만들어 놓은 와이어 프레임이라고 가정하자
백엔드와 프론트엔드 끼리 어떻게 할지 의논하기 시작했다고 가정
PUT으로 했을 때
PUT으로 했을 때는 모든 정보를 알고 있어야한다.
만약 하나하나 변경을 하고 싶다
그럼 이렇게 만들 것이다.
근데 api 명세에는 이렇게 적혀 있는 것이다.
이름 | Method | URL | RequestBody |
유저 이름 변경 | PUT | /api/user/nickname | { "nickname" : "nickname" "introduce" : "introduce" "password" : "password" } |
유저 소개 변경 | PUT | /api/user/intro | { "nickname" : "nickname" "introduce" : "introduce" "password" : "password" } |
유저 비밀번호 변경 | PUT | /api/user/password | { "nickname" : "nickname" "introduce" : "introduce" "password" : "password" } |
어 굉장히 비효율 적인 방법 아닌가?
딱 봐도 보인다. 그래서 프론트에서 하나로 통일하자고 말한다.
이름 | Method | URL | RequestBody |
유저 정보 변경 | PUT | /api/user | { "nickname" : "nickname" "introduce" : "introduce" "password" : "password" } |
어 굉장히 효율적이게 보인다!!
근데 나는 이런 고민을 했다.
unique값 중복에 대한 예외 처리를 어떻게 해야하나? (회원 닉네임)
비밀번호를 변경할 때마다 회원 닉네임을 계속 검증하고, 회원 소개까지 보내줘야 하나? (회원 비밀번호, 회원 소개 동일)
만약에 다른 건 변경하고 싶지 않고 회원 소개만 바꾸고 싶다면?
만약에 다른 건 변경하고 싶지 않고 비밀번호만 바꾸고 싶다면?
그러면 너무 비효율 적이지 않은가?
유저 정보에서 PUT을 사용하는 사례를 찾아보았다
깃허브
Unique하지 않아도 되는 정보에는 PUT을 사용한다.
흠... 그래 너무 비효율 적이야.. Unique를 검증해야 하거나 굳이 변경을 안 해도 되는 부분까지 PUT으로 안보내도 돼
PATCH를 사용할 때
근데 이번 API 명세에서는 이렇게 적혀있다.
이름 | Method | URL | RequestBody |
유저 이름 변경 | PATCH | /api/user/nickname | { "nickname" : "nickname" } |
유저 소개 변경 | PATCH | /api/user/intro | { "introduce" : "introduce" } |
유저 비밀번호 변경 | PATCH | /api/user/password | { "password" : "password" } |
어? 굉장히 효율적으로 보인다.
RequestBody를 봤을 때도 의도가 정말 명확하고 이것만으로도 이 메서드는 PATCH 겠구나~ 생각할 수가 있어진다.
부분적으로만 업데이트 하기 때문에 리소스도 아낄 수 있고 충돌도 방지 할 수 있다.
거기에다가 예외처리를 하는 방법도 쉬워진다.
PUT으로 처리해야 할 예외의 개수가 많아질 때
만약에 PUT 메서드로만 처리했을 때 Unique 값이 여러개라고 생각해보자
이름 | Method | URL | RequestBody |
유저 정보 변경 | PUT | /api/user | { "username" : "username" "email" : "email@emaill.com" "nickname" : "nickname" "introduce" : "introduce" "password" : "password" } |
username (아이디), email (이메일), nickname(닉네임)
이 중복되면 안되는 즉, unique값을 가지는 필드다.
근데 예외 처리를 하려면??
if(username.equals(dbUsername)) {
throw new Exception("중복된 아이디입니다")
}
if(email.equals(dbEmail)) {
throw new Exception("중복된 이메일입니다")
}
if(nickname.equals(dbNickname)) {
throw new Exception("중복된 닉네임입니다")
}
이런 식으로 짜서 걸러줘야할텐데
만약에 사용자가 셋 다 중복 되는 값을 입력하면?
예시)
username (중복)
email (중복)
nickname (중복)
[확인]
확인 버튼을 누르면 예외 처리가 순서대로 있기 때문에
확인을 누르면
"중복된 아이디입니다." 출력
흠... 중복이네.. 바꿔야지
또 확인 누르면
"중복된 이메일입니다" 출력
하.. 이것도 중복이네.. 바꿔야지..
마지막으로 확인 누르면
"중복된 닉네임입니다" 출력
여기 개발자 누구야?!?!?!
이렇게 되는 거다
물론! 중복 처리에 대한 알고리즘을 짤 수도 있다.
각 오류 마다 int 타입 count 변수를 지정해서 선언하고(예. nicknameCount, emailCount) 중복 된 값이 있을 때마다 count++
만약 각 count마다 검사를 했을 때 전부 1이면
"중복된 아이디,이메일,닉네임 입니다."
이런 식의 알고리즘을 정말 어렵게 짤 수도 있다.
근데 여기서부터가 비효율 적이라는 얘기다...
그래서 상황에 맞게 PUT과 PATCH를 잘 활용해야 한다.
'TIL' 카테고리의 다른 글
TIL 2023-11-23 영화진흥위원회 오픈 API 사용 (파싱 후 DB 저장 방법) (0) | 2023.11.23 |
---|---|
TIL 2023-11-22 gradle 외부 라이브러리 jar 적용 오류 (0) | 2023.11.22 |
TIL 2023-11-20 CascadeType.REMOVE orphanRemoval = true 차이 (0) | 2023.11.20 |
TIL 2023-11-17 Entity 연관 관계 정리! (0) | 2023.11.17 |
TIL 2023-11-16 RestTemplate 짧은 설명 (1) | 2023.11.16 |