Spring Boot에서 자주 사용하는 애노테이션 가이드

Spring Boot에서 자주 사용하는 애노테이션은 크게 세 가지 유형으로 나눌 수 있습니다: 컨테이너에 빈을 등록하는 애노테이션, 컨테이너에서 빈을 주입받는 애노테이션, 그리고 기능을 제공하는 애노테이션입니다. 전자는 제어의 역전(IoC), 후자는 의존성 주입(DI)의 개념과 연결됩니다.

컨테이너에 빈 등록 애노테이션

이 유형의 애노테이션은 클래스나 메서드가 생성한 객체를 Spring IoC 컨테이너가 관리하도록 선언합니다.

1. @Component
클래스 레벨에 적용되어 일반 POJO 클래스를 Spring 컨테이너의 빈으로 등록합니다. @Controller, @Service, @Repository 등 많은 애노테이션이 내부적으로 @Component를 포함합니다.

2. @Bean
메서드 레벨에 적용되며, XML 설정에서 <bean>을 정의하는 것과 동일합니다. 이 메서드는 일반적으로 엔티티 객체를 반환하며, Spring은 이 메서드를 한 번만 호출하여 반환된 객체를 컨테이너에서 관리합니다. 빈의 이름은 기본적으로 메서드 이름입니다.

3. @Configuration
클래스 레벨에 적용되어 해당 클래스가 설정 클래스임을 나타냅니다. 내부에 선언된 @Bean 메서드의 반환 객체를 Spring 컨테이너에 등록하며, 이는 @Component를 기반으로 동작합니다.

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Component
public @interface Configuration {
    String value() default "";
}

4. @ConfigurationProperties
설정 파일(예: application.properties)의 값을 객체에 매핑합니다. prefix 속성으로 접두사를 설정하고, 나머지 키 이름이 객체의 속성명과 일치하면 자동으로 주입됩니다. 이를 위해 객체는 해당 속성의 getter와 setter 메서드를 제공해야 하며, Spring은 리플렉션을 통해 setter를 호출합니다.

@ConfigurationProperties(prefix = "spring.datasource.test1")
public class Datasource1 {
    private String url;
    private String username;
    private String password;
    // getter, setter 메서드
}

# application.properties
spring.datasource.test1.url=jdbc:mysql://localhost:3307/multipledatasource1?useUnicode=true&characterEncoding=UTF-8&serverTimezone=UTC&useSSL=false
spring.datasource.test1.username=root
spring.datasource.test1.password=root
spring.datasource.test1.driver-class-name=com.mysql.cj.jdbc.Driver

5. @Value
설정 파일의 단일 값을 변수에 주입합니다. @ConfigurationProperties와 달리 필드 레벨에 적용되며, 변수 이름이 설정 파일의 키와 일치할 필요는 없지만 SpEL 표현식(${...}) 내의 키는 일치해야 합니다.

@Value("${myapp.config.value}")
private String customVariable;

# application.properties
myapp.config.value=someValue

6. @RestController, @Controller, @Service, @Repository
이 네 가지 애노테이션은 모두 @Component를 기반으로 하며, 기능적으로는 유사합니다. @RestController는 @Controller와 @ResponseBody의 조합입니다. Spring 5.x 이전에는 구조적 계층 구분(웹, 서비스, 데이터 액세스)을 위해 사용되었지만, 내부 구현은 동일합니다. 예를 들어 Controller 계층에 @Service를 사용해도 Spring은 정상적으로 동작하며, 이는 계층 구분을 위한 관례입니다.

@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Component
public @interface Controller {
    String value() default "";
}

@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Component
public @interface Service {
    String value() default "";
}

컨테이너에서 빈 주입 애노테이션

이 유형의 애노테이션은 의존성 주입(DI)을 구현하며, 컨테이너가 관리하는 빈을 필요한 곳에 주입합니다.

