Spring Boot JPA : @Entity를 사용할 때 @NoArgsConstructor를 하지 않으면 에러가 나는 이유

2024. 10. 20. 21:55·[Spring]

📌 개요

혹시 Spring boot Data JPA 를 사용하면서, @Entity 어노테이션을 활용하여 엔티티를 생성할 때, 

기본생성자 직접 명시, 혹은 @NoArgsConstructor 를 명시하지 않은 경우,

다음과 같은 에러를 마주하신 적이 있으실 것 입니다.

 

그렇다면,  JPA가 Entity 를 생성할 때 기본생성자를 명시하지 않으면 경고/에러가 발생하는지, 알아보겠습니다!

 

 

📌 JPA는 Entity를 생성 할 때 Reflection 기법을 사용한다.

 

해당 포스팅에선 Reflection에 대해선 자세하게 다루지 않고 간단하게 설명하고 넘어가겠습니다!

 

즉, 리플렉션은 해당 클래스에 대해서 타입을 알지 못하더라도, 해당 클래스의 메서드, 타입, 생성자, 변수들에 접근할 수 있도록 해주는 기법입니다.

컴파일이 아닌 실행시간(런타임)에 동적으로 해당 클래스의 정보를 추출하고 사용할 수 있는 기법이라고 볼 수 있습니다.

 

 

 

❓ 왜 JPA 는 Entity를 관리할 때 간단한 new 연산자를 사용하지 않고, 굳이 복잡한 Reflection을 사용할까?

만일, JPA 가 new 연산자를 사용하게 될 경우, 다음과 같은 한계가 있습니다.

 

❌동적 객체 생성이 어려움

JPA는 런타임에 어떤 엔티티 객체가 필요한지 미리 알 수 없습니다. 예를 들어, 쿼리 결과에 따라 여러 엔티티를 다룰 수 있어야 하는데, new 연산자로는 동적으로 어떤 객체를 생성해야 할지 알기 어렵습니다.

 

예를 들어, Member 엔티티를 데이터베이스에서 조회한다고 가정하겠습니다.

JPA는 SQL 쿼리를 통해 데이터를 받아오고, 이 데이터를 기반으로 Member 객체를 만들어야 합니다. 이때, 프로그램은 이 데이터를 받아올 때 어떤 엔티티 객체를 만들어야 할지 미리 알 수 없습니다. 즉, 조회하는 엔티티 클래스가 여러 개일 수 있고, 그에 맞게 동적으로 엔티티 객체를 생성해야 합니다.  따라서, 동적 객체 생성은 반드시 필요로 됩니다.

 

 

❌ 프록시 객체를 생성할 수 없음

JPA는 성능 최적화를 위해 Lazy Loading(지연 로딩) 같은 기법을 사용하는데, 이때 프록시(Proxy) 객체라는 것을 사용합니다.

프록시 객체는 진짜 엔티티 객체처럼 행동하지만, 실제 데이터를 데이터베이스에서 나중에 로드합니다. 이 프록시 객체는 런타임에 동적으로 생성되어야 하기 때문에, new 연산자로는 생성할 수 없습니다.

 

 

반대로 말하자면, Reflection 은 위의 단점을 보완할 수 있는 장점을 가질 수 있습니다.

 

✅동적 객체 생성

리플렉션을 통해 JPA는 런타임에 클래스 정보를 조회하고, 기본 생성자를 사용해 엔티티 객체를 동적으로 생성할 수 있습니다.

즉, 미리 어떤 엔티티를 생성할지 몰라도, 쿼리 결과에 따라 적절한 엔티티를 만들 수 있습니다.

 

✅프록시 객체 생성

리플렉션을 사용하면 프록시 객체와 같은 런타임에 동적으로 생성된 객체도 관리할 수 있습니다. 

 

 

 

만일, 해당 reflection 내용이 이해가 잘 가지 않더라도, 이렇게 받아들이면 편할 것 같습니다.

"아~ 뭔지는 잘 모르겠지만, 객체를 생성할 때 우리는 계속 new 를 사용했었는데, 
해당 방법으로는 JPA가 DB와 매핑하고 효율적으로 사용 하는것이 어렵다는거구나! 

