ObjectMapper, JPA Entity @NoArgsConstructor ? `Java Reflection`

블로그를 옮겼습니당·2021년 4월 14일
0
post-thumbnail
  • 아직 쓰는 중 - 2021-04-16

시작

우리는 Entity를 쓸 때, 기계처럼 @NoArgsConstructor를 쓴다. 근데 여기서 한 번쯤은 의문이 있어야하지 않나? 최근에 나는 RequestDto를 @RequestBody에 바인딩이 어떻게 되는지 궁금했었다. 그 과정속에서 @Setter은 필요가없었고 @Setter, @Getter 둘 중 하나만 있으면 된다는 것을 알았으며 또한 내부적으로 ObjectMapper를 통해 바인딩이 되는 것으로 끝을 냈다. 또한 @NoArgsConstructor를 왜 쓰는지 궁금했고 그 결과 Reflection 때문이라는 것만 알고 넘어갔다.

하지만 그 후, 최근 어떠한 계기로. 나는 몸소 느꼈다. '이거다. 아는 사람과 모르는 사람의 차이'
올라가려면, 좀 더 내가 누군지 알리고 인정받으려면 달라야한다. 그게 이런 것을 아는 사람과 모르는 사람의 차이구나.

간단히 Reflection

간단하게 알아보려합니다. 우리는 두가지의 시간이 있습니다. Compile Time, Run Time. 여기서 Reflection은 Run Time 시간에 클래스의 정보를 객체화를 통해 분석 및 추출하는 Java API 라고 생각하면 됩니다.
예를 들어 ParentObject, SonObject라는 Class를 만들어보았습니다.

어라? 왜 에러가 나는 걸까요? 이유는 Compile Time 때 Type을 확인하고 결정합니다. 그렇기에 parentObject는 자기가 ParentObject라는 것만 인지하는 겁니다. 그렇기에 SonObject의 say메소드를 사용 못하는 겁니다. 그럼 여기서 가능하게 해보겠습니다.

우리는 Class 영역을 Static영역이라고도 부릅니다. Reflection은 이 영역에 저장된 클래스에 대한 정보, 클래스에 대한 변수를 참고하여 위와 같은 상황이 나오겠끔 만들어줍니다.

이게 굉장히 중요합니다. 위에 에러가 났던 예를 보면 애초에 Compile Time 에는 Type을 ParentObject로만 알고 에러를 내뿜었다면, Reflection을 통해서 Compile Time에도 에러를 나지 않게 하고 그 값이 제대로 나오게끔 하는게 중요합니다.

여기서 Compile Time ? 에 말이 Run Time 아닌가? 할 수 있는데 맞습니다. Reflection은 Run Time에 클래스 이름을 기반으로 런타임에 인스턴스 또는 개체를 만듭니다.

@NoArgsConstructor - 나의 생각 흐름

포스팅을 하면서 JPA 김영한님의 책에도 나와있던 문장을 쓰려고 하다가 DOCS가 더 명확한 것 같아 DOCS를 넣었습니다.

그러면 왜? 기본 생성자일까?

여기저기 구글링을 하면서 찾은 점은 우선 Hibernate는 Entity에 여러 생성자 형태의 Method가 있으면 어느 것을 이용하여 인스턴스화 해야할 지 불분명하다는게 문제입니다. 그러면 여기서 이런 생각을 할 수 있습니다. 우선 적으로 기본 생성자를 하나 만들고 그 필요한 필드값을 주입시키자.

또 다른 생각은 Hibernate는 무조건 Reflection을 전제로 Entity를 만든다. 우선 기본 생성자를 만들기 위해서 Reflection은 Static 영역에서 Class에 대한 정보를 참고해서 Compile Time 임에도 에러없이 구현가능하게 만들수 있지만 단 !! 생성자에 대한 인자를 갖고 오지 못한다는 단점이 있다. 즉, 그래서 기본 생성자를 넣어야한다.

마지막으로 Hibernate 뿐 아니라 Spring Framework Dependecy Injection 또한 Reflection으로 만들며 기본 생성자는 정의되어야 한다는 것입니다. 즉, Reflection을 이용하여 만들지 않는다! 라는 확실성이 있어야 안쓰는 것이고 그 외의 모든 경우에는 써야한다는게 BUG 라고 하는 글도 있었습니다.

등의 여러 글이 있었습니다.

Hibernate Entity



ObjectMapper 는?

readValue를 보면 지정된 JSON 내용 문자열에서 JSON 내용을 역직렬화하는 방법라고 써있습니다. 즉, @RequestBody에서 Dto에 바인딩할 때, 사용되는 메소드라 할 수 있습니다.

끝내며

profile
https://github.com/minyul

0개의 댓글