코딩무비

[lombok] boolean 타입의 @getter 유의점 (ex. "is")

by 코딩무비
반응형

dto 객체를 반환 할 때 boolean타입의 필드 명 중 isXXX로 작성한 경우 XXX가 key로 저장되는 것을 확인할 수 있었다. 왜 이런 문제가 발생하는지 궁금하여 이 글을 작성하게 되었다.

 

간단한 예제를 만들어보자.

 

우리는 이름, 나이, 개발자 여부의 회원 정보를 나타내는 기능 개발을 한다고 하자.

 

Member생성

@Getter
@AllArgsConstructor
public class Member {
    String name;
    int age;
    boolean isDeveloper;
}

Lombok의 @Getter와 모든 파라미터로 생성자를 생성하게 하고 있다. 이제 컨트롤러를 이용하여 회원 객체를 반환해보자.

 

 

MemberController 

@RestController
@RequestMapping("/member")
public class MemberController {

    @GetMapping
    Member returnSampleMember(){
        // Service 생략
        Member member= new Member("jinho", 29, true);
        return member;
    }

}

간단한 예시를 위하여 Service, Repository을 생략

그러면 결과 값으로 어떻게 나올까??

 

 

Response값으로 "is"가 빠져있는 것을 확인할 수 있다. 왜 그런 것일까???

 

그 이유는 @Getter을 사용하는 LombokJackson 라이브러리에 있다.

 

 

Lombok?

Lombok은 Java 개발자들이 자주 사용하는 명령어(getters, setters, 생성자, toString(), equals(), hashCode() 등)의 @어노테이션을 통하여 자동 생성을 지원해주는 라이브러리이다.

 

 

Lombok에서는 @Getter, @Setter 등 어노테이션 이용하여  메서드를 자동으로 만들어 준다.

 

여기서 주의할 것은 boolean 필드 명이 isXXX의 경우 isIsXXX가 아니라 isXXX()로 getter 메서드를 생성하게 된다.

 

Jackson?

Jackson 라이브러리는 Java 언어로 작성된, 고성능 JSON 처리를 위한 라이브러리이다. JSON 형식의 데이터를 생성하고, 파싱하는데 사용되며, Java 객체와 JSON 데이터 간의 변환을 쉽게 할 수 있게 도와준다.

 

직렬화란?

객체의 내용을 바이트 단위로 변환하여 파일 또는 네트워크를 통해서 스트림(송수신)이 가능하도록 하는 것

우리는 Java 객체를 사용하게 되면 객체의 주소 값을 이용하여 JVM Heap 영역의 객체에 값을 저장한다. 우리는 이 값을 외부로 보내기 위해서는 바이트 단위로 변환하여 넘겨줘야 한다. 

 

스프링 프레임워크에서 객체를 반환하게 되면 우리는 아무 설정도 하지 않았지만 객체를 자동으로 직렬화하는 것을 볼 수 있는 데

그 이유는 컨트롤러에 사용한 @ResponseBody 어노테이션 덕분이다.

 

@RestController 어노테이션

@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Controller
@ResponseBody
public @interface RestController {
    @AliasFor(
        annotation = Controller.class
    )
    String value() default "";
}

@RestController 또한 내부적으로 @ResponseBody 어노테이션을 사용한다.

 

컨트롤러 메서드에 @ResponseBody 어노테이션을 사용하면 Spring MVC가 메시지 컨버터로 객체를 반환할 때는  Jackson 라이브러리 중 MappingJackson2HttpMessageConverter을 사용하게 된다.

해당 구현체는 key:value 형태로 json포맷을 만들어 준다.

 

그런데..value는 객체의 값을 이용하면 될 것이고, key은 어떻게 생성될까?

1. Java Bean 규약에 따라 getter 메서드가 있다면 해당 메서드에서 get/is을 빼고 나머지 문자를 JSON key값이 설정됨.

2. 필드가 public이라면 해당 필드명을 JSON key값이 설정됨.

이러한 이유로 boolean 필드에서는 is을 제외한 key가 생성이 된 것이다.

 

 

 

 

그렇다면 어떻게 해결할 수 있을까?

 

해결방법

1.  직접 getter 메서드 구현하기

@Getter
@AllArgsConstructor
public class Member {
    private String name;
    private int age;
    private boolean isDeveloper;


    public boolean isIsDeveloper(){
        return isDeveloper;
    }
}

key 생성 규칙 중 1번을 이용(getter 메서드명 사용)하여 boolean 필드의 getter 메서드를 isIsXXX()형식으로 직접 구현을 한다.

직렬화 수행시 Jackson 라이브러리에서 isDeveloper 필드에 대한 getter메서드를 찾게 된다.

 

2.  필드에 JsonProperty() 이용하기

@Getter
@Setter(AccessLevel.PRIVATE)
@AllArgsConstructor
public class Member {
    private String name;
    private int age;
    @JsonProperty("isDeveloper")
    private boolean isDeveloper;

}

필드에 JsonProperty()어노테이션을 사용하여 Jackson 라이브러리에게  지정한(name)으로 getter와 setter 메서드 이름을 지정할 수 있다.

3. boolean -> Boolean 변경하기

@Getter
@AllArgsConstructor
public class Member {
    private String name;
    private int age;
    private Boolean isDeveloper;
}

Boolean과 같이 레퍼의 경우 getter메서드 생성시 getIsDeveloper로 생성한다. 

 

 

### 결론

1. boolean 값의 getter의 경우 getXXX가 아닌 isXXX을 사용함.

2. 만약 boolean 필드명이 isXXX이라면 Lombok은 isXXX()로 getter 메서드를 만듦(isIsXXX가 아님)

3. Spring 프레임워크에서  객체를 리턴할 때 Jackson 라이브러리를 사용하여 직렬화 수행

4. JackSon 라이브러리에서 직렬화할 때 key: value 형태로 만듦

5. key로 결정하는 방식으로 Java Bean 규약에 따라 getter메서드가 있다면 해당 메서드 이름에서 get or is 을 뺀 나머지를 key값으로 사용

6. 2번에 의하여 롬복에서 만든 boolean의 getter 메서드는 isIsXXX()가 아닌 isXXX()형식으로 생성되므로 is가 빠지게 된 것

반응형

블로그의 정보

코딩무비

코딩무비

활동하기