2월 2일 오늘 정확히 7시간 6분 동안 이 에러때문에 코딩을 못 해서 억울해서라도 처음부터 끝까지 정리하는 에러
@Componentscan
, @EntityScan
등의 어노테이션에 각 패키지 명을 명시함결론적으로, 이 두 어노테이션은 완전히 다른 목적을 위해 존재한다. Spring 애플리케이션을 구성하는 데 있어서는 동일한 역할을 한다. @EntityScan은 Entity로 인식되길 원하는 패키지를 지정한다. 반면, @ComponentScan은 Spring 빈을 스캔해야 하는 패키지를 지정할 때 사용된다.
@EntityScan | @ComponentScan |
---|---|
Entity (JPA 사용 시) | @Controller |
@Service | |
@Repository | |
@Component |
@Retention(value=RUNTIME)@Target(value=TYPE)@Documented@Repeatable(value=ComponentScans.class)public @interface ComponentScan은 @Configuration 클래스와 함께 사용하도록 컴포넌트 스캔 지시문을 설정하는 것이다.
이는 Spring XML의 <context:component-scan>
요소를 작성하는 것과 같은데, value() 속성을 특정 패키지를 스캔하도록 정의하는데 사용할 수 있다. 만약 특정 패키지가 정의되지 않으면, 이 어노테이션이 선언된 클래스의 패키지에서 스캔이 발생하는 것이다.
XML의 <context:component-scan>
을 사용할 때, annotation-config
이라는 속성이 있다. 이는 불리언 플래그로 "암시적 어노테이션 후처리기가 활성화되어야 하는지를 나타낸다. 기본값은 'true'이다." 간단히 말해서, true일 경우 @Controller, @Service, @Repository 등으로 주석 처리된 클래스의 객체를 만들고 의존성을 해결할 수 있다. false로 설정하면 모든 Spring Beans를 XML에 선언해야 하는 것이다.
그러나, @ComponentScan을 사용할 때는 거의 모든 경우에서 기본 어노테이션 구성 처리 (예: @Autowired 처리 등)가 가정된다.
쇼핑몰 앱을 만들고 있다고 가정해보자. 사용자는 제품을 검색하고, 제품을 장바구니에 추가하고, 결제를 할 수 있어야 한다. 이런 각각의 기능을 구현하는 코드들은 각각 다른 패키지에 있을 수 있다.
여기서 @ComponentScan 어노테이션은 스프링이 어떤 패키지를 찾아가면서 해당 패키지에 있는 컴포넌트(@Controller, @Service 등등)를 스프링 빈으로 등록할지 지정해주는 역할을 한다. 즉, @ComponentScan이 'com.example.shopping'을 스캔하도록 설정되어 있다면, 스프링은 'com.example.shopping' 패키지와 그 하위 패키지를 찾아다니면서 @Controller, @Service 등 표시된 클래스를 찾아서 스프링 빈으로 등록하게 된다.
다음으로 @EntityScan 어노테이션은 JPA가 데이터베이스와 상호작용하기 위해 사용하는 엔티티 클래스를 어디에서 찾을지 지정해준다. 예를 들어, 'com.example.shopping' 패키지에 있는 모든 JPA 엔티티 클래스를 데이터베이스 작업에 사용하려면, @EntityScan 어노테이션에 'com.example.shopping'을 지정하면 된다.
@EntityScan은 엔티티 클래스를 스캔하기 위한 자동-구성 시 사용되는 기본 패키지를 설정하는 것이다.
@EntityScan을 사용하면, 자동구성이 다음을 수행하게 된다:
Description:
Parameter 0 of constructor in com.sb.musicapi.service.MusicService required a bean of type 'com.sb.musicapi.repository.MusicRepository' that could not be found.
Action:
Consider defining a bean of type 'com.sb.musicapi.repository.MusicRepository' in your configuration.
에러 풀어보면서 선언해둔 @NoBeanRepository 어노테이션 바로 삭제해주고 다시 구동했다.
|-->package1
|-->package2
|Main.java
spring-boot-starter-data-jpa
임(이게 맞는 Dependency) 을 확인하였음.스프링부트 3.2.2를 사용하고 있었다.
Spring Boot3 릴리즈 일부인 JPA 모듈이javax.persistence.api
대신 Jakarta Persistence API를 적용하도록 바뀌었다.
implementation 'jakarta.persistence:jakarta.persistence-api:3.1.0'
따라서, @EntityScan과 같은 JPA 어노테이션을 설정하더라도 엔티티를 찾지 못 한다. Spring Boot 버전 3을 사용하려면, Persistence API도 함께 마이그레이션 해줘야한다.
javax.persistence.api
대신 Jakarta Persistence API를 적용하도록 변경되었다. 이때까지 javax를 import 해서 Entity 어노테이션을 사용했던 것이 문제였다. 내 Entity는 Entity가 아니었던 것이다. 해결해서 기쁘다. 그러니까 이런 문제를 겪고 있다면 @Entity 지정 시 Jakarta를 Import 해야한다..
와.... 감사합니다