๊ด€๋ฆฌ ๋ฉ”๋‰ด

์‚ถ์˜ ๊ณต์œ 

[Spring] ๊ณ ๊ธ‰ ์–ด๋…ธํ…Œ์ด์…˜ ์ •๋ฆฌ: @Conditional, @Import ์™„๋ฒฝ ๊ฐ€์ด๋“œ ๋ณธ๋ฌธ

Web Dev/BackEnd

[Spring] ๊ณ ๊ธ‰ ์–ด๋…ธํ…Œ์ด์…˜ ์ •๋ฆฌ: @Conditional, @Import ์™„๋ฒฝ ๊ฐ€์ด๋“œ

dkrehd 2025. 4. 25. 22:45
728x90
๋ฐ˜์‘ํ˜•

๐Ÿšฆ Spring ๊ณ ๊ธ‰ ์–ด๋…ธํ…Œ์ด์…˜ ์ •๋ฆฌ: @Conditional, @Import ์™„๋ฒฝ ๊ฐ€์ด๋“œ (์˜ˆ์‹œ ํฌํ•จ)

Spring์€ ํ”„๋กœ์ ํŠธ์˜ ํ™•์žฅ์„ฑ๊ณผ ์œ ์—ฐ์„ฑ์„ ๋†’์ด๊ธฐ ์œ„ํ•œ ๋‹ค์–‘ํ•œ ๊ณ ๊ธ‰ ์–ด๋…ธํ…Œ์ด์…˜์„ ์ œ๊ณตํ•ฉ๋‹ˆ๋‹ค. ๊ทธ ์ค‘ ํŠนํžˆ, ์ƒํ™ฉ์— ๋”ฐ๋ผ ๋นˆ(Bean)์„ ๋“ฑ๋กํ• ์ง€ ๊ฒฐ์ •ํ•˜๋Š” @Conditional, ์™ธ๋ถ€ ์„ค์ • ํด๋ž˜์Šค๋‚˜ ๋นˆ์„ ์ถ”๊ฐ€๋กœ ๊ฐ€์ ธ์˜ฌ ๋•Œ ์‚ฌ์šฉํ•˜๋Š” **@Import**๋Š” ๋งค์šฐ ์œ ์šฉํ•œ ๊ธฐ๋Šฅ์ž…๋‹ˆ๋‹ค.

์ด ๊ธ€์—์„œ๋Š” ์‹ค์ œ ์ฝ”๋“œ ์˜ˆ์‹œ๋ฅผ ํ†ตํ•ด ๋‘ ์–ด๋…ธํ…Œ์ด์…˜์„ ํ™•์‹คํžˆ ์ •๋ฆฌํ•˜๊ฒ ์Šต๋‹ˆ๋‹ค.


โœ… @Conditional ์–ด๋…ธํ…Œ์ด์…˜ ์ดํ•ดํ•˜๊ธฐ

@Conditional์€ ํŠน์ • ์กฐ๊ฑด์ด ์ถฉ์กฑ๋  ๋•Œ๋งŒ ๋นˆ์„ ๋“ฑ๋กํ•˜๋Š” ๋ฐ ์‚ฌ์šฉํ•˜๋Š” ์–ด๋…ธํ…Œ์ด์…˜์ž…๋‹ˆ๋‹ค. ์ฃผ๋กœ ํ™˜๊ฒฝ๋ณ„๋กœ ๋นˆ์„ ๋‹ค๋ฅด๊ฒŒ ๋“ฑ๋กํ•  ๋•Œ ๋งค์šฐ ์œ ์šฉํ•ฉ๋‹ˆ๋‹ค.

 

