본문 바로가기
Develop/Spring+JPA

PATCH 메소드는 언제 사용하는가?

by 연로그 2022. 1. 25.
반응형

목차

1. 문제 발생

2. 개념 되짚어보기

3. Java와 PATCH

4. 개선 방법


 


1. 문제 발생

 

현재 JPA, Spring 기반으로 토이 프로젝트를 진행 중인데 고민이 하나 생겼다.

설정 값들은 RDB에 저장되며 PK를 제외하고는 값 수정이 가능하다.

 

예를 들어 이름, 나이, 생일, 직장을 변경할 수 있다고 하자.


그러면 API를 아래와 같은 방법으로 설계해볼 수 있다.

 

  • 이름, 나이, 생일, 직장 각 필드마다 API 따로 설계
    • 이름만 변경하는 경우 이름 API만 호출해도 됨
    • 모든 값을 변경하는 경우 API 4개 호출하는 상황 발생
  • 이름, 나이, 생일, 직장 한 번에 변경되는 API 설계
    • 이름만 변경하는 경우 나이, 생일, 직장을 null 체크 해주거나 나이, 생일, 직장에 대한 정보도 함께 받아야 함
    • 모든 값을 변경하는 경우 API 1개만 호출해도 됨

 

문뜩 다른 분들은 어떻게 설계할까? 궁금해져서 참여중인 스터디에 질문을 올렸다.

 

JSCODE 스터디 - ㅈ영님, ㄱㅇ정님 감사합니다!

 

아래 답변은 예상했던 충분히 납득 가는 답변이었는데 PATCH 메소드를 사용한다는건 의외였다.

이전 회사에 다닐 때 브라우저 호환성 문제로 인해 POST, GET 외의 메소드는 잘 쓰지 않는다라고 배우기도 했고...

PATCH는 수정할 때 주로 사용하는 메소드 정도로만 기억하고 있어서 이 기회에 다시 한번 살펴봤다.

 


2. 개념 되짚어보기

 

1. POST, GET 외 메소드는 잘 사용하지 않는다?

이전 회사에서 '몇몇 HTTP 메소드들은 일부 브라우저에서 호환되지 않는다.', '실무에서는 POST, GET만 사용한다.' 라고 배웠다.

그런데 다른 스터디원분들은 실무에서도 다른 메소드들을 사용한다 하셔서 위 말에 의심이 들어서 찾아봤다.

 

https://stackoverflow.com/questions/24257327/http-patch-support-in-browsers

 

HTTP PATCH support in browsers

I am designing REST endpoints for my application and i need to use PATCH for a few of the endpoints. Will all browsers that support HTTP/1.1 be able to support the PATCH ?

stackoverflow.com

 

위 글에 따르면 당시 HTTP 1.1 에서는 PATCH라는 메소드를 정의하지 않았던 것으로 보인다.

전 회사에서 서비스 되던 프로젝트들은 10년 이상 유지되던 것이 많아 그 당시의 개발 상황을 고려한 것이라 예상한다.

 

2. PUT과 PATCH의 차이

많은 사람들이 PUT과 PATCH를 아래와 같이 비교한다.

  PUT PUT PATCH
원본 {"name":"yeonLog", "age":26}
before {"name":"yeonLog", "age":26} {"name":"yeonLog"} {"name":"yeonLog"}
after {"name":"yeonLog", "age":26} {"name":"yeonLog", "age":null} {"name":"yeonLog", "age":26}

이론적으로 PATCH는 자원의 부분 교체를 목적으로 사용하기 때문에 일부만 전송해도 원본 데이터가 유지된다.

 

🔻 PATCH은 멱등성이 아니다?

더보기
멱등성: 같은 행위를 여러 번 반복하더라도 같은 결과를 유지하는 성질

 

PUT 메소드의 경우에는 리소스를 완전히 교체해버린다. (👉 멱등)

PATCH 메소드는 멱등으로 설계할 수도 있고, 멱등이 아니게도 설계할 수 있다.

 

예를 들어 PATCH를 통해 name을 "kim"으로 바꿨다.

이 경우에는 기존 값이 새로운 값으로 완전히 교체되었으니 멱등이다.

 

반면에 PATCH를 통해 age를 받으면 해당 값만큼 +가 된다.

기존의 age가 10이었다고 가정할 때, {"age":10}을 받으면 age는 20이 된다.

{"age":10}를 한 번 더 호출하면 age는 30이 된다.

