본문 바로가기

Spring Boot

[Spring Boot] Rest API Put 메서드 + boolean is 변수명의 문제점

728x90
Method 의미 CRUD 멱등성 안전성 Path Variable Query Parameter DataBody
GET 리소스 취득 R (Read) O O O O X
POST 리소스 생성, 추가 C (Create) X X O O
PUT 리소스 갱신, 생성 U / C
Update, Create
O X O O

 

PUT 메서드

PUT 메서드는 기본적으로 데이터를 갱신하며, 갱신할 데이터가 없을 시에는 새로운 데이터를 생성하는 역할을 합니다.

  • 특징:
    • Path Variable: 가질 수 있습니다.
    • Query Parameter: 사용할 수는 있지만 데이터를 필터링하는 역할로 사용하기에는 적합하지 않습니다.
    • DataBody: 가질 수 있습니다.

멱등성과 안전성

PUT 메서드는 멱등성을 가집니다. 즉, 같은 요청을 여러 번 보내더라도 결과가 항상 동일하게 유지됩니다. 하지만 데이터가 변경되기 때문에 안전성은 보장되지 않습니다.

import com.fasterxml.jackson.databind.PropertyNamingStrategies;
import com.fasterxml.jackson.databind.annotation.JsonNaming;
import lombok.*;

@Data
@AllArgsConstructor
@NoArgsConstructor
@JsonNaming(value = PropertyNamingStrategies.SnakeCaseStrategy.class)
public class UserRequest {
    private String userName;

    private String email;

    private int userAge;

}

 

import me.sonwheesung.springbootdeveloper.model.UserRequest;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
@RequestMapping("/api")
public class PutApiController {

    @PutMapping("/put")
    public UserRequest put(
            @RequestBody UserRequest userRequest
            ) {
        return userRequest;
    }
}

위 코드는 PUT 메서드를 사용하여 클라이언트가 보낸 데이터를 받아서 매핑하는 예시입니다.

PUT 메서드는 REST API에서 데이터의 갱신과 생성을 위해 사용되며,

POST와 달리 멱등성을 가지면서도 안전성은 보장되지 않는 특성을 가집니다.

 

 

 


사실 이번 게시물은 boolean isKorean이 더 중요한 내용인 것 같습니다

PUT은 POST와 사용 방식은 다른게 거의 없기 때문입니다

 

 

boolean is변수명의 문제

 

객체로 boolean 타입을 사용하면서 is 라는 변수 명을 사용했을 때 JSON 데이터와 객체간에

해당 boolean 타입만 매핑이 되지 않은 경우가 생깁니다

 

import com.fasterxml.jackson.databind.PropertyNamingStrategies;
import com.fasterxml.jackson.databind.annotation.JsonNaming;
import lombok.*;

@Data
@AllArgsConstructor
@NoArgsConstructor
@JsonNaming(value = PropertyNamingStrategies.SnakeCaseStrategy.class)
public class UserRequest {
    private String userName;

    private String email;

    private int userAge;

    private boolean isKorean;

}

 

is_korean으로 보냈지만 korean이라는 이름으로 나오며

default값인 false가 나오면서 매핑이 되지 않았다라는 것을 알 수 있습니다

 

왜 그런걸까요??

boolean vs. Boolean

boolean

기본 자료형(primitive type)으로, true와 false 두 개의 값을 가질 수 있습니다.

Boolean

참조형 타입(reference type)으로, Object에 해당하며 null 값을 가질 수 있습니다. 따라서 true, false, null 세 가지 값을 가질 수 있습니다.

Default 값

변수를 초기화할 때 가지는 값은 다음과 같습니다:

  • boolean: false
  • Boolean: null

컬렉션과 기본 자료형

List나 Map과 같은 컬렉션은 객체만을 받아들일 수 있습니다. 즉, int, double, char와 같은 기본 자료형은 담을 수 없고, Integer, String, Double, Boolean과 같은 참조 자료형만 넣을 수 있습니다.