ํ•ต์‹ฌ ์š”์†Œ:

  • Condition ์ธํ„ฐํŽ˜์ด์Šค: ์กฐ๊ฑด์„ ์ •์˜ํ•˜๋Š” ๋กœ์ง์„ ๋‹ด๋Š” ์ธํ„ฐํŽ˜์ด์Šค์ž…๋‹ˆ๋‹ค. matches() ๋ฉ”์„œ๋“œ๋ฅผ ๊ตฌํ˜„ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.
  • matches(ConditionContext context, AnnotatedTypeMetadata metadata) ๋ฉ”์„œ๋“œ:
    • ์ด ๋ฉ”์„œ๋“œ๊ฐ€ true๋ฅผ ๋ฐ˜ํ™˜ํ•˜๋ฉด ํ•ด๋‹น @Conditional์ด ๋ถ™์€ ๋Œ€์ƒ(ํด๋ž˜์Šค ๋˜๋Š” @Bean ๋ฉ”์„œ๋“œ)์ด ํ™œ์„ฑํ™”๋ฉ๋‹ˆ๋‹ค.
    • ConditionContext: ํ˜„์žฌ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์˜ ํ™˜๊ฒฝ(Environment), ๋นˆ ํŒฉํ† ๋ฆฌ(BeanFactory), ํด๋ž˜์Šค ๋กœ๋”(ClassLoader) ๋“ฑ์— ์ ‘๊ทผํ•  ์ˆ˜ ์žˆ๋Š” ์ปจํ…์ŠคํŠธ ์ •๋ณด๋ฅผ ์ œ๊ณตํ•ฉ๋‹ˆ๋‹ค.
    • AnnotatedTypeMetadata: @Conditional์ด ์ ์šฉ๋œ ํด๋ž˜์Šค๋‚˜ ๋ฉ”์„œ๋“œ์˜ ์–ด๋…ธํ…Œ์ด์…˜ ๋ฉ”ํƒ€๋ฐ์ดํ„ฐ์— ์ ‘๊ทผํ•  ์ˆ˜ ์žˆ๊ฒŒ ํ•ด์ค๋‹ˆ๋‹ค.

๐Ÿ“Œ ์˜ˆ์ œ ์ฝ”๋“œ๋กœ ์•Œ์•„๋ณด๊ธฐ

Case 1: ํ•ญ์ƒ ์ฐธ์ธ ์กฐ๊ฑด (TrueCondition)

// ํ•ญ์ƒ true๋ฅผ ๋ฐ˜ํ™˜ํ•˜๋Š” Condition ๊ตฌํ˜„์ฒด
class TrueCondition implements Condition {
    public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {
        System.out.println("Checking TrueCondition: Always true");
        return true;
    }
}

// Engine ์ปดํฌ๋„ŒํŠธ๋Š” TrueCondition์„ ์‚ฌ์šฉํ•˜๋ฏ€๋กœ ํ•ญ์ƒ ๋นˆ์œผ๋กœ ๋“ฑ๋ก๋ฉ๋‹ˆ๋‹ค.
@Component
@Conditional(TrueCondition.class)
class Engine {
    // ... (Engine ํด๋ž˜์Šค ๋‚ด์šฉ)
}
  • ์„ค๋ช…: TrueCondition์€ matches() ๋ฉ”์„œ๋“œ์—์„œ ํ•ญ์ƒ true๋ฅผ ๋ฐ˜ํ™˜ํ•ฉ๋‹ˆ๋‹ค. ๋”ฐ๋ผ์„œ @Conditional(TrueCondition.class)๊ฐ€ ๋ถ™์€ Engine ํด๋ž˜์Šค๋Š” ์–ด๋–ค ํ™˜๊ฒฝ์—์„œ๋“  ํ•ญ์ƒ ์Šคํ”„๋ง ๋นˆ์œผ๋กœ ๋“ฑ๋ก๋ฉ๋‹ˆ๋‹ค.

Case 2: ํ™˜๊ฒฝ ์†์„ฑ ๊ธฐ๋ฐ˜ ์กฐ๊ฑด (OsCondition)

Java
 
// ์‹œ์Šคํ…œ ํ™˜๊ฒฝ ์†์„ฑ 'mode'๊ฐ€ 'dev'์ผ ๋•Œ๋งŒ true๋ฅผ ๋ฐ˜ํ™˜ํ•˜๋Š” Condition ๊ตฌํ˜„์ฒด
class OsCondition implements Condition {
    public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {
        Environment env = context.getEnvironment();
        String mode = env.getProperty("mode");
        System.out.println("Checking OsCondition for mode: " + mode);
        // 'mode' ์†์„ฑ์ด 'dev'์™€ ์ผ์น˜ํ•˜๋Š”์ง€ ํ™•์ธ
        return "dev".equals(mode);
    }
}

