## Derived Record Creation (JEP 468)
JEP 468은 Java의 **Record(레코드)** 클래스를 사용할 때, 기존 인스턴스를 바탕으로 **일부 값만 변경된 새로운 인스턴스를 쉽게 생성**할 수 있게 해주는 **'Derived Record Creation(유도된 레코드 생성)'** 기능을 도입하려는 제안입니다. (현재 JDK 23에서 Preview 단계입니다.)
핵심 내용을 쉽게 풀어서 해설해 드리겠습니다.
---
### 1. 배경: 왜 필요한가?
레코드는 **불변(Immutable)** 데이터 객체입니다. 따라서 값을 바꾸고 싶을 때 기존 객체의 필드를 수정하는 것이 아니라, 바뀐 값을 가진 **새로운 객체**를 만들어야 합니다.
기존에는 다음과 같이 작성해야 했습니다:
Java
```java
// 기존 방식
record Point(int x, int y, int z) {}
Point oldLoc = new Point(1, 2, 3);
// x만 10으로 바꾸고 싶을 때
Point newLoc = new Point(10, oldLoc.y(), oldLoc.z());
```
필드가 많아질수록 모든 필드를 일일이 다시 넣어주는 작업이 매우 번거롭고 코드가 지저분해집니다. 이를 해결하기 위해 개발자들은 보통 `withX(int x)` 같은 메서드를 직접 만들곤 했습니다(Wither 메서드).
### 2. 주요 기능: `with` 키워드 도입
JEP 468은 **`with`** 키워드와 블록을 사용하여 이 과정을 자동화합니다.
### 기본 문법
Java
```java
Point newLoc = oldLoc with {
x = 10;
};
```
이 코드는 내부적으로 다음과 같이 동작합니다:
1. `oldLoc`의 모든 필드(x, y, z)를 복사한 임시 변수를 만듭니다.
2. 블록 내에서 명시한 값(`x = 10`)만 업데이트합니다.
3. 최종적으로 변경된 값들을 가지고 레코드의 정준 생성자(Canonical Constructor)를 호출하여 새 객체를 반환합니다.
### 3. 주요 특징 및 장점
- **간결함:** 변경하려는 필드만 명시하면 됩니다. 나머지 필드는 자동으로 유지됩니다.
- **안전성:** 마지막에 생성자를 호출하기 때문에, 레코드에 정의된 **데이터 유효성 검증 로직이 그대로 적용**됩니다.
- 예: `Rational(int num, int denom)` 레코드에서 `denom`이 0이 될 수 없도록 설정했다면, `with { denom = 0; }` 실행 시 예외가 발생하여 잘못된 객체 생성을 막습니다.
- **복합 계산 가능:** 블록 안에서 복잡한 계산을 수행할 수 있습니다.
Java
```java
Point finalLoc = oldLoc with {
x *= 2;
y = x + 10;
};
```
- **중첩 사용:** 레코드 안에 레코드가 있는 경우에도 중첩해서 사용할 수 있어 매우 편리합니다.
### 4. 주의사항
- **레코드 전용:** 이 기능은 일반 클래스가 아닌 **Record 클래스**에만 적용됩니다. (일반 클래스는 생성자 구조가 제각각이라 자동화하기 어렵기 때문입니다.)
- **Preview 단계:** 이 기능은 아직 실험적인 기능이므로, 실제 프로젝트에서 사용하려면 컴파일 및 실행 시 `-enable-preview` 옵션을 주어야 합니다.
### 요약
JEP 468은 "기존 레코드 객체에서 특정 값만 살짝 바꾼 복사본을 만드는 기능"을 Java 언어 차원에서 공식 지원하려는 시도입니다. 이를 통해 불변 객체를 다루는 코드가 훨씬 더 읽기 쉽고 안전해질 것으로 기대됩니다.
댓글
댓글 쓰기