Home > 2024 > Spring & Spring Boots > πŸƒ[Spring Boot] μŠ€ν”„λ§?

πŸƒ[Spring Boot] μŠ€ν”„λ§?
Spring Boot Framework Spring

Intro.

  • μŠ€ν”„λ§ ν”„λ ˆμž„μ›Œν¬(Spring Framework) λŠ” μžλ°”(Java) κ°€λ°˜μ˜ μ• ν”Œλ¦¬μΌ€μ΄μ…˜ ν”„λ ˆμž„μ›Œν¬λ‘œ μ—”ν„°ν”„λΌμ΄μ¦ˆκΈ‰ μ• ν”Œλ¦¬μΌ€μ΄μ…˜μ„ κ°œλ°œν•˜κΈ° μœ„ν•œ λ‹€μ–‘ν•œ κΈ°λŠ₯을 μ œκ³΅ν•©λ‹ˆλ‹€.
  • μŠ€ν”„λ§μ€ λͺ©μ μ— 따라 λ‹€μ–‘ν•œ ν”„λ‘œμ νŠΈλ₯Ό μ œκ³΅ν•˜λŠ”λ°, 그쀑 ν•˜λ‚˜κ°€ μŠ€ν”„λ§ λΆ€νŠΈ(Spring Boot) μž…λ‹ˆλ‹€.

이번 ν¬μŠ€νŒ…μ—μ„œλŠ” λ¨Όμ € μŠ€ν”„λ§ λΆ€νŠΈμ˜ 기반인 μŠ€ν”„λ§ ν”„λ ˆμž„μ›Œν¬λ₯Ό μ•Œμ•„λ³΄κ³ , μŠ€ν”„λ§μ΄ μ œκ³΅ν•˜λŠ” λ‹€μ–‘ν•œ ν”„λ‘œμ νŠΈ 쀑 ν•˜λ‚˜μΈ μŠ€ν”„λ§ λΆ€νŠΈμ˜ νŠΉμ§•μ„ μ„€λͺ…ν•˜κ² μŠ΅λ‹ˆλ‹€.

μŠ€ν”„λ§ ν”„λ ˆμž„μ›Œν¬.

μŠ€ν”„λ§ ν”„λ ˆμž„μ›Œν¬(이후 μŠ€ν”„λ§) λŠ” μžλ°”μ—μ„œ κ°€μž₯ 많이 μ‚¬μš©ν•˜λŠ” ν”„λ ˆμž„μ›Œν¬μž…λ‹ˆλ‹€.
μŠ€ν”„λ§μ€ μžλ°” μ–Έμ–΄λ₯Ό μ΄μš©ν•΄ μ—”ν„°ν”„λΌμ΄μ¦ˆκΈ‰ κ°œλ°œμ„ νŽΈλ¦¬ν•˜κ²Œ λ§Œλ“€μ–΄μ£ΌλŠ” β€˜μ˜€ν”ˆμ†ŒμŠ€ κ²½λŸ‰κΈ‰ μ• ν”Œλ¦¬μΌ€μ΄μ…˜ ν”„λ ˆμž„μ›Œν¬β€™λ‘œ 뢈리고 μžˆμŠ΅λ‹ˆλ‹€.
μ‰½κ²Œ λ§ν•΄μ„œ μžλ°”λ‘œ μ• ν”Œλ¦¬μΌ€μ΄μ…˜μ„ κ°œλ°œν•˜λŠ” 데 ν•„μš”ν•œ κΈ°λŠ₯을 μ œκ³΅ν•˜κ³  μ‰½κ²Œ μ‚¬μš©ν•˜λ„λ‘ λ•λŠ” λ„κ΅¬μž…λ‹ˆλ‹€.

TIP: β€˜μ—”ν„°ν”„λΌμ΄μ¦ˆκΈ‰ 개발?’