// Door ์ปดํฌ๋„ŒํŠธ๋Š” OsCondition์„ ์‚ฌ์šฉํ•˜๋ฏ€๋กœ 'mode=dev'์ผ ๋•Œ๋งŒ ๋นˆ์œผ๋กœ ๋“ฑ๋ก๋ฉ๋‹ˆ๋‹ค.
@Component
@Conditional(OsCondition.class)
class Door {
    // ... (Door ํด๋ž˜์Šค ๋‚ด์šฉ)
}
  • ์„ค๋ช…: OsCondition์€ ConditionContext๋ฅผ ํ†ตํ•ด Environment ๊ฐ์ฒด๋ฅผ ์–ป์–ด์™€ mode๋ผ๋Š” ํ™˜๊ฒฝ ์†์„ฑ ๊ฐ’์„ ํ™•์ธํ•ฉ๋‹ˆ๋‹ค. ๋งŒ์•ฝ mode ์†์„ฑ ๊ฐ’์ด "dev"๋ผ๋ฉด true๋ฅผ ๋ฐ˜ํ™˜ํ•˜๊ณ , ๊ทธ๋ ‡์ง€ ์•Š์œผ๋ฉด false๋ฅผ ๋ฐ˜ํ™˜ํ•ฉ๋‹ˆ๋‹ค.
  • ๊ฒฐ๊ณผ: Door ํด๋ž˜์Šค๋Š” ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜ ์‹คํ–‰ ์‹œ -Dmode=dev ์™€ ๊ฐ™์€ JVM ์˜ต์…˜์ด๋‚˜, ํ™˜๊ฒฝ ๋ณ€์ˆ˜, application.properties ํŒŒ์ผ ๋“ฑ์„ ํ†ตํ•ด mode ์†์„ฑ์ด "dev"๋กœ ์„ค์ •๋œ ๊ฒฝ์šฐ์—๋งŒ ์Šคํ”„๋ง ๋นˆ์œผ๋กœ ๋“ฑ๋ก๋ฉ๋‹ˆ๋‹ค. ๋‹ค๋ฅธ ๊ฐ’(prod ๋“ฑ)์ด๊ฑฐ๋‚˜ ์„ค์ •๋˜์ง€ ์•Š์•˜๋‹ค๋ฉด Door ๋นˆ์€ ์ƒ์„ฑ๋˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค.
  • ํ™œ์šฉ: ์ด์ฒ˜๋Ÿผ @Conditional์„ ์‚ฌ์šฉํ•˜๋ฉด ๊ฐœ๋ฐœ ํ™˜๊ฒฝ, ์šด์˜ ํ™˜๊ฒฝ ๋“ฑ ํŠน์ • ํ™˜๊ฒฝ์— ๋งž๋Š” ๋นˆ์„ ์„ ํƒ์ ์œผ๋กœ ๋“ฑ๋กํ•˜๊ฑฐ๋‚˜, ํŠน์ • ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ ์กด์žฌ ์—ฌ๋ถ€์— ๋”ฐ๋ผ ๋นˆ ๋“ฑ๋ก์„ ๊ฒฐ์ •ํ•˜๋Š” ๋“ฑ ๋งค์šฐ ์œ ์—ฐํ•œ ์„ค์ •์ด ๊ฐ€๋Šฅํ•ด์ง‘๋‹ˆ๋‹ค. (์˜ˆ: ํŠน์ • OS์—์„œ๋งŒ ๋™์ž‘ํ•˜๋Š” ๋นˆ, Feature Toggle ๋“ฑ)

 

* JVM ์˜ต์…˜ ๋ณ€๊ฒฝ

 


 

โœ… @Import ์–ด๋…ธํ…Œ์ด์…˜ ์ดํ•ดํ•˜๊ธฐ

@Import ์–ด๋…ธํ…Œ์ด์…˜์€ ํ•˜๋‚˜์˜ ์„ค์ • ํด๋ž˜์Šค์—์„œ ๋‹ค๋ฅธ ์„ค์ • ํด๋ž˜์Šค๋‚˜ ๋นˆ์„ ๋ถˆ๋Ÿฌ์˜ฌ ๋•Œ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค. ํŠนํžˆ ์กฐ๊ฑด์— ๋”ฐ๋ผ ๋™์ ์œผ๋กœ ์ถ”๊ฐ€ ์„ค์ •์„ ๊ฐ€์ ธ์˜ฌ ๋•Œ ์œ ์šฉํ•ฉ๋‹ˆ๋‹ค.