기본 자료형을 박스화한 것을 boxed primitive type이라고 하며, 이 변환 과정을 boxing이라 하고, 반대로 박스화된 기본 자료형을 기본 자료형으로 변환하는 것을 unboxing이라고 합니다.

 

 

Spring Boot에서 boolean 사용 시 주의사항

Spring Boot에서 boolean 타입을 사용할 때, 변수명과 관련된 매핑 문제가 발생할 수 있습니다.

예를 들어, private boolean isKorean; 필드를 선언했을 때

클라이언트에서 보낸 데이터는 is_korean과 같은 형태로 올 수 있습니다.

그러나 Spring Boot는 기본적으로 getter와 setter를 생성할 때 JavaBeans 규칙에 따라서 이름을 매칭시키는데,

boolean 타입의 경우 getter의 이름이 is + 변수명 형식을 따르기 때문에 문제가 발생할 수 있습니다.

 

 

 

 

 

JavaBeans 규칙에 따르면 isKorean과 같은 boolean 타입 변수를 사용할 때, Lombok은 다음과 같은 메서드들을 생성합니다:

  1. Getter 메서드: boolean 타입의 변수인 경우, getter 메서드의 이름은 is + 변수명으로 생성됩니다.
    따라서 isKorean 변수의 getter 메서드는 isKorean()으로 생성됩니다.
  2. Setter 메서드: setter 메서드는 getter 메서드를 기반으로 생성됩니다.
    예를 들어, isKorean()의 경우 setter 메서드는 setKorean()으로 생성됩니다.
    이 때, setter 메서드는 getter 메서드의 is를 제거하고 set을 붙입니다.

이 규칙을 통해 isKorean 변수를 사용할 때, Lombok이 자동으로 getter와 setter를 생성하여 JavaBeans 규칙을 준수하게 됩니다.

 

해결 방법으로는 다음과 같은 접근이 있습니다:

  1. Boolean 타입 사용: boolean 대신 Boolean을 사용하면 getter에는 get을 붙이고, setter에는 set을 붙이며 is를 사용해도 문제가 없습니다.
  2. 변수명 변경: is를 사용하지 않고 변수명을 변경하는 방법입니다.
  3. JSON 데이터의 맴버명 조정: 클라이언트에서 보내는 JSON 데이터의 맴버명을 is를 제외하고 변수명에 맞추는 방법이 있으나, 이 방법은 코드의 가독성을 해칠 수 있습니다.

저는 해결방법으로는 Boolean을 사용했습니다

import com.fasterxml.jackson.databind.PropertyNamingStrategies;
import com.fasterxml.jackson.databind.annotation.JsonNaming;
import lombok.*;

@Data
@AllArgsConstructor
@NoArgsConstructor
@JsonNaming(value = PropertyNamingStrategies.SnakeCaseStrategy.class)
public class UserRequest {
    private String userName;

    private String email;

    private int userAge;

    private Boolean isKorean;

}

Boolean으로 하니 getter와 setter가 원하는 메서드명으로 바뀌었고 매핑도 잘 된 것을 확인 할 수 있습니다

 

추가 지식

 

  • 자동 매핑: Spring Framework의 @RequestBody 어노테이션을 사용하면 HTTP 요청의 Body에 있는 JSON 데이터가 자동으로 지정된 객체의 필드로 매핑됩니다.
  • Setter 메서드 활용: 매핑 과정에서는 setter 메서드가 사용되어 객체의 각 필드에 JSON 데이터의 값을 설정합니다. 예를 들어, setUserName() 메서드는 JSON 데이터의 userName 필드 값을 UserRequest 객체의 userName 필드에 할당합니다.
  • 간편한 데이터 처리: 이 과정을 통해 개발자는 별도의 데이터 변환 로직 없이도 클라이언트가 보낸 JSON 데이터를 객체로 쉽게 변환하고 필요한 비즈니스 로직을 수행할 수 있습니다.

 

 

728x90