왜 JPA는 우리가 직접 사용하지도 않는 기본 생성자를 요구할까?

FIRE-918·2026년 6월 17일

Kotlin을 쓰다가 Java로 돌아오며 다시 생각하게 된 생성자

Kotlin을 쓰다가 다시 Java를 사용하게 되면서, 한동안 너무 당연하게 사용했던 개념들을 다시 생각하게 되었습니다.

그중 하나가 바로 생성자(Constructor) 입니다.

Kotlin에서는 data class 덕분에 생성자를 직접 다루지 않아도 자동으로 처리되는 경우가 많습니다.

data class User(
    val name: String,
    val age: Int
)

이렇게만 작성해도 생성자뿐 아니라 getter, equals(), hashCode(), toString()까지 자동으로 생성됩니다.

그래서 자연스럽게 생성자라는 개념을 깊게 생각하지 않고 넘어갔던 것 같습니다.

하지만 Java로 다시 돌아오니 상황이 달라졌습니다.

User user = new User("지민", 20);

그리고 JPA를 사용하면서는 기본 생성자까지 등장합니다.

protected User() {}

그러다 문득 이런 생각이 들었습니다.

왜 생성자는 두 개나 필요한 걸까?


생성자는 무엇일까?

생성자를 한마디로 정의하면

객체가 생성될 때 자동으로 실행되는 초기화 코드

입니다.

new User("지민", 20);

이 코드는 단순히 메모리에 객체를 만드는 것이 아닙니다.

객체를 생성하면서 동시에 초기 상태를 설정하는 과정까지 포함하고 있습니다.

즉, 생성자는 객체가 올바른 상태로 시작할 수 있도록 도와주는 역할을 합니다.


생성자가 없다면?

다음과 같은 클래스가 있다고 가정해 보겠습니다.

class User {
    String name;
    int age;
}

객체를 생성하면

User user = new User();

필드에는 기본값이 들어갑니다.

  • name → null
  • age → 0

즉, 객체는 생성되었지만 의미 있는 상태라고 보기는 어렵습니다.


그래서 등장한 파라미터 생성자

이 문제를 해결하기 위해 사용하는 것이 파라미터 생성자입니다.

public User(String name, int age) {
    this.name = name;
    this.age = age;
}

이제 객체는 생성과 동시에 필요한 값을 가지게 됩니다.

User user = new User("지민", 20);

결과적으로 객체는 처음부터 의미 있는 상태를 유지할 수 있습니다.


그런데 왜 기본 생성자가 따로 있을까?

Java와 JPA를 사용하다 보면 자주 보게 되는 코드가 있습니다.

protected User() {}

흥미로운 점은 우리가 직접 이 생성자를 호출하는 경우는 거의 없다는 것입니다.

그렇다면 이 생성자는 누가 사용하며 왜 필요한 것일까요?

바로 JPA와 같은 프레임워크가 사용합니다.

JPA는 데이터베이스에서 조회한 값을 이용해 객체를 생성할 때 우리가 작성한 파라미터 생성자를 호출하지 않습니다.

먼저 기본 생성자를 이용해 빈 객체를 만든 뒤

리플렉션(Reflection)을 사용하여 필드에 값을 채워 넣는 방식으로 객체를 완성합니다.

그래서 JPA 명세에서는 엔티티에 기본 생성자가 반드시 존재해야 하며 외부에서 무분별하게 사용되지 않도록 보통 protected 접근 제한자를 사용합니다.

즉

  • 파라미터 생성자는 개발자가 의미 있는 객체를 만들기 위해 사용하고
  • 기본 생성자는 JPA와 같은 프레임워크가 객체를 생성하기 위해 사용합니다.

둘은 서로 역할이 다른 생성자인 셈입니다.


마무리하며

Kotlin에서는 많은 것들이 자동으로 처리되기 때문에 깊게 생각하지 않고 넘어갔던 부분들이 있었습니다.

하지만 Java로 돌아와 보니 생성자는 단순히 객체를 생성하기 위한 문법이 아니었습니다.

생성자는

객체를 어떤 상태로 만들 것인지
그리고 누가 어떤 방식으로 객체를 생성할 것인지를 정의하는 핵심 구조

였습니다.

그리고 기본 생성자와 파라미터 생성자 역시 중복된 존재가 아니라

각각 프레임워크를 위한 생성자와 개발자를 위한 생성자라는 서로 다른 역할을 가지고 있었습니다.

앞으로는 생성자를 볼 때 단순히 문법으로 받아들이기보다

"이 객체는 누가, 어떤 방식으로 생성하는가?"

를 먼저 생각해보려 합니다.

profile
학습한 내용을 기록하고 공유하며 함께 성장하는 백엔드 개발자입니다.

0개의 댓글