[F-Lab 66해빗 페이백 챌린지 ]

[F-Lab 모각코 페이백 32일차] Spring ComponentScan

everydeveloper 2023. 7. 13. 12:44

 

학습 목표

  • Spring ComponentScan

 

TIL

  • Spring ComponentScan

 

Q.

Spring ComponentScan의 동작 원리

A.

Spring Framework에서 `@ComponentScan`는 Spring이 Java 클래스를 찾아서 Spring Application Context에 Bean으로 등록할 수 있게 하는 역할을 합니다. 즉, `@ComponentScan`은 지정된 패키지에서 `@Component`, `@Service`, `@Repository`, `@Controller` 등과 같이 특정 어노테이션이 선언된 클래스를 찾아 Spring IoC(Inversion of Control) 컨테이너에 빈으로 등록합니다.

 

`@ComponentScan`의 동작 원리는 다음과 같습니다:

 

1. **스캔 시작:** Spring은 `@ComponentScan` 어노테이션과 함께 지정된 패키지를 시작점으로 하여 모든 하위 패키지를 스캔합니다. `@ComponentScan` 어노테이션이 지정되지 않은 경우, 현재 클래스의 패키지를 시작점으로 합니다.

 

2. **클래스 탐색:** Spring은 지정된 패키지에서 모든 클래스를 탐색하고, `@Component`, `@Service`, `@Repository`, `@Controller` 등의 어노테이션이 선언된 클래스를 찾습니다.

 

3. **빈 등록:** 해당 어노테이션을 가진 클래스를 찾으면, Spring은 이를 Spring IoC 컨테이너에 빈으로 등록합니다. 

 

또한 `@ComponentScan`은 `includeFilters`와 `excludeFilters` 속성을 사용하여 스캔할 클래스를 세밀하게 제어할 수 있습니다. `includeFilters`는 스캔 범위를 제한하고, `excludeFilters`는 특정 클래스나 패키지를 스캔에서 제외하는데 사용됩니다.

 

이렇게 Spring의 `@ComponentScan` 기능을 통해 개발자는 수동으로 모든 빈을 등록할 필요 없이 자동으로 의존성을 주입(Dependency Injection)하는 것이 가능합니다. 이는 코드의 가독성을 높이고 유지 관리를 용이하게 만드는 데 큰 도움이 됩니다.

 

 

Q.

Spring ComponentScan은 뭐야?

A.

Spring Framework에서 `@ComponentScan`은 어노테이션이 선언된 패키지 및 하위 패키지를 검색하여 `@Component`, `@Repository`, `@Service`, `@Controller` 등의 어노테이션이 적용된 클래스를 찾아서 Spring IoC(Inversion of Control) 컨테이너에 Bean으로 등록하는 역할을 합니다.

 

Spring Application에서는 `@Configuration`이 붙은 설정 클래스에서 주로 `@ComponentScan`을 사용합니다. 이를 사용하면 개발자는 매번 빈을 수동으로 등록하는 대신, Spring이 자동으로 의존성을 관리하게 만들 수 있습니다. 이렇게 하면 프로젝트의 복잡성이 줄어들고, 유지 관리가 용이해집니다.

 

다음은 `@ComponentScan`의 사용 예입니다:

 

```java

@Configuration

@ComponentScan(basePackages = "com.example.project")

public class AppConfig {

 

}

```

 

위 코드에서 `@ComponentScan(basePackages = "com.example.project")`는 "com.example.project" 패키지와 그 하위 패키지에서 Spring이 관리하는 클래스를 찾아서 자동으로 Bean으로 등록하게 합니다. 

 

그러나 `@ComponentScan` 어노테이션을 사용하지 않으면, 모든 빈은 개발자가 수동으로 `@Bean` 어노테이션을 사용해 등록해야 합니다. 이 방법은 빈의 수가 많아질수록 복잡해지고 관리하기 어려워집니다. 따라서 대부분의 Spring 프로젝트에서는 `@ComponentScan`을 사용하여 자동화합니다.

 

 

Q.

예전에 컴포넌트 스캔을 쓰면 범위를 설정했떤 것 같애 맞아?ㅎ

A.

네, 맞습니다. `@ComponentScan` 어노테이션을 사용할 때 `basePackages` 속성을 사용해서 스캔할 패키지의 범위를 설정할 수 있습니다. 이를 통해 Spring은 지정된 패키지와 그 하위 패키지를 검색하여 `@Component`, `@Service`, `@Repository`, `@Controller` 등의 어노테이션이 붙은 클래스를 찾아 Spring IoC 컨테이너에 빈으로 등록합니다.

 