1. @Resource
기본적으로 이름을 기준으로 빈을 주입하며, 일치하는 이름이 없으면 타입을 기준으로 주입합니다. name과 type 속성을 모두 지정할 수 있으며, 둘 다 생략하면 byName 방식으로 동작합니다.

@Resource(type = ShiroService.class, name = "shiroService")
private ShiroService shiroService;

주입 순서: name과 type 모두 지정 → 정확히 일치하는 빈 검색, name만 지정 → 이름 일치 검색, type만 지정 → 타입 일치 검색(유일해야 함), 모두 미지정 → byName 자동 주입.

2. @Autowired
기본적으로 타입을 기준으로 빈을 주입합니다. required 속성을 false로 설정하면 일치하는 빈이 없을 때 null을 허용하고 예외를 방지합니다.

@Autowired(required = false)
private ShiroService shiroService;

3. @Qualifier
@Autowired와 함께 사용하여 특정 이름의 빈을 지정합니다. 동일한 타입의 빈이 여러 개 있을 때 모호성을 해결합니다. @Resource의 name 속성 역할과 유사합니다.

@Autowired
@Qualifier("adminDAO")
private AdminDAO adminDAO;

기능 제공 애노테이션

이 애노테이션들은 특정 기능(예: 자동 설정, 비동기, 스케줄링)을 활성화하거나 구성합니다.

1. @SpringBootApplication
메인 클래스에 적용되며, @SpringBootConfiguration, @EnableAutoConfiguration, @ComponentScan을 통합합니다. @SpringBootConfiguration은 설정 클래스임을, @EnableAutoConfiguration은 Spring Boot의 자동 설정을 활성화하고, @ComponentScan은 동일 패키지의 컴포넌트를 자동 스캔합니다.

2. @EnableConfigurationProperties
@ConfigurationProperties가 적용된 클래스를 Spring 컨테이너의 빈으로 등록합니다. @ConfigurationProperties만 사용하면 동작하지 않으며, 이 애노테이션을 메인 클래스나 설정 클래스에 추가해야 합니다.

3. @Async와 @EnableAsync
@Async는 메서드를 비동기로 실행하도록 지정하며, @EnableAsync는 애플리케이션에서 비동기 기능을 활성화합니다(주로 메인 클래스에 추가). @Async를 사용하면 메서드가 별도의 스레드에서 실행됩니다.

@RestController
public class AsyncController {
    @Autowired
    private AsyncService asyncService;

    @RequestMapping("/syncTest")
    public String syncTest() {
        System.out.println("start sync");
        asyncService.syncMethod();
        System.out.println("end sync");
        return "done";
    }

    @RequestMapping("/asyncTest")
    public String asyncTest() {
        System.out.println("start async");
        asyncService.asyncMethod();
        System.out.println("end async");
        return "done";
    }
}

@Service
public class AsyncService {
    public void syncMethod() {
        System.out.println("begin sync work");
        for (int i = 0; i < 5; i++) {
            System.out.println(i);
        }
        System.out.println("end sync work");
    }

    @Async
    public void asyncMethod() {
        System.out.println("begin async work");
        for (int i = 0; i < 5; i++) {
            System.out.println(i);
        }
        System.out.println("end async work");
    }
}

실행 결과: syncTest는 순차적으로 출력되지만, asyncTest는 start asyncend async가 먼저 출력되고 begin async work가 나중에 출력됩니다(비동기 실행). 이는 @Async가 새로운 스레드를 생성하는 것과 유사합니다.

4. @Scheduled와 @EnableScheduling
@Scheduled는 메서드를 정기적으로 실행하도록 예약하며, @EnableScheduling은 스케줄링 기능을 활성화합니다(메인 클래스에 추가). cron 표현식을 사용하여 실행 주기를 정의합니다.

@Scheduled(cron = "0/5 * * * * ?")
public void periodicTask() {
    System.out.println(new SimpleDateFormat("YYYY-MM-dd HH:mm:ss").format(new Date()));
}

태그: Spring Boot Java 애노테이션 IOC DI @Component

7월 7일 19:04에 게시됨