์Šคํ”„๋ง @Conditional

2023. 4. 27. 09:08ใ†์ธํ”„๋Ÿฐ/์Šคํ”„๋ง ๋ถ€ํŠธ - ํ•ต์‹ฌ ์›๋ฆฌ์™€ ํ™œ์šฉ

728x90

 

 

0๏ธโƒฃ ์˜ˆ์ œ ํ”„๋กœ์ ํŠธ ๋งŒ๋“ค๊ธฐ 

์Šคํ”„๋ง ๋ถ€ํŠธ๊ฐ€ ์ œ๊ณตํ•˜๋Š” ์ž๋™ ๊ตฌ์„ฑ์— ๋Œ€ํ•ด์„œ ์•Œ์•„๋ณด๊ธฐ ์ „์— 

๊ฐ„๋‹จํ•œ ์˜ˆ์ œ ํ”„๋กœ์ ํŠธ๋ฅผ ๋งŒ๋“ค ๊ฒƒ์ธ๋ฐ ์ด ์˜ˆ์ œ ํ”„๋กœ์ ํŠธ๋Š” ์‹ค์‹œ๊ฐ„์œผ๋กœ ์ž๋ฐ” ๋ฉ”๋ชจ๋ฆฌ ์‚ฌ์šฉ๋Ÿ‰์„ ์›น์œผ๋กœ ํ™•์ธํ•˜๋Š” ์˜ˆ์ œ์ด๋‹ค. 

 

Memory

public class Memory
{
   private long used;
   private long max;
   
   public Memory(long used, long max)
   {
      this.used = used;
      this.max = max;
   }
   
   public long getUsed()
   {
      return used;
   }
   
   public long getMax()
   {
      return max;
   }
   
   @Override
   public String toString()
   {
      return "Memory{" +
            "used=" + used +
            ", max=" + max +
            '}';
   }
}

uesd๋Š” ํ˜„์žฌ ์‚ฌ์šฉ์ค‘์ธ ๋ฉ”๋ชจ๋ฆฌ์ด๊ณ , max๋Š” ์ตœ๋Œ€ ๋ฉ”๋ชจ๋ฆฌ๋กœ used๊ฐ€ max๋ฅผ ๋„˜์–ด๊ฐ€๋ฉด ๋ฉ”๋ชจ๋ฆฌ ๋ถ€์กฑ ์˜ค๋ฅ˜๊ฐ€ ๋ฐœ์ƒํ•˜๋Š” ๊ฒƒ์ด๋‹ค. 

 

 

MemoryFinder

@Slf4j
public class MemoryFinder
{
   
   public Memory get()
   {
      long max = Runtime.getRuntime().maxMemory(); // JVM์ด ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋Š” ์ตœ๋Œ€ ๋ฉ”๋ชจ๋ฆฌ
      long total = Runtime.getRuntime().totalMemory();  // JVM์ด ํ™•๋ณดํ•œ ์ „์ฒด ๋ฉ”๋ชจ๋ฆฌ
      long free = Runtime.getRuntime().freeMemory();  /// JVM์ด ํ™•๋ณดํ•œ ์ „์ฒด ๋ฉ”๋ชจ๋ฆฌ ์ค‘ ์‚ฌ์šฉํ•˜์ง€ ์•Š์€ ๊ฒƒ
      
      long used = total - free;
      
      return new Memory(used, max);
   }
   
   @PostConstruct
   public void init()
   {
      log.info("init MemoryFinder");
   }
}

MemoryFinder์—์„œ ์ด์ œ ๋ฉ”๋ชจ๋ฆฌ ์ •๋ณด๋ฅผ ์‹ค์‹œ๊ฐ„์œผ๋กœ ์กฐํšŒํ•˜๋Š” ๊ธฐ๋Šฅ์ด๋‹ค. 

max : JVM์ด ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋Š” ์ตœ๋Œ€ ๋ฉ”๋ชจ๋ฆฌ

total : JVM์ด ํ™•๋ณดํ•œ ์ „์ฒด ๋ฉ”๋ชจ๋ฆฌ (JVM์ด ์ฒ˜์Œ๋ถ€ํ„ฐ max๊นŒ์ง€ ๋‹ค ํ™•๋ณดํ•˜๋Š” ๊ฒƒ์ด ์•„๋‹ˆ๊ณ  ํ•„์š”ํ•  ๋•Œ ๋งˆ๋‹ค ์กฐ๊ธˆ์”ฉ ํ™•๋ณดํ•œ๋‹ค.)

