반응형
record 등장 ?!
❓Java 14에 처음 등장
❗️Java 16부터 정식
✅ Java 21에서 거의 주력으로 자리잡은 record.
record에서 간략하게 알아보자.
- setter ❌
- getter, 생성자, equals, hashCode, toString 자동생성
- final 필드로 수정 ❌ (불변객체)
- 직렬화 가능
- Swagger 문서화 도구 사용 가능
✅ 겉으로 보이는 차이점: 일반 객체(DTO)와 record 비교
일반 객체(DTO)와 비교해보자.
생성자 | 명시적으로 작성해야 함 | 자동 생성 (canonical constructor) |
getter | 직접 생성 or Lombok 필요 | 자동 생성 |
setter | 직접 생성 or Lombok 필요 | ❌ 없음 (불변) |
equals/hashCode/toString | 수동 or Lombok 필요 | 자동 생성 |
필드 수정 가능 여부 | ✅ 가능 | ❌ 불변 |
불변성 보장 | ❌ | ✅ |
JSON 직렬화 | 가능 | 가능 (Jackson 지원) |
Swagger 설명 | ✅ @Schema, @Parameter 등 사용 가능 | ✅ Java 21 기준 사용 가능 |
✔️ 결론: record는 DTO용으로 거의 완벽하게 쓸 수 있어.
그렇다면 겉에서 보이는 차이점뿐 아니라, 내부적인 동작, 컴파일 타임, 성능 차이까지 궁금할 수 있지❓
✅ 눈에 안 보이는 차이점
단순한 클래스가 아니다.
- record는 내부적으로 java.lang.Record를 반드시 상속한다.
- final class 라 상속은 불가능
- 생성자, getter, equals, hashcode, toString 자동생성
- JEP 395에서 공식적으로 도입(Java 16)
🔍 컴파일 결과 구조
record는 컴파일 후 바이트코드를 보면 일반 클래스와 다르게 JVM이 특별하게 인식하는 FLAG가 붙는다.
이를 확인하는 방법은 javap 명령어를 사용해서 확인이 가능하다.
javap -c MyRecord.class
public record UserDto(String name, int age) {}
바이트코드 결과
public final class MyRecord extends java.lang.Record {
private final java.lang.String name;
private final int age;
public MyRecord(java.lang.String, int);
public java.lang.String name();
public int age();
public java.lang.String toString();
public final boolean equals(java.lang.Object);
public final int hashCode();
}
✅ 여기서 extends java.lang.Record 가 record만의 특별한 특징이다.
✅ 일반 클래스는 Object를 상속하지만, record는 java.lang.Record를 강제 상속
즉, JVM이 "이건 일반 클래스가 아니라 record다!" 하고 특별 취급
🚀 컴파일 속도
record는 컴파일 시 자동 생성되는 코드가 많기 때문에:
- 내가 코드를 직접 작성한 것보다 더 최적화된 바이트코드가 생성됨
- 컴파일 속도는 오히려 빨라짐 (보일러플레이트 줄어드니까)
👉 Lombok 기반 DTO보다도 빠름 (Lombok은 애노테이션 프로세서 기반이라 상대적으로 컴파일 타임이 조금 느림)
🧠 런타임 성능
record는 final 클래스이고, 모든 필드도 final
- 인라인 캐싱: 메서드 호출 위치에 해당 메서드를 인라인으로 삽입해서 호출 비용을 줄이는 최적화
자바는 다형성 때문에 메서드 호출할 때 실제 구현체를 런타임에 결정하지만
불변객체여서 자주 쓰는 타입에 대해 캐시함 - escape analysis: 객체가 메서드 밖으로 return 하지 않는 경우, JVM은 그 객체를 힙이 아니라 스택에 할당하여 최적화
- 위 상황으로 JIT(Just-In-Time) 컴파일러가 최적화하기 더 쉬움
JIT: 자주 실행되는 부분을 컴파일러가 기계어로 변환에 캐싱
✅ 한 줄 요약
record는 final, 불변, 단순 구조 덕분에 JIT 컴파일러가 더 빠르게, 더 공격적으로 최적화할 수 있는 조건을 잘 갖추고 있다.
반응형
'Java' 카테고리의 다른 글
[스프링부트] 하나의 인터페이스로 여러 구현체 선택 방법 (0) | 2025.03.27 |
---|---|
REST API에서 요청 DTO를 매번 만들어야 하나? (0) | 2025.03.25 |
REST API 설계, GET 방식과 보안이슈 (0) | 2025.03.25 |
Java 버전별 변천사 ( Java 6 ~ ) (2) | 2025.03.15 |
자바의 특징 (0) | 2025.03.13 |