JPA는 스펙상 엔티티, 임베디드 값 타입에 리플렉션(Reflection), 프록시(Proxy) 기술을 적용하기 위해 public 또는 protected의 기본 생성자를 두는 것을 정의하고 있다.

 

 

리플렉션이란?

더보기

Java Reflection API

 

자바는 컴파일 시점에서 타입이 결정되는데 다음과 같이 구체적인 클래스로 생성하지 않을 경우 컴파일 시점에서 Object 타입으로 결정이 되기 때문에 Car 클래스의 메소드 등에 접근할 수가 없다.

 

Object car = new Car(); 

 

자바에서는 JVM이 실행되면 자바 코드가 컴파일러를 거쳐 바이트코드로 변환되어 static 영역에 저장되는데 리플렉션은 이 정보를 활용하여 구체적인 클래스 타입을 알지 못해도 그 클래스의 메소드, 타입, 변수들에 접근할 수 있도록 해준다. 하지만 런타임 시점에 동적으로 타입을 분석하기 때문에 JVM을 최적화할 수 없는 등 여러 문제점이 있어서 일반적으로는 사용하지 않는 것이 좋다.

리플렉션은 애플리케이션 개발보다 프레임워크나 라이브러리에서 많이 사용하는데 프레임워크나 라이브러리는 사용자가 어떤 클래스를 만들지 예측할 수가 없기 때문에 리플렉션을 활용한다.

JPA도 동적으로 객체 생성시 리플렉션을 활용하는데 리플렉션으로 가져올 수 없는 정보 중 하나가 생성자의 인자 정보이다. 그래서 기본 생성자가 반드시 있어야 객체를 생성할 수 있다. 기본 생성자로 객체를 생성만 하면 필드 값 등을 리플렉션으로 넣어줄 수 있다.

 

 

Reflection API 간단히 알아보자.

Spring Framework를 학습하다 보면 Java Reflection API를 자주 접하게 된다. 하지만 Reflection API…

tecoble.techcourse.co.kr

 

 

하이버네이트 같은 구현체들은 기본 생성자가 없어도 라이브러리들을 통해 이러한 문제를 어느정도 회피하지만 완벽한 해결책이 아니기 때문에 기본 생성자를 필수로 두는 것이 좋다. 기본 생성자를 public으로 열어두면 의도치 않은 무분별한 생성이 될 수 있기 때문에  protected로 선언하여 다른 패키지에서 기본 생성자를 생성할 수 없도록 제한한다.

 

그리고 엔티티는 생성자나 Setter를 사용하는 것보다는 빌더(Builder) 패턴 또는 정적 팩토리 메서드(static factory method)를 사용하는 것이 좋은데 빌더 패턴은 필요한 데이터만 설정할 수 있고 유연성, 가독성이 뛰어나며 변경 가능성을 최소화 할 수 있다.

 

[Java] 빌더 패턴(Builder Pattern)을 사용해야 하는 이유

객체를 생성하기 위해서는 생성자 패턴, 정적 메소드 패턴, 수정자 패턴, 빌더 패턴 등을 사용할 수 있습니다. 개인적으로 객체를 생성할 때에는 반드시 빌더 패턴을 사용해야 한다고 생각하는

mangkyu.tistory.com

 

정적 팩토리 메서드(static factory method)는 객체 생성을 캡슐화하는 기법으로 객체를 생성하는 메소드를 만들고 static으로 선언하여 사용한다. 메서드명을 의미 있게 지을 수 있어 생성자에 비해 가독성이 좋아지고 호출할 때마다 새로운 객체를 생성할 필요가 없다. 그리고 하위 타입 객체를 반환할 수 있으며 입력 매개변수에 따라 매번 다른 클래스의 객체를 반환할 수 있다. 

 

public static User createUser(String name, int age) {
    OrderItem orderItem = new OrderItem();
    this.name = name;
    this.age = age;
    
    return user;
}

 

파라미터가 많거나 변경 가능성이 많은 경우에는 빌더 패턴을, 그렇지 않은 경우에는 정적 팩토리 메소드를 사용하는 것이 좋다.

+ Recent posts