본문 바로가기
스터디/Spring

[Spring] PUT 과 PATCH 사용시 주의할 점

by zoodi 2024. 7. 6.
728x90

목차

  1. 1. Spring 에서 PUT 과 PATCH 사용 시 발생하는 이슈
  2. 2. PUT method
  3. 3. PATCH method
  4. 4. JsonNullable 관련 설정 추가

 

 

 

1. Spring 에서 PUT 과 PATCH 사용 시 발생하는 이슈

일반적으로 PUT은 전체 수정, PATCH 는 일부 필드 수정으로 이해하고 사용하고있습니다.

Spring 을 사용하면서 해당 Http Method 를 사용하다가 이슈가 발생한 경험이있는데요, 어떤 이슈가 있었고 어떻게 해결하는지 알아보겠습니다.

 

 

2. PUT method

예시 코드

class TestController {

   @PutMapping("/test/put")
	public void putSample( @RequestBody Task task) {
		System.out.println(task);
	}
}

class Task {
  private String title;
  private String content;

  ...
}

 

 

Request & Result

{
    "title": "this is title",
    "content" : "this is content"
}
//Task{title='this is title', content='this is content'}

{
    "title": "this is title",
}
//Task{title='this is title', content='null'}


{
    "title": "this is title",
    "content" : null
}
//Task{title='this is title', content='null'}
  • PUT 메소드는 content 필드를 보내지 않으면 null 값으로 적용됩니다.

 

 

3. PATCH method

예시 코드

class TestController {

   @PatchMapping("/test/patch")
	public void putSample( @RequestBody Task task) {
		System.out.println(task);
	}
}

class Task {
  private String title;
  private String content;

  ...
}

 

Request & Result

{
    "title": "this is title",
    "content" : "this is content"
}
//Task{title='this is title', content='this is content'}

{
    "title": "this is title",
}
//Task{title='this is title', content='null'}
//여기서 이슈 발생
//원하는 시나리오는 content는 기존값을 유지하고 title만 변경하는 것인데 content=null 로 업데이트가 될 수 있다.

{
    "title": "this is title",
    "content" : null
}
//Task{title='this is title', content='null'}
  • PATCH 메소드를 사용할 경우 Request에 content 필드를 보내지 않으면 기대 결과는 content는 기존값 유지, title만 변경되는 것입니다.
  • 하지만 실제로 content = null 로 변경이됩니다.

 

4. JsonNullable 관련 설정 추가

여기서 문제는 Spring Boot 기반의 기본 프로젝트 구성으로는 특정 필드를 null로 교체하라는 것인지, 교체 대상이 아니라는 것인지 식별할 수 있는 방법이 없다는 것입니다.

이러한 이슈를 해결하기위해 Jackson 기반의 모듈인 JsonNullable 관련 설정을 추가해줍니다.

 

- build.gradle

dependencies {
	implementation 'org.springframework.boot:spring-boot-starter-web'
	testImplementation 'org.springframework.boot:spring-boot-starter-test'
	implementation("org.openapitools:jackson-databind-nullable:0.2.4")   // 의존성 추가
}

 

- Todo.java

public class Todo {
	private JsonNullable<String> title;
	private JsonNullable<String> content;
	...
}

 

- Controller

@PatchMapping("/test/patch")
	public void patchSample( @RequestBody Todo todo) {
		System.out.println(task);
		if (todo.getTitle().isPresent()) {
			System.out.println("todo title 존재: " + todo.getTitle());
		}
		if (todo.getContent().isPresent()) {
			System.out.println("todo content 존재: " + todo.getContent());
		}
	}

 

- Request

{
    "title": "this is title"
}

Todo{title='JsonNullable[this is title]', content='JsonNullable.undefined'}
todo title 존재: JsonNullable[this is title]

 

{
    "title": "this is title",
    "content": null
}
Todo{title='JsonNullable[this is title]', content='JsonNullable[null]'}
todo title 존재: JsonNullable[this is title]
todo content 존재: JsonNullable[null]
  • JsonNullable 을 적용하면 content 필드를 보내지 않을 경우 undefined 로, null 로 보내면 null 로 요청이 들어옵니다.

<참고자료>

728x90

댓글