Lombok을 쓰며 겪었던 문제

2

시행착오

목록 보기
6/22
post-thumbnail

뭐야 상징물 왜저래

Lombok이 뭐야?

Lombok Features 링크
Lombok Features experimental 링크

피쳐 링크에 들어가보면 대충 감이 올텐데
getter, setter, equals, toString, constructor, builder 등을 어노테이션만으로 자동으로 만들어주는 라이브러리다.

쉽고 짱쎈줄 알았는데 생각보다 쉽지 않았다...
파이썬 같은 녀석...
쉽다길래 해봤는데 생각보다 쉽지 않더만...

어떤 점이 쉽지 않았나?

Getter의 prefix를 없애기

Lombok @Getter/@Setter 링크

공식 가이드에 어떻게 하면 prefix를 없앨 수 있다고 설명이 있긴 한데

이렇게 나와있어서 한참 해맸다.

@Accessors를 이용하여 prefix를 없애기

Lombok @Accessors 링크
여기에 들어가니 예제 코드에 @Accessors(fluent = true) 를 쓰면 식별자와 Getter가 이름이 같아지는게 나와있다.

@Accessors(fluent = true)
@Getter

이렇게 하면 모든 식별자에 대한 Getter가 동일한 이름으로 자동 생성된다.

Jackson이랑 연동하기

Lombok @Jacksonized 링크
이름부터 Jacksonized다. 이것만 쓰면 될 것 같이 생겼다.
응 아니야

공식 문서를 자세히 읽어보면 @Builder@SuperBuilder와 같이 써야한다고 적혀있다.
빌더를 쓰기 싫어서 다른 방법을 찾아보니
Serialization과 Deserialization을 만들면 된다는데
그냥 그렇게 복잡하게 할 바에야 빌더를 쓸게요 하는 생각이 들어서 그냥 빌더를 썼다.

@Builder

Lombok @Builder 링크
일단 자동으로 className + "builder" 으로 빌더 클래스가 자동 생성된다.

나는 그 클래스 이름이 그냥 builder 였으면 좋겠어서
@Builder(builderClassName = "builder")
이렇게 만들었다.

모든게 잘 되는 것 같았다.
테스트 커버리지가 100%가 나오지 않는걸 확인하기 전 까지는.

class builderpublic static builder builder()

대체 이유를 알 수 없었는데
builder를 호출하려고 클래스 이름을 치고 .을 치는 순간
IDE가 builderbuilder( ) 이렇게 두개를 보여주는걸 보고 뭔가 이상함을 느꼈다.

가이드 중간에

Example usage where all options are changed from their defaults:
@Builder(
    builderClassName = "HelloWorldBuilder",
    buildMethodName = "execute",
    builderMethodName = "helloWorld",
    toBuilder = true,
    access = AccessLevel.PRIVATE,
    setterPrefix = "set"
)

이런 부분이 있는데, builderMethodName 라는게 눈이 갔다.
가이드 맨 위에 이런 내용이 있었기 때문이다.

@Builder(builderMethodName = "") is legal (and will suppress generation of the builder method)
starting with lombok v1.18.8.

빌더 클래스를 만드는데 왜 빌더 메서드를 생성하는거고 저걸 억제하는걸 알려주는거지? 하고
저걸 그대로 써봤더니 테스트 커버리지가 그제서야 100%가 되었다.

@Builder(builderClassName = "builder", builderMethodName = "") 이렇게 써야한다.

builder를 숨길 수 없어

위 예제에 access = AccessLevel.PRIVATE 라는 부분이 보여서 써먹어봤는데,
ObjectMapper로 string을 파싱하려 하면 저게 프라이빗이라 접근할 수 없다고 에러가 난다.
그래... Jackson때문에 빌더를 썼는데 private으로 만들면 Jackson이 쓸 수 없겠지 ㅠㅠ

@JsonGetter의 역할을 찾아야 한다.

이것도 한참 헤맸다.

@FieldDefaults(makeFinal = true, level = AccessLevel.PRIVATE)
@Accessors(fluent = true)
@Getter

클래스 위에 어노테이션을 이렇게 만들어놓으니 getter의 이름이 식별자와 동일하게 만들어져서
Jackson이 Getter가 뭔지 찾지 못하는 것이다.

@JsonProperty 어노테이션을 쓰니까 된다.

아무리 검색해도 좋은 방법이 나오지 않아서 혼자 삽질하다 알아낸건데,

@JsonProperty("name")
String name;

이런 식으로 식별자 위에 @JsonProperty 어노테이션을 써주니 성공했다.

위 코드에 "저거 public 아닌가? 문제될게 있음?" 이라고 생각할 수 있는데
@FieldDefaults(makeFinal = true, level = AccessLevel.PRIVATE)
이 어노테이션 때문에 실제로는
private final String name;
이렇게 인식된다.

다시 생각해보니 그냥 constructor를 수동으로 만들걸...

이렇게 힘들게 고생할 바에야
그냥 constructor에 @JsonCreator 어노테이션을 붙여서 직접 만드는게 더 빨랐을걸 싶다.

그래도 좋은 경험이었다...ㅠㅠ

profile
지상 최강의 개발자 쥬니니

0개의 댓글