
spring boot를 공부할 때 lombok은 많은 편의를 가져다주는 좋은 툴이라고 할 수 있다.
지금부터 간단하게 lombok에 대해 알아가는 시간을 가져보겠다.
lombok 이란?
간단하게 정의하자면 lombok은 자바 개발에서 반복적인 코드 작성을 줄여 개발 생산성을 높이기 위해 사용한다.
개발자들은 객체를 생성해 getter/setter 그리고 toString 메서드를 만든다.
처음엔 개발 초기 단계라 깔끔하게 할 수 있다 하더라도 잦은 수정과 필드명의 변경, 추가에 따라 관리하는 것이 쉽지 않다.
이런 경우에 롬복을 사용하면 자바 클래스를 만들 때 사용되는 getter/setter나 toString 등의 코드들을 @(어노테이션)으로 대체해서 선언하고 java 코드를 만든다.
시각적으로 보기 좋게 정리해보자.
Lombok의 역할
1. 자동으로 Getter/Setter 생성 :
- @Getter, @Setter 어노테이션을 사용하면 필드에 대한 getter와 setter 메서드를 자동으로 생성한다.
2. 생성자 자동 생성 :
- @NoArgsConstructor, @AllArgsConstructor, @RequiredArgsConstructor과 같은 어노테이션을 사용해서 기본 생성자, 모든 필드를 매개변수로 받는 생성자, 필수 필드만 받는 생성자를 자동으로 생성할 수 있다.
3. toString, equals, hashCode 메서드 자동 생성 :
- @ToString, @EqualsAndHashCode 어노테이션을 사용하면 이 메서드들을 자동으로 생성한다.
4. 빌더 패턴 지원 :
- @Builder 어노테이션을 사용하면 빌더 패턴을 쉽게 구현 가능하다.
5. 로그 자동 생성 :
- @Slf4j, @Log4j와 같은 어노테이션을 통해 로그 객체를 자동으로 생성할 수 있다.
6. 데이터 클래스 자동 생성
- @Data 어노테이션은 getter/setter, toString, equals, hashCode, RequiredArgsConstructor 등을 한 번에 생성해준다.
이렇게 편한 lombok 이지만 단점이 존재하는데, 바로 컴파일 타임에 코드에 개입하므로, 디버깅할 경우 코드가 보이지 않아 디버깅이 어려울 수 있다는 단점이 존재한다.
이제 lombok 어노테이션에 대해 설명해보겠다.
자주 사용하는 lombok 어노테이션
@Getter/@Setter
만약 @Getter을 사용하지 않는다면?
public class Product {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long number;
@Column(nullable = false)
private String name;
@Column(nullable = false)
private Integer price;
@Column(nullable = false)
private Integer stock;
private LocalDateTime createdAt;
private LocalDateTime updatedAt;
public Long getNumber() {
return this.number;
}
public String getName() {
return this.name;
}
public Integer getPrice() {
return this.price;
}
public Integer getStock() {
return this.stock;
}
public LocalDateTime getCreatedAt() {
return this.createdAt;
}
public LocalDateTime getUpdatedAt() {
return this.updatedAt;
}
}
굉장히 반복작업이 많은 것이 보인다.
@Getter 사용
@Getter
public class Product {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long number;
@Column(nullable = false)
private String name;
@Column(nullable = false)
private Integer price;
@Column(nullable = false)
private Integer stock;
private LocalDateTime createdAt;
private LocalDateTime updatedAt;
}
생성자 자동 생성 관련 어노테이션
1. @NoArgsConstructor
- @NoArgsConstructor은 매개변수가 없는 기본 생성자를 자동으로 생성한다.
- 객체를 기본 상태로 초기화할 때 유용하다.
import lombok.NoArgsConstructor;
import lombok.Getter;
import lombok.Setter;
@NoArgsConstructor
@Getter
@Setter
public class Product {
private Long number;
private String name;
private Integer price;
private Integer stock;
// Lombok에 의해 다음과 같은 기본 생성자가 자동으로 생성.
// public Product() { }
}
Product 클래스에 기본 생성자를 추가한다.
2. @AllArgsConstructor
- 모든 필드를 매개변수로 받는 생성자를 생성한다.
Lombok을 사용하여 복잡한 생성자 작성 시간이 단축되는 장점이 생긴다.
import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.Setter;
@AllArgsConstructor
@Getter
@Setter
public class Product {
private Long number;
private String name;
private Integer price;
private Integer stock;
}
lombok을 사용하지 않았다면 모든 필드를 초기화하는 생성자 코드를 추가로 작성해야 하므로 코드가 길어지고 유지보수가 어려워질 수 있다.
import lombok.Getter;
import lombok.Setter;
@Getter
@Setter
public class Product {
private Long number;
private String name;
private Integer price;
private Integer stock;
// 수동으로 작성한 모든 필드를 초기화하는 생성자
public Product(Long number, String name, Integer price, Integer stock) {
this.number = number;
this.name = name;
this.price = price;
this.stock = stock;
}
}
이렇게 추가적인 코드가 생긴다.
3. @RequiredArgsConstructor
- final 필드와 @ NonNull 어노테이션이 붙은 필드에 대한 생성자를 자동으로 생성해주는 기능을 제공한다.
- 여기서 NonNull이란 메서드의 매개변수나 필드가 null 값이 아닌 값이어야 한다는 것을 명시하고자 하는 Lombok 어노테이션이다.
import lombok.RequiredArgsConstructor;
import lombok.Getter;
@RequiredArgsConstructor
@Getter
public class Product {
private final Long number;
private final String name;
private Integer price;
private Integer stock;
// Lombok에 의해 자동으로 생성되는 생성자:
// public Product(Long number, String name) {
// this.number = number;
// this.name = name;
// }
}
@ToString
ToString 어노테이션의 기능
- 자동 생성 : 클래스의 모든 필드를 포함하여 toString() 메서드를 자동으로 생성한다.
- 옵션 설정 : 기본적으로 모든 필드를 포함하지만 특정 옵션을 설정하여 포함할 필드를 조절할 수 있다.
import lombok.ToString;
@ToString
public class Product {
private Long number;
private String name;
private Integer price;
private Integer stock;
}
이 코드에서 @ToString을 생성하면 toString() 메서드가 자동으로 생성된다.
@Override
public String toString() {
return "Product(number=" + number + ", name=" + name + ", price=" + price + ", stock=" + stock + ")";
}
이 메서드를 사용하지 않아도 자동으로 생성되는 것이다.
@ToString의 주요 옵션
옵션:
- includeFieldNames: 필드 이름을 포함할지 여부
- exclude: 특정 필드를 제외
- callSuper: 상위 클래스의 toString() 메서드 호출 여부
- of: 포함할 필드를 직접 지정
이렇게 크게 네 가지 옵션이 있다. 자세히 알아보자.
1. includeFieldNames > 필드 이름을 포함할지 여부를 결정한다. 기본값은 true이다.
@ToString(includeFieldNames = false)
public class Product {
private Long number;
private String name;
private Integer price;
private Integer stock;
}
이 경우에 생성된 toString() 메서드는 필드 이름을 포함하지 않는다.
@Override
public String toString() {
return "Product(number=" + number + ", name=" + name + ", price=" + price + ", stock=" + stock + ")";
}
2. exclude > 특정 필드를 toString() 메서드에서 제외할 수 있다.
@ToString(exclude = {"price", "stock"})
public class Product {
private Long number;
private String name;
private Integer price;
private Integer stock;
}
이 경우 price와 stock 필드는 메서드에 포함되지 않는다.
3. callSupser > 상위 클래스의 toString() 메서드를 호출할지 여부를 결정한다. 기본값은 false이다.
@ToString(callSuper = true)
public class Product extends SomeSuperClass {
private Long number;
private String name;
private Integer price;
private Integer stock;
}
이렇게 SomeSuperClass에 있는 상위 클래스의 toString() 메서드가 호출되고 현재 클래스의 필드가 추가된다.
4. of > toString() 메서드에서 포함할 필드를 직접 지정할 수 있다.
@ToString(of = {"number", "name"})
public class Product {
private Long number;
private String name;
private Integer price;
private Integer stock;
}
이 경우엔 number과 name 필드만 메서드에 포함된다.
@Override
public String toString() {
return "Product(number=" + number + ", name=" + name + ")";
}
@EqualsAndHashCode
@EqualsAndHashCode 어노테이션은 객체의 동등성(equals)과 동일성(hashCode)을 비교하는 연산 메서드를 생성한다.
동등성은 두 객체의 내용이 같은지
동일성은 두 객체가 같은 객체인지이다.
import lombok.EqualsAndHashCode;
@EqualsAndHashCode
public class Product {
private Long number;
private String name;
private Integer price;
private Integer stock;
}
이 경우에 자동으로 생성된 메서드는 다음과 같다.
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Product product = (Product) o;
return Objects.equals(number, product.number) &&
Objects.equals(name, product.name) &&
Objects.equals(price, product.price) &&
Objects.equals(stock, product.stock);
}
@Override
public int hashCode() {
return Objects.hash(number, name, price, stock);
}
@EqualsAndHashCode의 주요 옵션
옵션:
- callSuper: 상위 클래스의 메서드 호출 여부 설정
- of: 특정 필드만을 사용하여 비교 및 해시 코드 생성
- exclude: 특정 필드를 제외하여 비교 및 해시 코드 생성
callSuper > 상위 클래스의 equals() 및 hashCode() 메서드를 호출할지 여부를 설정한다. 기본값은 false이다.
@EqualsAndHashCode(callSuper = true)
public class Product extends BaseEntity {
// 필드 정의
}
of > 비교 및 해시 코드를 생성할 때 사용할 특정 필드를 지정할 수 있다.
필드를 명시적으로 지정하면, 지정된 필드만을 기준으로 equals() 및 hashCode()를 생성한다.
@EqualsAndHashCode(of = {"number", "name"})
이 경우엔 메서드에 number과 name 필드만을 사용해서 equals() 및 hashCode()를 생성한다.
exclude > 비교 및 해시 코드 생성을 제외할 필드를 지정할 수 있다.
@EqualsAndHashCode(exclude = {"price", "stock"})
이 경우 price와 stock 필드를 equals() 및 hashCode() 계산에서 제외된다.
@Data
@Data는 앞의 모든 어노테이션을 포함하는 어노테이션이다.
'Backend > Spring Boot' 카테고리의 다른 글
코드로 알아보는 생성자 주입(DI) feat. 리팩토링 (5) | 2024.10.05 |
---|---|
[Spring] 스프링 빈(Bean)이란? (1) | 2024.09.10 |
MVC 패턴 (63) | 2024.08.18 |
spring-boot-devtools 라이브러리를 통한 핫 리로드 활성화 (35) | 2024.07.24 |
Maven과 Gradle (18) | 2024.06.19 |