์ฃผ์š” ์‚ฌ์šฉ๋ฒ•:

  1. ๋‹ค๋ฅธ @Configuration ํด๋ž˜์Šค ์ง์ ‘ ์ž„ํฌํŠธ: ๊ฐ€์žฅ ๊ธฐ๋ณธ์ ์ธ ๋ฐฉ๋ฒ•์ž…๋‹ˆ๋‹ค.
  2. ImportSelector ๊ตฌํ˜„์ฒด ์ž„ํฌํŠธ: ๋™์ ์œผ๋กœ ์ž„ํฌํŠธํ•  ์„ค์ • ํด๋ž˜์Šค๋ฅผ ์„ ํƒํ•ด์•ผ ํ•  ๋•Œ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค.
  3. ImportBeanDefinitionRegistrar ๊ตฌํ˜„์ฒด ์ž„ํฌํŠธ: ํ”„๋กœ๊ทธ๋ž˜๋ฐ ๋ฐฉ์‹์œผ๋กœ ๋นˆ ์ •์˜๋ฅผ ์ง์ ‘ ๋“ฑ๋กํ•ด์•ผ ํ•  ๋•Œ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค. (๊ณ ๊ธ‰ ๊ธฐ๋Šฅ)
  4. (์ถ”๊ฐ€) ์ผ๋ฐ˜ ํด๋ž˜์Šค ์ž„ํฌํŠธ: @Component ๋“ฑ์ด ๋ถ™์ง€ ์•Š์€ ์ผ๋ฐ˜ ํด๋ž˜์Šค๋ฅผ ์ง€์ •ํ•˜๋ฉด, ํ•ด๋‹น ํด๋ž˜์Šค๊ฐ€ ๋นˆ์œผ๋กœ ๋“ฑ๋ก๋ฉ๋‹ˆ๋‹ค.

๐Ÿ“Œ ์˜ˆ์ œ ์ฝ”๋“œ๋กœ ์•Œ์•„๋ณด๊ธฐ

์‚ฌ์šฉ๋ฒ• 1: ๋‹ค๋ฅธ @Configuration ํด๋ž˜์Šค ์ง์ ‘ ์ž„ํฌํŠธ

๊ฐ€์žฅ ๊ฐ„๋‹จํ•œ ๋ฐฉ๋ฒ•์€ @Import ์–ด๋…ธํ…Œ์ด์…˜์— ์ž„ํฌํŠธํ•˜๊ณ  ์‹ถ์€ ์„ค์ • ํด๋ž˜์Šค๋“ค์„ ์ง์ ‘ ๋ช…์‹œํ•˜๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค.

// ์˜ˆ์‹œ: MainConfig์— ์ง์ ‘ Config1๊ณผ Config2๋ฅผ ์ž„ํฌํŠธํ•˜๋Š” ๊ฒฝ์šฐ
@Configuration
@Import({Config1.class, Config2.class}) // Config1๊ณผ Config2๋ฅผ ๋ชจ๋‘ ๊ฐ€์ ธ์˜ด
class MainConfig {
    @Bean Car car() { return new Car(); }
}