free : total ์ค‘์—์„œ ์‚ฌ์šฉํ•˜์ง€ ์•Š์€ ๋ฉ”๋ชจ๋ฆฌ (JVM์ด ํ™•๋ณดํ•œ ์ „์ฒด ๋ฉ”๋ชจ๋ฆฌ ์ค‘์—์„œ ์‚ฌ์šฉํ•˜์ง€ ์•Š์€ ๊ฒƒ) 

used : total - free ๋กœ JVM์ด ์‚ฌ์šฉ์ค‘์ธ ๋ฉ”๋ชจ๋ฆฌ์ด๋‹ค. 

 

 

MemoryController

@Slf4j
@RestController
@RequiredArgsConstructor
public class MemoryController
{
   
   private final MemoryFinder memoryFinder;
   
   @GetMapping("/memory")
   public Memory system()
   {
      Memory memory = memoryFinder.get();
      log.info("memory = {}" , memory);
      
      return memory;
   }
}

MemoryController์—์„œ๋Š” ์ด์ œ ๋ฉ”๋ชจ๋ฆฌ ์ •๋ณด๋ฅผ ์กฐํšŒํ•˜๋Š” ์ปจํŠธ๋กค๋Ÿฌ๋กœ memoryFinder๋ฅผ ์ฃผ์ž…๋ฐ›์•„์„œ ์‚ฌ์šฉํ•œ๋‹ค. 

 

 

MemoryConfig

@Configuration
public class MemoryConfig
{
   
   @Bean
   public MemoryController memoryController()
   {
      return new MemoryController(memoryFinder());
   }
   
   @Bean
   public MemoryFinder memoryFinder()
   {
      return new MemoryFinder();
   }
}

๊ทธ๋ฆฌ๊ณ  ์ด์ œ MemoryConfig์— MemoryController์™€ MemoryFinder๋ฅผ ๋นˆ์œผ๋กœ ๋“ฑ๋กํ•ด์คฌ๋‹ค.

 

๋นˆ์œผ๋กœ ๋“ฑ๋กํ›„ localhost:8080/memory๋ฅผ ์‹คํ–‰ํ•˜๋ฉด ๊ฐ„๋‹จํ•˜๊ฒŒ ๋ฉ”๋ชจ๋ฆฌ ์‚ฌ์šฉ๋Ÿ‰์„ ์‹ค์‹œ๊ฐ„์œผ๋กœ ํ™•์ธํ•  ์ˆ˜ ์žˆ๋‹ค. 

 

 

 

1๏ธโƒฃ Conditional 

์ด์ œ ์œ„์—์„œ ๋งŒ๋“  ํ”„๋กœ์ ํŠธ๋ฅผ ์‚ฌ์šฉํ•˜๋Š”๋ฐ ํ•ญ์ƒ ๋ฉ”๋ชจ๋ฆฌ ์กฐํšŒ ๊ธฐ๋Šฅ์„ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ์ด ์•„๋‹ˆ๋ผ ํŠน์ • ์กฐ๊ฑด์ผ ๋•Œ๋งŒ ํ•ด๋‹น ๊ธฐ๋Šฅ์ด ํ™œ์„ฑํ™”๋˜๋„๋ก ํ•˜๊ณ  ์‹ถ๋‹ค๋ฉด?? 

์Šคํ”„๋ง์ด ์ œ๊ณตํ•˜๋Š” @Conditional ์–ด๋…ธํ…Œ์ด์…˜์ด ์žˆ๋‹ค. 

-> ์ด ์–ด๋…ธํ…Œ์ด์…˜์€ ๊ฐ™์€ ์†Œ์Šค ์ฝ”๋“œ์ธ๋ฐ ํŠน์ • ์ƒํ™ฉ์ผ ๋•Œ๋งŒ ํŠน์ • ๋นˆ๋“ค์„ ๋“ฑ๋กํ•ด์„œ ์‚ฌ์šฉํ•˜๋„๋ก ๋„์™€์ฃผ๋Š” ๊ธฐ๋Šฅ์ด๋‹ค. 

(if๋ฌธ์„ ๋„ฃ๋Š”๊ฒƒ๊ณผ ๋น„์Šทํ•˜๋‹ค.) 

 

Condition

@FunctionalInterface
public interface Condition {