다음은 `@ComponentScan`을 사용한 예제 코드입니다:

 

```java

@Configuration

@ComponentScan(basePackages = "com.example.myapp")

public class AppConfig {

}

```

 

위 코드에서 `basePackages = "com.example.myapp"`으로 설정하면, `com.example.myapp` 패키지와 그 하위 패키지를 대상으로 컴포넌트 스캔을 수행합니다.

 

또한 `basePackages`를 설정하지 않은 경우에는 `@ComponentScan`이 선언된 현재 클래스가 있는 패키지를 기준으로 스캔을 수행합니다.

 

이렇게 범위를 지정함으로써, 원하는 패키지만 스캔의 대상이 되도록 하여 불필요한 클래스를 스캔하는 시간을 절약할 수 있습니다.

 

 

Q.

그러면 컨트롤러나 서비스 어노테이션을 선언하고도 컴포넌트 스캔의 범위에 들어가지 않는다면 해당 컨트롤러나 서비스는 빈으로 등록되지 않는 다는 거야?? 2가지 어노테이션이 적어도 필요하네

A.

네, 맞습니다. `@Controller`, `@Service`, `@Repository`, `@Component` 등의 어노테이션은 Spring에게 해당 클래스를 빈으로 관리하도록 지시하는 역할을 합니다. 하지만 실제로 이 클래스들이 빈으로 등록되려면, 해당 클래스가 위치한 패키지가 `@ComponentScan`의 범위에 있어야 합니다.

 

예를 들어, 'com.example.myapp' 패키지를 대상으로 컴포넌트 스캔을 수행하는데 'com.example.other' 패키지에 `@Service` 어노테이션이 선언된 클래스가 있다면, 이 클래스는 Spring IoC 컨테이너에 빈으로 등록되지 않습니다. 이는 'com.example.other' 패키지가 컴포넌트 스캔의 범위에 포함되지 않기 때문입니다.

 

따라서 빈으로 등록하려는 클래스에 적절한 어노테이션(`@Component`, `@Service`, `@Repository`, `@Controller` 등)을 선언하고, 해당 클래스가 컴포넌트 스캔의 범위에 포함되도록 해야 합니다.

 

물론, 모든 빈을 자동으로 등록하지 않고 일부 빈만 수동으로 등록하려는 경우에는, `@ComponentScan` 없이 `@Bean` 어노테이션을 사용해서 직접 빈을 등록할 수도 있습니다. 하지만 대체로 많은 개발자들이 `@ComponentScan`을 통해 빈을 자동으로 등록하는 것을 선호합니다.

 

 

Q.

Spring ComponentScan이 나오기 전에는 어떤 방식과 작동방식과 원리로 동작했어?

A.

`@ComponentScan`과 같은 자동화 기능이 등장하기 전, Spring에서는 XML 기반의 설정을 사용하여 빈을 등록했습니다. 즉, 개발자들은 `applicationContext.xml`과 같은 XML 설정 파일에 `<bean>` 태그를 사용하여 각각의 빈을 수동으로 등록해야 했습니다.

 

예를 들어, 다음은 XML을 이용하여 빈을 등록하는 방법입니다:

 

    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

    xsi:schemaLocation="http://www.springframework.org/schema/beans

    http://www.springframework.org/schema/beans/spring-beans.xsd">



    <bean id="myBean" class="com.example.MyClass"/>

</beans>

 

이 방법은 간단하고 명시적이지만, 빈이 많아질수록 XML 파일이 복잡해지는 문제가 있습니다. 또한, 빈의 상태를 변경하거나 새로운 빈을 추가하려면 XML 파일을 직접 수정해야 하므로 유지보수가 어렵습니다.

 

이런 문제점을 해결하기 위해, Spring 2.5버전부터 애노테이션 기반의 설정 방식이 도입되었습니다. 이 방식에서는 `@Component`, `@Service`, `@Repository`, `@Controller` 등의 애노테이션을 사용하여 클래스를 빈으로 등록할 수 있습니다. 그리고 `@ComponentScan` 애노테이션을 사용하여 지정된 패키지를 스캔하고, 해당 애노테이션을 선언한 클래스를 자동으로 빈으로 등록합니다.

 

따라서 `@ComponentScan` 등장한 후로는 개발자들이 XML 파일을 직접 수정하는 수고를 덜고, 자동화된 방식을 통해 빈을 쉽게 등록하고 관리할 있게 되었습니다.