[TIL] @Controller vs @RestController, JPA reflection에…

2025-04-18 TIL

📝 TIL (Today I Learned)
🔗 원본 이슈: #43
📅 작성일: 2025-04-18
🔄 최종 수정: 2025년 04월 22일


🍀 새롭게 배운 것

1️⃣ @Controller vs @RestController

  • @Controller
    • View를 반환하기 위해 사용
    • 하지만 Data를 반환해야 하는 경우도 있음
      • 이때는 @ResponseBody 어노테이션을 사용해야함
  • @RestController
    • @Controller + @ResponseBody
    • JSON 형태로 객체 데이터를 반환하는 것
  • 참고 URL

2️⃣ JPA reflection에서의 @NoArgConstructor

@NoArgsConstructor, @AllArgsConstructor의 동시 필요성의 차이를 알아보다가 @NoArgsConstructor는 JPA의 reflection과 관련이 있다는 것을 알게 되어 좀 더 공부해보았다.

  • JPA는 객체를 생성할 때 reflection을 사용하기 때문에 “기본 생성자(파라미터 없는 생성자)”가 반드시 필요하다.
    • 따라서 JPA는 @NoArgsConstructor가 꼭 필요함!
    • reflection이란?
      • 자바에서 코드 자체를 런타임(실행 중)에 들여다 보고 조작하는 기능
      • 예를 들면
        • 어떤 클래스인지 모르는데도 필드, 메서드, 생성자를 꺼내서 확인하거나,
        • private 필드에도 강제로 접근하거나,
        • 생성자를 호출해서 객체를 만들 수 있음
  • JPA에서 리플렉션이 필요한 이유
    • JPA는 직접 new로 객체를 만들지 않음
      • 내부적으로 Hibernate가 리플렉션을 사용해 객체를 생성하고 필드 값을 채워 넣음
      • 그래서 기본 생성자(@NoArgsConstructor)가 반드시 필요한 것
    • 예시
      • User user = entityManager.find(User.class, 1L);
        • 이 내부에서는 Hibernate가 리플렉션으로
          1. User.class.newInstance()로 기본 생성자 호출
          2. 리플렉션으로 각 필드 값 설정
  • Spring의 DI와 리플렉션의 관계
    • Spring은 @Component, @Service같은 에너테이션이 붙은 클래스들을 자동으로 Bean으로 등록하는데, 이때 객체를 직접 new하는게 아니라 리플렉션으로 객체를 생성한다.
    • 예제
      •   @Service
          public class HelloService {
              public void hello() {
                  System.out.println("Hello from Spring Bean!");
              }
          }
        
        • Spring이 Bean을 만들 때 내부적으로 하는 일 (비공식 흐름)
            Class<?> clazz = HelloService.class;
            Object bean = clazz.getDeclaredConstructor().newInstance();
          
          • 리플렉션으로 객체를 만들고, 그걸 Spring Container에 등록해서 DI해주는 것!