영한쌤이 주신 기본 프로젝트 폴더를 천천히 둘러보는 중에 배운 인사이트가 있어서 적어본다.
아래 메인함수를 보자. 평소 spring Initializer로 만든 프로젝트의 기본 메인함수와 다르다!!!
@Import(MemoryConfig.class)
@SpringBootApplication(scanBasePackages = "hello.itemservice.web")
public class ItemServiceApplication {
	public static void main(String[] args) {
		SpringApplication.run(ItemServiceApplication.class, args);
	}
	@Bean
	@Profile("local")
	public TestDataInit testDataInit(ItemRepository itemRepository) {
		return new TestDataInit(itemRepository);
	}
}
먼저 @SpringBootApplication(scanBasePackages = “hello.itemservice.web”)으로 빈으로 등록시켜놓을 범위를 좁혔다! 정확하게 말하면 컴포넌트 스캔의 범위를 .web 패키지로 줄이고! @Import(MemoryConfig.class)를 통해 커스텀 컨테이너를 추가하여 연습마다 바꿔줄 빈들을 추가할 수 있게끔 유연하게 설계하였다!! → 처음 봤을 때 좀 많이 놀랐다!
그리고 @Bean, @Profile(”local”) 이 붙은 testDataInit() 매서드를 볼 수 있는데, 아래의 TestDataInit 클래스를 보자!
@Slf4j
@RequiredArgsConstructor
public class TestDataInit {
    private final ItemRepository itemRepository;
    /**
     * 확인용 초기 데이터 추가
     */
    @EventListener(ApplicationReadyEvent.class)
    public void initData() {
        log.info("test data init");
        itemRepository.save(new Item("itemA", 10000, 10));
        itemRepository.save(new Item("itemB", 20000, 20));
    }
}
@EventListener(ApplicationReadyEvent.class) : 스프링 컨테이너가 완전히 초기화를 다 끝내고,
실행 준비가 되었을 때 발생하는 이벤트이다. 스프링이 이 시점에 해당 애노테이션이 붙은 initData() 메서드
를 호출해준다.
참고로 이 기능 대신 @PostConstruct 를 사용할 경우 AOP 같은 부분이 아직 다 처리되지 않은 시점에
호출될 수 있기 때문에, 간혹 문제가 발생할 수 있다. 예를 들어서 @Transactional 과 관련된 AOP가 적
용되지 않은 상태로 호출될 수 있다.
@EventListener(ApplicationReadyEvent.class) 는 AOP를 포함한 스프링 컨테이너가 완전
히 초기화 된 이후에 호출되기 때문에 이런 문제가 발생하지 않는다.
그리고 메인함수에서 initData()를 @Profile(”local”)을 붙혀준 이유가 뭘까? application.properties 들어가보니 그냥 아래처럼 profile = local로 되어있던데… 라고 생각했었다.
spring.profiles.active=local
근데 test의 application.properties를 들어가보니??!