Java Record와 Sealed Classes
Java 14에서 도입된 Record와 Java 17에서 정식 도입된 Sealed Classes는 데이터 클래스와 상속을 보다 명확하게 관리할 수 있도록 도와줍니다. 이 글에서는 실제 개발 경험을 바탕으로 두 개념을 어떻게 활용하면 좋은지 살펴보겠습니다.
1. Java Record: 불변 데이터 클래스 간소화
자바에서는 데이터를 저장하는 용도로 클래스를 만들 때 일반적으로 getter
, toString
, equals
, hashCode
를 구현해야 했습니다. 하지만 Record를 사용하면 이런 반복적인 코드 작성을 줄일 수 있습니다.
1.1 기존 방식의 데이터 클래스
public class Person {
private final String name;
private final int age;
public Person(String name, int age) {
this.name = name;
this.age = age;
}
public String getName() { return name; }
public int getAge() { return age; }
@Override
public boolean equals(Object o) { /* equals 구현 */ }
@Override
public int hashCode() { /* hashCode 구현 */ }
@Override
public String toString() { return "Person[name=" + name + ", age=" + age + "]"; }
}
1.2 Record를 사용한 간결한 코드
public record Person(String name, int age) {}
Record를 사용하면 생성자, getter, toString()
, equals()
, hashCode()
가 자동으로 생성됩니다.
2. Sealed Classes: 상속 제한
자바에서는 기본적으로 클래스의 상속을 제어하기 어려웠습니다. 하지만 Java 17부터 도입된 Sealed Classes를 활용하면 어떤 클래스가 상속받을 수 있는지 명확하게 제한할 수 있습니다.
2.1 기존 상속의 문제
기존 방식에서는 어떤 클래스가 상속받을지 제한하려면 final
을 사용하거나 문서화를 해야 했습니다.
2.2 Sealed Class를 이용한 상속 제어
public sealed class Shape permits Circle, Rectangle {}
public final class Circle extends Shape {}
public final class Rectangle extends Shape {}
이렇게 하면 Shape
를 상속할 수 있는 클래스는 Circle
과 Rectangle
로 제한됩니다.
3. Record와 Sealed Classes를 함께 활용
이 두 개념을 함께 사용하면 불변 데이터를 유지하면서도 안전한 상속 구조를 만들 수 있습니다.
public sealed interface Vehicle permits Car, Truck {}
public record Car(String model, int year) implements Vehicle {}
public record Truck(String model, int capacity) implements Vehicle {}
4. Record의 활용 사례
Record는 불변 객체를 만들기 때문에 DTO(Data Transfer Object)나 설정 정보를 저장하는 용도로 많이 사용됩니다.
public record AppConfig(String apiUrl, int timeout) {}
이처럼 설정 정보를 record
로 정의하면 불필요한 boilerplate 코드를 줄일 수 있습니다.
5. Sealed Class와 패턴 매칭
Sealed Class를 사용하면 패턴 매칭을 활용해 타입 검사를 더욱 안전하게 수행할 수 있습니다.
sealed interface Payment permits CreditCard, Cash {}
record CreditCard(String number) implements Payment {}
record Cash(int amount) implements Payment {}
public class PaymentProcessor {
public static void process(Payment payment) {
switch (payment) {
case CreditCard cc -> System.out.println("Processing credit card: " + cc.number());
case Cash cash -> System.out.println("Processing cash payment: " + cash.amount());
}
}
}
6. 끝으로
Java Record와 Sealed Classes는 불필요한 코드를 줄이면서도 유지보수성을 높이는 강력한 도구입니다. 실무에서 적극적으로 활용하면 개발 효율성을 높일 수 있습니다.
Comments
Post a Comment