β€˜μ—”ν„°ν”„λΌμ΄μ¦ˆκΈ‰ κ°œλ°œβ€™μ€ κΈ°μ—… ν™˜κ²½μ„ λŒ€μƒμœΌλ‘œ ν•˜λŠ” κ°œλ°œμ„ λœ»ν•©λ‹ˆλ‹€.
λ„€μ΄λ²„λ‚˜ μΉ΄μΉ΄μ˜€ν†‘ 같은 λŒ€κ·œλͺ¨ 데이터λ₯Ό μ²˜λ¦¬ν•˜λŠ” ν™˜κ²½μ„ μ—”ν„°ν”„λΌμ΄μ¦ˆ ν™˜κ²½μ΄λΌκ³  λΆ€λ¦…λ‹ˆλ‹€.
μŠ€ν”„λ§μ€ 이 ν™˜κ²½μ— μ•Œλ§žκ²Œ μ„€κ³„λ˜μ–΄ μžˆμ–΄ κ°œλ°œμžλŠ” μ• ν”Œλ¦¬μΌ€μ΄μ…˜μ„ κ°œλ°œν•  λ•Œ λ§Žμ€ μš”μ†Œλ₯Ό ν”„λ ˆμž„μ›Œν¬μ— μœ„μž„ν•˜κ³  λΉ„μ¦ˆλ‹ˆμŠ€ λ‘œμ§μ„ κ΅¬ν˜„ν•˜λŠ” 데 집쀑할 수 μžˆμŠ΅λ‹ˆλ‹€.

μŠ€ν”„λ§μ˜ 핡심 κ°€μΉ˜λŠ” β€œμ• ν”Œλ¦¬μΌ€μ΄μ…˜ κ°œλ°œμ— ν•„μš”ν•œ κΈ°λ°˜μ„ μ œκ³΅ν•΄μ„œ κ°œλ°œμžκ°€ λΉ„μ¦ˆλ‹ˆμŠ€ 둜직 κ΅¬ν˜„μ—λ§Œ 집쀑할 수 μžˆκ²Œλ” ν•˜λŠ” 것” μž…λ‹ˆλ‹€.

μ œμ–΄ 역적(IoC)

일반적인 μžλ°” 개발의 경우 객체λ₯Ό μ‚¬μš©ν•˜κΈ° μœ„ν•΄ μ•„λž˜μ˜ 예제 μ½”λ“œμ™€ 같은 μ½”λ“œλ₯Ό μ‚¬μš©ν•©λ‹ˆλ‹€.

@RestController
public class NoDIController {
    
    private MyService service = new MyServiceImpl();
    
    @GetMapping("/no-di/hello")
    public String getHello() {
        return service.getHello();
    }
}

즉, μ‚¬μš©ν•˜λ €λŠ” 객체λ₯Ό μ„ μ–Έν•˜κ³  ν•΄λ‹Ή 객체의 μ˜μ‘΄μ„±μ„ μƒμ„±ν•œ ν›„ κ°μ²΄μ—μ„œ μ œκ³΅ν•˜λŠ” κΈ°λŠ₯을 μ‚¬μš©ν•©λ‹ˆλ‹€.
객체λ₯Ό μƒμ„±ν•˜κ³  μ‚¬μš©ν•˜λŠ” 일련의 μž‘μ—…μ„ κ°œλ°œμžκ°€ 직접 μ œμ–΄ν•˜λŠ” κ΅¬μ‘°μž…λ‹ˆλ‹€.

ν•˜μ§€λ§Œ μ œμ–΄ μ—­μ „(IoC: Inversion of Controller) 을 νŠΉμ§•μœΌλ‘œ ν•˜λŠ” μŠ€ν”„λ§μ€ κΈ°μ‘΄ μžλ°” 개발 방식과 λ‹€λ₯΄κ²Œ λ™μž‘ν•©λ‹ˆλ‹€.
IoCλ₯Ό μ μš©ν•œ ν™˜κ²½μ—μ„œλŠ” μ‚¬μš©ν•  객체λ₯Ό 직접 μƒμ„±ν•˜μ§€ μ•Šκ³  객체의 생λͺ…μ£ΌκΈ° 관리λ₯Ό 외뢀에 μœ„μž„ν•©λ‹ˆλ‹€.
μ—¬κΈ°μ„œ β€˜μ™ΈλΆ€β€™ λŠ” μŠ€ν”„λ§ μ»¨ν…Œμ΄λ„ˆ(Spring Container) λ˜λŠ” IoC μ»¨ν…Œμ΄λ„ˆ(IoC Container) λ₯Ό μ˜λ―Έν•©λ‹ˆλ‹€.

