“The ratio of time spent reading vs. writing code is well over 10 to 1. Making it easy to read makes it easier to write.” — Robert C. Martin — Author of Clean Code: A Handbook of Agile Software Craftsmanship
위 저자의 말을 해석하면 이렇습니다. -> "코드를 읽는 데 소요되는 시간 대 코드를 작성하는 데 소요되는 시간 비율은 10 대 1을 웃돌 정도입니다. 읽기 쉽게 만들면 쓰기가 쉬워집니다."
먼저 전통적인 방식으로 프로젝트에서 User라는 클래스를 정의하고 사용해보겠습니다.
public class User {
private String username;
private String email;
private int userId;
public User(String username, String email, int userId) {
this.username = username;
this.email = email;
this.userId = userId;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
public int getUserId() {
return userId;
}
public void setUserId(int userId) {
this.userId = userId;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
User user = (User) o;
if (userId != user.userId) return false;
if (username != null ? !username.equals(user.username) : user.username != null) return false;
return email != null ? email.equals(user.email) : user.email == null;
}
@Override
public int hashCode() {
int result = username != null ? username.hashCode() : 0;
result = 31 * result + (email != null ? email.hashCode() : 0);
result = 31 * result + userId;
return result;
}
@Override
public String toString() {
return "User{" +
"username='" + username + '\'' +
", email='" + email + '\'' +
", userId=" + userId +
'}';
}
}
세가지 값(username, email, userId)을 저장하고 사용하는 데에 65줄 정도의 코드가 필요합니다.
여기서 Lombok 라이브러리를 사용하면 훨씬 줄여서 사용할 수 있읍니다. Lombok은 Java클래스와 관련된 boilerplate 코드를 줄여줄 수 있습니다.
import lombok.Data;
@Data
public class User {
private String username;
private String email;
private int userId;
}
@Data 어노테이션은 모든 필드에 대한 모든 게터 함수, 세터 함수, toString 함수, 생성자, hashCode 및 equals 함수를 자동으로 생성해줍니다!
그러나 Lombok 사용에는 몇 가지 문제가 있습니다:
1. 외부 종속성: 이런 사소한 일들을 위해 외부 라이브러리에 의존하게 됩니다. Lombok은 라이브러리의 유지 보수를 위해 커뮤니티 지원에 의존하는데요.. 라이브러리와의 호환성 문제나 라이브러리가 더 이상 지원되지 않든다면?? 바로 코드베이스에 문제가 발생할 수 있습니다.
2. IDE 호환성: Lombok은 애플리케이션 컴파일 시 코드 생성에 의존하며, 바로 모든 개발 환경(IDE) 에서 항상 원활하게 작동하지 않을 수 있습니다. 일부 IDE는 Lombok 기능을 완전히 지원하지 않아 생성된 코드를 이해하고 탐색하기 어려울 수 있습니다 ㅜㅜ
그럼 더 나은 대안이 있을까요? 바로 Java의 Records를 사용할 수 있을 것 같습니다.!!!
Records는 Java 14부터 도입된 새로운 기능으로, Java 16에서 공식적으로 도입되었습니다. Records는 주로 데이터를 캡슐화하는 데 사용되는 간단한 클래스를 간결하게 정의하는 방법을 제공합니다. 필드를 기반으로 생성자, equals(), hashCode(), toString()과 같은 일반적인 메서드를 자동으로 생성하는 클래스의 한 유형입니다.
즉, Lombok과 Records 둘 다 동일한 목표를 달성할 수 있는 것입니다.
Records를 사용하는 방법은 다음과 같습니다.
public record UserRecord(String username, String email, int userId) {
}
위와 같이 전통적인 코딩으로 65줄, Lombok으로 5줄로 했던 것을 한줄로 단축할 수 있습니다. 더불어 외부 라이브러리에 의존할 필요도 없습니다.
Records 클래스를 만든 후에는 Java 내부적으로 세 개의 final 변수와 그에 대한 게터 메서드를 정의하며, 이외에도 toString, hashCode 및 equals와 같은 클래스 수준의 메서드를 정의합니다.
Records에 대해 좀 더 자세히 알아보자면, lombok과 조금 다른 점은 'get'키워드 없이 getter메소드를 사용합니다. 예를들면 lombok 사용시 getEmail()로 조회하던것을 Records에서는 아래처럼 email()로 호출합니다.
// Record 초기화
UserRecord userRecord = new UserRecord("rana", "rana@yopmail.com", 1234);
// 속성 얻기
System.out.println(userRecord.email());
System.out.println(userRecord.toString());
그 외에도 Records가 가지는 특징은 더 있으나, Lombok과의 비교는 아니므로 관련 내용은 찾아보시는게 좋을 것 같습니다!
마지막으로 Lombok과 Records를 빠르게 비교해보면 다음과 같습니다!
성능 차이가 있을까요?
NO!!입니다. 성능 측면에서는 Java Records와 Lombok 어노테이션을 사용하는 것 사이에 큰 차이가 없다고 합니다. 둘 다 성능 특성 측면에서는 컴파일된 후에 손으로 작성된 코드와 별 다를 게 없습니다. 따라서 생성된 코드는 Java 컴파일러에 의해 최적화되므로 성능 overhead등이 전혀 없습니다.
결론:
이 글은 더 깨끗하고 읽기 쉬운 코드를 작성하기 위해 Records를 사용할 수 있습니다. Records는 외부 라이브러리 없이 보일러플레이트 코드를 줄이는 데 도움도 된다고 봤습니다..! Lombok은 일부 IDE와의 호환성 문제가 있기때문에 이런 문제가 없는 Records를 써보는게 어떨까 생각했습니다. 아직 실무에서 써보진 않지만 언젠가 쓰겠죠.?
Lombok은 오래된 Java 버전에서 작업하거나 확장 가능하고 가변 클래스를 작성하려는 경우에만 사용해야 합니다. 그 외 대부분의 목적에 대해 Records가 나은 선택일 것 같습니다!