class Config1 { @Bean Car sportsCar() { return new SportsCar(); }}
class Config2 { @Bean Car sportsCar() { return new SportsCar2(); }}
  • ๋™์ž‘ ๋ฐฉ์‹: ์œ„์™€ ๊ฐ™์ด MainConfig์— @Import({Config1.class, Config2.class})๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด, Spring์€ MainConfig๋ฅผ ๋กœ๋“œํ•  ๋•Œ Config1๊ณผ Config2์— ์ •์˜๋œ ๋นˆ๋“ค๋„ ํ•จ๊ป˜ ๋กœ๋“œํ•ฉ๋‹ˆ๋‹ค.
  • ์ฃผ์˜์ : ์ด ๋ฐฉ์‹์€ ์ง€์ •๋œ ๋ชจ๋“  ์„ค์ •์„ ๋ฌด์กฐ๊ฑด ๊ฐ€์ ธ์˜ต๋‹ˆ๋‹ค. ๋งŒ์•ฝ ์œ„ ์˜ˆ์‹œ์ฒ˜๋Ÿผ Config1๊ณผ Config2 ๋ชจ๋‘ "sportsCar"๋ผ๋Š” ์ด๋ฆ„์˜ ๋นˆ์„ ์ •์˜ํ•˜๊ณ  ์žˆ๋‹ค๋ฉด ์–ด๋–ป๊ฒŒ ๋ ๊นŒ์š”? Spring์€ ๋™์ผํ•œ ์ด๋ฆ„์˜ ๋นˆ์ด ์—ฌ๋Ÿฌ ๊ฐœ ์ •์˜๋œ ๊ฒƒ์„ ๊ฐ์ง€ํ•˜๊ณ , ์–ด๋–ค ๋นˆ์„ ์‚ฌ์šฉํ•ด์•ผ ํ• ์ง€ ๊ฒฐ์ •ํ•  ์ˆ˜ ์—†์–ด ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜ ์‹œ์ž‘ ์‹œ์ ์— NoUniqueBeanDefinitionException ๊ฐ™์€ ์˜ค๋ฅ˜๋ฅผ ๋ฐœ์ƒ์‹œํ‚ฌ ๊ฐ€๋Šฅ์„ฑ์ด ๋†’์Šต๋‹ˆ๋‹ค. (๋ฌผ๋ก  @Primary ์–ด๋…ธํ…Œ์ด์…˜ ๋“ฑ์œผ๋กœ ์šฐ์„ ์ˆœ์œ„๋ฅผ ์ง€์ •ํ•  ์ˆ˜๋Š” ์žˆ์ง€๋งŒ, ์˜๋„ํ•˜์ง€ ์•Š์€ ์ถฉ๋Œ์ด ๋ฐœ์ƒํ•˜๊ธฐ ์‰ฝ์Šต๋‹ˆ๋‹ค.)
  • ์ ํ•ฉํ•œ ๊ฒฝ์šฐ: ์ž„ํฌํŠธํ•˜๋ ค๋Š” ์„ค์ •๋“ค์ด ์„œ๋กœ ๋‹ค๋ฅธ ์ด๋ฆ„์˜ ๋นˆ๋“ค์„ ์ •์˜ํ•˜๊ณ  ์žˆ๊ฑฐ๋‚˜, ๋ช…ํ™•ํ•œ ์˜๋„๋ฅผ ๊ฐ€์ง€๊ณ  ๋นˆ ์ •์˜๋ฅผ ์˜ค๋ฒ„๋ผ์ด๋”ฉํ•˜๋ ค๋Š” ๊ฒฝ์šฐ์— ์ ํ•ฉํ•ฉ๋‹ˆ๋‹ค. ํ•˜์ง€๋งŒ ์กฐ๊ฑด์— ๋”ฐ๋ผ ํŠน์ • ์„ค์ •๋งŒ ์„ ํƒ์ ์œผ๋กœ ๋กœ๋“œํ•˜๊ณ  ์‹ถ๋‹ค๋ฉด ์ด ๋ฐฉ์‹์€ ์ ํ•ฉํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. ์ด๋•Œ ImportSelector๊ฐ€ ํ•„์š”ํ•ฉ๋‹ˆ๋‹ค.

์‚ฌ์šฉ๋ฒ• 2: ImportSelector๋กœ ๋™์  ์„ ํƒํ•˜๊ธฐ

์กฐ๊ฑด์— ๋”ฐ๋ผ ์ž„ํฌํŠธํ•  ์„ค์ •์„ ๋™์ ์œผ๋กœ ๊ฒฐ์ •ํ•ด์•ผ ํ•  ๋•Œ ImportSelector ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค. selectImports() ๋ฉ”์„œ๋“œ์—์„œ ๋กœ๋“œํ•  ์„ค์ • ํด๋ž˜์Šค์˜ ์ด๋ฆ„ ๋ฐฐ์—ด์„ ๋ฐ˜ํ™˜ํ•˜์—ฌ ์ด ๋ฌธ์ œ๋ฅผ ํ•ด๊ฒฐํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

์˜ˆ์ œ ์ฝ”๋“œ ๋‹ค์‹œ ์‚ดํŽด๋ณด๊ธฐ (ImportSelector ํ™œ์šฉ)

// ์„ค์ • ํด๋ž˜์Šค 1: SportsCar ๋นˆ ์ •์˜
class Config1 { @Bean Car sportsCar() { return new SportsCar(); }}
// ์„ค์ • ํด๋ž˜์Šค 2: SportsCar2 ๋นˆ ์ •์˜
class Config2 { @Bean Car sportsCar() { return new SportsCar2(); }}

// ImportSelector ๊ตฌํ˜„์ฒด: @EnableMyAutoConfiguration์˜ value ์†์„ฑ ๊ฐ’์— ๋”ฐ๋ผ Config1 ๋˜๋Š” Config2๋ฅผ ์„ ํƒ
class MyImportSelector implements ImportSelector {
    @Override
    public String[] selectImports(AnnotationMetadata importingClassMetadata) {
        AnnotationAttributes attr = AnnotationAttributes.fromMap(
                importingClassMetadata.getAnnotationAttributes(EnableMyAutoConfiguration.class.getName()));
        String mode = attr.getString("value");
        System.out.println("MyImportSelector mode: " + mode);
        if ("test".equals(mode)) {
            return new String[] {Config1.class.getName()};
        } else {
            return new String[] {Config2.class.getName()};
        }
    }
}