β€œκ°μ²΄μ˜ 관리λ₯Ό μ»¨ν…Œμ΄λ„ˆμ— 맑겨 μ œμ–΄κΆŒμ΄ λ„˜μ–΄κ°„ 것”을 μ œμ–΄ 역전이라고 λΆ€λ₯΄λ©°, μ œμ–΄ 역전을 톡해 μ˜μ‘΄μ„± μ£Όμž…(DI: Dependency Injection), 관점 지ν–₯ ν”„λ‘œκ·Έλž˜λ°(AOP: Aspect-Oriented Programming) 등이 κ°€λŠ₯ν•΄μ§‘λ‹ˆλ‹€.

μŠ€ν”„λ§ 을 μ‚¬μš©ν•˜λ©΄ 객체의 μ œμ–΄κΆŒμ„ μ»¨ν…Œμ΄λ„ˆλ‘œ λ„˜κΈ°κΈ° λ•Œλ¬Έμ— β€œκ°œλ°œμžλŠ” λΉ„μ¦ˆλ‹ˆμŠ€ λ‘œμ§μ„ μž‘μ„±ν•˜λŠ” 데 더 집쀑” ν•  수 μžˆμŠ΅λ‹ˆλ‹€.

μ˜μ‘΄μ„± μ£Όμž…(DI)

μ˜μ‘΄μ„± μ£Όμž…(DI: Dependency Injection)μ΄λž€ β€œμ œμ–΄ μ—­μ „μ˜ 방법 쀑 ν•˜λ‚˜β€λ‘œ, μ‚¬μš©ν•  객체λ₯Ό 직접 μƒμ„±ν•˜μ§€ μ•Šκ³  μ™ΈλΆ€ μ»¨ν…Œμ΄λ„ˆκ°€ μƒμ„±ν•œ 객체λ₯Ό μ£Όμž…λ°›μ•„ μ‚¬μš©ν•˜λŠ” 방식을 μ˜λ―Έν•©λ‹ˆλ‹€.

μŠ€ν”„λ§μ—μ„œ μ˜μ‘΄μ„±μ„ μ£Όμž…λ°›λŠ” 방법은 3가지가 μžˆμŠ΅λ‹ˆλ‹€.

  1. μƒμ„±μžλ₯Ό ν†΅ν•œ μ˜μ‘΄μ„± μ£Όμž…
  2. ν•„λ“œ 객체 선언을 ν†΅ν•œ μ˜μ‘΄μ„± μ£Όμž…
  3. setter λ©”μ„œλ“œλ₯Ό ν†΅ν•œ μ˜μ‘΄μ„± μ£Όμž…

μŠ€ν”„λ§μ—μ„œλŠ” @AutowiredλΌλŠ” μ–΄λ…Έν…Œμ΄μ…˜(annotation)을 톡해 μ˜μ‘΄μ„±μ„ μ£Όμž…ν•  수 μžˆμŠ΅λ‹ˆλ‹€.
μŠ€ν”„λ§ 4.3 이후 버전은 μƒμ„±μžλ₯Ό 톡해 μ˜μ‘΄μ„±μ„ μ£Όμž…ν•  λ•Œ @Autowired μ–΄λ…Έν…Œμ΄μ…˜μ„ μƒλž΅ν•  μˆ˜λ„ μžˆμŠ΅λ‹ˆλ‹€.
ν•˜μ§€λ§Œ μŠ€ν”„λ§μ„ 처음 λ‹€λ£° λ•ŒλŠ” 가독성을 μœ„ν•΄ μ–΄λ…Έν…Œμ΄μ…˜μ„ λͺ…μ‹œν•˜κΈ°λ₯Ό ꢌμž₯ν•©λ‹ˆλ‹€.