   /**
    * Determine if the condition matches.
    * @param context the condition context
    * @param metadata the metadata of the {@link org.springframework.core.type.AnnotationMetadata class}
    * or {@link org.springframework.core.type.MethodMetadata method} being checked
    * @return {@code true} if the condition matches and the component can be registered,
    * or {@code false} to veto the annotated component's registration
    */
   boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata);

}

matches ๋ฉ”์„œ๋“œ๊ฐ€ true๋ฅผ ๋ฐ˜ํ™˜ํ•˜๋ฉด ์กฐ๊ฑด์ด ๋งŒ์กฑํ•˜๋Š” ๊ฒƒ์œผ๋กœ ํŠน์ • ๊ธฐ๋Šฅ์„ ๋™์ž‘ํ•˜๊ณ , false๋ฅผ ๋ฐ˜ํ™˜ํ•˜๋ฉด ๋™์ž‘ํ•˜์ง€ ์•Š๋„๋ก ํ•œ๋‹ค. 

 

 

MemoryCondition 

@Slf4j
public class MemoryCondition implements Condition
{
   
   @Override
   public boolean matches(ConditionContext context,
         AnnotatedTypeMetadata metadata)
   {
      // -Dmemory=on
      String memory = context.getEnvironment().getProperty("memory");
      log.info("memory = {} ", memory);
      
      return "on".equals(memory);
   }
}

MemoryConditon์€ Condition ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ๊ตฌํ˜„ํ•ด์„œ ์ž๋ฐ” ์‹œ์Šคํ…œ ์†์„ฑ์ด memory = on์œผ๋กœ ์„ค์ •๋œ ๊ฒฝ์šฐ์—๋งŒ true๋ฅผ ๋ฐ˜ํ™˜ํ•ด์„œ ๋ฉ”๋ชจ๋ฆฌ ์กฐํšŒํ•  ์ˆ˜์žˆ๋‹ค. 

 

VM ์˜ต์…˜ ์„ค์ •์— -Dmemory=on ์„ค์ •ํ•ด์ฃผ๋ฉด ๋œ๋‹ค. 

 

๊ทธ ๋‹ค์Œ MemoryConfig ์—์„œ @Conditional ์–ด๋…ธํ…Œ์ด์…˜์„ ์ถ”๊ฐ€ํ•ด์ค€๋‹ค. 

@Configuration
@Conditional(MemoryCondition.class)
public class MemoryConfig
{
   
   @Bean
   public MemoryController memoryController()
   {
      return new MemoryController(memoryFinder());
   }
   
   @Bean
   public MemoryFinder memoryFinder()
   {
      return new MemoryFinder();
   }
}

@Conditional(MemoryCondition.class) 

-> ์ด ์–ด๋…ธํ…Œ์ด์…˜์„ ์ถ”๊ฐ€ํ•˜๊ณ  ๋‚˜๋ฉด ์ด์ œ ๋ฉ”๋ชจ๋ฆฌ ์กฐํšŒ ๊ธฐ๋Šฅ์„ ํ•ญ์ƒ ์‹คํ–‰ํ•  ์ˆ˜ ์žˆ๋Š” ๊ฒƒ์ด ์•„๋‹ˆ๋ผ ํŠน์ • ์กฐ๊ฑด์— ๋งž๋Š” ๊ฒฝ์šฐ์—๋งŒ ์‹คํ–‰ํ•  ์ˆ˜ ์žˆ๋‹ค.

์ฆ‰, @Conditional์— ์ง€์ •ํ•œ MemoryConfig์˜ ์กฐ๊ฑด์— ๋”ฐ๋ผ true ์ธ ๊ฒฝ์šฐ์—๋งŒ MemoryConfig๊ฐ€ ์ ์šฉ ๋  ์ˆ˜ ์žˆ๋‹ค. 

 

MemoryCondition์˜ matches()๋ฅผ ์‹คํ–‰ํ•ด๋ณด๊ณ , ๊ทธ ๋‹ค์Œ ๊ฒฐ๊ณผ๊ฐ€ true ์ด๋ฉด MemoryConfig๊ฐ€ ์ •์ƒ ๋™์ž‘๋˜๊ณ , MemoryController, MemoryFinder๊ฐ€ ๋นˆ์œผ๋กœ ๋“ฑ๋ก๋œ๋‹ค. 