// ์ปค์Šคํ…€ ์–ด๋…ธํ…Œ์ด์…˜: MyImportSelector๋ฅผ ์ž„ํฌํŠธํ•˜๋„๋ก ์„ค์ •
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Import(MyImportSelector.class)
@interface EnableMyAutoConfiguration {
    String value() default "";
}

// ๋ฉ”์ธ ์„ค์ • ํด๋ž˜์Šค: @EnableMyAutoConfiguration ์‚ฌ์šฉ
@EnableMyAutoConfiguration("test2")
class MainConfig {
    @Bean Car car() { return new Car(); }
}

// ... (Main ํด๋ž˜์Šค ์‹คํ–‰ ๋ถ€๋ถ„์€ ๋™์ผ) ...
  • ๋™์ž‘ ์„ค๋ช…: (์ด์ „ ์„ค๋ช…๊ณผ ๋™์ผ) MainConfig์˜ @EnableMyAutoConfiguration("test2") ๋•Œ๋ฌธ์— MyImportSelector๊ฐ€ ๋™์ž‘ํ•˜๊ณ , value ๊ฐ’ "test2"๋ฅผ ์ฝ์–ด Config2๋ฅผ ์ž„ํฌํŠธํ•ฉ๋‹ˆ๋‹ค. ๊ฒฐ๊ณผ์ ์œผ๋กœ "sportsCar" ๋นˆ์€ SportsCar2 ํƒ€์ž…์ด ๋ฉ๋‹ˆ๋‹ค.

์™œ @EnableMyAutoConfiguration ๊ฐ™์€ ์ปค์Šคํ…€ ์–ด๋…ธํ…Œ์ด์…˜์„ ์‚ฌ์šฉํ• ๊นŒ์š”?

์—ฌ๊ธฐ์„œ ํ•œ ๊ฐ€์ง€ ์˜๋ฌธ์ด ์ƒ๊ธธ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. "๊ตณ์ด @EnableMyAutoConfiguration ์–ด๋…ธํ…Œ์ด์…˜์„ ๋งŒ๋“ค ํ•„์š” ์—†์ด, MainConfig์— ์ง์ ‘ @Import(MyImportSelector.class)๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด ์•ˆ ๋˜๋‚˜์š”?"

 