μŠ€ν”„λ§μ—μ„œ μ˜μ‘΄μ„±μ„ μ£Όμž…λ°›λŠ” 각 방법에 λŒ€ν•œ μ˜ˆμ‹œ μ½”λ“œλŠ” μ•„λž˜μ™€ κ°™μŠ΅λ‹ˆλ‹€.

// μƒμ„±μžλ₯Ό ν†΅ν•œ μ˜μ‘΄μ„± μ£Όμž…
@RestController
public class DIController {
    
    // <-- μ˜μ‘΄μ„±μ„ μ£Όμž… λ°›λŠ” μ£Όμš”λΆ€λΆ„ 
    MyService myService;
    @Autowired
    public DIController(MyService myService) {
        this.myService = myServicel
    }
    // -->
    
    @GetMapping("di/hello")
    public String getHello() {
        return myService.getHello();
    }
}
// ν•„λ“œ 객체 선언을 ν†΅ν•œ μ˜μ‘΄μ„± μ£Όμž…
@RestController
public class FieldInjectionController {
    // <-- μ˜μ‘΄μ„±μ„ μ£Όμž… λ°›λŠ” μ£Όμš”λΆ€λΆ„
    @Autowired
    private MyService myService;
    // -->
}
// setter λ©”μ„œλ“œλ₯Ό ν†΅ν•œ μ˜μ‘΄μ„± μ£Όμž…
@RestController
public class SetterInjectionController {
    // <-- μ˜μ‘΄μ„±μ„ μ£Όμž… λ°›λŠ” μ£Όμš”λΆ€λΆ„
    MyService myService;
    
    @Autowired
    public void setMyService(MyService myService) {
        this.myService = myService;
    }
    // -->
}

μŠ€ν”„λ§ 곡식 λ¬Έμ„œμ—μ„œ ꢌμž₯ν•˜λŠ” μ˜μ‘΄μ„± μ£Όμž… 방법은 β€œμƒμ„±μžλ₯Ό 톡해 μ˜μ‘΄μ„±μ„ μ£Όμž…λ°›λŠ” 방식” μž…λ‹ˆλ‹€.
λ‹€λ₯Έ λ°©μ‹κ³ΌλŠ” λ‹€λ₯΄κ²Œ μƒμ„±μžλ₯Ό 톡해 μ˜μ‘΄μ„±μ„ μ£Όμž…λ°›λŠ” 방식은 β€œλ ˆνΌλŸ°μŠ€ 객체 μ—†μ΄λŠ” 객체λ₯Ό μ΄ˆκΈ°ν™”ν•  수 μ—†κ²Œ 섀계할 수 있기 λ•Œλ¬Έμž…λ‹ˆλ‹€.”

관점 지ν–₯ ν”„λ‘œκ·Έλž˜λ°(AOP)

관점 지ν–₯ ν”„λ‘œκ·Έλž˜λ°(이후 AOP: Aspect-Oriented Programming) 은 μŠ€ν”„λ§μ˜ μ•„μ£Ό μ€‘μš”ν•œ νŠΉμ§•μž…λ‹ˆλ‹€.
AOPλŠ” OOPλ₯Ό λ”μš± 잘 μ‚¬μš©ν•˜λ„λ‘ λ•λŠ” κ°œλ…μœΌλ‘œ λ³΄λŠ” 것이 μ’‹μŠ΅λ‹ˆλ‹€.

μŠ€ν„°λ”” κ°€μ΄λ“œ

OOPλ₯Ό μš”μ•½ν•˜μžλ©΄ 각 κΈ°λŠ₯을 μž¬μ‚¬μš© κ°€λŠ₯ν•œ κ°œλ³„ 객체둜 ꡬ성해 ν”„λ‘œκ·Έλž˜λ°ν•˜λŠ” 것을 λœ»ν•©λ‹ˆλ‹€.

