= 스프링 부트 2.0.3 그리고 1.5.14 출시
honeymon, <ihoneymon@gmail.com>
v0.0.1, 2018/06/15

[IMPORTANT]
====
**1.16.22 에서 컴파일 에러있음** 그러니 [red]#**1.18.2**# 버전을 사용하라.
====

* link:https://spring.io/blog/2018/06/14/spring-boot-1-5-14-available-now[Spring Boot 1.5.14 available now]
* link:https://spring.io/blog/2018/06/14/spring-boot-2-0-3-available-now[Spring Boot 2.0.3 available now]

지난 2018/06/14 스프링 부트 1.5 와 2.0 새로운 버전이 출시되었다. 기존에 있던 결함을 수정하고 의존성 라이브러리들을 업데이트 하는 수준이었다.

그런데 의도치 않게 내게 큰 문제가 발생을 하니... 바로 Lombok과 관련된 문제였다.

두 버전 모두 lombok 1.16.22 버전을 사용한다.

1.16.20 은 이상이 없었지만 1.16.22 버전에서는 다음과 같이 사용하면 컴파일 에러가 발생한다.

[source,java]
----
@Data
@NoArgsConstructor
public class Transfer {
    private String name;
    private Integer value;

    public Transfer(String name, Integer value) {
        this.name = name;
        this.value = value;
    }
}
----

[source,java]
----
Error:(9, 1) java: constructor Transfer() is already defined in class io.honeymon.boot.springboot.training.Transfer
----

이 문제를 해결하는 방법은 간단하다.

* 참고: link:http://kwonnam.pe.kr/wiki/java/lombok/pitfall#data_%EC%82%AC%EC%9A%A9%EA%B8%88%EC%A7%80[`@Data` 사용금지]

위 내용을 살펴보고, 세부적인 항목들을 명시적으로 작성하자.

[source,java]
----
@Getter
@Setter
@NoArgsConstructor
@ToString(onlyExplicitlyIncluded = true)  // <1>
@EqualsAndHashCode(onlyExplicitlyIncluded = true) // <2>
public class Transfer {

    @ToString.Include // <1>
    @EqualsAndHashCode.Include // <2>
    private String name;

    @ToString.Include
    @EqualsAndHashCode.Include
    private Integer value;

    @Builder
    public Transfer(String name, Integer value) {
        this.name = name;
        this.value = value;
    }
}
----
<1>, <2> lombok 1.16.22 버전부터 추가된 ``@Include``와 ``@Exclude`` 를 이용해서 필드에서 ``toString()``과 ``equals()``, ``hashCode()`` 에서 사용할 필드를 지정할 수 있다. ``(onlyExplicitlyIncluded = true)``를 선언해줘야 실제로 적용된다.

[NOTE]
====
명시적으로 필드선언을 했을 때 타입에 선언된 부분에 ``(onlyExplicitlyIncluded = true)``를 선언해야 적용된다.

[source,java]
----
/**
 * Only include fields and methods explicitly marked with {@code @ToString.Include}.
 * Normally, all (non-static) fields are included by default.
 */
boolean onlyExplicitlyIncluded() default false;
----
====

[WARNING]
====
그런데 이번에 배포된 1.16.22 에서는 ``(onlyExplicitlyIncluded = true)`` 부분에서 컴파일 에러가 발생한다. 이를 해결하기 위해서는 롬복 1.18.0 으로 변경해야 한다.

[source]
----
Error:(12, 45) java: Can't translate a class java.lang.Boolean to the expected class java.lang.Boolean
----

* link:https://projectlombok.org/changelog[Lombok changelog] v1.18.0 확인
====

이전에는

[source,java]
----
@Getter
@Setter
@NoArgsConstructor
@ToString(of={"name", "value"})
@EqualsAndHashCode(of={"name", "value"})
public class Transfer {

    private String name;

    private Integer value;

    @Builder
    public Transfer(String name, Integer value) {
        this.name = name;
        this.value = value;
    }
}
----

위와 같이 ``of`` 속성에 문자배열로 등록해야해서 복사하여 붙여넣거나 타이핑을 하다가 오타가 발생할 가능성이 있었던 것을 피할 수 있게 되었다.

[source,java]
----
@Getter
@Setter
@NoArgsConstructor
@ToString(onlyExplicitlyIncluded = true)
@EqualsAndHashCode(onlyExplicitlyIncluded = true)
public class Baggage {
    @EqualsAndHashCode.Include
    @ToString.Include
    private String name;    // 수화물명

    @EqualsAndHashCode.Include
    @ToString.Include
    private Integer value;  // 가치

    @EqualsAndHashCode.Include
    @ToString.Include
    private String departure;   // 출발지

    @EqualsAndHashCode.Include
    @ToString.Include
    private String arrival;     // 도착지

    private String description;

    @Builder
    public Baggage(String name, Integer value, String departure, String arrival, String description) {
        this.name = name;
        this.value = value;
        this.departure = departure;
        this.arrival = arrival;
        this.description = description;
    }
}
----

위와 같이 작성하면 된다.

= 정리
* 스프링 부트 1.15.14와 2.0.3 출시
* 롬복(Lombok)
** 위 버전에 추가된 Lombok 1.16.22 버전 명시
** ``@Data``와 ``@NoArgsConstructor`` 는 함께 사용할 수 없다.
*** ``@Data``와 ``@NoArgsConstructor``가 기본 생성자(Default Consturctor)를 생성하는 부분에서 컴파일러 에러가 발생하는 것으로 추측할 수 있다.
** ``@ToString``와 ``@EqualsAndHashCode``를 필드에 선언할 수 있다. 이 기능을 적용하려면 타입영역에서 ``@ToString(onlyExplicitlyIncluded = true)`` 으로 선언해야 한다.
** 1.16.22 에서 컴파일 에러가 있어서 1.18.0 이 나옴
** 1.18.0 버전을 사용하라.