๋‹ต๋ณ€: ๊ธฐ์ˆ ์ ์œผ๋กœ๋Š” ๊ฐ€๋Šฅํ•˜์ง€๋งŒ, @EnableMyAutoConfiguration ๊ฐ™์€ ์ปค์Šคํ…€ ์–ด๋…ธํ…Œ์ด์…˜์„ ์‚ฌ์šฉํ•˜๋Š” ๋ฐ์—๋Š” ๋ช‡ ๊ฐ€์ง€ ์ค‘์š”ํ•œ ์ด์œ ๊ฐ€ ์žˆ์Šต๋‹ˆ๋‹ค.

  1. ์ถ”์ƒํ™” ๋ฐ ๊ฐ€๋…์„ฑ ํ–ฅ์ƒ: @EnableMyAutoConfiguration("test2")๋Š” "ํŠน์ • ๋ชจ๋“œ('test2')์— ๋งž๋Š” ์ž๋™ ์„ค์ •์„ ํ™œ์„ฑํ™”ํ•œ๋‹ค"๋Š” ์˜๋„๋ฅผ ๋ช…ํ™•ํ•˜๊ฒŒ ๋“œ๋Ÿฌ๋ƒ…๋‹ˆ๋‹ค. ๋ฐ˜๋ฉด @Import(MyImportSelector.class)๋Š” ๋‹จ์ˆœํžˆ '์–ด๋–ค Selector๋ฅผ ์‚ฌ์šฉํ•œ๋‹ค'๋Š” ๊ตฌํ˜„ ๋ฐฉ์‹์„ ๋ณด์—ฌ์ค„ ๋ฟ์ž…๋‹ˆ๋‹ค. ์‚ฌ์šฉ์ž๋Š” MyImportSelector์˜ ๋‚ด๋ถ€ ๋™์ž‘์„ ๋ชฐ๋ผ๋„ @EnableMyAutoConfiguration๋งŒ ๋ณด๊ณ  ์–ด๋–ค ๊ธฐ๋Šฅ์ด ํ™œ์„ฑํ™”๋˜๋Š”์ง€ ์‰ฝ๊ฒŒ ์ดํ•ดํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์ด๋Š” Spring Boot์˜ ์ˆ˜๋งŽ์€ @Enable... ์–ด๋…ธํ…Œ์ด์…˜๋“ค์ด ๋”ฐ๋ฅด๋Š” ๋ฐฉ์‹์ด๊ธฐ๋„ ํ•ฉ๋‹ˆ๋‹ค.
  2. ํŒŒ๋ผ๋ฏธํ„ฐ ์ „๋‹ฌ ์šฉ์ด์„ฑ: MyImportSelector๋Š” "mode" ๊ฐ’("test" ๋˜๋Š” "test2")์— ๋”ฐ๋ผ ๋‹ค๋ฅธ ์„ค์ •์„ ์ž„ํฌํŠธํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. @EnableMyAutoConfiguration ์–ด๋…ธํ…Œ์ด์…˜์— value() ์†์„ฑ์„ ์ •์˜ํ•จ์œผ๋กœ์จ, ์‚ฌ์šฉํ•˜๋Š” ์ชฝ(MainConfig)์—์„œ @EnableMyAutoConfiguration("test2")์ฒ˜๋Ÿผ ๋ช…ํ™•ํ•˜๊ณ  ๊ฐ„๊ฒฐํ•˜๊ฒŒ ํŒŒ๋ผ๋ฏธํ„ฐ๋ฅผ ์ „๋‹ฌํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๋งŒ์•ฝ @Import(MyImportSelector.class)๋ฅผ ์ง์ ‘ ์‚ฌ์šฉํ•œ๋‹ค๋ฉด, ์ด "mode" ๊ฐ’์„ MyImportSelector์— ์ „๋‹ฌํ•  ๋‹ค๋ฅธ ๋ฐฉ๋ฒ•์„ ์ฐพ์•„์•ผ ํ•ฉ๋‹ˆ๋‹ค (์˜ˆ: ๋ณ„๋„์˜ ์–ด๋…ธํ…Œ์ด์…˜์„ ์ถ”๊ฐ€๋กœ ๋ถ™์ด๊ฑฐ๋‚˜, ํ™˜๊ฒฝ ๋ณ€์ˆ˜๋ฅผ ํ†ตํ•˜๋Š” ๋“ฑ). ์ปค์Šคํ…€ ์–ด๋…ธํ…Œ์ด์…˜์˜ ์†์„ฑ์„ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ์ด ํ›จ์”ฌ ์ง๊ด€์ ์ด๊ณ  ๊น”๋”ํ•ฉ๋‹ˆ๋‹ค.
  3. ์žฌ์‚ฌ์šฉ์„ฑ ๋ฐ ์บก์Аํ™”: @EnableMyAutoConfiguration์€ MyImportSelector๋ผ๋Š” ๊ตฌ์ฒด์ ์ธ ๊ตฌํ˜„์„ ์‚ฌ์šฉ์ž๋กœ๋ถ€ํ„ฐ ์ˆจ๊น๋‹ˆ๋‹ค(์บก์Аํ™”). ๋‚˜์ค‘์— ์„ ํƒ ๋กœ์ง์ด ๋ฐ”๋€Œ์–ด MyImportSelector2๋ฅผ ์‚ฌ์šฉํ•ด์•ผ ํ•˜๋”๋ผ๋„, @EnableMyAutoConfiguration์˜ ๋‚ด๋ถ€ @Import ๋Œ€์ƒ๋งŒ ๋ณ€๊ฒฝํ•˜๋ฉด ์‚ฌ์šฉ์ž๋Š” ๊ธฐ์กด์˜ @EnableMyAutoConfiguration("test2") ์ฝ”๋“œ๋ฅผ ์ˆ˜์ •ํ•  ํ•„์š”๊ฐ€ ์—†์Šต๋‹ˆ๋‹ค. ๋˜ํ•œ, ์ด @Enable... ์–ด๋…ธํ…Œ์ด์…˜์€ ๋‹ค๋ฅธ ์—ฌ๋Ÿฌ ์„ค์ • ํด๋ž˜์Šค์—์„œ ์žฌ์‚ฌ์šฉ๋  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
  4. ๊ด€๋ก€ ์ค€์ˆ˜: Spring ์ปค๋ฎค๋‹ˆํ‹ฐ์—์„œ๋Š” ํŠน์ • ๊ธฐ๋Šฅ์ด๋‚˜ ์„ค์ •์„ ํ™œ์„ฑํ™”ํ•  ๋•Œ @Enable... ํ˜•ํƒœ์˜ ์–ด๋…ธํ…Œ์ด์…˜์„ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ์ด ์ผ๋ฐ˜์ ์ธ ๊ด€๋ก€์ž…๋‹ˆ๋‹ค. ์ด ๊ด€๋ก€๋ฅผ ๋”ฐ๋ฅด๋ฉด ๋‹ค๋ฅธ ๊ฐœ๋ฐœ์ž๋“ค์ด ์ฝ”๋“œ๋ฅผ ์ดํ•ดํ•˜๊ธฐ ์‰ฌ์›Œ์ง‘๋‹ˆ๋‹ค.