λ‹€μŒκ³Ό 같은 OOP의 ν•΅μ‹¬ν‚€μ›Œλ“œλ₯Ό μ΄ν•΄ν•œλ‹€λ©΄ 더 λ‚˜μ€ 객체지행 ν”„λ‘œκ·Έλž˜λ°μ΄ κ°€λŠ₯ν•©λ‹ˆλ‹€.

  • 좔상화(abstraction)
  • μΊ‘μŠν™”(encapsulation)
  • 상속(inheritance)
  • λ‹€ν˜•μ„±(polymorphism)

β€œAOPλŠ” 관점을 κΈ°μ€€μœΌλ‘œ λ¬Άμ–΄ κ°œλ°œν•˜λŠ” 방식을 μ˜λ―Έν•©λ‹ˆλ‹€.”
μ—¬κΈ°μ„œ β€œκ΄€μ (aspect)” μ΄λž€ β€œμ–΄λ–€ κΈ°λŠ₯을 κ΅¬ν˜„ν•  λ•Œ κ·Έ κΈ°λŠ₯을 β€˜ν•΅μ‹¬ κΈ°λŠ₯’과 β€˜λΆ€κ°€ κΈ°λŠ₯β€™μœΌλ‘œ ꡬ뢄해 각각을 ν•˜λ‚˜μ˜ κ΄€μ μœΌλ‘œ λ³΄λŠ” 것을 μ˜λ―Έβ€ ν•©λ‹ˆλ‹€.

  • β€œν•΅μ‹¬κΈ°λŠ₯”
    • λΉ„μ¦ˆλ‹ˆμŠ€λ‘œμ§μ„ κ΅¬ν˜„ν•˜λŠ” κ³Όμ •μ—μ„œ λΉ„μ¦ˆλ‹ˆμŠ€ 둜직이 μ²˜λ¦¬ν•˜λ €λŠ” λͺ©μ  κΈ°λŠ₯을 λ§ν•©λ‹ˆλ‹€.
      • 예λ₯Ό λ“€λ©΄, ν΄λΌμ΄μ–ΈνŠΈλ‘œλΆ€ν„° μƒν’ˆ 정보 등둝 μš”μ²­μ„ λ°›μ•„ λ°μ΄ν„°λ² μ΄μŠ€μ— μ €μž₯ν•˜κ³ , κ·Έ μƒν’ˆ 정보λ₯Ό μ‘°νšŒν•˜λŠ” λΉ„μ¦ˆλ‹ˆμŠ€ λ‘œμ§μ„ κ΅¬ν˜„ν•œλ‹€λ©΄
        • (1) μƒν’ˆ 정보λ₯Ό λ°μ΄ν„°λ² μ΄μŠ€μ— μ €μž₯ν•˜κ³ ,
        • (2) μ €μž₯된 μƒν’ˆ 정보 데이터λ₯Ό λ³΄μ—¬μ£ΌλŠ” μ½”λ“œκ°€ 핡심 κΈ°λŠ₯μž…λ‹ˆλ‹€.

그런데 μ‹€μ œ μ• ν”Œλ¦¬μΌ€μ΄μ…˜μ„ κ°œλ°œν•  λ•ŒλŠ” 핡심 κΈ°λŠ₯에 λΆ€κ°€ κΈ°λŠ₯을 μΆ”κ°€ν•  상황이 μƒκΉλ‹ˆλ‹€.
β€œν•΅μ‹¬ κΈ°λŠ₯인 λΉ„μ¦ˆλ‹ˆμŠ€ 둜직 사이에 λ‘œκΉ… 처리λ₯Ό ν•˜κ±°λ‚˜ νŠΈλžœμž­μ…˜μ„ μ²˜λ¦¬ν•˜λŠ” μ½”λ“œλ₯Ό 예둜 λ“€ 수 μžˆμŠ΅λ‹ˆλ‹€.”