같은 값을 보냈음에도 불구하고 age의 결과는 다르게 나오니 멱등이 아니다.

 

나의 경우에는?

equest라는건 프론트와 협의에 따라 얼마든지 필요한 필드가 달라질 수 있다.

수정이 편하도록 Entity와는 별개로 requestDTO를 생성하는 방법이 효율적이다.

 

requestDTO가 있는 경우에는 코드가 아래와 같은 순서로 동작된다.

 

  1. JSON 형식으로 데이터를 받으면 ReqeustDTO에 매핑
    (데이터를 보내지 않으면 당연히 RequestDTO에 null 값이 세팅됨)
  2. RequestDTO의 필드 값이 null인지 확인하고 getVal()
  3. 2의 값을 Entity에 setVal()

 

2의 null 체크 부분이 너무너무 불편하게 느껴졌다.

필드 늘어날때마다 null 체크 할거야!? 단순 반복 싫어!

어차피 모든 필드에 대해 null 체크를 해야만 한다면 PUT 메소드랑 다를게 없지 않나?

 

그렇게 시작된 폭풍 검색.. 폭풍 질문..

 


3. Java와 PATCH

 

다양한 실무자 분들이 계신 스터디에 질문을 해보았다.

감사하게도 많은 분들이 답변 해주셨다.

 

PATCH는 일부 값만 변경할 때 사용하지만
 Spring 환경의 서버 단에서 별도의 로직이 필요하다.

 

 

적어도 Spring/Java 기반에서는 적절히 사용하기 어려워 보이고

Node.js 같은 json을 다루기 쉬운 언어나 프레임워크에서는 고려 정도는 해볼만 할 것 같다고 하셨다.

 

🔻 답변 전문

더보기
블로그 포스팅 스터디 - ㅂㅊ원님 감사합니다!
블로그 포스팅 스터디 - ㅊㄹ준님 감사합니다!
블로그 포스팅 스터디 - ㄱㄴ윤님 감사합니다!

 


4. 개선 방법

 

그럼 이제 API를 개선하느냐는 크게 두 가지로 나뉜다.

(사실 위에서 말한거랑 별로 다른건 없다.😅)

 

  1. 변경되지 않는 값을 포함해 모든 값을 다 보내주도록 설계한다.
  2. 일부만 보내도 상관 없도록 설계한다. (이 경우 null 체크 필요)

 

1의 경우에는 별도의 로직이 필요 없다.

requestDTO의 모든 값들을 Entity에 set 해주기만 하면 된다.

 

2의 경우에 null 체크 로직을 제거하는 방법은 여러가지가 있다.

모각코 - ㅁ님, 스프링 이즈 커밍! - ㅋㅍㄴㅈ님 감사합니다!

  • mapstruct 같은 라이브러리 이용하기
  • @NotNull 등의 어노테이션을 이용해 Exception 발생
  • null 체크 로직 직접 생성하기

 

결론부터 말하자면 나는 null 체크 로직을 직접 생성하는 방식을 선택했다.

 

mapstruct 같은 라이브러리는 getter, setter를 생성하면 이를 이용해 값을 넣는다.

DTO라는건 계층간의 데이터 교환을 위해 사용하는 것인데, 생성자로만 값을 세팅해도 충분하게 느껴졌다.

다르게 말하자면 setter 메소드를 만들어 값이 변할 수도 있는 상황을 만들기 싫었다.

 

@NotNull 같은 어노테이션을 통해 Exception을 발생시키는건 너무 극단적으로 보였다.

프론트와의 협의 하에 잘 조율하면 발생하지 않을 Exception이긴 하다.

하지만 값을 수정하는 API가 한두개만 있는 것도 아니고, 프론트 입장에서 어떤 값을 수정하든간에 모든 데이터를 긁어와서 서버에 보내줘야한다는게 번거롭지 않을까? 라는 생각이 들었다.

(이건 신입의 주관적 의견이므로 이런 생각도 있구나 하고 넘어가면 될 것 같다...)

 

 

PATCH에 대해 더 알게된 것도 좋았지만 많은 개발 커뮤니티에 자문하고 기꺼이 도와주시려하시는 개발자 분들의 모습에 감동할 수 있는 시간이었다. 

다들 정말 감사합니다. 사랑 또 사랑😭❤❤❤


기타 참고 링크

  1. https://www.baeldung.com/http-put-patch-difference-spring
  2. https://www.inflearn.com/questions/110644
  3. https://stackoverflow.com/questions/24257327/http-patch-support-in-browsers
반응형