자바 언어·플랫폼 용어 사전
모던 자바sealed · 패턴 매칭 · switch 식

record

값 객체의 보일러플레이트를 없애는 타입. sealed·패턴 매칭과 짝을 이뤄 대수적 데이터 타입을 만든다.

데이터를 담는 것이 목적인 클래스의 보일러플레이트를 없앤 타입(Java 16 정식).

record Point(int x, int y) { }

// 자동으로 생기는 것
// · private final 필드 x, y
// · 표준 생성자
// · 접근자 x() · y()   (getX() 가 아니다)
// · equals · hashCode · toString

검증은 컴팩트 생성자에서

record Point(int x, int y) {
    Point {                                   // 파라미터 목록도 대입도 없다
        if (x < 0 || y < 0) throw new IllegalArgumentException();
        x = Math.min(x, 100);                 // 값을 보정할 수도 있다
    }
}

얕은 불변이다

record Order(Long id, List<String> items) { }
var list = new ArrayList<String>();
var o = new Order(1L, list);
list.add("변경");                              // o.items() 가 바뀐다

// 방어적 복사를 직접 해야 한다
record Order(Long id, List<String> items) {
    Order { items = List.copyOf(items); }
}

sealed — 닫힌 계층

sealed interface Result permits Success, Failure { }
record Success(String data) implements Result { }
record Failure(String reason) implements Result { }

"이 인터페이스를 구현할 수 있는 건 이 둘뿐" 을 컴파일러에게 알려 준다

  • switch 에서 default 없이 망라 검사가 가능해진다
  • 새 구현을 추가하면 모든 switch 가 컴파일 에러로 알려 준다 ← 결정적 이득

패턴 매칭 switch

String describe(Result r) {
    return switch (r) {
        case Success(String data) -> "성공: " + data;    // 레코드 분해(deconstruction)
        case Failure(String reason) -> "실패: " + reason;
        // default 가 필요 없다 — sealed 라 컴파일러가 전부임을 안다
    };
}
// instanceof 패턴 — 캐스팅이 사라진다
if (obj instanceof Member m && m.age() > 20) { ... }   // m 을 바로 쓴다

// 조건을 덧붙이는 when 절
case Success(String d) when d.isEmpty() -> "빈 성공";

왜 강력한가 — 대수적 데이터 타입

  • sealed(선택지가 닫혀 있다) + record(각 선택지의 데이터)

    • = 상태를 타입으로 표현한다
  • 예전: — status 필드 + if-else 체인 + "이 상태에서 이 필드는 null" 이라는 암묵적 규칙

  • 지금: — 각 상태가 자기 데이터를 갖는 별도 타입 → 컴파일러가 누락을 잡아 준다

record가 안 맞는 곳

  • JPA 엔티티 — 기본 생성자와 가변 필드가 필요하다 (프록시·변경 감지)

  • 상속이 필요한 경우 — record 는 final 이고 확장할 수 없다

  • 필드가 많고 일부만 채우는 경우 — 빌더가 더 낫다

  • 잘 맞는 곳: DTO · 응답 모델 · 값 객체 · 다중 반환 · 맵의 복합 키

면접 함정

  • "record는 불변이다" → 얕은 불변이다. 가변 필드를 담으면 깨진다.
  • "record의 게터는 getX()" → 필드명 그대로 x()다.

함께 보면 좋은 용어

노트에서 맥락과 함께 보기 — 모듈·모던 Java