일반적인 OOP ν˜•μ‹μœΌλ‘œ λΉ„μ¦ˆλ‹ˆμŠ€ λ‘œμ§μ„ μž‘μ„±ν•˜λ©΄ μ•„λž˜ κ·Έλ¦Όκ³Ό 같이 λΉ„μ¦ˆλ‹ˆμŠ€ λ™μž‘ 흐름이 λ°œμƒν•©λ‹ˆλ‹€.

OOP λ°©μ‹μ˜ μ• ν”Œλ¦¬μΌ€μ΄μ…˜ λ‘œμ§μ—μ„œλŠ” μœ„ κ·Έλ¦Όκ³Ό 같이 κ°μ±„λ§ˆλ‹€ 핡심 κΈ°λŠ₯을 μˆ˜ν–‰ν•˜κΈ° μœ„ν•œ β€œλ‘œμ§β€ κ³Ό ν•¨κ»˜ λΆ€κ°€ κΈ°λŠ₯인 β€œλ‘œκΉ…β€, β€œνŠΈλžœμž­μ…˜β€ λ“±μ˜ μ½”λ“œλ₯Ό μž‘μ„±ν•©λ‹ˆλ‹€.
μœ„ 그림의 μƒν’ˆμ •λ³΄ 등둝 κΈ°λŠ₯κ³Ό μƒν’ˆμ •λ³΄ 쑰회 κΈ°λŠ₯은 μ—„μ—°νžˆ λ‹€λ₯Έ κΈ°λŠ₯으둜, 각자 둜직이 κ΅¬ν˜„λΌ μžˆμŠ΅λ‹ˆλ‹€.

ν•˜μ§€λ§Œ μœ μ§€λ³΄μˆ˜ λͺ©μ μ΄λ‚˜ λ°μ΄ν„°λ² μ΄μŠ€ 접근을 μœ„ν•΄ μž‘μ„±λœ β€œλ‘œκΉ…β€ κ³Ό β€œνŠΈλžœμž­μ…˜β€ μ˜μ—­μ€ μƒν’ˆμ •λ³΄λ₯Ό 등둝할 λ•Œλ‚˜ μƒν’ˆμ •λ³΄λ₯Ό μ‘°νšŒν•  λ•Œ λ™μΌν•œ κΈ°λŠ₯을 μˆ˜ν–‰ν•  ν™•λ₯ μ΄ λ†’μŠ΅λ‹ˆλ‹€.

즉, 핡심 κΈ°λŠ₯을 κ΅¬ν˜„ν•œ 두 λ‘œμ§μ— λ™μΌν•œ μ½”λ“œκ°€ ν¬ν•¨λœλ‹€λŠ” 것을 μ˜λ―Έν•©λ‹ˆλ‹€.

AOP의 κ΄€μ μ—μ„œλŠ” λΆ€κ°€ κΈ°λŠ₯은 핡심 κΈ°λŠ₯이 μ–΄λ–€ κΈ°λŠ₯인지에 κ΅¬κ΄€ν•˜κ²Œ 둜직이 μˆ˜ν–‰λ˜κΈ° μ „ λ˜λŠ” 후에 μˆ˜ν–‰λ˜κΈ°λ§Œ ν•˜λ©΄ λ©λ‹ˆλ‹€.
κ·Έλž˜μ„œ μ•„λž˜ κ·Έλ¦Όκ³Ό 같은 κ΅¬μ„±μœΌλ‘œ λ§Œλ“€ 수 μžˆμŠ΅λ‹ˆλ‹€.

이처럼 μ—¬λŸ¬ λΉ„μ¦ˆλ‹ˆμŠ€ λ‘œμ§μ—μ„œ λ°˜λ³΅λ˜λŠ” λΆ€κ°€ κΈ°λŠ₯을 ν•˜λ‚˜μ˜ β€œκ³΅ν†΅ 둜직으둜 μ²˜λ¦¬ν•˜λ„λ‘ λͺ¨λ“ˆν™”ν•΄ μ‚½μž…ν•˜λŠ” 방식” 을 β€œAOP” 라고 ν•©λ‹ˆλ‹€.