๊ฒฐ๋ก ์ ์œผ๋กœ, @EnableMyAutoConfiguration๊ณผ ๊ฐ™์€ ์ปค์Šคํ…€ ์–ด๋…ธํ…Œ์ด์…˜์€ ImportSelector๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ๋ฐ ํ•„์ˆ˜๋Š” ์•„๋‹ˆ์ง€๋งŒ, ์ฝ”๋“œ์˜ ๊ฐ€๋…์„ฑ, ์ถ”์ƒํ™” ์ˆ˜์ค€, ์žฌ์‚ฌ์šฉ์„ฑ, ํŒŒ๋ผ๋ฏธํ„ฐ ์ „๋‹ฌ์˜ ํŽธ์˜์„ฑ์„ ํฌ๊ฒŒ ๋†’์—ฌ์ฃผ๊ธฐ ๋•Œ๋ฌธ์— ์ ๊ทน ๊ถŒ์žฅ๋˜๋Š” ๋ฐฉ์‹์ž…๋‹ˆ๋‹ค. ๊ตฌํ˜„ ์„ธ๋ถ€์‚ฌํ•ญ์„ ์ˆจ๊ธฐ๊ณ  ๋ช…ํ™•ํ•œ ์˜๋„๋ฅผ ๋“œ๋Ÿฌ๋‚ด๋Š” ์ข‹์€ ์„ค๊ณ„ ํŒจํ„ด์ž…๋‹ˆ๋‹ค.

 

๐ŸŽฏ ์ข…ํ•ฉ ์ •๋ฆฌ: ์™œ ํ•„์š”ํ•˜๊ณ  ์–ธ์ œ ์‚ฌ์šฉํ• ๊นŒ์š”?

๊ธฐ๋Šฅ๋ชฉ์ ์˜ˆ์‹œ
@Conditional ์กฐ๊ฑด๋ถ€ ๋นˆ ๋“ฑ๋ก ํ™˜๊ฒฝ(๊ฐœ๋ฐœ, ์šด์˜, ํ…Œ์ŠคํŠธ)์— ๋”ฐ๋ผ ๋‹ค๋ฅธ ๋นˆ ๋“ฑ๋ก
@Import ์™ธ๋ถ€ ์„ค์ • ํด๋ž˜์Šค ๊ฐ€์ ธ์˜ค๊ธฐ ํ™˜๊ฒฝ์— ๋”ฐ๋ผ ์„ค์ • ํŒŒ์ผ์ด๋‚˜ ๋นˆ ๋“ฑ๋ก ๋ณ€๊ฒฝ

@Conditional๊ณผ @Import๋Š” Spring์—์„œ ์ œ๊ณตํ•˜๋Š” ๊ฐ€์žฅ ๊ฐ•๋ ฅํ•œ ์–ด๋…ธํ…Œ์ด์…˜ ์ค‘ ํ•˜๋‚˜๋กœ, ๋ณต์žกํ•œ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜ ํ™˜๊ฒฝ์—์„œ ์œ ์—ฐํ•˜๊ณ  ๊ด€๋ฆฌ๊ฐ€ ์‰ฌ์šด ๋นˆ ๋“ฑ๋ก ๋ฐฉ์‹์„ ์ œ๊ณตํ•ฉ๋‹ˆ๋‹ค.
์ด๋ฅผ ์ž˜ ์ดํ•ดํ•˜๊ณ  ํ™œ์šฉํ•˜๋ฉด ์ฝ”๋“œ ํ’ˆ์งˆ๊ณผ ์œ ์ง€๋ณด์ˆ˜์„ฑ์„ ํฌ๊ฒŒ ๋†’์ผ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

๋ฐ˜์‘ํ˜•