오늘은 Lombok이 도입되어 있지 않은 레거시 프로젝트에 롬복 라이브러리를 도입시도를 하며 경험했던 이야기를 해보려고 합니다.
Lombok은 Java를 기반으로한 프로젝트에서 당연시 되는 라이브러리입니다.
하지만 제가 이번에 요구사항을 반영하고 코드 수정이 필요했던 프로젝트는 워낙 오래된 Spring 프로젝트이기도 했고 히스토리를 들어보니 Lombok을 도입하면 발생할 수 있는 사이드 이펙트에 대한 고민때문에 Lombok이 도입되어 있지 않은 상태였습니다.
그러면 왜 이제? 잘돌아 가는거 냅두면 되지 왜 롬복을 추가하냐 라는 점을 생각해 보았는데
결국 제가 생각할 수 있던 이유는 생산성이였습니다.
public class MemberDto {
private String name;
private String email;
private String nickName;
private String birthday;
public String getName() {
return name;
}
public String getEmail() {
return email;
}
public String getNickName() {
return nickName;
}
public String getBirthday() {
return birthday;
}
public void setName(String name) {
this.name = name;
}
public void setEmail(String email) {
this.email = email;
}
public void setNickName(String nickName) {
this.nickName = nickName;
}
public void setBirthday(String birthday) {
this.birthday = birthday;
}
}
일반적으로 Lombok을 사용하지 않고 Getter, Setter만 추가한다고 했을때 (필드의 개수 * 2) 메소드를 필요로 하고 추가적으로 ToString등등 Override해야할 메소드까지 생각한다면 간단한 객체를 만든다고 해도 코드의 길이가 길어지고 사람이 인지할 수 있는 직관적인 부분이 떨어집니다.
@Getter
@Setter
public class MemberDto {
private String name;
private String email;
private String nickName;
private String birthday;
}
만약 Lombok을 도입한다면? 코드의 간결성이 높아짐과 동시에 해당 객체를 개발자가 파악함에 있어 직관적인 코드가 된다고 생각합니다. 추가적인 요구사항을 반영하기 위해 필드를 추가한다고 해도 계속해서 Getter, Setter를 구현할 필요가 없으니 유지보수성에도 큰 이점을 취할 수 있다고 생각합니다.
public class MemberDto {
private String name;
private String email;
private String nickName;
private String birthday;
public static Builder builder() {
return new Builder();
}
public static class Builder {
private String name;
private String email;
private String nickName;
private String birthday;
public Builder name(String name) {
this.name = name;
return this;
}
public Builder email(String email) {
this.email = email;
return this;
}
public Builder nickName(String nickName) {
this.nickName = nickName;
return this;
}
public Builder birthday(String birthday) {
this.birthday = birthday;
return this;
}
public MemberDto build() {
MemberDto memberDto = new MemberDto();
memberDto.name = this.name;
memberDto.email = this.email;
memberDto.nickName = this.nickName;
memberDto.birthday = this.birthday;
return memberDto;
}
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
public String getNickName() {
return nickName;
}
public void setNickName(String nickName) {
this.nickName = nickName;
}
public String getBirthday() {
return birthday;
}
public void setBirthday(String birthday) {
this.birthday = birthday;
}
}
Lombok에서 자주 사용되는 @Builder또한 직접 구현하게 된다면 코드의 양이 어마무시하게 늘어나는데
@Setter
@Getter
@Builder
public class MemberDto {
private String name;
private String email;
private String nickName;
private String birthday;
}
Lombok을 적용하면 코드의 간결성을 통해 개발자가 이해하기 쉬운 직관적인 코드를 작성할 수 있게되고 오로지 비즈니스로직에 집중하여 코드를 작성 할 수 있게 됩니다.
Side Effect
다만 Lombok 이라는 편리한 도구를 통해 간결하게 구현할 수 있었지만 Lombok 또한 잘못 사용하게 되면 개발자가 의도하지 않은바로 로직이 동작하게 되는 경우가 있습니다. @Data, @AllArgsConstructor, @RequiredArgsConstructor등등이 Lombok에서 사이드이펙트가 발생할 여지가 높은 애노테이션들 입니다.
해당 사이드 이펙트에 대해서는 앞서 선대 개발자분들께서 이미 잘 정리해놓은 내용들이 있기 때문에 아래 링크를 통해 전달드리도록 하겠습니다
https://kwonnam.pe.kr/wiki/java/lombok/pitfall
Side Effect가 있음에도 왜 Lombok을 도입해야하는가?
저는 은총알은 없다라는 말을 정말 좋아합니다. 내가 좋아하는 물건은 누군가에는 필요없는 물건일 수 있고 내가 흥미로워하는 분야는 누구에게는 고리타분한 분야일 수 있습니다. 이말은 모두를 만족할 수 있는 수단은 없다라는 의미입니다. 그러면 새로운 기술을 도입할때 판단해야할 부분은 무엇인가를 생각해 보았을때 이 기술을 도입하면서 고려해야할 사이드 이펙트보다 취할 이점이 더 크다면 도입하는 방향으로 가는게 좋다고 생각합니다 (물론 개발조직에서 해당 기술에 대한 사이드 이펙트와 이점을 충분히 논의한후 모두의 동의가 가장 중요한 부분이긴 합니다).
이러한 근거로 판단했을때 Lombok의 사이드 이펙트는 선대의 개발자들이 정의해놓은 사이드 이펙트에 대한 방지 대책을 팀의 룰로 정의하고 사용한다면 고려해야할 사이드 이펙트 대비 취할 이점이 크다 생각하여 Lombok도입을 건의하기로 하였습니다.
Side Effect를 어떻게 방지할 것인가?
결국 모두가 동의하는 Ground Rule에 Lombok 주의사항, 사용방법을 정의하고 모두가 해당룰을 준수하며 코드를 작성하고 코드 리뷰를 통해 모두가 코드룰을 준수하는지 체크하는 방향으로 진행해야한다고 생각합니다. 그러면 만약 코드작성자, 코드 리뷰어들이 Lombok 사이드 이펙트가 발생할 수 있는 코드를 확인하지 못하는 휴먼 에러가 발생할때는 어떻게 할 것인가 에 대한 고민이 있을 수 있는데 Lombok에서는 config파일을 통해서 사용제한을 하여 만약 허용을 하지 않는 Lombok기능을 사용할 경우 컴파일 단계에서 오류를 발생시켜 휴먼에러를 방지할 수 있습니다.
// lombok.config
# @Getter, @Setter, @Builder, @NoArgsConstructor만 허용하고 나머지는 비활성화
lombok.allArgsConstructor.flagUsage=error
lombok.requiredArgsConstructor.flagUsage=error
lombok.data.flagUsage=error
lombok.value.flagUsage=error
lombok.toString.flagUsage=error
lombok.equals.flagUsage=error
lombok.equalsAndHashCode.flagUsage=error
lombok.slf4j.flagUsage=error
lombok.log.flagUsage=error
lombok.synchronized.flagUsage=error
lombok.cleanup.flagUsage=error
Lombok에서 자주사용하는 기능인 @Getter, @Setter, @Builder, @NoArgsConstructor만 사용하고 그외 기능들은 전부 비활성화 하고싶다면 lombok.config를 통해 허용여부를 설정하여 휴먼에러를 방지할 수 있습니다. 해당 lombok.config파일은 자바 프로젝트 root위치에 존재해야 해당 설정이 적용됩니다.
글을 정리하며..
정말 당연시 사용해왔고 롬복 도입을 고민해야해? 라는 생각도 있지만 프로젝트 도메인별로 기술 도입에 대해 보수적으로 생각해야되는 부분도 있을 수 있다는 생각을 할 수 있었고 당연시 해왔던 Lombok에 대해 내가 취하던 이점은 무엇이고 관리해야했던 사이드 이펙트들은 무엇인지 다시한번 글로서 정리할 수 있엇던 귀중한 시간이였던것 같습니다.
'Spring > experience' 카테고리의 다른 글
SpringFramework NullPointException 방지법 (0) | 2025.01.13 |
---|---|
Spring Boot Batch 프로젝트에서 Webclient 사용시 주의점 (0) | 2024.12.05 |
Spring Framework ResponseEntity 사용에 대한 고찰 (0) | 2024.11.17 |
현업에서 자주 사용한 Java Stream Api (3) | 2024.11.10 |
스프링 서버가 우아하게 죽는법 "Graceful Shutdown" (0) | 2024.09.10 |