μ΄λŸ¬ν•œ AOPλ₯Ό κ΅¬ν˜„ν•˜λŠ” 방법은 크게 μ„Έ 가지가 μžˆμŠ΅λ‹ˆλ‹€.

  • 컴파일 과정에 μ‚½μž…ν•˜λŠ” 방식
  • λ°”μ΄νŠΈμ½”λ“œλ₯Ό λ©”λͺ¨λ¦¬μ— λ‘œλ“œν•˜λŠ” 과정에 μ‚½μž…ν•˜λŠ” 방식
  • ν”„λ½μ‹œ νŒ¨ν„΄μ„ μ΄μš©ν•œ 방식

이 κ°€μš΄λ° μŠ€ν”„λ§μ€ λ””μžμΈ νŒ¨ν„΄ 쀑 ν•˜λ‚˜μΈ β€œν”„λ½μ‹œ νŒ¨ν„΄β€ 을 톡해 β€œAOP” κΈ°λŠ₯을 μ œκ³΅ν•˜κ³  μžˆμŠ΅λ‹ˆλ‹€.

μŠ€ν”„λ§ AOP의 λͺ©μ μ€ OOP와 λ§ˆμ°¬κ°€μ§€λ‘œ λͺ¨λ“ˆν™”ν•΄μ„œ μž¬μ‚¬μš© κ°€λŠ₯ν•œ ꡬ성을 λ§Œλ“œλŠ” 것이고, λͺ¨λ“ˆν™”λœ 객체λ₯Ό νŽΈν•˜κ²Œ μ μš©ν•  수 있게 ν•¨μœΌλ‘œμ¨ κ°œλ°œμžκ°€ λΉ„μ¦ˆλ‹ˆμŠ€ λ‘œμ§μ„ κ΅¬ν˜„ν•˜λŠ” 데만 집쀑할 수 있게 λ„μ™€μ£ΌλŠ” κ²ƒμž…λ‹ˆλ‹€.

μŠ€ν”„λ§ ν”„λ ˆμž„μ›Œν¬μ˜ λ‹€μ–‘ν•œ λͺ¨λ“ˆ

μŠ€ν”„λ§ ν”„λ ˆμž„μ›Œν¬λŠ” κΈ°λŠ₯λ³„λ‘œ κ΅¬λΆ„λœ μ•½ 20μ—¬ 개의 λͺ¨λ“ˆλ‘œ ꡬ성돼 μžˆμŠ΅λ‹ˆλ‹€.

μ•„λž˜ 그림은 μŠ€ν”„λ§ 곡식 λ¬Έμ„œμ—μ„œ μ œκ³΅ν•˜λŠ” λ‹€μ΄μ–΄κ·Έλž¨μž…λ‹ˆλ‹€.

μŠ€ν”„λ§ ν”„λ ˆμž„μ›Œν¬ 곡식 λ¬Έμ„œμ—μ„œλŠ” μŠ€ν”„λ§ λ²„μ „λ³„λ‘œ λ‹€λ₯Έ λ‹€μ΄μ–΄κ·Έλž¨μ„ μ œμ‹œν•˜κ³  μžˆμ§€λ§Œ 큰 틀은 μœ μ‚¬ν•©λ‹ˆλ‹€.
그리고 μŠ€ν”„λ§ ν”„λ ˆμž„μ›Œν¬λ₯Ό μ‚¬μš©ν•œλ‹€κ³  ν•΄μ„œ λͺ¨λ“  λͺ¨λ“ˆμ„ μ‚¬μš©ν•  ν•„μš”λŠ” μ—†μŠ΅λ‹ˆλ‹€.
μ• ν”Œλ¦¬μΌ€μ΄μ…˜ κ°œλ°œμ— ν•„μš”ν•œ λͺ¨λ“ˆλ§Œ μ„ νƒν•΄μ„œ μ‚¬μš©ν•˜κ²Œλ” 섀계돼 있으며, 이λ₯Ό β€œκ²½λŸ‰ μ»¨ν…Œμ΄λ„ˆ 섀계”라고 λΆ€λ¦…λ‹ˆλ‹€.