๋ฐ˜๋Œ€๋กœ ๊ฒฐ๊ณผ๊ฐ€ false ์ธ ๊ฒฝ์šฐ์—๋Š” MemoryConfig๋Š” ๋ฌดํšจํ™” ๋˜์–ด์„œ ๋นˆ์œผ๋กœ ๋“ฑ๋ก๋˜์ง€ ์•Š๋Š”๋‹ค. 

 

 

 

2๏ธโƒฃ @Conditional์˜ ๋‹ค์–‘ํ•œ ๊ธฐ๋Šฅ 

์œ„์—์„œ ๋ณด๋ฉด MemoryCondition์ด Condition์„ ์ง์ ‘ ๊ตฌํ˜„ํ•ด์„œ ๊ตฌํ˜„์ฒด๋ฅผ ๋งŒ๋“ค์—ˆ๋Š”๋ฐ ์‚ฌ์‹ค ์Šคํ”„๋ง์€ ์ด๋ฏธ ํ•„์š”ํ•œ ๊ฒƒ์„ ์ œ๊ณตํ•˜๊ณ  ์žˆ๋‹ค. 

 

MemoryConfig

@Configuration
//@Conditional(MemoryCondition.class)
@ConditionalOnProperty(name = "memory", havingValue = "on")
public class MemoryConfig
{
   
   @Bean
   public MemoryController memoryController()
   {
      return new MemoryController(memoryFinder());
   }
   
   @Bean
   public MemoryFinder memoryFinder()
   {
      return new MemoryFinder();
   }
}

@Conditional ์–ด๋…ธํ…Œ์ด์…˜ ๋Œ€์‹  @ConditionalOnProperty(name = "memory", havingValue = "on") ์–ด๋…ธํ…Œ์ด์…˜์œผ๋กœ ๋ฐ”๊ฟ”์ฃผ๋ฉด ์œ„์—์„œ ํ–ˆ๋˜ ๊ฒƒ๊ณผ ๋˜‘๊ฐ™์ด ๋™์ž‘ํ•œ๋‹ค! 

@ConditionalOnProperty ์–ด๋…ธํ…Œ์ด์…˜์„ ๋ณด๋ฉด ๊ทธ ์•ˆ์— @Conditional ์–ด๋…ธํ…Œ์ด์…˜์„ ๊ฐ€์ง€๊ณ  ์žˆ๋Š” ๊ฒƒ์„ ํ™•์ธํ•  ์ˆ˜ ์žˆ๋‹ค. 

๊ทธ๋ฆฌ๊ณ  OnPropertyCondition ํด๋ž˜์Šค๋ฅผ ๋ณด๋ฉด Condition์„ ๊ตฌํ˜„ํ•˜๊ณ  ์žˆ๋Š” ๊ฒƒ๋„ ํ™•์ธํ•  ์ˆ˜ ์žˆ๋‹ค. 

 

 

๐Ÿ’Œ ์Šคํ”„๋ง์ด ์ œ๊ณตํ•˜๋Š” @ConditionalOnXxx

- @ConditionalOnClass, @ConditionalOnMissingClass 

: ํด๋ž˜์Šค๊ฐ€ ์žˆ๋Š” ๊ฒฝ์šฐ์— ๋™์ž‘ํ•œ๋‹ค, ์—†๋Š” ๊ฒฝ์šฐ์— ๋™์ž‘ํ•œ๋‹ค. 

 

- @ConditionalOnBean, @ConditionalOnMissingBean

: ๋นˆ์ด ๋“ฑ๋ก๋˜์–ด ์žˆ๋Š” ๊ฒฝ์šฐ์— ๋™์ž‘ํ•œ๋‹ค, ์—†๋Š” ๊ฒฝ์šฐ์— ๋™์ž‘ํ•œ๋‹ค. 

 

- @ConditionalOnProperty 

: ํ™˜๊ฒฝ ์ •๋ณด๊ฐ€ ์žˆ๋Š” ๊ฒฝ์šฐ์— ๋™์ž‘ํ•œ๋‹ค. 

 

- @ConditionalOnResource

: ๋ฆฌ์†Œ์Šค๊ฐ€ ์žˆ๋Š” ๊ฒฝ์šฐ์— ๋™์ž‘ํ•œ๋‹ค. 

 

- @ConditionalOnWebApplication, @ConditionalOnNotWebApplication

: ์›น ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์ธ ๊ฒฝ์šฐ์— ๋™์ž‘ํ•œ๋‹ค, ์•„๋‹Œ ๊ฒฝ์šฐ์— ๋™์ž‘ํ•œ๋‹ค.

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

728x90