그래서 JPA 는 "new" 를 사용해서 객체를 생성하지 않고 "Reflection" 이라는 기법을 사용해서 
객체를 만든다는 거구나!"

 

 

 

 

📌 JPA 가 실행중에 Entity를 Reflection을 통해 생성하고 관리한다. ⭐이때 기본생성자로 생성한다. 

 

앞선 설명으로, JPA는 엔티티 객체를 생성할 때 리플렉션(Reflection) 을 사용한다고 말씀드렸습니다. 

이때 리플렉션 기법으로 JPA가 리플렉션으로 엔티티 객체를 생성할 때, 매개변수가 있는 생성자는 호출할 수 없고 기본 생성자만 사용할 수 있기 때문에 기본 생성자가 필수입니다.

 

그렇다면 이제 아래의 에러가 이해가 될 것 같습니다.

 

따라서 기본생성자를 명시해주지 않으면 다음과 같은 빨간줄을 만나보게 되는 것 입니다!

 

앞으로 JPA 가 객체를 만들게 하기 위해서 기본생성자는 반드시 명시해줍시다!

 

 

 

 

 

✅ 조금 더 나아가서,

❓ 그래서 @AllArgsConstructor, @Builder 를 쓰면 빨간줄이 나오는거구나?

 

실제로 자바는 아무것도 생성자에 대해 명시하지 않았다면, 기본생성자를 자동으로 생성해줍니다.

그리고  JPA 또한 자동으로 생성된 기본생성자를 활용해서 어쩌면 문제 없이 돌아갈 것 입니다.

 

하지만 !

 

롬복의 기능으로 사용하는 @AllArgsConstructor , @Builder 를 사용하게 된다면, 해당 클래스는 매개변수를 받는 생성자를 

만들게 되었다고 해석할 수 있습니다. 

 

💥 매개변수가 있는 생성자를 만들었다. 

더이상, 기본생성자는 자체적으로 생성되지 않음으로, 직접 명시를 해줘야한다.

 

따라서 아무런 생각없이, @AllArgsConstructor, @Builder 의 어노테이션을 사용 하였다면, 

해당 에러를 마주하게 되는 것 입니다 ! 

 

 

 

이상, 해당 포스팅을 읽어주셔서 감사합니다 :-) 🙇‍♀️🙇‍♂️

'[Spring]' 카테고리의 다른 글

Spring - @Controller 와 @RestController 차이  (0) 2025.03.01
다양한 Lock 기법을 활용한 동시성 제어 방법 ( Synchronized , Database , Redis )  (1) 2024.12.30
Bean을 등록하는 2가지 방법 (@Component / @Bean + @Configuration)  (0) 2024.08.04
Spring Security로 로그인 구현해보기  (0) 2024.07.25
Lombok 롬복의 @Builder, @NoArgsConstructor 와의 충돌 이유  (0) 2024.07.08
'[Spring]' 카테고리의 다른 글
  • Spring - @Controller 와 @RestController 차이
  • 다양한 Lock 기법을 활용한 동시성 제어 방법 ( Synchronized , Database , Redis )
  • Bean을 등록하는 2가지 방법 (@Component / @Bean + @Configuration)
  • Spring Security로 로그인 구현해보기
7.06com
7.06com
우당탕탕 코딩하기
  • 7.06com
    우당탕탕 개발자의 이야기
    7.06com
  • 전체
    오늘
    어제
    • 분류 전체보기 (54)
      • [Spring] (7)
      • [JAVA] (3)
      • [디자인패턴] (1)
      • [TIL] (7)
      • [CI,CD] (5)
      • [협업] (1)
      • [Database] (4)
      • [CS] (1)
      • [코딩테스트] (15)
      • [알고리즘] (0)
      • [후기-회고] (1)
  • 블로그 메뉴

    • 홈
    • 태그
    • 방명록
  • 링크

  • 공지사항

  • 인기 글

  • 태그

  • 최근 댓글

  • 최근 글

  • hELLO· Designed By정상우.v4.10.1
7.06com
Spring Boot JPA : @Entity를 사용할 때 @NoArgsConstructor를 하지 않으면 에러가 나는 이유
상단으로

티스토리툴바