레코드, 클래스, Lombok 비교
적절한 도구를 선택할 수 있도록 레코드와 전통적인 클래스, Lombok 주석을 비교합니다.
레코드, 클래스, Lombok 비교은(는) CoddyKit의 무료 Java Academy 강의입니다. 이것은 4개 중 4번째 강의입니다. 아래에서 전체 강의를 무료로 읽을 수 있으며, 내장 코드 에디터와 24/7 AI 튜터와 함께 브라우저에서 직접 실습할 수 있습니다. 이 강의는 Java Academy 학습 경로의 일부이며, 진행 상황이 웹과 CoddyKit 앱에 동기화됩니다. Java Academy 강의에는 총 4개의 강의가 포함되어 있습니다.
레코드, 클래스, Lombok 비교
Java에서는 데이터를 전달하는 타입을 만드는 여러 방법을 제공합니다. 반복 코드가 있는 일반 클래스, 레코드(Java 16 이상), Lombok 어노테이션을 사용할 수 있습니다. 올바른 선택은 사용 사례에 따라 달라집니다.
반복 코드 문제
단순한 데이터 전달 객체를 위한 일반 Java 클래스에는 생성자, 접근자, equals, hashCode, toString 등 몇 개의 필드만을 위해서도 상당한 반복 코드가 필요합니다.
// Traditional class — lots of boilerplate
class ProductOld {
private final String id;
private final String name;
private final double price;
public ProductOld(String id, String name, double price) {
this.id = id; this.name = name; this.price = price;
}
public String getId() { return id; }
public String getName() { return name; }
public double getPrice() { return price; }
@Override public boolean equals(Object o) { /* ... */ }
@Override public int hashCode() { /* ... */ }
@Override public String toString() { /* ... */ }
}레코드 솔루션
레코드를 사용하면 같은 클래스를 한 줄로 줄일 수 있습니다. 컴파일러가 모든 반복 코드를 자동으로 생성합니다.
// Record — one line, same functionality
record Product(String id, String name, double price) {}
// Usage is almost identical except accessors use component names (no get prefix)
Product p = new Product("P001", "Laptop", 999.99);
System.out.println(p.id()); // P001 (not getId())
System.out.println(p.name()); // Laptop
System.out.println(p.price()); // 999.99
System.out.println(p); // Product[id=P001, name=Laptop, price=999.99]Lombok의 @Data와 @Value
Lombok은 어노테이션을 통해 컴파일 시 반복 코드를 생성합니다. @Value는 레코드와 비슷한 변경 불가능한 클래스를 만들고, @Data는 변경 가능한 클래스를 만듭니다.
// Lombok @Value — immutable (closest to record)
import lombok.Value;
@Value
public class LombokProduct {
String id;
String name;
double price;
// Lombok generates: all-args constructor, getters, equals, hashCode, toString
// Note: accessors follow getX() naming convention (getPrice(), not price())
}
// Lombok @Data — mutable
import lombok.Data;
@Data
public class MutableProduct {
private String id;
private String name;
private double price;
// Generates: getters, setters, equals, hashCode, toString, no-args constructor
}주요 차이점
레코드, Lombok @Value 및 일반 클래스의 중요한 차이점은 다음과 같습니다.
- 접근자 명명: 레코드는
name()을 사용하고, Lombok은getName()을 사용합니다 - 가변 변형: 레코드는 항상 불변이며, Lombok은 가변성을 위한 @Data를 제공합니다
- 상속: 레코드는 클래스를 확장할 수 없지만, Lombok 클래스는 확장할 수 있습니다
- 빌드 도구 의존성: Lombok은 주석 처리기 설정이 필요하지만, 레코드는 기본 제공됩니다
레코드를 사용하는 경우
다음과 같은 경우 레코드가 적합합니다.
- 형식이 주로 투명한 데이터 전달 객체(DTO, 값 객체)인 경우
- 설계상 불변성이 필요한 경우
- Java 16 이상을 사용하며 의존성을 전혀 추가하고 싶지 않은 경우
- 형식이 패턴 매칭에 참여하는 경우(sealed + 레코드)
// Perfect record use cases:
record Coordinates(double lat, double lon) {}
record JwtClaims(String subject, String role, long expiresAt) {}
record PageRequest(int page, int size, String sortBy) {}
record ErrorResponse(int code, String message, String path) {}
// These are all simple data carriers with no mutable stateLombok을 사용하는 경우
다음과 같은 경우 Lombok을 선호합니다.
- 가변 JavaBeans가 필요한 경우(예: JPA 엔터티, Spring 설정 클래스)
- 프레임워크와의 호환성을 위해 접근자 명명이 JavaBeans 규칙(
getX)을 따라야 하는 경우 - 복잡한 객체 생성을 위해
@Builder가 필요한 경우 - 일부 필드에 부분적인 가변성이 필요한 경우(
@NonFinal사용)
// Lombok @Builder — great for complex object construction
import lombok.*;
@Builder
@Value
public class EmailMessage {
String to;
String from;
String subject;
String body;
List<String> attachments;
}
EmailMessage msg = EmailMessage.builder()
.to("user@example.com")
.from("noreply@app.com")
.subject("Welcome!")
.body("Thank you for signing up")
.attachments(List.of())
.build();일반 클래스를 사용하는 경우
다음과 같은 경우 일반 클래스가 여전히 적합합니다.
- 클래스가 단순한 데이터 전달을 넘어 복잡한 동작을 포함하는 경우
- 다른 클래스를 확장해야 하는 경우
- hashCode/equals를 세밀하게 제어해야 하는 경우
- 캡슐화를 적용한 가변 상태가 필요한 경우
// Plain class — when behavior dominates over data
class ShoppingCart {
private final List<CartItem> items = new ArrayList<>();
private final String customerId;
public ShoppingCart(String customerId) {
this.customerId = customerId;
}
public void addItem(CartItem item) { items.add(item); }
public void removeItem(String sku) { items.removeIf(i -> i.sku().equals(sku)); }
public double total() { return items.stream().mapToDouble(CartItem::lineTotal).sum(); }
public boolean isEmpty() { return items.isEmpty(); }
}레코드와 클래스 함께 사용하기
레코드와 클래스는 원활하게 함께 사용할 수 있습니다. 가변 상태를 관리하는 클래스 내부의 불변 데이터에는 레코드를 사용하십시오.
// Record for the immutable event data
record UserEvent(String userId, String action, java.time.Instant timestamp) {
public static UserEvent now(String userId, String action) {
return new UserEvent(userId, action, java.time.Instant.now());
}
}
// Class for the mutable event store
class EventLog {
private final List<UserEvent> events = new ArrayList<>();
public void record(String userId, String action) {
events.add(UserEvent.now(userId, action));
}
public List<UserEvent> eventsFor(String userId) {
return events.stream()
.filter(e -> e.userId().equals(userId)).toList();
}
}Spring Boot에서 레코드 사용하기
레코드는 Spring Boot에서 요청/응답 body로 사용할 때 잘 통합됩니다. Spring Boot의 Jackson 매퍼는 최소한의 설정만으로 레코드를 처리합니다.
// Spring Boot REST controller using records
import org.springframework.web.bind.annotation.*;
record CreateProductRequest(String name, double price, String category) {}
record ProductResponse(long id, String name, double price, String category) {}
@RestController
@RequestMapping("/api/products")
class ProductController {
@PostMapping
public ProductResponse create(@RequestBody CreateProductRequest req) {
// Jackson automatically deserializes JSON into the record
long id = productService.save(req);
return new ProductResponse(id, req.name(), req.price(), req.category());
}
}성능 비교
세 가지 방식 모두 단순한 데이터 전달 객체에 대해 본질적으로 동일한 바이트코드를 생성합니다. 성능도 동일하므로, 선택 기준은 개발자 경험과 요구 사항입니다.
// All three compile to approximately equivalent bytecode:
// - Records: compiler-generated, always immutable
// - Lombok @Value: annotation-processor-generated, always immutable
// - Plain class: hand-written
// The key runtime difference:
// Records: accessor is a method matching field name (price() not getPrice())
// Lombok/Class: accessor follows JavaBeans (getPrice())
// Jackson compatibility:
// Records: work natively in Jackson 2.12+ with no config
// Lombok: work with @JsonProperty or jackson-databind-lombok module빠른 확인
레코드 접근자는 어떤 명명 규칙을 따릅니까?
복습: 레코드와 클래스와 Lombok
핵심 내용:
- 레코드는 생성자, 접근자(get 접두사 없음), equals, hashCode, toString을 자동으로 생성합니다
- 레코드는 항상 불변이므로, 가변 상태에는 일반 클래스를 사용하십시오
- Lombok @Value는 레코드와 비슷한 기능을 제공하지만 getX() 명명을 사용하고 설정이 필요합니다
- Lombok @Builder는 선택적 필드가 많은 복잡한 객체 생성에 특히 적합합니다
- 레코드는 DTO, 값 객체, API 요청/응답 body에 적합합니다
- 동작이 중심이거나 상속이 필요한 경우에는 일반 클래스가 여전히 가장 적합합니다
자주 묻는 질문
“레코드, 클래스, Lombok 비교” 강의는 무료인가요?
네 — “레코드, 클래스, Lombok 비교” 전체 내용을 이 웹사이트에서 무료로 읽을 수 있습니다. 인터랙티브하게 실습하려면(내장 코드 에디터와 24/7 AI 튜터), CoddyKit PRO로 업그레이드하면 Java Academy 강의 전체를 잠금 해제할 수 있습니다. Java Academy 강의에는 총 4개의 강의가 포함되어 있습니다.
“레코드, 클래스, Lombok 비교”에서 뭘 배우나요?
적절한 도구를 선택할 수 있도록 레코드와 전통적인 클래스, Lombok 주석을 비교합니다. 브라우저에서 직접 실행하는 실습 코드로 Java Academy을(를) 배우며, 24/7 AI 튜터가 강의를 진행하면서 질문에 답변해줍니다.
Java Academy을(를) 시작하는 데 경험이 필요한가요?
사전 경험은 필요하지 않습니다. CoddyKit의 Java Academy은(는) 초급자부터 고급 학습자까지를 위해 구성되어 있으므로, 여기서 시작하거나 처음부터 시작할 수 있으며 자신의 속도대로 진행할 수 있습니다. 이것은 4개 중 4번째 강의입니다.
“레코드, 클래스, Lombok 비교” 강의는 얼마나 걸리나요?
대부분의 CoddyKit 강의는 약 5~10분이 소요됩니다. 각 강의는 간결하고 인터랙티브하여 꾸준한 진행이 가능하며, 웹과 앱에서 중단한 부분부터 바로 시작할 수 있습니다.
이 Java Academy 강의에서 코드를 작성하고 실행할 수 있나요?
네. 모든 Java Academy 강의에는 내장 코드 에디터가 포함되어 있으므로, 브라우저에서 바로 실제 코드를 작성하고 실행한 후 즉시 AI 피드백을 받을 수 있습니다 — 로컬 설정이 필요 없습니다.
이 강의의 모든 강의
- 레코드 소개
- 간결한 생성자와 유효성 검사
- 레코드의 사용자 정의 메서드
- 레코드, 클래스, Lombok 비교